diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/BatchStatus.java b/spring-batch-core/src/main/java/org/springframework/batch/core/BatchStatus.java index c548a1d85..c5a2798a5 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/BatchStatus.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/BatchStatus.java @@ -27,15 +27,15 @@ package org.springframework.batch.core; public enum BatchStatus { /** - * The order of the status values is significant because it can be used to - * aggregate a set of status values. The result should be the maximum - * value. Since {@code COMPLETED} is first in the order, only if all elements of an - * execution are {@code COMPLETED} can the aggregate status be COMPLETED. A running - * execution is expected to move from {@code STARTING} to {@code STARTED} to {@code COMPLETED} - * (through the order defined by {@link #upgradeTo(BatchStatus)}). Higher - * values than {@code STARTED} signify more serious failures. {@code ABANDONED} is used for - * steps that have finished processing but were not successful and where - * they should be skipped on a restart (so {@code FAILED} is the wrong status). + * The order of the status values is significant because it can be used to aggregate a + * set of status values. The result should be the maximum value. Since + * {@code COMPLETED} is first in the order, only if all elements of an execution are + * {@code COMPLETED} can the aggregate status be COMPLETED. A running execution is + * expected to move from {@code STARTING} to {@code STARTED} to {@code COMPLETED} + * (through the order defined by {@link #upgradeTo(BatchStatus)}). Higher values than + * {@code STARTED} signify more serious failures. {@code ABANDONED} is used for steps + * that have finished processing but were not successful and where they should be + * skipped on a restart (so {@code FAILED} is the wrong status). */ /** @@ -72,8 +72,8 @@ public enum BatchStatus { UNKNOWN; /** - * Convenience method to return the higher value status of the statuses passed to the method. - * + * Convenience method to return the higher value status of the statuses passed to the + * method. * @param status1 The first status to check. * @param status2 The second status to check. * @return The higher value status of the two statuses. @@ -84,7 +84,6 @@ public enum BatchStatus { /** * Convenience method to decide if a status indicates that work is in progress. - * * @return true if the status is STARTING, STARTED */ public boolean isRunning() { @@ -92,9 +91,7 @@ public enum BatchStatus { } /** - * Convenience method to decide if a status indicates execution was - * unsuccessful. - * + * Convenience method to decide if a status indicates execution was unsuccessful. * @return {@code true} if the status is {@code FAILED} or greater. */ public boolean isUnsuccessful() { @@ -102,13 +99,12 @@ public enum BatchStatus { } /** - * Method used to move status values through their logical progression, and - * override less severe failures with more severe ones. This value is - * compared with the parameter, and the one that has higher priority is - * returned. If both are {@code STARTED} or less than the value returned is the - * largest in the sequence {@code STARTING}, {@code STARTED}, {@code COMPLETED}. Otherwise, the value - * returned is the maximum of the two. - * + * Method used to move status values through their logical progression, and override + * less severe failures with more severe ones. This value is compared with the + * parameter, and the one that has higher priority is returned. If both are + * {@code STARTED} or less than the value returned is the largest in the sequence + * {@code STARTING}, {@code STARTED}, {@code COMPLETED}. Otherwise, the value returned + * is the maximum of the two. * @param other Another status to which to compare. * @return either this or the other status, depending on their priority. */ @@ -151,7 +147,6 @@ public enum BatchStatus { * Find a {@code BatchStatus} that matches the beginning of the given value. If no * match is found, return {@code COMPLETED} as the default because it has low * precedence. - * * @param value A string representing a status. * @return a {BatchStatus} object. */ @@ -164,4 +159,5 @@ public enum BatchStatus { // Default match should be the lowest priority return COMPLETED; } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/ChunkListener.java b/spring-batch-core/src/main/java/org/springframework/batch/core/ChunkListener.java index 2cd2539cb..d7339459c 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/ChunkListener.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/ChunkListener.java @@ -18,9 +18,8 @@ package org.springframework.batch.core; import org.springframework.batch.core.scope.context.ChunkContext; /** - * Listener interface for the lifecycle of a chunk. A chunk - * can be thought of as a collection of items that are - * committed together. + * Listener interface for the lifecycle of a chunk. A chunk can be thought of as a + * collection of items that are committed together. * * @author Lucas Ward * @author Michael Minella @@ -36,7 +35,6 @@ public interface ChunkListener extends StepListener { /** * Callback before the chunk is executed, but inside the transaction. - * * @param context The current {@link ChunkContext} */ default void beforeChunk(ChunkContext context) { @@ -44,24 +42,23 @@ public interface ChunkListener extends StepListener { /** * Callback after the chunk is executed, outside the transaction. - * * @param context The current {@link ChunkContext} */ default void afterChunk(ChunkContext context) { } /** - * Callback after a chunk has been marked for rollback. It is invoked - * after transaction rollback. While the rollback will have occurred, - * transactional resources might still be active and accessible. Due to - * this, data access code within this callback still "participates" in - * the original transaction unless it declares that it runs in its own - * transaction. As a result, you should use {@code PROPAGATION_REQUIRES_NEW} for any - * transactional operation that is called from here. - * - * @param context the chunk context containing the exception that caused - * the underlying rollback. + * Callback after a chunk has been marked for rollback. It is invoked after + * transaction rollback. While the rollback will have occurred, transactional + * resources might still be active and accessible. Due to this, data access code + * within this callback still "participates" in the original transaction unless it + * declares that it runs in its own transaction. As a result, you should use + * {@code PROPAGATION_REQUIRES_NEW} for any transactional operation that is called + * from here. + * @param context the chunk context containing the exception that caused the + * underlying rollback. */ default void afterChunkError(ChunkContext context) { } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/DefaultJobKeyGenerator.java b/spring-batch-core/src/main/java/org/springframework/batch/core/DefaultJobKeyGenerator.java index 967577c9b..4301ed59a 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/DefaultJobKeyGenerator.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/DefaultJobKeyGenerator.java @@ -25,10 +25,10 @@ import org.springframework.util.Assert; import org.springframework.util.DigestUtils; /** - * Default implementation of the {@link JobKeyGenerator} interface. - * This implementation provides a single hash value based on the {@link JobParameters} object - * passed in. Only identifying parameters (as per {@link JobParameter#isIdentifying()}) - * are used in the calculation of the key. + * Default implementation of the {@link JobKeyGenerator} interface. This implementation + * provides a single hash value based on the {@link JobParameters} object passed in. Only + * identifying parameters (as per {@link JobParameter#isIdentifying()}) are used in the + * calculation of the key. * * @author Michael Minella * @author Mahmoud Ben Hassine @@ -50,16 +50,17 @@ public class DefaultJobKeyGenerator implements JobKeyGenerator { Collections.sort(keys); for (String key : keys) { JobParameter jobParameter = props.get(key); - if(jobParameter.isIdentifying()) { - String value = jobParameter.getValue()==null ? "" : jobParameter.toString(); + if (jobParameter.isIdentifying()) { + String value = jobParameter.getValue() == null ? "" : jobParameter.toString(); stringBuffer.append(key).append("=").append(value).append(";"); } } try { return DigestUtils.md5DigestAsHex(stringBuffer.toString().getBytes("UTF-8")); - } catch (UnsupportedEncodingException e) { - throw new IllegalStateException( - "UTF-8 encoding not available. Fatal (should be in the JDK)."); + } + catch (UnsupportedEncodingException e) { + throw new IllegalStateException("UTF-8 encoding not available. Fatal (should be in the JDK)."); } } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/Entity.java b/spring-batch-core/src/main/java/org/springframework/batch/core/Entity.java index a2efa8200..0a37448f7 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/Entity.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/Entity.java @@ -21,10 +21,9 @@ import java.io.Serializable; import org.springframework.util.ClassUtils; /** - * Batch Domain Entity class. Any class that should be uniquely identifiable - * from another should subclass from Entity. See Domain - * Driven Design, by Eric Evans, for more information on this pattern - * and the difference between Entities and Value Objects. + * Batch Domain Entity class. Any class that should be uniquely identifiable from another + * should subclass from Entity. See Domain Driven Design, by Eric Evans, for more + * information on this pattern and the difference between Entities and Value Objects. * * @author Lucas Ward * @author Dave Syer @@ -48,15 +47,14 @@ public class Entity implements Serializable { /** * The constructor for the {@link Entity} where the ID is established. - * * @param id The ID for the entity. */ public Entity(Long id) { super(); - //Commented out because StepExecutions are still created in a disconnected - //manner. The Repository should create them, then this can be uncommented. - //Assert.notNull(id, "Entity id must not be null."); + // Commented out because StepExecutions are still created in a disconnected + // manner. The Repository should create them, then this can be uncommented. + // Assert.notNull(id, "Entity id must not be null."); this.id = id; } @@ -95,23 +93,24 @@ public class Entity implements Serializable { public void incrementVersion() { if (version == null) { version = 0; - } else { + } + else { version = version + 1; } } - /** - * Creates a string representation of the {@code Entity}, - * including the {@code id}, {@code version}, and class name. - */ + /** + * Creates a string representation of the {@code Entity}, including the {@code id}, + * {@code version}, and class name. + */ @Override public String toString() { return String.format("%s: id=%d, version=%d", ClassUtils.getShortName(getClass()), id, version); } /** - * Attempt to establish identity based on {@code id} if both exist. If either {@code id} - * does not exist, use {@code Object.equals()}. + * Attempt to establish identity based on {@code id} if both exist. If either + * {@code id} does not exist, use {@code Object.equals()}. * * @see java.lang.Object#equals(java.lang.Object) */ @@ -135,14 +134,13 @@ public class Entity implements Serializable { /** * Use {@code id}, if it exists, to establish a hash code. Otherwise fall back to - * {@code Object.hashCode()}. It is based on the - * same information as {@code equals}, so, if that - * changes, this will. Note that this follows the contract of {@code Object.hashCode()} - * but will cause problems for anyone adding an unsaved {@link Entity} to a - * {@code Set} because {@code Set.contains()} almost certainly returns false for the - * {@link Entity} after it is saved. Spring Batch does not store any of its - * entities in sets as a matter of course, so this is internally consistent. - * Clients should not be exposed to unsaved entities. + * {@code Object.hashCode()}. It is based on the same information as {@code equals}, + * so, if that changes, this will. Note that this follows the contract of + * {@code Object.hashCode()} but will cause problems for anyone adding an unsaved + * {@link Entity} to a {@code Set} because {@code Set.contains()} almost certainly + * returns false for the {@link Entity} after it is saved. Spring Batch does not store + * any of its entities in sets as a matter of course, so this is internally + * consistent. Clients should not be exposed to unsaved entities. * * @see java.lang.Object#hashCode() */ diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/ExitStatus.java b/spring-batch-core/src/main/java/org/springframework/batch/core/ExitStatus.java index 17785ea1d..4f93ce7da 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/ExitStatus.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/ExitStatus.java @@ -22,8 +22,7 @@ import java.io.Serializable; import java.io.StringWriter; /** - * Value object used to carry information about the status of a - * job or step execution. + * Value object used to carry information about the status of a job or step execution. * * {@code ExitStatus} is immutable and, therefore, thread-safe. * @@ -34,17 +33,16 @@ import java.io.StringWriter; public class ExitStatus implements Serializable, Comparable { /** - * Convenient constant value representing unknown state - assumed to not - * be continuable. + * Convenient constant value representing unknown state - assumed to not be + * continuable. */ public static final ExitStatus UNKNOWN = new ExitStatus("UNKNOWN"); /** - * Convenient constant value representing continuable state where processing - * is still taking place, so no further action is required. Used for - * asynchronous execution scenarios where the processing is happening in - * another thread or process and the caller is not required to wait for the - * result. + * Convenient constant value representing continuable state where processing is still + * taking place, so no further action is required. Used for asynchronous execution + * scenarios where the processing is happening in another thread or process and the + * caller is not required to wait for the result. */ public static final ExitStatus EXECUTING = new ExitStatus("EXECUTING"); @@ -54,8 +52,8 @@ public class ExitStatus implements Serializable, Comparable { public static final ExitStatus COMPLETED = new ExitStatus("COMPLETED"); /** - * Convenient constant value representing a job that did no processing - * (for example, because it was already complete). + * Convenient constant value representing a job that did no processing (for example, + * because it was already complete). */ public static final ExitStatus NOOP = new ExitStatus("NOOP"); @@ -65,8 +63,7 @@ public class ExitStatus implements Serializable, Comparable { public static final ExitStatus FAILED = new ExitStatus("FAILED"); /** - * Convenient constant value representing finished processing with - * interrupted status. + * Convenient constant value representing finished processing with interrupted status. */ public static final ExitStatus STOPPED = new ExitStatus("STOPPED"); @@ -75,8 +72,8 @@ public class ExitStatus implements Serializable, Comparable { private final String exitDescription; /** - * Constructor that accepts the exit code and sets the exit description to an empty {@link String}. - * + * Constructor that accepts the exit code and sets the exit description to an empty + * {@link String}. * @param exitCode The exit code to be used for the {@link ExitStatus}. */ public ExitStatus(String exitCode) { @@ -84,8 +81,8 @@ public class ExitStatus implements Serializable, Comparable { } /** - * Constructor that establishes the exit code and the exit description for the {@link ExitStatus}. - * + * Constructor that establishes the exit code and the exit description for the + * {@link ExitStatus}. * @param exitCode The exit code to be used for the {@link ExitStatus}. * @param exitDescription The exit description to be used for the {@link ExitStatus}. */ @@ -97,7 +94,6 @@ public class ExitStatus implements Serializable, Comparable { /** * Getter for the exit code (defaults to blank). - * * @return the exit code. */ public String getExitCode() { @@ -106,7 +102,6 @@ public class ExitStatus implements Serializable, Comparable { /** * Getter for the exit description (defaults to blank) - * * @return {@link String} containing the exit description. */ public String getExitDescription() { @@ -114,11 +109,10 @@ public class ExitStatus implements Serializable, Comparable { } /** - * Create a new {@link ExitStatus} with a logical combination of the exit - * code and a concatenation of the descriptions. If either value has a - * higher severity, its exit code is used in the result. In the - * case of equal severity, the exit code is replaced if the new value is - * alphabetically greater.
+ * Create a new {@link ExitStatus} with a logical combination of the exit code and a + * concatenation of the descriptions. If either value has a higher severity, its exit + * code is used in the result. In the case of equal severity, the exit code is + * replaced if the new value is alphabetically greater.
*
* * Severity is defined by the exit code: @@ -133,10 +127,9 @@ public class ExitStatus implements Serializable, Comparable { * Others have severity 7, so custom exit codes always win.
* * If the input is {@code null} just return this. - * * @param status An {@link ExitStatus} object to combine with this one. - * @return a new {@link ExitStatus} combining the current value and the - * argument provided. + * @return a new {@link ExitStatus} combining the current value and the argument + * provided. */ public ExitStatus and(ExitStatus status) { if (status == null) { @@ -151,8 +144,8 @@ public class ExitStatus implements Serializable, Comparable { /** * @param status An {@link ExitStatus} to compare - * @return greater than zero, 0, or less than zero, - * according to the severity and exit code. + * @return greater than zero, 0, or less than zero, according to the severity and exit + * code. * @see java.lang.Comparable */ @Override @@ -167,8 +160,8 @@ public class ExitStatus implements Serializable, Comparable { } /** - * Determines severity (an int between 1 and 7, inclusive) - * based on an {@code ExitStatus} object. + * Determines severity (an int between 1 and 7, inclusive) based on an + * {@code ExitStatus} object. * @param status The {@code ExitStatus} object from which to determine the severity. * @return the severity number. */ @@ -228,12 +221,10 @@ public class ExitStatus implements Serializable, Comparable { } /** - * Add an exit code to an existing {@link ExitStatus}. If there is already a - * code present, it will be replaced. - * + * Add an exit code to an existing {@link ExitStatus}. If there is already a code + * present, it will be replaced. * @param code The code to add. - * @return a new {@link ExitStatus} with the same properties but a new exit - * code. + * @return a new {@link ExitStatus} with the same properties but a new exit code. */ public ExitStatus replaceExitCode(String code) { return new ExitStatus(code, exitDescription); @@ -241,7 +232,6 @@ public class ExitStatus implements Serializable, Comparable { /** * Check if this status represents a running process. - * * @return {@code true} if the exit code is {@code EXECUTING} or {@code UNKNOWN}. */ public boolean isRunning() { @@ -249,10 +239,8 @@ public class ExitStatus implements Serializable, Comparable { } /** - * Add an exit description to an existing {@link ExitStatus}. If there is - * already a description present, the two are concatenated with a - * semicolon. - * + * Add an exit description to an existing {@link ExitStatus}. If there is already a + * description present, the two are concatenated with a semicolon. * @param description The description to add. * @return a new {@link ExitStatus} with the same properties but a new exit * description. @@ -273,9 +261,8 @@ public class ExitStatus implements Serializable, Comparable { } /** - * Extract the stack trace from the throwable provided and append it to - * the existing description. - * + * Extract the stack trace from the throwable provided and append it to the existing + * description. * @param throwable A {@link Throwable} instance containing the stack trace. * @return a new ExitStatus with the stack trace appended. */ @@ -287,16 +274,18 @@ public class ExitStatus implements Serializable, Comparable { } /** - * @param status The {@code ExitStatus} object containing the exit code to be evaluated. + * @param status The {@code ExitStatus} object containing the exit code to be + * evaluated. * @return {@code true} if the value matches a known exit code. */ public static boolean isNonDefaultExitStatus(ExitStatus status) { - return status == null || status.getExitCode() == null || - status.getExitCode().equals(ExitStatus.COMPLETED.getExitCode()) || - status.getExitCode().equals(ExitStatus.EXECUTING.getExitCode()) || - status.getExitCode().equals(ExitStatus.FAILED.getExitCode()) || - status.getExitCode().equals(ExitStatus.NOOP.getExitCode()) || - status.getExitCode().equals(ExitStatus.STOPPED.getExitCode()) || - status.getExitCode().equals(ExitStatus.UNKNOWN.getExitCode()); + return status == null || status.getExitCode() == null + || status.getExitCode().equals(ExitStatus.COMPLETED.getExitCode()) + || status.getExitCode().equals(ExitStatus.EXECUTING.getExitCode()) + || status.getExitCode().equals(ExitStatus.FAILED.getExitCode()) + || status.getExitCode().equals(ExitStatus.NOOP.getExitCode()) + || status.getExitCode().equals(ExitStatus.STOPPED.getExitCode()) + || status.getExitCode().equals(ExitStatus.UNKNOWN.getExitCode()); } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/ItemProcessListener.java b/spring-batch-core/src/main/java/org/springframework/batch/core/ItemProcessListener.java index a81df47c4..23f6cf4bd 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/ItemProcessListener.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/ItemProcessListener.java @@ -19,10 +19,9 @@ import org.springframework.batch.item.ItemProcessor; import org.springframework.lang.Nullable; /** - * Listener interface for the processing of an item. Implementations - * of this interface are notified before and after an item is - * passed to the {@link ItemProcessor} and in the event of any - * exceptions thrown by the processor. + * Listener interface for the processing of an item. Implementations of this interface are + * notified before and after an item is passed to the {@link ItemProcessor} and in the + * event of any exceptions thrown by the processor. * * @author Dave Syer * @author Mahmoud Ben Hassine @@ -32,17 +31,15 @@ public interface ItemProcessListener extends StepListener { /** * Called before {@link ItemProcessor#process(Object)}. - * * @param item to be processed. */ default void beforeProcess(T item) { } /** - * Called after {@link ItemProcessor#process(Object)} returns. If the - * processor returns {@code null}, this method is still called, with - * a {@code null} result, allowing for notification of "filtered" items. - * + * Called after {@link ItemProcessor#process(Object)} returns. If the processor + * returns {@code null}, this method is still called, with a {@code null} result, + * allowing for notification of "filtered" items. * @param item to be processed * @param result of processing */ @@ -51,10 +48,10 @@ public interface ItemProcessListener extends StepListener { /** * Called if an exception was thrown from {@link ItemProcessor#process(Object)}. - * * @param item attempted to be processed * @param e - exception thrown during processing. */ default void onProcessError(T item, Exception e) { } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/ItemReadListener.java b/spring-batch-core/src/main/java/org/springframework/batch/core/ItemReadListener.java index 5b50c74cb..d12e80e62 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/ItemReadListener.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/ItemReadListener.java @@ -33,10 +33,8 @@ public interface ItemReadListener extends StepListener { } /** - * Called after {@link ItemReader#read()}. - * This method is called only for actual items (that is, it is not called when the - * reader returns {@code null}). - * + * Called after {@link ItemReader#read()}. This method is called only for actual items + * (that is, it is not called when the reader returns {@code null}). * @param item returned from read() */ default void afterRead(T item) { @@ -44,9 +42,9 @@ public interface ItemReadListener extends StepListener { /** * Called if an error occurs while trying to read. - * * @param ex thrown from {@link ItemReader} */ default void onReadError(Exception ex) { } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/ItemWriteListener.java b/spring-batch-core/src/main/java/org/springframework/batch/core/ItemWriteListener.java index 396d7c11a..bcb388960 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/ItemWriteListener.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/ItemWriteListener.java @@ -22,20 +22,18 @@ import org.springframework.batch.item.ItemWriter; /** *

- * Listener interface for the writing of items. Implementations - * of this interface are notified before, after, and in case - * of any exception thrown while writing a list of items. + * Listener interface for the writing of items. Implementations of this interface are + * notified before, after, and in case of any exception thrown while writing a list of + * items. *

* *

- * Note: This listener is designed to work around the - * lifecycle of an item. This means that each method should be - * called once within the lifecycle of an item and that, in fault-tolerant - * scenarios, any transactional work that is done in - * one of these methods is rolled back and not re-applied. - * Because of this, it is recommended to not perform any logic - * that participates in a transaction when using this listener. - *

+ * Note: This listener is designed to work around the lifecycle of an item. This + * means that each method should be called once within the lifecycle of an item and that, + * in fault-tolerant scenarios, any transactional work that is done in one of these + * methods is rolled back and not re-applied. Because of this, it is recommended to not + * perform any logic that participates in a transaction when using this listener. + *

* * @author Lucas Ward * @author Mahmoud Ben Hassine @@ -45,31 +43,28 @@ public interface ItemWriteListener extends StepListener { /** * Called before {@link ItemWriter#write(java.util.List)} - * * @param items to be written */ default void beforeWrite(List items) { } /** - * Called after {@link ItemWriter#write(java.util.List)}. This is - * called before any transaction is committed, and before + * Called after {@link ItemWriter#write(java.util.List)}. This is called before any + * transaction is committed, and before * {@link ChunkListener#afterChunk(ChunkContext)}. - * * @param items written items */ default void afterWrite(List items) { } /** - * Called if an error occurs while trying to write. Called inside a - * transaction, but the transaction will normally be rolled back. There is - * no way to identify from this callback which of the items (if any) caused - * the error. - * + * Called if an error occurs while trying to write. Called inside a transaction, but + * the transaction will normally be rolled back. There is no way to identify from this + * callback which of the items (if any) caused the error. * @param exception thrown from {@link ItemWriter} * @param items attempted to be written. */ default void onWriteError(Exception exception, List items) { } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/Job.java b/spring-batch-core/src/main/java/org/springframework/batch/core/Job.java index 66533ba71..fe0d0fbf1 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/Job.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/Job.java @@ -20,9 +20,8 @@ import org.springframework.lang.Nullable; /** * Batch domain object representing a job. {@code Job} is an explicit abstraction - * representing the configuration of a job specified by a developer. - * Note that the restart policy is applied to the job as a whole and not to a - * step. + * representing the configuration of a job specified by a developer. Note that the restart + * policy is applied to the job as a whole and not to a step. * * @author Dave Syer * @author Mahmoud Ben Hassine @@ -33,29 +32,28 @@ public interface Job { /** * Flag to indicate if this job can be restarted, at least in principle. - * - * @return true if this job can be restarted after a failure. Defaults to {@code true}. + * @return true if this job can be restarted after a failure. Defaults to + * {@code true}. */ default boolean isRestartable() { return true; } /** - * Run the {@link JobExecution} and update the meta information, such as status - * and statistics, as necessary. This method should not throw any exceptions - * for failed execution. Clients should be careful to inspect the - * {@link JobExecution} status to determine success or failure. - * + * Run the {@link JobExecution} and update the meta information, such as status and + * statistics, as necessary. This method should not throw any exceptions for failed + * execution. Clients should be careful to inspect the {@link JobExecution} status to + * determine success or failure. * @param execution a {@link JobExecution} */ void execute(JobExecution execution); /** - * If clients need to generate new parameters for the next execution in a - * sequence, they can use this incrementer. The return value may be {@code null}, - * when this job does not have a natural sequence. - * - * @return an incrementer to be used for creating new parameters. Defaults to {@code null}. + * If clients need to generate new parameters for the next execution in a sequence, + * they can use this incrementer. The return value may be {@code null}, when this job + * does not have a natural sequence. + * @return an incrementer to be used for creating new parameters. Defaults to + * {@code null}. */ @Nullable default JobParametersIncrementer getJobParametersIncrementer() { @@ -63,10 +61,9 @@ public interface Job { } /** - * A validator for the job parameters of a {@link JobExecution}. Clients of - * a {@code Job} may need to validate the parameters for a launch or before or during + * A validator for the job parameters of a {@link JobExecution}. Clients of a + * {@code Job} may need to validate the parameters for a launch or before or during * the execution. - * * @return a validator that can be used to check parameter values (never * {@code null}). Defaults to {@link DefaultJobParametersValidator}. */ diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/JobExecution.java b/spring-batch-core/src/main/java/org/springframework/batch/core/JobExecution.java index aed509e6e..8617966f7 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/JobExecution.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/JobExecution.java @@ -67,8 +67,8 @@ public class JobExecution extends Entity { private transient volatile List failureExceptions = new CopyOnWriteArrayList<>(); /** - * Constructor that sets the state of the instance to the {@link JobExecution} parameter. - * + * Constructor that sets the state of the instance to the {@link JobExecution} + * parameter. * @param original The {@link JobExecution} to be copied. */ public JobExecution(JobExecution original) { @@ -88,12 +88,13 @@ public class JobExecution extends Entity { } /** - * Because a JobExecution is not valid unless the job is set, this - * constructor is the only valid one from a modeling point of view. - * + * Because a JobExecution is not valid unless the job is set, this constructor is the + * only valid one from a modeling point of view. * @param job The job of which this execution is a part. - * @param id A {@link Long} that represents the {@code id} for the {@code JobExecution}. - * @param jobParameters A {@link JobParameters} instance for this {@code JobExecution}. + * @param id A {@link Long} that represents the {@code id} for the + * {@code JobExecution}. + * @param jobParameters A {@link JobParameters} instance for this + * {@code JobExecution}. */ public JobExecution(JobInstance job, Long id, @Nullable JobParameters jobParameters) { super(id); @@ -103,9 +104,9 @@ public class JobExecution extends Entity { /** * Constructor for transient (unsaved) instances. - * * @param job The enclosing {@link JobInstance}. - * @param jobParameters The {@link JobParameters} instance for this {@code JobExecution}. + * @param jobParameters The {@link JobParameters} instance for this + * {@code JobExecution}. */ public JobExecution(JobInstance job, JobParameters jobParameters) { this(job, null, jobParameters); @@ -113,7 +114,6 @@ public class JobExecution extends Entity { /** * Constructor that accepts the job execution {@code id} and {@link JobParameters}. - * * @param id The job execution {@code id}. * @param jobParameters The {@link JobParameters} for the {@link JobExecution}. */ @@ -123,7 +123,6 @@ public class JobExecution extends Entity { /** * Constructor that accepts the job execution {@code id}. - * * @param id The job execution {@code id}. */ public JobExecution(Long id) { @@ -147,7 +146,6 @@ public class JobExecution extends Entity { /** * Set the {@link JobInstance} used by the {@link JobExecution}. - * * @param jobInstance The {@link JobInstance} used by the {@link JobExecution}. */ public void setJobInstance(JobInstance jobInstance) { @@ -156,7 +154,6 @@ public class JobExecution extends Entity { /** * Set the end time. - * * @param endTime The {@link Date} to be used for the end time. */ public void setEndTime(Date endTime) { @@ -173,7 +170,6 @@ public class JobExecution extends Entity { /** * Set the start time. - * * @param startTime The {@link Date} to be used for the start time. */ public void setStartTime(Date startTime) { @@ -189,7 +185,6 @@ public class JobExecution extends Entity { /** * Set the value of the {@code status} field. - * * @param status The status to set. */ public void setStatus(BatchStatus status) { @@ -197,10 +192,9 @@ public class JobExecution extends Entity { } /** - * Upgrade the {@code status} field if the provided value is greater than the - * existing one. Clients using this method to set the status can be sure - * to not overwrite a failed status with a successful one. - * + * Upgrade the {@code status} field if the provided value is greater than the existing + * one. Clients using this method to set the status can be sure to not overwrite a + * failed status with a successful one. * @param status The new status value. */ public void upgradeStatus(BatchStatus status) { @@ -210,7 +204,6 @@ public class JobExecution extends Entity { /** * Convenience getter for the {@code id} of the enclosing job. Useful for DAO * implementations. - * * @return the @{code id} of the enclosing job. */ public Long getJobId() { @@ -243,7 +236,6 @@ public class JobExecution extends Entity { /** * Accessor for the step executions. - * * @return the step executions that were registered. */ public Collection getStepExecutions() { @@ -253,8 +245,7 @@ public class JobExecution extends Entity { /** * Register a step execution with the current job execution. * @param stepName the name of the step the new execution is associated with. - * @return an empty {@link StepExecution} associated with this - * {@code JobExecution}. + * @return an empty {@link StepExecution} associated with this {@code JobExecution}. */ public StepExecution createStepExecution(String stepName) { StepExecution stepExecution = new StepExecution(stepName, this); @@ -263,9 +254,8 @@ public class JobExecution extends Entity { } /** - * Test if this {@link JobExecution} indicates that it is running. - * Note that this does not necessarily mean that it has been persisted. - * + * Test if this {@link JobExecution} indicates that it is running. Note that this does + * not necessarily mean that it has been persisted. * @return {@code true} if the end time is null and the start time is not null. */ public boolean isRunning() { @@ -273,8 +263,7 @@ public class JobExecution extends Entity { } /** - * Test if this {@link JobExecution} indicates that it has been signalled to - * stop. + * Test if this {@link JobExecution} indicates that it has been signalled to stop. * @return {@code true} if the status is {@link BatchStatus#STOPPING}. */ public boolean isStopping() { @@ -283,7 +272,6 @@ public class JobExecution extends Entity { /** * Sets the {@link ExecutionContext} for this execution. - * * @param executionContext The context. */ public void setExecutionContext(ExecutionContext executionContext) { @@ -291,9 +279,8 @@ public class JobExecution extends Entity { } /** - * Returns the {@link ExecutionContext} for this execution. The content is - * expected to be persisted after each step completion (successful or not). - * + * Returns the {@link ExecutionContext} for this execution. The content is expected to + * be persisted after each step completion (successful or not). * @return The {@link ExecutionContext}. */ public ExecutionContext getExecutionContext() { @@ -315,8 +302,8 @@ public class JobExecution extends Entity { } /** - * Package-private method for re-constituting the step executions from - * existing instances. + * Package-private method for re-constituting the step executions from existing + * instances. * @param The {@code stepExecution} execution to be added. */ void addStepExecution(StepExecution stepExecution) { @@ -326,9 +313,8 @@ public class JobExecution extends Entity { /** * Get the date representing the last time this {@code JobExecution} was updated in * the {@link org.springframework.batch.core.repository.JobRepository}. - * - * @return a {@code Date} object representing the last time this - * {@code JobExecution} was updated. + * @return a {@code Date} object representing the last time this {@code JobExecution} + * was updated. */ @Nullable public Date getLastUpdated() { @@ -337,9 +323,8 @@ public class JobExecution extends Entity { /** * Set the last time this {@code JobExecution} was updated. - * - * @param lastUpdated The {@link Date} instance to which to set - * the job execution's {@code lastUpdated} attribute. + * @param lastUpdated The {@link Date} instance to which to set the job execution's + * {@code lastUpdated} attribute. */ public void setLastUpdated(Date lastUpdated) { this.lastUpdated = lastUpdated; @@ -355,7 +340,6 @@ public class JobExecution extends Entity { /** * Add the provided throwable to the failure exception list. - * * @param t A {@link Throwable} instance to be added failure exception list. */ public synchronized void addFailureException(Throwable t) { @@ -363,9 +347,8 @@ public class JobExecution extends Entity { } /** - * Return all failure causing exceptions for this {@code JobExecution}, including - * step executions. - * + * Return all failure causing exceptions for this {@code JobExecution}, including step + * executions. * @return a {@code List} containing all exceptions causing failure for * this {@code JobExecution}. */ @@ -380,11 +363,8 @@ public class JobExecution extends Entity { } /** - * Deserialize and ensure transient fields are re-instantiated when read - * back. - * + * Deserialize and ensure transient fields are re-instantiated when read back. * @param stream instance of {@link ObjectInputStream}. - * * @throws IOException if an error occurs during read. * @throws ClassNotFoundException thrown if the class is not found. */ @@ -400,9 +380,9 @@ public class JobExecution extends Entity { */ @Override public String toString() { - return super.toString() - + String.format(", startTime=%s, endTime=%s, lastUpdated=%s, status=%s, exitStatus=%s, job=[%s], jobParameters=[%s]", - startTime, endTime, lastUpdated, status, exitStatus, jobInstance, jobParameters); + return super.toString() + String.format( + ", startTime=%s, endTime=%s, lastUpdated=%s, status=%s, exitStatus=%s, job=[%s], jobParameters=[%s]", + startTime, endTime, lastUpdated, status, exitStatus, jobInstance, jobParameters); } /** @@ -410,9 +390,10 @@ public class JobExecution extends Entity { * @param stepExecutions The step executions to add to the current list. */ public void addStepExecutions(List stepExecutions) { - if (stepExecutions!=null) { + if (stepExecutions != null) { this.stepExecutions.removeAll(stepExecutions); this.stepExecutions.addAll(stepExecutions); } } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/JobExecutionException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/JobExecutionException.java index 8a6ca49fa..6f557ba90 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/JobExecutionException.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/JobExecutionException.java @@ -16,10 +16,10 @@ package org.springframework.batch.core; /** - * Root of exception hierarchy for checked exceptions in job and step execution. - * Clients of the {@link Job} should expect to have to catch and deal with these - * exceptions because they signal a user error or an inconsistent state between - * the user's instructions and the data. + * Root of exception hierarchy for checked exceptions in job and step execution. Clients + * of the {@link Job} should expect to have to catch and deal with these exceptions + * because they signal a user error or an inconsistent state between the user's + * instructions and the data. * * @author Dave Syer * @@ -36,13 +36,12 @@ public class JobExecutionException extends Exception { } /** - * Construct a {@link JobExecutionException} with a generic message and a - * cause. - * + * Construct a {@link JobExecutionException} with a generic message and a cause. * @param msg The message. * @param cause The cause of the exception. */ public JobExecutionException(String msg, Throwable cause) { super(msg, cause); } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/JobExecutionListener.java b/spring-batch-core/src/main/java/org/springframework/batch/core/JobExecutionListener.java index d5dab4db3..bd0c7b6a9 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/JobExecutionListener.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/JobExecutionListener.java @@ -16,10 +16,10 @@ package org.springframework.batch.core; /** - * Provide callbacks at specific points in the lifecycle of a {@link Job}. - * Implementations can be stateful if they are careful to either ensure thread - * safety or to use one instance of a listener per job, assuming that job - * instances themselves are not used by more than one thread. + * Provide callbacks at specific points in the lifecycle of a {@link Job}. Implementations + * can be stateful if they are careful to either ensure thread safety or to use one + * instance of a listener per job, assuming that job instances themselves are not used by + * more than one thread. * * @author Dave Syer * @author Parikshit Dutta @@ -28,17 +28,15 @@ public interface JobExecutionListener { /** * Callback before a job executes. - * * @param jobExecution the current {@link JobExecution} */ default void beforeJob(JobExecution jobExecution) { } /** - * Callback after completion of a job. Called after both successful and - * failed executions. To perform logic on a particular status, use + * Callback after completion of a job. Called after both successful and failed + * executions. To perform logic on a particular status, use * {@code if (jobExecution.getStatus() == BatchStatus.X)}. - * * @param jobExecution the current {@link JobExecution} */ default void afterJob(JobExecution jobExecution) { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/JobInstance.java b/spring-batch-core/src/main/java/org/springframework/batch/core/JobInstance.java index d6597de63..d1211c23a 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/JobInstance.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/JobInstance.java @@ -19,18 +19,17 @@ package org.springframework.batch.core; import org.springframework.util.Assert; /** - * Batch domain object representing a uniquely identifiable job run. - * {@code JobInstance} can be restarted multiple times in case of execution failure, and - * its lifecycle ends with first successful execution. + * Batch domain object representing a uniquely identifiable job run. {@code JobInstance} + * can be restarted multiple times in case of execution failure, and its lifecycle ends + * with first successful execution. * * Trying to execute an existing {@code JobInstance} that has already completed - * successfully results in an error. An error is also raised for an attempt - * to restart a failed {@code JobInstance} if the {@code Job} is not restartable. + * successfully results in an error. An error is also raised for an attempt to restart a + * failed {@code JobInstance} if the {@code Job} is not restartable. * * @see Job * @see JobParameters * @see JobExecution - * * @author Lucas Ward * @author Dave Syer * @author Robert Kasanicky @@ -45,7 +44,6 @@ public class JobInstance extends Entity { /** * Constructor for {@link JobInstance}. - * * @param id The instance ID. * @param jobName The name associated with the {@link JobInstance}. */ @@ -62,9 +60,9 @@ public class JobInstance extends Entity { return jobName; } - /** + /** * Adds the job name to the string representation of the super class ({@link Entity}). - */ + */ @Override public String toString() { return super.toString() + ", Job=[" + jobName + "]"; @@ -76,4 +74,5 @@ public class JobInstance extends Entity { public long getInstanceId() { return super.getId(); } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/JobInterruptedException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/JobInterruptedException.java index 94baeece4..bec41fdb0 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/JobInterruptedException.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/JobInterruptedException.java @@ -16,13 +16,11 @@ package org.springframework.batch.core; - /** - * Exception to indicate the job has been interrupted. The exception state - * indicated is not normally recoverable by batch application clients, but - * it is used internally to force a check. The exception is often wrapped - * in a runtime exception (usually {@link UnexpectedJobExecutionException}) before - * reaching the client. + * Exception to indicate the job has been interrupted. The exception state indicated is + * not normally recoverable by batch application clients, but it is used internally to + * force a check. The exception is often wrapped in a runtime exception (usually + * {@link UnexpectedJobExecutionException}) before reaching the client. * * @author Lucas Ward * @author Dave Syer @@ -35,7 +33,6 @@ public class JobInterruptedException extends JobExecutionException { /** * Constructor that sets the message for the exception. - * * @param msg The message for the exception. */ public JobInterruptedException(String msg) { @@ -44,9 +41,9 @@ public class JobInterruptedException extends JobExecutionException { /** * Constructor that sets the message for the exception. - * * @param msg The message for the exception. - * @param status The desired {@link BatchStatus} of the surrounding execution after interruption. + * @param status The desired {@link BatchStatus} of the surrounding execution after + * interruption. */ public JobInterruptedException(String msg, BatchStatus status) { super(msg); @@ -55,10 +52,10 @@ public class JobInterruptedException extends JobExecutionException { /** * The desired status of the surrounding execution after the interruption. - * * @return the status of the interruption (default STOPPED) */ public BatchStatus getStatus() { return status; } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/JobKeyGenerator.java b/spring-batch-core/src/main/java/org/springframework/batch/core/JobKeyGenerator.java index fe5e67ef5..589434b97 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/JobKeyGenerator.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/JobKeyGenerator.java @@ -16,12 +16,11 @@ package org.springframework.batch.core; /** - * Strategy interface for the generation of the key used in identifying - * unique {@link JobInstance} objects. + * Strategy interface for the generation of the key used in identifying unique + * {@link JobInstance} objects. * * @author Michael Minella * @author Mahmoud Ben Hassine - * * @param The type of the source data used to calculate the key. * @since 2.2 */ @@ -29,11 +28,10 @@ public interface JobKeyGenerator { /** * Method to generate the unique key used to identify a job instance. - * - * @param source Source information used to generate the key (must not be {@code null}). - * - * @return a unique string identifying the job based on the information - * supplied. + * @param source Source information used to generate the key (must not be + * {@code null}). + * @return a unique string identifying the job based on the information supplied. */ String generateKey(T source); + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/JobParameter.java b/spring-batch-core/src/main/java/org/springframework/batch/core/JobParameter.java index d7968be8f..98fd6d80b 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/JobParameter.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/JobParameter.java @@ -23,10 +23,9 @@ import org.springframework.lang.NonNull; import org.springframework.util.Assert; /** - * Domain representation of a parameter to a batch job. Only the following types - * can be parameters: String, Long, Date, and Double. The identifying flag is - * used to indicate if the parameter is to be used as part of the identification of - * a job instance. + * Domain representation of a parameter to a batch job. Only the following types can be + * parameters: String, Long, Date, and Double. The identifying flag is used to indicate if + * the parameter is to be used as part of the identification of a job instance. * * @author Lucas Ward * @author Dave Syer @@ -54,7 +53,6 @@ public class JobParameter implements Serializable { /** * Construct a new {@code JobParameter} from a {@link Long}. - * * @param parameter {@link Long} instance. Must not be {@code null}. * @param identifying {@code true} if the {@code JobParameter} should be identifying. */ @@ -64,7 +62,6 @@ public class JobParameter implements Serializable { /** * Construct a new {@code JobParameter} from a {@link Date}. - * * @param parameter {@link Date} instance. Must not be {@code null}. * @param identifying {@code true} if the {@code JobParameter} should be identifying. */ @@ -74,7 +71,6 @@ public class JobParameter implements Serializable { /** * Construct a new {@code JobParameter} from a {@link Double}. - * * @param parameter {@link Double} instance. Must not be {@code null}. * @param identifying {@code true} if the {@code JobParameter} should be identifying. */ @@ -91,7 +87,6 @@ public class JobParameter implements Serializable { /** * Construct a new {@code JobParameter} from a {@link String}. - * * @param parameter A {@link String} instance. */ public JobParameter(String parameter) { @@ -100,7 +95,6 @@ public class JobParameter implements Serializable { /** * Construct a new {@code JobParameter} from a {@link Long}. - * * @param parameter A {@link Long} instance. */ public JobParameter(Long parameter) { @@ -109,7 +103,6 @@ public class JobParameter implements Serializable { /** * Construct a new {@code JobParameter} as a {@link Date}. - * * @param parameter A {@link Date} instance. */ public JobParameter(Date parameter) { @@ -118,7 +111,6 @@ public class JobParameter implements Serializable { /** * Construct a new {@code JobParameter} from a {@link Double}. - * * @param parameter A {@link Double} instance. */ public JobParameter(Double parameter) { @@ -126,7 +118,8 @@ public class JobParameter implements Serializable { } /** - * @return The identifying flag. It is set to {@code true} if the job parameter is identifying. + * @return The identifying flag. It is set to {@code true} if the job parameter is + * identifying. */ public boolean isIdentifying() { return identifying; @@ -162,7 +155,7 @@ public class JobParameter implements Serializable { @Override public String toString() { - return parameterType == ParameterType.DATE ? "" + ((Date) parameter).getTime() : parameter.toString(); + return parameterType == ParameterType.DATE ? "" + ((Date) parameter).getTime() : parameter.toString(); } @Override @@ -191,5 +184,7 @@ public class JobParameter implements Serializable { * Double parameter type. */ DOUBLE; + } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/JobParameters.java b/spring-batch-core/src/main/java/org/springframework/batch/core/JobParameters.java index e27172105..f0514ae2e 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/JobParameters.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/JobParameters.java @@ -27,14 +27,13 @@ import java.util.Properties; import org.springframework.lang.Nullable; /** - * Value object representing runtime parameters to a batch job. Because the - * parameters have no individual meaning outside - * of the {@code JobParameters} object they are - * contained within, it is a value object rather than an entity. It is also - * extremely important that a parameters object can be reliably compared to - * another for equality, in order to determine if one {@code JobParameters} object - * equals another. Furthermore, because these parameters need to be - * persisted, it is vital that the types added are restricted. + * Value object representing runtime parameters to a batch job. Because the parameters + * have no individual meaning outside of the {@code JobParameters} object they are + * contained within, it is a value object rather than an entity. It is also extremely + * important that a parameters object can be reliably compared to another for equality, in + * order to determine if one {@code JobParameters} object equals another. Furthermore, + * because these parameters need to be persisted, it is vital that the types added are + * restricted. * * This class is immutable and, therefore, thread-safe. * @@ -47,7 +46,7 @@ import org.springframework.lang.Nullable; @SuppressWarnings("serial") public class JobParameters implements Serializable { - private final Map parameters; + private final Map parameters; /** * Default constructor. @@ -57,174 +56,163 @@ public class JobParameters implements Serializable { } /** - * Constructor that is initialized with the content of a {@link Map} - * that contains a {@code String} key and a {@link JobParameter} value. - * - * @param parameters The {@link Map} that contains a {@code String} key - * and a {@link JobParameter} value. + * Constructor that is initialized with the content of a {@link Map} that contains a + * {@code String} key and a {@link JobParameter} value. + * @param parameters The {@link Map} that contains a {@code String} key and a + * {@link JobParameter} value. */ - public JobParameters(Map parameters) { + public JobParameters(Map parameters) { this.parameters = new LinkedHashMap<>(parameters); } /** * Typesafe getter for the {@link Long} represented by the provided key. - * * @param key The key for which to get a value. * @return The {@link Long} value or {@code null} if the key is absent. */ @Nullable - public Long getLong(String key){ + public Long getLong(String key) { if (!parameters.containsKey(key)) { return null; } Object value = parameters.get(key).getValue(); - return value==null ? null : ((Long)value).longValue(); + return value == null ? null : ((Long) value).longValue(); } /** - * Typesafe getter for the {@link Long} represented by the provided key. If the - * key does not exist, the default value is returned. - * + * Typesafe getter for the {@link Long} represented by the provided key. If the key + * does not exist, the default value is returned. * @param key The key for which to return the value. * @param defaultValue The default value to return if the value does not exist. - * @return the parameter represented by the provided key or, if that is - * missing, the default value. + * @return the parameter represented by the provided key or, if that is missing, the + * default value. */ @Nullable - public Long getLong(String key, @Nullable Long defaultValue){ - if(parameters.containsKey(key)){ + public Long getLong(String key, @Nullable Long defaultValue) { + if (parameters.containsKey(key)) { return getLong(key); } - else{ + else { return defaultValue; } } /** * Typesafe getter for the {@link String} represented by the provided key. - * * @param key The key for which to get a value. * @return The {@link String} value or {@code null} if the key is absent. */ @Nullable - public String getString(String key){ + public String getString(String key) { JobParameter value = parameters.get(key); - return value==null ? null : value.toString(); + return value == null ? null : value.toString(); } /** - * Typesafe getter for the {@link String} represented by the provided key. If the - * key does not exist, the default value is returned. - * + * Typesafe getter for the {@link String} represented by the provided key. If the key + * does not exist, the default value is returned. * @param key The key for which to return the value. * @param defaultValue The defult value to return if the value does not exist. - * @return the parameter represented by the provided key or, if that is - * missing, the default value. + * @return the parameter represented by the provided key or, if that is missing, the + * default value. */ @Nullable - public String getString(String key, @Nullable String defaultValue){ - if(parameters.containsKey(key)){ + public String getString(String key, @Nullable String defaultValue) { + if (parameters.containsKey(key)) { return getString(key); } - else{ + else { return defaultValue; } } /** * Typesafe getter for the {@link Long} represented by the provided key. - * * @param key The key for which to get a value. * @return The {@link Double} value or {@code null} if the key is absent. */ @Nullable - public Double getDouble(String key){ + public Double getDouble(String key) { if (!parameters.containsKey(key)) { return null; } - Double value = (Double)parameters.get(key).getValue(); - return value==null ? null : value.doubleValue(); + Double value = (Double) parameters.get(key).getValue(); + return value == null ? null : value.doubleValue(); } /** - * Typesafe getter for the {@link Double} represented by the provided key. If the - * key does not exist, the default value is returned. - * + * Typesafe getter for the {@link Double} represented by the provided key. If the key + * does not exist, the default value is returned. * @param key The key for which to return the value. * @param defaultValue The default value to return if the value does not exist. - * @return the parameter represented by the provided key or, if that is - * missing, the default value. + * @return the parameter represented by the provided key or, if that is missing, the + * default value. */ @Nullable - public Double getDouble(String key, @Nullable Double defaultValue){ - if(parameters.containsKey(key)){ + public Double getDouble(String key, @Nullable Double defaultValue) { + if (parameters.containsKey(key)) { return getDouble(key); } - else{ + else { return defaultValue; } } /** * Typesafe getter for the {@link Date} represented by the provided key. - * * @param key The key for which to get a value. - * @return the {@link java.util.Date} value or {@code null} if the key - * is absent. + * @return the {@link java.util.Date} value or {@code null} if the key is absent. */ @Nullable - public Date getDate(String key){ - return this.getDate(key,null); + public Date getDate(String key) { + return this.getDate(key, null); } /** - * Typesafe getter for the {@link Date} represented by the provided key. If the - * key does not exist, the default value is returned. - * + * Typesafe getter for the {@link Date} represented by the provided key. If the key + * does not exist, the default value is returned. * @param key The key for which to return the value. * @param defaultValue The default value to return if the value does not exist. - * @return the parameter represented by the provided key or, if that is - * missing, the default value. + * @return the parameter represented by the provided key or, if that is missing, the + * default value. */ @Nullable - public Date getDate(String key, @Nullable Date defaultValue){ - if(parameters.containsKey(key)){ - return (Date)parameters.get(key).getValue(); + public Date getDate(String key, @Nullable Date defaultValue) { + if (parameters.containsKey(key)) { + return (Date) parameters.get(key).getValue(); } - else{ + else { return defaultValue; } } /** - * Get a map of all parameters, including {@link String}, - * {@link Long}, and {@link Date} types. - * + * Get a map of all parameters, including {@link String}, {@link Long}, and + * {@link Date} types. * @return an unmodifiable map containing all parameters. */ - public Map getParameters(){ + public Map getParameters() { return Collections.unmodifiableMap(parameters); } /** * @return {@code true} if the parameters object is empty or {@code false} otherwise. */ - public boolean isEmpty(){ + public boolean isEmpty() { return parameters.isEmpty(); } @Override public boolean equals(Object obj) { - if(obj instanceof JobParameters == false){ + if (obj instanceof JobParameters == false) { return false; } - if(obj == this){ + if (obj == this) { return true; } - JobParameters rhs = (JobParameters)obj; + JobParameters rhs = (JobParameters) obj; return this.parameters.equals(rhs.parameters); } @@ -239,7 +227,8 @@ public class JobParameters implements Serializable { } /** - * @return The {@link Properties} that contain the key and values for the {@link JobParameter} objects. + * @return The {@link Properties} that contain the key and values for the + * {@link JobParameter} objects. */ public Properties toProperties() { Properties props = new Properties(); @@ -252,4 +241,5 @@ public class JobParameters implements Serializable { return props; } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/JobParametersBuilder.java b/spring-batch-core/src/main/java/org/springframework/batch/core/JobParametersBuilder.java index 1d80522ec..bbe2b7aba 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/JobParametersBuilder.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/JobParametersBuilder.java @@ -28,14 +28,13 @@ import org.springframework.util.Assert; /** * Helper class for creating {@link JobParameters}. Useful because all - * {@link JobParameter} objects are immutable and must be instantiated separately - * to ensure type safety. Once created, it can be used in the - * same was a {@link java.lang.StringBuilder} (except that order is irrelevant), by adding - * various parameter types and creating a valid {@link JobParameters} object once - * finished.
+ * {@link JobParameter} objects are immutable and must be instantiated separately to + * ensure type safety. Once created, it can be used in the same was a + * {@link java.lang.StringBuilder} (except that order is irrelevant), by adding various + * parameter types and creating a valid {@link JobParameters} object once finished.
*
- * Using the {@code identifying} flag indicates if the parameter should be used - * in the identification of a {@link JobInstance} object. That flag defaults to {@code true}. + * Using the {@code identifying} flag indicates if the parameter should be used in the + * identification of a {@link JobInstance} object. That flag defaults to {@code true}. * * @author Lucas Ward * @author Michael Minella @@ -59,7 +58,8 @@ public class JobParametersBuilder { } /** - * @param jobExplorer {@link JobExplorer} used for looking up previous job parameter information. + * @param jobExplorer {@link JobExplorer} used for looking up previous job parameter + * information. */ public JobParametersBuilder(JobExplorer jobExplorer) { this.jobExplorer = jobExplorer; @@ -75,17 +75,18 @@ public class JobParametersBuilder { } /** - * Constructor to add conversion capabilities to support JSR-352. Per the spec, it is expected that all - * keys and values in the provided {@link Properties} instance are {@link String} objects. - * + * Constructor to add conversion capabilities to support JSR-352. Per the spec, it is + * expected that all keys and values in the provided {@link Properties} instance are + * {@link String} objects. * @param properties the job parameters to be used. */ public JobParametersBuilder(Properties properties) { this.parameterMap = new LinkedHashMap<>(); - if(properties != null) { + if (properties != null) { for (Map.Entry curProperty : properties.entrySet()) { - this.parameterMap.put((String) curProperty.getKey(), new JobParameter((String) curProperty.getValue(), false)); + this.parameterMap.put((String) curProperty.getKey(), + new JobParameter((String) curProperty.getValue(), false)); } } } @@ -93,7 +94,8 @@ public class JobParametersBuilder { /** * Copy constructor. Initializes the builder with the supplied parameters. * @param jobParameters {@link JobParameters} instance used to initialize the builder. - * @param jobExplorer {@link JobExplorer} used for looking up previous job parameter information. + * @param jobExplorer {@link JobExplorer} used for looking up previous job parameter + * information. */ public JobParametersBuilder(JobParameters jobParameters, JobExplorer jobExplorer) { this.jobExplorer = jobExplorer; @@ -102,7 +104,6 @@ public class JobParametersBuilder { /** * Add a new identifying String parameter for the given key. - * * @param key The parameter accessor. * @param parameter The runtime parameter. Must not be {@code null}. * @return a reference to this object. @@ -114,10 +115,10 @@ public class JobParametersBuilder { /** * Add a new String parameter for the given key. - * * @param key The parameter accessor. * @param parameter The runtime parameter. Must not be {@code null}. - * @param identifying The indicates if the parameter is used as part of identifying a job instance. + * @param identifying The indicates if the parameter is used as part of identifying a + * job instance. * @return a reference to this object. */ public JobParametersBuilder addString(String key, @NonNull String parameter, boolean identifying) { @@ -127,7 +128,6 @@ public class JobParametersBuilder { /** * Add a new identifying {@link Date} parameter for the given key. - * * @param key The parameter accessor. * @param parameter The runtime parameter. Must not be {@code null}. * @return a reference to this object. @@ -139,10 +139,10 @@ public class JobParametersBuilder { /** * Add a new {@link Date} parameter for the given key. - * * @param key The parameter accessor. * @param parameter The runtime parameter. Must not be {@code null}. - * @param identifying Indicates if the parameter is used as part of identifying a job instance + * @param identifying Indicates if the parameter is used as part of identifying a job + * instance * @return a reference to this object. */ public JobParametersBuilder addDate(String key, @NonNull Date parameter, boolean identifying) { @@ -152,7 +152,6 @@ public class JobParametersBuilder { /** * Add a new identifying {@link Long} parameter for the given key. - * * @param key The parameter accessor. * @param parameter The runtime parameter. Must not be {@code null}. * @return a reference to this object. @@ -164,10 +163,10 @@ public class JobParametersBuilder { /** * Add a new {@link Long} parameter for the given key. - * * @param key The parameter accessor. * @param parameter The runtime parameter. Must not be {@code null}. - * @param identifying Indicates if the parameter is used as part of identifying a job instance. + * @param identifying Indicates if the parameter is used as part of identifying a job + * instance. * @return a reference to this object. */ public JobParametersBuilder addLong(String key, @NonNull Long parameter, boolean identifying) { @@ -177,7 +176,6 @@ public class JobParametersBuilder { /** * Add a new identifying {@link Double} parameter for the given key. - * * @param key The parameter accessor. * @param parameter The runtime parameter. Must not be {@code null}. * @return a reference to this object. @@ -189,10 +187,10 @@ public class JobParametersBuilder { /** * Add a new {@link Double} parameter for the given key. - * * @param key The parameter accessor. * @param parameter The runtime parameter. Must not be {@code null}. - * @param identifying Indicates if the parameter is used as part of identifying a job instance. + * @param identifying Indicates if the parameter is used as part of identifying a job + * instance. * @return a reference to this object. */ public JobParametersBuilder addDouble(String key, @NonNull Double parameter, boolean identifying) { @@ -201,9 +199,8 @@ public class JobParametersBuilder { } /** - * Conversion method that takes the current state of this builder and - * returns it as a {@code JobParameters} object. - * + * Conversion method that takes the current state of this builder and returns it as a + * {@code JobParameters} object. * @return a valid {@link JobParameters} object. */ public JobParameters toJobParameters() { @@ -212,7 +209,6 @@ public class JobParametersBuilder { /** * Add a new {@link JobParameter} for the given key. - * * @param key The parameter accessor. * @param jobParameter The runtime parameter. * @return a reference to this object. @@ -238,12 +234,13 @@ public class JobParametersBuilder { /** * Initializes the {@link JobParameters} based on the state of the {@link Job}. This - * should be called after all parameters have been entered into the builder. - * All parameters already set on this builder instance are appended to - * those retrieved from the job incrementer, overriding any with the same key (this is the same - * behavior as {@link org.springframework.batch.core.launch.support.CommandLineJobRunner} - * with the {@code -next} option and {@link org.springframework.batch.core.launch.JobOperator#startNextInstance(String)}). - * + * should be called after all parameters have been entered into the builder. All + * parameters already set on this builder instance are appended to those retrieved + * from the job incrementer, overriding any with the same key (this is the same + * behavior as + * {@link org.springframework.batch.core.launch.support.CommandLineJobRunner} with the + * {@code -next} option and + * {@link org.springframework.batch.core.launch.JobOperator#startNextInstance(String)}). * @param job The job for which the {@link JobParameters} are being constructed. * @return a reference to this object. * @@ -252,7 +249,8 @@ public class JobParametersBuilder { public JobParametersBuilder getNextJobParameters(Job job) { Assert.state(this.jobExplorer != null, "A JobExplorer is required to get next job parameters"); Assert.notNull(job, "Job must not be null"); - Assert.notNull(job.getJobParametersIncrementer(), "No job parameters incrementer found for job=" + job.getName()); + Assert.notNull(job.getJobParametersIncrementer(), + "No job parameters incrementer found for job=" + job.getName()); String name = job.getName(); JobParameters nextParameters; @@ -280,4 +278,5 @@ public class JobParametersBuilder { this.parameterMap = nextParametersMap; return this; } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/JobParametersIncrementer.java b/spring-batch-core/src/main/java/org/springframework/batch/core/JobParametersIncrementer.java index ec8216aca..18fcae594 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/JobParametersIncrementer.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/JobParametersIncrementer.java @@ -28,10 +28,8 @@ import org.springframework.lang.Nullable; public interface JobParametersIncrementer { /** - * Increments the provided parameters. If the input is empty, this method - * should return a bootstrap or initial value to be used on the first - * instance of a job. - * + * Increments the provided parameters. If the input is empty, this method should + * return a bootstrap or initial value to be used on the first instance of a job. * @param parameters the last value used * @return the next value to use (never {@code null}) */ diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/JobParametersInvalidException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/JobParametersInvalidException.java index d7234c573..40c0f3a08 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/JobParametersInvalidException.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/JobParametersInvalidException.java @@ -1,37 +1,35 @@ -/* - * Copyright 2009-2022 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core; - -/** - * Exception for {@link Job} to signal that some {@link JobParameters} are - * invalid. - * - * @author Dave Syer - * - */ -@SuppressWarnings("serial") -public class JobParametersInvalidException extends JobExecutionException { - - /** - * Constructor that sets the message for the exception. - * - * @param msg The {@link String} message for the {@link Exception}. - */ - public JobParametersInvalidException(String msg) { - super(msg); - } - -} +/* + * Copyright 2009-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core; + +/** + * Exception for {@link Job} to signal that some {@link JobParameters} are invalid. + * + * @author Dave Syer + * + */ +@SuppressWarnings("serial") +public class JobParametersInvalidException extends JobExecutionException { + + /** + * Constructor that sets the message for the exception. + * @param msg The {@link String} message for the {@link Exception}. + */ + public JobParametersInvalidException(String msg) { + super(msg); + } + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/JobParametersValidator.java b/spring-batch-core/src/main/java/org/springframework/batch/core/JobParametersValidator.java index 6cd664443..c8d488df3 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/JobParametersValidator.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/JobParametersValidator.java @@ -1,39 +1,38 @@ -/* - * Copyright 2010-2022 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core; - -import org.springframework.lang.Nullable; - -/** - * Strategy interface for a {@link Job} to use in validating its parameters for - * an execution. - * - * @author Dave Syer - * @author Mahmoud Ben Hassine - * - */ -public interface JobParametersValidator { - - /** - * Check that the parameters meet whatever requirements are appropriate, and - * throw an exception if not. - * - * @param parameters some {@link JobParameters} (can be {@code null}) - * @throws JobParametersInvalidException if the parameters are invalid - */ - void validate(@Nullable JobParameters parameters) throws JobParametersInvalidException; - -} +/* + * Copyright 2010-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core; + +import org.springframework.lang.Nullable; + +/** + * Strategy interface for a {@link Job} to use in validating its parameters for an + * execution. + * + * @author Dave Syer + * @author Mahmoud Ben Hassine + * + */ +public interface JobParametersValidator { + + /** + * Check that the parameters meet whatever requirements are appropriate, and throw an + * exception if not. + * @param parameters some {@link JobParameters} (can be {@code null}) + * @throws JobParametersInvalidException if the parameters are invalid + */ + void validate(@Nullable JobParameters parameters) throws JobParametersInvalidException; + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/SkipListener.java b/spring-batch-core/src/main/java/org/springframework/batch/core/SkipListener.java index 0956ba941..57c79e56d 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/SkipListener.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/SkipListener.java @@ -16,35 +16,31 @@ package org.springframework.batch.core; /** - * Interface for listener to skipped items. Callbacks are called by - * {@link Step} implementations at the appropriate time in the step lifecycle. - * Implementers of this interface should not assume that any method is - * called immediately after an error has been encountered. Because there - * may be errors later on in processing the chunk, this listener is not - * called until just before committing. + * Interface for listener to skipped items. Callbacks are called by {@link Step} + * implementations at the appropriate time in the step lifecycle. Implementers of this + * interface should not assume that any method is called immediately after an error has + * been encountered. Because there may be errors later on in processing the chunk, this + * listener is not called until just before committing. * * @author Dave Syer * @author Robert Kasanicky * @author Mahmoud Ben Hassine * */ -public interface SkipListener extends StepListener { +public interface SkipListener extends StepListener { /** * Callback for a failure on read that is legal and, consequently, is not going to be * re-thrown. In case a transaction is rolled back and items are re-read, this - * callback occurs repeatedly for the same cause. This happens only - * if read items are not buffered. - * + * callback occurs repeatedly for the same cause. This happens only if read items are + * not buffered. * @param t cause of the failure */ default void onSkipInRead(Throwable t) { } /** - * This item failed on write with the given exception, and a skip was called - * for. - * + * This item failed on write with the given exception, and a skip was called for. * @param item the failed item * @param t the cause of the failure */ @@ -52,9 +48,7 @@ public interface SkipListener extends StepListener { } /** - * This item failed on processing with the given exception, and a skip was called - * for. - * + * This item failed on processing with the given exception, and a skip was called for. * @param item the failed item * @param t the cause of the failure */ diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/StartLimitExceededException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/StartLimitExceededException.java index 6cbd1e155..7af4a41e9 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/StartLimitExceededException.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/StartLimitExceededException.java @@ -24,10 +24,10 @@ public class StartLimitExceededException extends RuntimeException { /** * Constructor that sets the message for the exception. - * * @param message The message for the exception. */ public StartLimitExceededException(String message) { super(message); } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/Step.java b/spring-batch-core/src/main/java/org/springframework/batch/core/Step.java index 4190b24a0..834cfac6c 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/Step.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/Step.java @@ -16,8 +16,9 @@ package org.springframework.batch.core; /** - * Batch domain interface representing the configuration of a step. As with a {@link Job}, a {@link Step} is meant to - * explicitly represent the configuration of a step by a developer but also the ability to execute the step. + * Batch domain interface representing the configuration of a step. As with a {@link Job}, + * a {@link Step} is meant to explicitly represent the configuration of a step by a + * developer but also the ability to execute the step. * * @author Dave Syer * @author Mahmoud Ben Hassine @@ -36,8 +37,8 @@ public interface Step { String getName(); /** - * @return {@code true} if a step that is already marked as complete can be started again. - * Defaults to {@code false}. + * @return {@code true} if a step that is already marked as complete can be started + * again. Defaults to {@code false}. */ default boolean isAllowStartIfComplete() { return false; @@ -52,14 +53,13 @@ public interface Step { } /** - * Process the step and assign progress and status meta information to the {@link StepExecution} provided. The - * {@link Step} is responsible for setting the meta information and also saving it, if required by the - * implementation.
- * - * It is not safe to reuse an instance of {@link Step} to process multiple concurrent executions. + * Process the step and assign progress and status meta information to the + * {@link StepExecution} provided. The {@link Step} is responsible for setting the + * meta information and also saving it, if required by the implementation.
* + * It is not safe to reuse an instance of {@link Step} to process multiple concurrent + * executions. * @param stepExecution an entity representing the step to be executed. - * * @throws JobInterruptedException if the step is interrupted externally. */ void execute(StepExecution stepExecution) throws JobInterruptedException; diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/StepContribution.java b/spring-batch-core/src/main/java/org/springframework/batch/core/StepContribution.java index 054b0e50c..e879fed98 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/StepContribution.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/StepContribution.java @@ -18,8 +18,8 @@ package org.springframework.batch.core; import java.io.Serializable; /** - * Represents a contribution to a {@link StepExecution}, buffering changes until - * they can be applied at a chunk boundary. + * Represents a contribution to a {@link StepExecution}, buffering changes until they can + * be applied at a chunk boundary. * * @author Dave Syer * @author Mahmoud Ben Hassine @@ -57,7 +57,6 @@ public class StepContribution implements Serializable { /** * Set the {@link ExitStatus} for this contribution. - * * @param status {@link ExitStatus} instance to be used to set the exit status. */ public void setExitStatus(ExitStatus status) { @@ -66,7 +65,6 @@ public class StepContribution implements Serializable { /** * Public getter for the {@code ExitStatus}. - * * @return the {@link ExitStatus} for this contribution */ public ExitStatus getExitStatus() { @@ -75,7 +73,6 @@ public class StepContribution implements Serializable { /** * Increment the counter for the number of items processed. - * * @param count The {@code long} amount to increment by. */ public void incrementFilterCount(long count) { @@ -91,7 +88,6 @@ public class StepContribution implements Serializable { /** * Increment the counter for the number of items written. - * * @param count The {@code long} amount to increment by. */ public void incrementWriteCount(long count) { @@ -100,7 +96,6 @@ public class StepContribution implements Serializable { /** * Public access to the read counter. - * * @return the read item counter. */ public long getReadCount() { @@ -109,7 +104,6 @@ public class StepContribution implements Serializable { /** * Public access to the write counter. - * * @return the write item counter. */ public long getWriteCount() { @@ -118,7 +112,6 @@ public class StepContribution implements Serializable { /** * Public getter for the filter counter. - * * @return the filter counter. */ public long getFilterCount() { @@ -126,17 +119,16 @@ public class StepContribution implements Serializable { } /** - * @return the sum of skips accumulated in the parent {@link StepExecution} - * and this StepContribution. + * @return the sum of skips accumulated in the parent {@link StepExecution} and this + * StepContribution. */ public long getStepSkipCount() { return readSkipCount + writeSkipCount + processSkipCount + parentSkipCount; } /** - * @return the number of skips collected in this - * StepContribution (not including skips accumulated in the - * parent {@link StepExecution}). + * @return the number of skips collected in this StepContribution (not + * including skips accumulated in the parent {@link StepExecution}). */ public long getSkipCount() { return readSkipCount + writeSkipCount + processSkipCount; @@ -151,7 +143,6 @@ public class StepContribution implements Serializable { /** * Increment the read skip count for this contribution. - * * @param count The {@code long} amount to increment by. */ public void incrementReadSkipCount(long count) { @@ -173,8 +164,7 @@ public class StepContribution implements Serializable { } /** - * Public getter for the read skip count. - * + * Public getter for the read skip count. * @return the read skip count. */ public long getReadSkipCount() { @@ -182,8 +172,7 @@ public class StepContribution implements Serializable { } /** - * Public getter for the write skip count. - * + * Public getter for the write skip count. * @return the write skip count. */ public long getWriteSkipCount() { @@ -192,7 +181,6 @@ public class StepContribution implements Serializable { /** * Public getter for the process skip count. - * * @return the process skip count. */ public long getProcessSkipCount() { @@ -201,7 +189,6 @@ public class StepContribution implements Serializable { /** * Public getter for the parent step execution of this contribution. - * * @return parent step execution of this contribution */ public StepExecution getStepExecution() { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/StepExecution.java b/spring-batch-core/src/main/java/org/springframework/batch/core/StepExecution.java index 3708e120d..958048b92 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/StepExecution.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/StepExecution.java @@ -29,8 +29,8 @@ import org.springframework.util.Assert; /** * Batch domain object representation for the execution of a step. Unlike - * {@link JobExecution}, additional properties are related to the processing - * of items, such as commit count and others. + * {@link JobExecution}, additional properties are related to the processing of items, + * such as commit count and others. * * @author Lucas Ward * @author Dave Syer @@ -81,7 +81,6 @@ public class StepExecution extends Entity { /** * Constructor with mandatory properties. - * * @param stepName The step to which this execution belongs. * @param jobExecution The current job execution. * @param id The ID of this execution. @@ -96,7 +95,6 @@ public class StepExecution extends Entity { /** * Constructor that substitutes null for the execution ID. - * * @param stepName The step to which this execution belongs. * @param jobExecution The current job execution. */ @@ -108,10 +106,9 @@ public class StepExecution extends Entity { } /** - * Constructor that requires only a stepName. Intended only to be - * used over serialization libraries to address the circular - * reference between {@link JobExecution} and StepExecution. - * + * Constructor that requires only a stepName. Intended only to be used over + * serialization libraries to address the circular reference between + * {@link JobExecution} and StepExecution. * @param stepName The name of the executed step. */ @SuppressWarnings("unused") @@ -124,7 +121,6 @@ public class StepExecution extends Entity { /** * Returns the {@link ExecutionContext} for this execution. - * * @return the attributes. */ public ExecutionContext getExecutionContext() { @@ -133,7 +129,6 @@ public class StepExecution extends Entity { /** * Sets the {@link ExecutionContext} for this execution. - * * @param executionContext The attributes. */ public void setExecutionContext(ExecutionContext executionContext) { @@ -142,7 +137,6 @@ public class StepExecution extends Entity { /** * Returns the current number of commits for this execution. - * * @return the current number of commits. */ public long getCommitCount() { @@ -151,7 +145,6 @@ public class StepExecution extends Entity { /** * Sets the current number of commits for this execution. - * * @param commitCount The current number of commits. */ public void setCommitCount(long commitCount) { @@ -160,7 +153,6 @@ public class StepExecution extends Entity { /** * Returns the time when this execution ended or {@code null} if the step is running. - * * @return the time when this execution ended or {@code null} if the step is running. */ @Nullable @@ -170,7 +162,6 @@ public class StepExecution extends Entity { /** * Sets the time when this execution ended. - * * @param endTime The time when this execution ended. */ public void setEndTime(Date endTime) { @@ -179,7 +170,6 @@ public class StepExecution extends Entity { /** * Returns the current number of items read for this execution. - * * @return the current number of items read for this execution. */ public long getReadCount() { @@ -188,7 +178,6 @@ public class StepExecution extends Entity { /** * Sets the current number of read items for this execution. - * * @param readCount The current number of read items for this execution. */ public void setReadCount(long readCount) { @@ -197,7 +186,6 @@ public class StepExecution extends Entity { /** * Returns the current number of items written for this execution. - * * @return The current number of items written for this execution. */ public long getWriteCount() { @@ -206,7 +194,6 @@ public class StepExecution extends Entity { /** * Sets the current number of written items for this execution. - * * @param writeCount The current number of written items for this execution. */ public void setWriteCount(long writeCount) { @@ -215,7 +202,6 @@ public class StepExecution extends Entity { /** * Returns the current number of rollbacks for this execution. - * * @return the current number of rollbacks for this execution. */ public long getRollbackCount() { @@ -224,7 +210,6 @@ public class StepExecution extends Entity { /** * Returns the current number of items filtered out of this execution. - * * @return the current number of items filtered out of this execution. */ public long getFilterCount() { @@ -233,9 +218,7 @@ public class StepExecution extends Entity { /** * Sets the number of items filtered out of this execution. - * - * @param filterCount The number of items filtered out of this execution to - * set. + * @param filterCount The number of items filtered out of this execution to set. */ public void setFilterCount(long filterCount) { this.filterCount = filterCount; @@ -243,7 +226,6 @@ public class StepExecution extends Entity { /** * Sets the number of rollbacks for this execution. - * * @param rollbackCount {@code long} the number of rollbacks. */ public void setRollbackCount(long rollbackCount) { @@ -252,7 +234,6 @@ public class StepExecution extends Entity { /** * Gets the time this execution was created - * * @return the time when this execution was created. */ public Date getCreateTime() { @@ -261,7 +242,6 @@ public class StepExecution extends Entity { /** * Sets the time this execution was created - * * @param createTime creation time of this execution. */ public void setCreateTime(Date createTime) { @@ -270,7 +250,6 @@ public class StepExecution extends Entity { /** * Gets the time when this execution started. - * * @return the time when this execution started. */ @Nullable @@ -280,7 +259,6 @@ public class StepExecution extends Entity { /** * Sets the time when this execution started. - * * @param startTime The time when this execution started. */ public void setStartTime(Date startTime) { @@ -289,7 +267,6 @@ public class StepExecution extends Entity { /** * Returns the current status of this step. - * * @return the current status of this step. */ public BatchStatus getStatus() { @@ -298,7 +275,6 @@ public class StepExecution extends Entity { /** * Sets the current status of this step. - * * @param status The current status of this step. */ public void setStatus(BatchStatus status) { @@ -306,10 +282,9 @@ public class StepExecution extends Entity { } /** - * Upgrade the status field if the provided value is greater than the - * existing one. Clients using this method to set the status can be sure - * that they do not overwrite a failed status with a successful one. - * + * Upgrade the status field if the provided value is greater than the existing one. + * Clients using this method to set the status can be sure that they do not overwrite + * a failed status with a successful one. * @param status The new status value, */ public void upgradeStatus(BatchStatus status) { @@ -325,7 +300,6 @@ public class StepExecution extends Entity { /** * Accessor for the job execution ID. - * * @return the {@code jobExecutionId}. */ public Long getJobExecutionId() { @@ -336,7 +310,8 @@ public class StepExecution extends Entity { } /** - * @param exitStatus The {@link ExitStatus} instance used to establish the exit status. + * @param exitStatus The {@link ExitStatus} instance used to establish the exit + * status. */ public void setExitStatus(ExitStatus exitStatus) { this.exitStatus = exitStatus; @@ -351,9 +326,7 @@ public class StepExecution extends Entity { /** * Accessor for the execution context information of the enclosing job. - * - * @return the {@link JobExecution} that was used to start this step - * execution. + * @return the {@link JobExecution} that was used to start this step execution. */ public JobExecution getJobExecution() { return jobExecution; @@ -361,7 +334,6 @@ public class StepExecution extends Entity { /** * Factory method for {@link StepContribution}. - * * @return a new {@link StepContribution} */ public StepContribution createStepContribution() { @@ -370,10 +342,9 @@ public class StepExecution extends Entity { /** * This method should be called on successful execution just before a chunk commit. - * Synchronizes access to the {@link StepExecution} so that changes - * are atomic. - * - * @param contribution The {@link StepContribution} instance used to update the {@code StepExecution} state. + * Synchronizes access to the {@link StepExecution} so that changes are atomic. + * @param contribution The {@link StepContribution} instance used to update the + * {@code StepExecution} state. */ public synchronized void apply(StepContribution contribution) { readSkipCount += contribution.getReadSkipCount(); @@ -386,8 +357,8 @@ public class StepExecution extends Entity { } /** - * Increments the rollback count. - * Should be used on unsuccessful execution after a chunk has rolled back. + * Increments the rollback count. Should be used on unsuccessful execution after a + * chunk has rolled back. */ public synchronized void incrementRollbackCount() { rollbackCount++; @@ -401,8 +372,8 @@ public class StepExecution extends Entity { } /** - * Sets a flag that signals to an execution environment that this - * execution (and its surrounding job) wishes to exit. + * Sets a flag that signals to an execution environment that this execution (and its + * surrounding job) wishes to exit. */ public void setTerminateOnly() { this.terminateOnly = true; @@ -424,9 +395,8 @@ public class StepExecution extends Entity { /** * Convenience method to get the current job parameters. - * - * @return the {@link JobParameters} from the enclosing job or empty if - * that is {@code null}. + * @return the {@link JobParameters} from the enclosing job or empty if that is + * {@code null}. */ public JobParameters getJobParameters() { if (jobExecution == null) { @@ -451,8 +421,8 @@ public class StepExecution extends Entity { /** * Set the number of records skipped on read. - * - * @param readSkipCount A {@code long} containing the read skip count to be used for the step execution. + * @param readSkipCount A {@code long} containing the read skip count to be used for + * the step execution. */ public void setReadSkipCount(long readSkipCount) { this.readSkipCount = readSkipCount; @@ -460,8 +430,8 @@ public class StepExecution extends Entity { /** * Set the number of records skipped on write. - * - * @param writeSkipCount A {@code long} containing write skip count to be used for the step execution. + * @param writeSkipCount A {@code long} containing write skip count to be used for the + * step execution. */ public void setWriteSkipCount(long writeSkipCount) { this.writeSkipCount = writeSkipCount; @@ -476,8 +446,8 @@ public class StepExecution extends Entity { /** * Sets the number of records skipped during processing. - * - * @param processSkipCount A {@code long} containing the process skip count to be used for the step execution. + * @param processSkipCount A {@code long} containing the process skip count to be used + * for the step execution. */ public void setProcessSkipCount(long processSkipCount) { this.processSkipCount = processSkipCount; @@ -493,9 +463,8 @@ public class StepExecution extends Entity { /** * Sets the time when the {@code StepExecution} was last updated before persisting. - * - * @param lastUpdated the {@link Date} instance used to establish the last - * updated date for the {@code StepExecution}. + * @param lastUpdated the {@link Date} instance used to establish the last updated + * date for the {@code StepExecution}. */ public void setLastUpdated(Date lastUpdated) { this.lastUpdated = lastUpdated; @@ -510,7 +479,6 @@ public class StepExecution extends Entity { /** * Add a {@link Throwable} to failure exceptions. - * * @param throwable The {@link Throwable} to add to failure exceptions. */ public void addFailureException(Throwable throwable) { @@ -520,8 +488,7 @@ public class StepExecution extends Entity { /* * (non-Javadoc) * - * @see - * org.springframework.batch.container.common.domain.Entity#equals(java. + * @see org.springframework.batch.container.common.domain.Entity#equals(java. * lang.Object) */ @Override @@ -538,11 +505,8 @@ public class StepExecution extends Entity { } /** - * Deserialize and ensure transient fields are re-instantiated when read - * back. - * + * Deserialize and ensure transient fields are re-instantiated when read back. * @param stream An instance of {@link ObjectInputStream}. - * * @throws IOException If an error occurs during read. * @throws ClassNotFoundException If the class is not found. */ @@ -560,8 +524,8 @@ public class StepExecution extends Entity { public int hashCode() { Object jobExecutionId = getJobExecutionId(); Long id = getId(); - return super.hashCode() + 31 * (stepName != null ? stepName.hashCode() : 0) + 91 - * (jobExecutionId != null ? jobExecutionId.hashCode() : 0) + 59 * (id != null ? id.hashCode() : 0); + return super.hashCode() + 31 * (stepName != null ? stepName.hashCode() : 0) + + 91 * (jobExecutionId != null ? jobExecutionId.hashCode() : 0) + 59 * (id != null ? id.hashCode() : 0); } @Override @@ -570,15 +534,14 @@ public class StepExecution extends Entity { } /** - * @return The {@link String} containing a summary of the step execution. + * @return The {@link String} containing a summary of the step execution. */ public String getSummary() { - return super.toString() - + String.format( - ", name=%s, status=%s, exitStatus=%s, readCount=%d, filterCount=%d, writeCount=%d readSkipCount=%d, writeSkipCount=%d" - + ", processSkipCount=%d, commitCount=%d, rollbackCount=%d", stepName, status, - exitStatus.getExitCode(), readCount, filterCount, writeCount, readSkipCount, writeSkipCount, - processSkipCount, commitCount, rollbackCount); + return super.toString() + String.format( + ", name=%s, status=%s, exitStatus=%s, readCount=%d, filterCount=%d, writeCount=%d readSkipCount=%d, writeSkipCount=%d" + + ", processSkipCount=%d, commitCount=%d, rollbackCount=%d", + stepName, status, exitStatus.getExitCode(), readCount, filterCount, writeCount, readSkipCount, + writeSkipCount, processSkipCount, commitCount, rollbackCount); } } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/StepExecutionListener.java b/spring-batch-core/src/main/java/org/springframework/batch/core/StepExecutionListener.java index eb8a79533..e4cb6899f 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/StepExecutionListener.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/StepExecutionListener.java @@ -28,29 +28,27 @@ import org.springframework.lang.Nullable; public interface StepExecutionListener extends StepListener { /** - * Initialize the state of the listener with the {@link StepExecution} from - * the current scope. - * + * Initialize the state of the listener with the {@link StepExecution} from the + * current scope. * @param stepExecution instance of {@link StepExecution}. */ default void beforeStep(StepExecution stepExecution) { } /** - * Give a listener a chance to modify the exit status from a step. The value - * returned is combined with the normal exit status by using + * Give a listener a chance to modify the exit status from a step. The value returned + * is combined with the normal exit status by using * {@link ExitStatus#and(ExitStatus)}. * * Called after execution of the step's processing logic (whether successful or - * failed). Throwing an exception in this method has no effect, as it is only - * logged. - * + * failed). Throwing an exception in this method has no effect, as it is only logged. * @param stepExecution a {@link StepExecution} instance. - * @return an {@link ExitStatus} to combine with the normal value. Return - * {@code null} (the default) to leave the old value unchanged. + * @return an {@link ExitStatus} to combine with the normal value. Return {@code null} + * (the default) to leave the old value unchanged. */ @Nullable default ExitStatus afterStep(StepExecution stepExecution) { return null; } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/StepListener.java b/spring-batch-core/src/main/java/org/springframework/batch/core/StepListener.java index 04f66f15b..7e12fa48f 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/StepListener.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/StepListener.java @@ -16,9 +16,8 @@ package org.springframework.batch.core; /** - * Marker interface that acts as a parent to all step - * domain listeners, such as: {@link StepExecutionListener}, - * {@link ChunkListener}, {@link ItemReadListener}, and + * Marker interface that acts as a parent to all step domain listeners, such as: + * {@link StepExecutionListener}, {@link ChunkListener}, {@link ItemReadListener}, and * {@link ItemWriteListener} * * @author Lucas Ward diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/UnexpectedJobExecutionException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/UnexpectedJobExecutionException.java index 54f054d34..eda11002f 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/UnexpectedJobExecutionException.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/UnexpectedJobExecutionException.java @@ -17,18 +17,18 @@ package org.springframework.batch.core; /** - * Indicates to the framework that a critical error has occurred and processing - * should immediately stop. + * Indicates to the framework that a critical error has occurred and processing should + * immediately stop. * * @author Lucas Ward * */ public class UnexpectedJobExecutionException extends RuntimeException { + private static final long serialVersionUID = 8838982304219248527L; /** * Constructs a new instance with a message. - * * @param msg The exception message. * */ @@ -38,7 +38,6 @@ public class UnexpectedJobExecutionException extends RuntimeException { /** * Constructs a new instance with a message. - * * @param msg The exception message. * @param nested An instance of {@link Throwable} that is the cause of the exception. * diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/AfterChunk.java b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/AfterChunk.java index dd4404636..f3015aa68 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/AfterChunk.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/AfterChunk.java @@ -33,7 +33,7 @@ import java.lang.annotation.Target; * @see ChunkListener#afterChunk(ChunkContext context) */ @Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD}) +@Target({ ElementType.METHOD }) public @interface AfterChunk { } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/AfterChunkError.java b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/AfterChunkError.java index 5583c5fd4..b80866e76 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/AfterChunkError.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/AfterChunkError.java @@ -24,8 +24,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * Marks a method to be called after a chunk has failed and been - * marked for rollback.
+ * Marks a method to be called after a chunk has failed and been marked for rollback.
*
* Expected signature: void afterFailedChunk(ChunkContext context) * @@ -34,7 +33,7 @@ import java.lang.annotation.Target; * @see ChunkListener#afterChunkError(ChunkContext context) */ @Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD}) +@Target({ ElementType.METHOD }) public @interface AfterChunkError { } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/AfterJob.java b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/AfterJob.java index d822ff8e5..3759583c9 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/AfterJob.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/AfterJob.java @@ -26,8 +26,8 @@ import org.springframework.batch.core.JobExecution; import org.springframework.batch.core.JobExecutionListener; /** - * Marks a method to be called after a {@link Job} has completed. Annotated - * methods are called regardless of the status of the {@link JobExecution}.
+ * Marks a method to be called after a {@link Job} has completed. Annotated methods are + * called regardless of the status of the {@link JobExecution}.
*
* Expected signature: void afterJob({@link JobExecution} jobExecution) * @@ -36,7 +36,7 @@ import org.springframework.batch.core.JobExecutionListener; * @see JobExecutionListener */ @Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD}) +@Target({ ElementType.METHOD }) public @interface AfterJob { } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/AfterProcess.java b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/AfterProcess.java index 2b65912cc..a20ded0b5 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/AfterProcess.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/AfterProcess.java @@ -25,10 +25,9 @@ import org.springframework.batch.core.ItemProcessListener; import org.springframework.batch.item.ItemProcessor; /** - * Marks a method to be called after an item is passed to an - * {@link ItemProcessor}. {@code item} is the input item. - * {@code result} is the processed item. {@code result} can be null - * if the {@code item} is filtered.
+ * Marks a method to be called after an item is passed to an {@link ItemProcessor}. + * {@code item} is the input item. {@code result} is the processed item. {@code result} + * can be null if the {@code item} is filtered.
*
* Expected signature: void afterProcess(T item, S result) * @@ -37,7 +36,7 @@ import org.springframework.batch.item.ItemProcessor; * @see ItemProcessListener */ @Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD}) +@Target({ ElementType.METHOD }) public @interface AfterProcess { } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/AfterRead.java b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/AfterRead.java index 6c2562af0..5837e77cc 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/AfterRead.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/AfterRead.java @@ -27,13 +27,13 @@ import org.springframework.batch.item.ItemReader; * Marks a method to be called after an item is read from an {@link ItemReader}
*
* Expected signature: void afterRead(T item) - * + * * @author Lucas Ward * @since 2.0 * @see ItemReadListener */ @Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD}) +@Target({ ElementType.METHOD }) public @interface AfterRead { } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/AfterStep.java b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/AfterStep.java index ceadb5c12..aa77dda9e 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/AfterStep.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/AfterStep.java @@ -27,18 +27,17 @@ import org.springframework.batch.core.StepExecution; import org.springframework.batch.core.StepExecutionListener; /** - * Marks a method to be called after a {@link Step} has completed. Annotated - * methods are called regardless of the status of the {@link StepExecution}.
+ * Marks a method to be called after a {@link Step} has completed. Annotated methods are + * called regardless of the status of the {@link StepExecution}.
*
- * Expected signature: {@link ExitStatus} afterStep({@link StepExecution} - * stepExecution); + * Expected signature: {@link ExitStatus} afterStep({@link StepExecution} stepExecution); * * @author Lucas Ward * @since 2.0 * @see StepExecutionListener */ @Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD}) +@Target({ ElementType.METHOD }) public @interface AfterStep { } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/AfterWrite.java b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/AfterWrite.java index 1e7188e19..9d8bda813 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/AfterWrite.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/AfterWrite.java @@ -26,9 +26,9 @@ import org.springframework.batch.core.ItemWriteListener; import org.springframework.batch.item.ItemWriter; /** - * Marks a method to be called after an item is passed to an {@link ItemWriter}. - * Note that this annotation takes a {@link List} because Spring Batch - * generally processes a group of items (for the sake of efficiency).
+ * Marks a method to be called after an item is passed to an {@link ItemWriter}. Note that + * this annotation takes a {@link List} because Spring Batch generally processes a group + * of items (for the sake of efficiency).
*
* Expected signature: void afterWrite({@link List}<? extends S> items) * @@ -37,7 +37,7 @@ import org.springframework.batch.item.ItemWriter; * @see ItemWriteListener */ @Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD}) +@Target({ ElementType.METHOD }) public @interface AfterWrite { } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/BeforeChunk.java b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/BeforeChunk.java index 6068726e9..3140f6ae7 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/BeforeChunk.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/BeforeChunk.java @@ -33,7 +33,7 @@ import org.springframework.batch.core.scope.context.ChunkContext; * @see ChunkListener#beforeChunk(ChunkContext context) */ @Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD}) +@Target({ ElementType.METHOD }) public @interface BeforeChunk { } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/BeforeJob.java b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/BeforeJob.java index dc4cf037a..25aba3975 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/BeforeJob.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/BeforeJob.java @@ -28,9 +28,9 @@ import org.springframework.batch.core.Step; import org.springframework.beans.factory.annotation.Qualifier; /** - * Marks a method to be called before a {@link Job} is executed, which comes - * after a {@link JobExecution} is created and persisted but before the first - * {@link Step} is executed.
+ * Marks a method to be called before a {@link Job} is executed, which comes after a + * {@link JobExecution} is created and persisted but before the first {@link Step} is + * executed.
*
* Expected signature: void beforeJob({@link JobExecution} jobExecution) * @@ -39,7 +39,7 @@ import org.springframework.beans.factory.annotation.Qualifier; * @see JobExecutionListener */ @Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD}) +@Target({ ElementType.METHOD }) @Qualifier("JobExecutionListener") public @interface BeforeJob { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/BeforeProcess.java b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/BeforeProcess.java index 41e11ff46..c98639039 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/BeforeProcess.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/BeforeProcess.java @@ -24,17 +24,16 @@ import org.springframework.batch.core.ItemProcessListener; import org.springframework.batch.item.ItemProcessor; /** - * Marks a method to be called before an item is passed to an - * {@link ItemProcessor}
+ * Marks a method to be called before an item is passed to an {@link ItemProcessor}
*
* Expected signature: void beforeProcess(T item) - * + * * @author Lucas Ward * @since 2.0 * @see ItemProcessListener */ @Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD}) +@Target({ ElementType.METHOD }) public @interface BeforeProcess { } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/BeforeRead.java b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/BeforeRead.java index efe6f2fa6..382bc2215 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/BeforeRead.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/BeforeRead.java @@ -27,13 +27,13 @@ import org.springframework.batch.item.ItemReader; * Marks a method to be called before an item is read from an {@link ItemReader}
*
* Expected signature: void beforeRead() - * + * * @author Lucas Ward * @since 2.0 * @see ItemReadListener */ @Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD}) +@Target({ ElementType.METHOD }) public @interface BeforeRead { } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/BeforeStep.java b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/BeforeStep.java index 2a3e1df65..d34eb8023 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/BeforeStep.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/BeforeStep.java @@ -26,9 +26,8 @@ import org.springframework.batch.core.StepExecution; import org.springframework.batch.core.StepExecutionListener; /** - * Marks a method to be called before a {@link Step} is executed, which comes - * after a {@link StepExecution} is created and persisted but before the first - * item is read.
+ * Marks a method to be called before a {@link Step} is executed, which comes after a + * {@link StepExecution} is created and persisted but before the first item is read.
*
* Expected signature: void beforeStep({@link StepExecution} stepExecution) * @@ -37,7 +36,7 @@ import org.springframework.batch.core.StepExecutionListener; * @see StepExecutionListener */ @Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD}) +@Target({ ElementType.METHOD }) public @interface BeforeStep { } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/BeforeWrite.java b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/BeforeWrite.java index fcd6f57cb..7c5eb1ce8 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/BeforeWrite.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/BeforeWrite.java @@ -35,7 +35,7 @@ import org.springframework.batch.item.ItemWriter; * @see ItemWriteListener */ @Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD}) +@Target({ ElementType.METHOD }) public @interface BeforeWrite { } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/OnProcessError.java b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/OnProcessError.java index d01e623aa..8ea21c2ca 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/OnProcessError.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/OnProcessError.java @@ -25,8 +25,7 @@ import org.springframework.batch.core.ItemProcessListener; import org.springframework.batch.item.ItemProcessor; /** - * Marks a method to be called if an exception is thrown by an - * {@link ItemProcessor}.
+ * Marks a method to be called if an exception is thrown by an {@link ItemProcessor}.
*
* Expected signature: void onProcessError(T item, {@link Exception} e) * @@ -35,7 +34,7 @@ import org.springframework.batch.item.ItemProcessor; * @see ItemProcessListener */ @Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD}) +@Target({ ElementType.METHOD }) public @interface OnProcessError { } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/OnReadError.java b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/OnReadError.java index d6e3bb50e..a81c6a7f9 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/OnReadError.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/OnReadError.java @@ -24,8 +24,7 @@ import org.springframework.batch.core.ItemReadListener; import org.springframework.batch.item.ItemReader; /** - * Marks a method to be called if an exception is thrown by an - * {@link ItemReader}.
+ * Marks a method to be called if an exception is thrown by an {@link ItemReader}.
*
* Expected signature: void onReadError({@link Exception} ex) * @@ -34,7 +33,7 @@ import org.springframework.batch.item.ItemReader; * @see ItemReadListener */ @Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD}) +@Target({ ElementType.METHOD }) public @interface OnReadError { } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/OnSkipInProcess.java b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/OnSkipInProcess.java index c3a3c2fce..08c46fc34 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/OnSkipInProcess.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/OnSkipInProcess.java @@ -25,8 +25,8 @@ import org.springframework.batch.core.SkipListener; import org.springframework.batch.item.ItemProcessor; /** - * Marks a method to be called when an item is skipped due to an exception - * thrown in the {@link ItemProcessor}.
+ * Marks a method to be called when an item is skipped due to an exception thrown in the + * {@link ItemProcessor}.
*
* Expected signature: void onSkipInProcess(T item, {@link Throwable} t) * @@ -35,7 +35,7 @@ import org.springframework.batch.item.ItemProcessor; * @see SkipListener */ @Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD}) +@Target({ ElementType.METHOD }) public @interface OnSkipInProcess { } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/OnSkipInRead.java b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/OnSkipInRead.java index 0ba04ce41..89535bbbc 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/OnSkipInRead.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/OnSkipInRead.java @@ -25,8 +25,8 @@ import org.springframework.batch.core.SkipListener; import org.springframework.batch.item.ItemReader; /** - * Marks a method to be called when an item is skipped due to an exception - * thrown in the {@link ItemReader}.
+ * Marks a method to be called when an item is skipped due to an exception thrown in the + * {@link ItemReader}.
*
* Expected signature: void onSkipInRead({@link Throwable} t) * @@ -35,7 +35,7 @@ import org.springframework.batch.item.ItemReader; * @see SkipListener */ @Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD}) +@Target({ ElementType.METHOD }) public @interface OnSkipInRead { } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/OnSkipInWrite.java b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/OnSkipInWrite.java index 2f8ffca34..02c39dc79 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/OnSkipInWrite.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/OnSkipInWrite.java @@ -25,17 +25,17 @@ import org.springframework.batch.core.SkipListener; import org.springframework.batch.item.ItemWriter; /** - * Marks a method to be called when an item is skipped due to an exception - * thrown in the {@link ItemWriter}.
+ * Marks a method to be called when an item is skipped due to an exception thrown in the + * {@link ItemWriter}.
*
* Expected signature: void onSkipInWrite(S item, {@link Throwable} t) - * + * * @author Lucas Ward * @since 2.0 * @see SkipListener */ @Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD}) +@Target({ ElementType.METHOD }) public @interface OnSkipInWrite { } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/OnWriteError.java b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/OnWriteError.java index 89457d9e6..7d8283ba0 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/OnWriteError.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/annotation/OnWriteError.java @@ -26,20 +26,19 @@ import org.springframework.batch.core.ItemWriteListener; import org.springframework.batch.item.ItemWriter; /** - * Marks a method to be called if an exception is thrown by an - * {@link ItemWriter}. Note that this annotation takes a {@link List} - * because Spring Batch generally processes a group of items - * (for the sake of efficiency).
+ * Marks a method to be called if an exception is thrown by an {@link ItemWriter}. Note + * that this annotation takes a {@link List} because Spring Batch generally processes a + * group of items (for the sake of efficiency).
*
- * Expected signature: void onWriteError({@link Exception} exception, - * {@link List}<? extends S> items) + * Expected signature: void onWriteError({@link Exception} exception, {@link List}<? + * extends S> items) * * @author Lucas Ward * @since 2.0 * @see ItemWriteListener */ @Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD}) +@Target({ ElementType.METHOD }) public @interface OnWriteError { } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/BatchConfigurationException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/BatchConfigurationException.java index c3b2f0dbd..4f5782e44 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/BatchConfigurationException.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/BatchConfigurationException.java @@ -16,9 +16,9 @@ package org.springframework.batch.core.configuration; /** - * Represents an error has occurred in the configuration of base batch - * infrastructure (creation of a {@link org.springframework.batch.core.repository.JobRepository} - * for example. + * Represents an error has occurred in the configuration of base batch infrastructure + * (creation of a {@link org.springframework.batch.core.repository.JobRepository} for + * example. * * @author Michael Minella * @author Mahmoud Ben Hassine @@ -34,4 +34,5 @@ public class BatchConfigurationException extends RuntimeException { public BatchConfigurationException(Throwable t) { super(t); } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/DuplicateJobException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/DuplicateJobException.java index 993c3e975..52a7c423a 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/DuplicateJobException.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/DuplicateJobException.java @@ -19,18 +19,16 @@ import org.springframework.batch.core.Job; import org.springframework.batch.core.JobExecutionException; /** - * Checked exception that indicates a name clash when registering - * {@link Job} instances. - * + * Checked exception that indicates a name clash when registering {@link Job} instances. + * * @author Dave Syer - * + * */ @SuppressWarnings("serial") public class DuplicateJobException extends JobExecutionException { /** * Create an exception with the given message. - * * @param msg error message. */ public DuplicateJobException(String msg) { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/JobFactory.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/JobFactory.java index ca67696db..1b62b7e09 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/JobFactory.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/JobFactory.java @@ -19,7 +19,7 @@ import org.springframework.batch.core.Job; /** * Strategy for creating a single job. - * + * * @author Dave Syer * */ @@ -27,7 +27,6 @@ public interface JobFactory { /** * Create a new instance of {@link Job}. - * * @return The {@link Job}. */ Job createJob(); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/JobLocator.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/JobLocator.java index a22c4494f..9e195e10b 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/JobLocator.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/JobLocator.java @@ -22,22 +22,19 @@ import org.springframework.lang.Nullable; /** * A runtime service locator interface for retrieving job configurations by * name. - * + * * @author Dave Syer * @author Mahmoud Ben Hassine - * + * */ public interface JobLocator { /** * Locates a {@link Job} at runtime. - * - * @param name the name of the {@link Job} which should be - * unique + * @param name the name of the {@link Job} which should be unique * @return a {@link Job} identified by the given name - * - * @throws NoSuchJobException if the required configuration can - * not be found. + * @throws NoSuchJobException if the required configuration can not be found. */ Job getJob(@Nullable String name) throws NoSuchJobException; + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/JobRegistry.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/JobRegistry.java index ccb99e9fd..bd689adec 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/JobRegistry.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/JobRegistry.java @@ -20,27 +20,25 @@ import org.springframework.batch.core.Job; /** * A runtime service registry interface for registering job configurations by * name. - * + * * @author Dave Syer - * + * */ public interface JobRegistry extends ListableJobLocator { /** * Registers a {@link Job} at runtime. - * * @param jobFactory the {@link Job} to be registered - * - * @throws DuplicateJobException if a factory with the same job name has - * already been registered. + * @throws DuplicateJobException if a factory with the same job name has already been + * registered. */ void register(JobFactory jobFactory) throws DuplicateJobException; /** - * Unregisters a previously registered {@link Job}. If it was not - * previously registered there is no error. - * + * Unregisters a previously registered {@link Job}. If it was not previously + * registered there is no error. * @param jobName the {@link Job} to unregister. */ void unregister(String jobName); + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/ListableJobLocator.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/ListableJobLocator.java index a3ca54a07..0fe16eb21 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/ListableJobLocator.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/ListableJobLocator.java @@ -19,17 +19,17 @@ import java.util.Collection; /** * A listable extension of {@link JobLocator}. - * + * * @author Dave Syer - * + * */ public interface ListableJobLocator extends JobLocator { /** - * Provides the currently registered job names. The return value is - * unmodifiable and disconnected from the underlying registry storage. - * + * Provides the currently registered job names. The return value is unmodifiable and + * disconnected from the underlying registry storage. * @return a collection of String. Empty if none are registered. */ Collection getJobNames(); + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/StepRegistry.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/StepRegistry.java index 5a3d7384a..fc49b73d5 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/StepRegistry.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/StepRegistry.java @@ -30,34 +30,32 @@ import java.util.Collection; */ public interface StepRegistry { - /** - * Registers all the step of the given job. If the job is already registered, - * the method {@link #unregisterStepsFromJob(String)} is called before registering - * the given steps. - * - * @param jobName the give job name - * @param steps the job steps - * @throws DuplicateJobException if a job with the same job name has already been registered. - */ - void register(String jobName, Collection steps) throws DuplicateJobException; + /** + * Registers all the step of the given job. If the job is already registered, the + * method {@link #unregisterStepsFromJob(String)} is called before registering the + * given steps. + * @param jobName the give job name + * @param steps the job steps + * @throws DuplicateJobException if a job with the same job name has already been + * registered. + */ + void register(String jobName, Collection steps) throws DuplicateJobException; - /** - * Unregisters all the steps of the given job. If the job is not registered, - * nothing happens. - * - * @param jobName the given job name - */ - void unregisterStepsFromJob(String jobName); + /** + * Unregisters all the steps of the given job. If the job is not registered, nothing + * happens. + * @param jobName the given job name + */ + void unregisterStepsFromJob(String jobName); - /** - * Returns the {@link Step} of the specified job based on its name. - * - * @param jobName the name of the job - * @param stepName the name of the step to retrieve - * @return the step with the given name belonging to the mentioned job - * @throws NoSuchJobException no such job with that name exists - * @throws NoSuchStepException no such step with that name for that job exists - */ - Step getStep(String jobName, String stepName) throws NoSuchJobException, NoSuchStepException; + /** + * Returns the {@link Step} of the specified job based on its name. + * @param jobName the name of the job + * @param stepName the name of the step to retrieve + * @return the step with the given name belonging to the mentioned job + * @throws NoSuchJobException no such job with that name exists + * @throws NoSuchStepException no such step with that name for that job exists + */ + Step getStep(String jobName, String stepName) throws NoSuchJobException, NoSuchStepException; } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/AbstractBatchConfiguration.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/AbstractBatchConfiguration.java index 4d720b4e6..3c170e0d6 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/AbstractBatchConfiguration.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/AbstractBatchConfiguration.java @@ -40,9 +40,10 @@ import org.springframework.transaction.PlatformTransactionManager; import org.springframework.util.Assert; /** - * Base {@code Configuration} class providing common structure for enabling and using Spring Batch. - * Customization is available by implementing the {@link BatchConfigurer} interface. - * + * Base {@code Configuration} class providing common structure for enabling and using + * Spring Batch. Customization is available by implementing the {@link BatchConfigurer} + * interface. + * * @author Dave Syer * @author Michael Minella * @author Mahmoud Ben Hassine @@ -64,7 +65,6 @@ public abstract class AbstractBatchConfiguration implements ImportAware, Initial /** * Establish the {@link JobBuilderFactory} for the batch execution. - * * @return The instance of the {@link JobBuilderFactory}. * @throws Exception The {@link Exception} thrown if error occurs. */ @@ -75,7 +75,6 @@ public abstract class AbstractBatchConfiguration implements ImportAware, Initial /** * Establish the {@link StepBuilderFactory} for the batch execution. - * * @return The instance of the {@link StepBuilderFactory}. * @throws Exception The {@link Exception} thrown if error occurs. */ @@ -86,7 +85,6 @@ public abstract class AbstractBatchConfiguration implements ImportAware, Initial /** * Establish the {@link JobRepository} for the batch execution. - * * @return The instance of the {@link JobRepository}. * @throws Exception The {@link Exception} thrown if error occurs. */ @@ -95,7 +93,6 @@ public abstract class AbstractBatchConfiguration implements ImportAware, Initial /** * Establish the {@link JobLauncher} for the batch execution. - * * @return The instance of the {@link JobLauncher}. * @throws Exception The {@link Exception} thrown if error occurs. */ @@ -104,7 +101,6 @@ public abstract class AbstractBatchConfiguration implements ImportAware, Initial /** * Establish the {@link JobExplorer} for the batch execution. - * * @return The instance of the {@link JobExplorer}. * @throws Exception The {@link Exception} thrown if error occurs. */ @@ -113,7 +109,6 @@ public abstract class AbstractBatchConfiguration implements ImportAware, Initial /** * Establish the {@link JobRegistry} for the batch execution. - * * @return The instance of the {@link JobRegistry}. * @throws Exception The {@link Exception} thrown if error occurs. */ @@ -124,7 +119,6 @@ public abstract class AbstractBatchConfiguration implements ImportAware, Initial /** * Establish the {@link PlatformTransactionManager} for the batch execution. - * * @return The instance of the {@link PlatformTransactionManager}. * @throws Exception The {@link Exception} thrown if error occurs. */ @@ -132,8 +126,8 @@ public abstract class AbstractBatchConfiguration implements ImportAware, Initial @Override public void setImportMetadata(AnnotationMetadata importMetadata) { - Map annotationAttributes = - importMetadata.getAnnotationAttributes(EnableBatchProcessing.class.getName(), false); + Map annotationAttributes = importMetadata + .getAnnotationAttributes(EnableBatchProcessing.class.getName(), false); AnnotationAttributes enabled = AnnotationAttributes.fromMap(annotationAttributes); String message = "@EnableBatchProcessing is not present on importing class " + importMetadata.getClassName(); Assert.notNull(enabled, message); @@ -146,10 +140,12 @@ public abstract class AbstractBatchConfiguration implements ImportAware, Initial } /** - * If a {@link BatchConfigurer} exists, return it. If the configurers list is empty, create a {@link DefaultBatchConfigurer}. - * If more than one configurer is present in the list, an {@link IllegalStateException} is thrown. + * If a {@link BatchConfigurer} exists, return it. If the configurers list is empty, + * create a {@link DefaultBatchConfigurer}. If more than one configurer is present in + * the list, an {@link IllegalStateException} is thrown. * @param configurers The {@link Collection} of configurers to review. - * @return The {@link BatchConfigurer} that was in the configurers collection or the one created. + * @return The {@link BatchConfigurer} that was in the configurers collection or the + * one created. */ protected BatchConfigurer getConfigurer(Collection configurers) { if (this.configurer != null) { @@ -175,12 +171,14 @@ public abstract class AbstractBatchConfiguration implements ImportAware, Initial DataSource dataSource; try { dataSource = this.context.getBean(DataSource.class); - } catch (NoUniqueBeanDefinitionException exception) { + } + catch (NoUniqueBeanDefinitionException exception) { throw new IllegalStateException( - "Multiple data sources are defined in the application context and no primary candidate was found. " + - "To use the default BatchConfigurer, one of the data sources should be annotated with '@Primary'.", + "Multiple data sources are defined in the application context and no primary candidate was found. " + + "To use the default BatchConfigurer, one of the data sources should be annotated with '@Primary'.", exception); - } catch (NoSuchBeanDefinitionException exception) { + } + catch (NoSuchBeanDefinitionException exception) { throw new IllegalStateException( "To use the default BatchConfigurer, the application context must contain at least one data source.", exception); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/BatchConfigurationSelector.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/BatchConfigurationSelector.java index 609d9fb12..5c64e5afe 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/BatchConfigurationSelector.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/BatchConfigurationSelector.java @@ -21,9 +21,10 @@ import org.springframework.core.type.AnnotationMetadata; import org.springframework.util.Assert; /** - * Base {@code Configuration} class providing common structure for enabling and using Spring Batch. Customization is - * available by implementing the {@link BatchConfigurer} interface. - * + * Base {@code Configuration} class providing common structure for enabling and using + * Spring Batch. Customization is available by implementing the {@link BatchConfigurer} + * interface. + * * @author Dave Syer * @since 2.2 * @see EnableBatchProcessing @@ -33,8 +34,8 @@ public class BatchConfigurationSelector implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { Class annotationType = EnableBatchProcessing.class; - AnnotationAttributes attributes = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes( - annotationType.getName(), false)); + AnnotationAttributes attributes = AnnotationAttributes + .fromMap(importingClassMetadata.getAnnotationAttributes(annotationType.getName(), false)); Assert.notNull(attributes, String.format("@%s is not present on importing class '%s' as expected", annotationType.getSimpleName(), importingClassMetadata.getClassName())); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/BatchConfigurer.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/BatchConfigurer.java index caf8486a1..90e1f92c9 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/BatchConfigurer.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/BatchConfigurer.java @@ -21,10 +21,11 @@ import org.springframework.batch.core.repository.JobRepository; import org.springframework.transaction.PlatformTransactionManager; /** - * Strategy interface for users to provide as a factory for custom components needed by a Batch system. - * + * Strategy interface for users to provide as a factory for custom components needed by a + * Batch system. + * * @author Dave Syer - * + * */ public interface BatchConfigurer { @@ -51,4 +52,5 @@ public interface BatchConfigurer { * @throws Exception The {@link Exception} thrown if an error occurs. */ JobExplorer getJobExplorer() throws Exception; + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/DefaultBatchConfigurer.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/DefaultBatchConfigurer.java index 328450ccf..39bd845e2 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/DefaultBatchConfigurer.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/DefaultBatchConfigurer.java @@ -37,15 +37,18 @@ import org.springframework.util.Assert; public class DefaultBatchConfigurer implements BatchConfigurer { private DataSource dataSource; + private PlatformTransactionManager transactionManager; + private JobRepository jobRepository; + private JobLauncher jobLauncher; + private JobExplorer jobExplorer; /** - * Create a new {@link DefaultBatchConfigurer} with the passed datasource. This constructor - * will configure a default {@link DataSourceTransactionManager}. - * + * Create a new {@link DefaultBatchConfigurer} with the passed datasource. This + * constructor will configure a default {@link DataSourceTransactionManager}. * @param dataSource to use for the job repository and job explorer */ public DefaultBatchConfigurer(DataSource dataSource) { @@ -53,7 +56,8 @@ public class DefaultBatchConfigurer implements BatchConfigurer { } /** - * Create a new {@link DefaultBatchConfigurer} with the passed datasource and transaction manager. + * Create a new {@link DefaultBatchConfigurer} with the passed datasource and + * transaction manager. * @param dataSource to use for the job repository and job explorer * @param transactionManager to use for the job repository */ @@ -66,7 +70,6 @@ public class DefaultBatchConfigurer implements BatchConfigurer { /** * Sets the dataSource. - * * @param dataSource The data source to use. Must not be {@code null}. */ public void setDataSource(DataSource dataSource) { @@ -81,7 +84,6 @@ public class DefaultBatchConfigurer implements BatchConfigurer { return this.dataSource; } - @Override public JobRepository getJobRepository() { return this.jobRepository; @@ -103,7 +105,8 @@ public class DefaultBatchConfigurer implements BatchConfigurer { } /** - * Initialize the {@link DefaultBatchConfigurer} with the {@link JobRepository}, {@link JobExplorer}, and {@link JobLauncher}. + * Initialize the {@link DefaultBatchConfigurer} with the {@link JobRepository}, + * {@link JobExplorer}, and {@link JobLauncher}. */ @PostConstruct public void initialize() { @@ -111,14 +114,16 @@ public class DefaultBatchConfigurer implements BatchConfigurer { this.jobRepository = createJobRepository(); this.jobExplorer = createJobExplorer(); this.jobLauncher = createJobLauncher(); - } catch (Exception e) { + } + catch (Exception e) { throw new BatchConfigurationException(e); } } /** * @return An instance of {@link JobLauncher}. - * @throws Exception The {@link Exception} that is thrown if an error occurs while creating the {@link JobLauncher}. + * @throws Exception The {@link Exception} that is thrown if an error occurs while + * creating the {@link JobLauncher}. */ protected JobLauncher createJobLauncher() throws Exception { SimpleJobLauncher jobLauncher = new SimpleJobLauncher(); @@ -129,7 +134,8 @@ public class DefaultBatchConfigurer implements BatchConfigurer { /** * @return An instance of {@link JobRepository}. - * @throws Exception The {@link Exception} that is thrown if an error occurs while creating the {@link JobRepository}. + * @throws Exception The {@link Exception} that is thrown if an error occurs while + * creating the {@link JobRepository}. */ protected JobRepository createJobRepository() throws Exception { JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); @@ -141,7 +147,8 @@ public class DefaultBatchConfigurer implements BatchConfigurer { /** * @return An instance of {@link JobExplorer}. - * @throws Exception The {@link Exception} that is thrown if an error occurs while creating the {@link JobExplorer}. + * @throws Exception The {@link Exception} that is thrown if an error occurs while + * creating the {@link JobExplorer}. */ protected JobExplorer createJobExplorer() throws Exception { JobExplorerFactoryBean jobExplorerFactoryBean = new JobExplorerFactoryBean(); @@ -149,4 +156,5 @@ public class DefaultBatchConfigurer implements BatchConfigurer { jobExplorerFactoryBean.afterPropertiesSet(); return jobExplorerFactoryBean.getObject(); } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/EnableBatchProcessing.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/EnableBatchProcessing.java index d89eaf5c7..c23a31383 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/EnableBatchProcessing.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/EnableBatchProcessing.java @@ -33,8 +33,10 @@ import org.springframework.transaction.PlatformTransactionManager; /** *

- * Enable Spring Batch features and provide a base configuration for setting up batch jobs in an @Configuration - * class, roughly equivalent to using the {@code } XML namespace.

+ * Enable Spring Batch features and provide a base configuration for setting up batch jobs + * in an @Configuration class, roughly equivalent to using the {@code } XML + * namespace. + *

* *
  * @Configuration
@@ -62,8 +64,8 @@ import org.springframework.transaction.PlatformTransactionManager;
  * }
  * 
* - * The user should provide a {@link DataSource} as a bean in the context, or else implement {@link BatchConfigurer} in - * the configuration class itself, e.g. + * The user should provide a {@link DataSource} as a bean in the context, or else + * implement {@link BatchConfigurer} in the configuration class itself, e.g. * *
  * @Configuration
@@ -85,30 +87,41 @@ import org.springframework.transaction.PlatformTransactionManager;
  * }
  * 
* - * If multiple {@link javax.sql.DataSource}s are defined in the context, the primary autowire candidate - * will be used, otherwise an exception will be thrown. + * If multiple {@link javax.sql.DataSource}s are defined in the context, the primary + * autowire candidate will be used, otherwise an exception will be thrown. * - * Note that only one of your configuration classes needs to have the @EnableBatchProcessing - * annotation. Once you have an @EnableBatchProcessing class in your configuration you will have an - * instance of {@link StepScope} and {@link org.springframework.batch.core.scope.JobScope} so your beans inside steps - * can have @Scope("step") and @Scope("job") respectively. You will also be - * able to @Autowired some useful stuff into your context: + * Note that only one of your configuration classes needs to have the + * @EnableBatchProcessing annotation. Once you have an + * @EnableBatchProcessing class in your configuration you will have an + * instance of {@link StepScope} and {@link org.springframework.batch.core.scope.JobScope} + * so your beans inside steps can have @Scope("step") and + * @Scope("job") respectively. You will also be able to + * @Autowired some useful stuff into your context: * *
    - *
  • a {@link JobRepository} (bean name "jobRepository" of type {@link org.springframework.batch.core.repository.support.SimpleJobRepository})
  • - *
  • a {@link JobLauncher} (bean name "jobLauncher" of type {@link org.springframework.batch.core.launch.support.SimpleJobLauncher})
  • - *
  • a {@link JobRegistry} (bean name "jobRegistry" of type {@link org.springframework.batch.core.configuration.support.MapJobRegistry})
  • - *
  • a {@link org.springframework.batch.core.explore.JobExplorer} (bean name "jobExplorer" of type {@link org.springframework.batch.core.explore.support.SimpleJobExplorer})
  • - *
  • a {@link JobBuilderFactory} (bean name "jobBuilders") as a convenience to prevent you from having to inject the - * job repository into every job, as in the examples above
  • - *
  • a {@link StepBuilderFactory} (bean name "stepBuilders") as a convenience to prevent you from having to inject the - * job repository and transaction manager into every step
  • + *
  • a {@link JobRepository} (bean name "jobRepository" of type + * {@link org.springframework.batch.core.repository.support.SimpleJobRepository})
  • + *
  • a {@link JobLauncher} (bean name "jobLauncher" of type + * {@link org.springframework.batch.core.launch.support.SimpleJobLauncher})
  • + *
  • a {@link JobRegistry} (bean name "jobRegistry" of type + * {@link org.springframework.batch.core.configuration.support.MapJobRegistry})
  • + *
  • a {@link org.springframework.batch.core.explore.JobExplorer} (bean name + * "jobExplorer" of type + * {@link org.springframework.batch.core.explore.support.SimpleJobExplorer})
  • + *
  • a {@link JobBuilderFactory} (bean name "jobBuilders") as a convenience to prevent + * you from having to inject the job repository into every job, as in the examples + * above
  • + *
  • a {@link StepBuilderFactory} (bean name "stepBuilders") as a convenience to prevent + * you from having to inject the job repository and transaction manager into every + * step
  • *
* - * The transaction manager provided by this annotation will be of type {@link org.springframework.jdbc.datasource.DataSourceTransactionManager} - * configured with the {@link javax.sql.DataSource} provided within the context. + * The transaction manager provided by this annotation will be of type + * {@link org.springframework.jdbc.datasource.DataSourceTransactionManager} configured + * with the {@link javax.sql.DataSource} provided within the context. * - * In order to use a custom transaction manager, a custom {@link BatchConfigurer} should be provided. For example: + * In order to use a custom transaction manager, a custom {@link BatchConfigurer} should + * be provided. For example: * *
  * @Configuration
@@ -130,11 +143,13 @@ import org.springframework.transaction.PlatformTransactionManager;
  * }
  * 
* - * If the configuration is specified as modular=true then the context will also contain an - * {@link AutomaticJobRegistrar}. The job registrar is useful for modularizing your configuration if there are multiple - * jobs. It works by creating separate child application contexts containing job configurations and registering those - * jobs. The jobs can then create steps and other dependent components without needing to worry about bean definition - * name clashes. Beans of type {@link ApplicationContextFactory} will be registered automatically with the job + * If the configuration is specified as modular=true then the context will + * also contain an {@link AutomaticJobRegistrar}. The job registrar is useful for + * modularizing your configuration if there are multiple jobs. It works by creating + * separate child application contexts containing job configurations and registering those + * jobs. The jobs can then create steps and other dependent components without needing to + * worry about bean definition name clashes. Beans of type + * {@link ApplicationContextFactory} will be registered automatically with the job * registrar. Example: * *
@@ -157,12 +172,13 @@ import org.springframework.transaction.PlatformTransactionManager;
  * }
  * 
* - * Note that a modular parent context in general should not itself contain @Bean definitions for job, - * especially if a {@link BatchConfigurer} is provided, because cyclic configuration dependencies are otherwise likely - * to develop. + * Note that a modular parent context in general should not itself contain + * @Bean definitions for job, especially if a {@link BatchConfigurer} is provided, + * because cyclic configuration dependencies are otherwise likely to develop. * *

- * For reference, the first example above can be compared to the following Spring XML configuration: + * For reference, the first example above can be compared to the following Spring XML + * configuration: * *

  * {@code
@@ -173,7 +189,8 @@ import org.springframework.transaction.PlatformTransactionManager;
  *       
  *     
  *     
- *     
+ *     
  *       
  *     
  * 
@@ -191,12 +208,12 @@ import org.springframework.transaction.PlatformTransactionManager;
 public @interface EnableBatchProcessing {
 
 	/**
-	 * Indicate whether the configuration is going to be modularized into multiple application contexts. If true then
-	 * you should not create any @Bean Job definitions in this context, but rather supply them in separate (child)
-	 * contexts through an {@link ApplicationContextFactory}.
-	 *
-	 * @return boolean indicating whether the configuration is going to be
-	 * modularized into multiple application contexts.  Defaults to false.
+	 * Indicate whether the configuration is going to be modularized into multiple
+	 * application contexts. If true then you should not create any @Bean Job
+	 * definitions in this context, but rather supply them in separate (child) contexts
+	 * through an {@link ApplicationContextFactory}.
+	 * @return boolean indicating whether the configuration is going to be modularized
+	 * into multiple application contexts. Defaults to false.
 	 */
 	boolean modular() default false;
 
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/JobBuilderFactory.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/JobBuilderFactory.java
index a5d91a704..38f296cd5 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/JobBuilderFactory.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/JobBuilderFactory.java
@@ -19,11 +19,12 @@ import org.springframework.batch.core.job.builder.JobBuilder;
 import org.springframework.batch.core.repository.JobRepository;
 
 /**
- * Convenient factory for a {@link JobBuilder} which sets the {@link JobRepository} automatically.
- * 
+ * Convenient factory for a {@link JobBuilder} which sets the {@link JobRepository}
+ * automatically.
+ *
  * @author Dave Syer
  * @author Mahmoud Ben Hassine
- * 
+ *
  */
 public class JobBuilderFactory {
 
@@ -37,9 +38,9 @@ public class JobBuilderFactory {
 	}
 
 	/**
-	 * Creates a job builder and initializes its job repository. Note that if the builder is used to create a @Bean
-	 * definition then the name of the job and the bean name might be different.
-	 * 
+	 * Creates a job builder and initializes its job repository. Note that if the builder
+	 * is used to create a @Bean definition then the name of the job and the bean name
+	 * might be different.
 	 * @param name the name of the job
 	 * @return a job builder
 	 */
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/JobScope.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/JobScope.java
index ab6507f98..a36662185 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/JobScope.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/JobScope.java
@@ -24,9 +24,10 @@ import java.lang.annotation.RetentionPolicy;
 
 /**
  * 

- * Convenient annotation for job scoped beans that defaults the proxy mode, so that it doesn't have to be specified - * explicitly on every bean definition. Use this on any @Bean that needs to inject @Values from the job - * context, and any bean that needs to share a lifecycle with a job execution (e.g. an JobExecutionListener). E.g. + * Convenient annotation for job scoped beans that defaults the proxy mode, so that it + * doesn't have to be specified explicitly on every bean definition. Use this on any + * @Bean that needs to inject @Values from the job context, and any bean that + * needs to share a lifecycle with a job execution (e.g. an JobExecutionListener). E.g. *

* *
@@ -38,7 +39,10 @@ import java.lang.annotation.RetentionPolicy;
  * }
  * 
* - *

Marking a @Bean as @JobScope is equivalent to marking it as @Scope(value="job", proxyMode=TARGET_CLASS)

+ *

+ * Marking a @Bean as @JobScope is equivalent to marking it as + * @Scope(value="job", proxyMode=TARGET_CLASS) + *

* * @author Michael Minella * diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/ModularBatchConfiguration.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/ModularBatchConfiguration.java index 2093847a0..5eeb9fdd2 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/ModularBatchConfiguration.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/ModularBatchConfiguration.java @@ -30,8 +30,9 @@ import org.springframework.context.annotation.Configuration; import org.springframework.transaction.PlatformTransactionManager; /** - * Base {@code Configuration} class providing common structure for enabling and using Spring Batch. - * Customization is available by implementing the {@link BatchConfigurer} interface. + * Base {@code Configuration} class providing common structure for enabling and using + * Spring Batch. Customization is available by implementing the {@link BatchConfigurer} + * interface. * * @author Dave Syer * @author Mahmoud Ben Hassine @@ -45,7 +46,6 @@ public class ModularBatchConfiguration extends SimpleBatchConfiguration { /** * Creates a {@link AutomaticJobRegistrar} bean. - * * @return New instance of {@link AutomaticJobRegistrar}. * @throws Exception The {@link Exception} thrown if an error occurs. */ diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/ScopeConfiguration.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/ScopeConfiguration.java index 1745c59d9..390b7c401 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/ScopeConfiguration.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/ScopeConfiguration.java @@ -55,4 +55,5 @@ public class ScopeConfiguration { public static JobScope jobScope() { return jobScope; } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/SimpleBatchConfiguration.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/SimpleBatchConfiguration.java index 714ff2cf0..1e2d3b7f8 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/SimpleBatchConfiguration.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/SimpleBatchConfiguration.java @@ -35,8 +35,9 @@ import org.springframework.context.annotation.Configuration; import org.springframework.transaction.PlatformTransactionManager; /** - * Base {@code Configuration} class providing common structure for enabling and using Spring Batch. - * Customization is available by implementing the {@link BatchConfigurer} interface. + * Base {@code Configuration} class providing common structure for enabling and using + * Spring Batch. Customization is available by implementing the {@link BatchConfigurer} + * interface. * * @author Dave Syer * @author Mahmoud Ben Hassine diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/StepBuilderFactory.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/StepBuilderFactory.java index 72fa4ecee..7bf46d8b2 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/StepBuilderFactory.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/StepBuilderFactory.java @@ -22,10 +22,10 @@ import org.springframework.transaction.PlatformTransactionManager; /** * Convenient factory for a {@link StepBuilder} which sets the {@link JobRepository} and * {@link PlatformTransactionManager} automatically. - * + * * @author Dave Syer * @author Mahmoud Ben Hassine - * + * */ public class StepBuilderFactory { @@ -35,9 +35,9 @@ public class StepBuilderFactory { /** * Constructor for the {@link StepBuilderFactory}. - * * @param jobRepository The {@link JobRepository} to be used by the builder factory. - * @param transactionManager The {@link PlatformTransactionManager} to be used by the builder factory. + * @param transactionManager The {@link PlatformTransactionManager} to be used by the + * builder factory. */ public StepBuilderFactory(JobRepository jobRepository, PlatformTransactionManager transactionManager) { this.jobRepository = jobRepository; @@ -45,16 +45,14 @@ public class StepBuilderFactory { } /** - * Creates a step builder and initializes its job repository and transaction manager. Note that if the builder is - * used to create a @Bean definition then the name of the step and the bean name might be different. - * + * Creates a step builder and initializes its job repository and transaction manager. + * Note that if the builder is used to create a @Bean definition then the name of + * the step and the bean name might be different. * @param name the name of the step * @return a step builder */ public StepBuilder get(String name) { - return new StepBuilder(name) - .repository(this.jobRepository) - .transactionManager(this.transactionManager); + return new StepBuilder(name).repository(this.jobRepository).transactionManager(this.transactionManager); } } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/StepScope.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/StepScope.java index 893e82ee2..b6c1f5a88 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/StepScope.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/StepScope.java @@ -24,9 +24,10 @@ import java.lang.annotation.RetentionPolicy; /** *

- * Convenient annotation for step scoped beans that defaults the proxy mode, so that it doesn't have to be specified - * explicitly on every bean definition. Use this on any @Bean that needs to inject @Values from the step - * context, and any bean that needs to share a lifecycle with a step execution (e.g. an ItemStream). E.g. + * Convenient annotation for step scoped beans that defaults the proxy mode, so that it + * doesn't have to be specified explicitly on every bean definition. Use this on any + * @Bean that needs to inject @Values from the step context, and any bean that + * needs to share a lifecycle with a step execution (e.g. an ItemStream). E.g. *

* *
@@ -38,7 +39,10 @@ import java.lang.annotation.RetentionPolicy;
  * }
  * 
* - *

Marking a @Bean as @StepScope is equivalent to marking it as @Scope(value="step", proxyMode=TARGET_CLASS)

+ *

+ * Marking a @Bean as @StepScope is equivalent to marking it as + * @Scope(value="step", proxyMode=TARGET_CLASS) + *

* * @author Dave Syer * diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/AbstractApplicationContextFactory.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/AbstractApplicationContextFactory.java index e26a20ef1..3b087c5a8 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/AbstractApplicationContextFactory.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/AbstractApplicationContextFactory.java @@ -41,10 +41,12 @@ import org.springframework.util.Assert; import org.springframework.util.ClassUtils; /** - * {@link ApplicationContextFactory} implementation that takes a parent context and a path to the context to create. - * When createApplicationContext method is called, the child {@link ApplicationContext} will be returned. The child - * context is not re-created every time it is requested, it is lazily initialized and cached. Clients should ensure that - * it is closed when it is no longer needed. If a path is not set, the parent will always be returned. + * {@link ApplicationContextFactory} implementation that takes a parent context and a path + * to the context to create. When createApplicationContext method is called, the child + * {@link ApplicationContext} will be returned. The child context is not re-created every + * time it is requested, it is lazily initialized and cached. Clients should ensure that + * it is closed when it is no longer needed. If a path is not set, the parent will always + * be returned. * */ public abstract class AbstractApplicationContextFactory implements ApplicationContextFactory, ApplicationContextAware { @@ -62,9 +64,8 @@ public abstract class AbstractApplicationContextFactory implements ApplicationCo private Collection> beanPostProcessorExcludeClasses; /** - * Create a factory instance with the resource specified. The resources are Spring configuration files or java - * packages containing configuration files. - * + * Create a factory instance with the resource specified. The resources are Spring + * configuration files or java packages containing configuration files. * @param resource resource to be used in the creation of the ApplicationContext. */ public AbstractApplicationContextFactory(Object... resource) { @@ -75,17 +76,18 @@ public abstract class AbstractApplicationContextFactory implements ApplicationCo beanFactoryPostProcessorClasses.add(CustomEditorConfigurer.class); beanPostProcessorExcludeClasses = new ArrayList<>(); /* - * Assume that a BeanPostProcessor that is BeanFactoryAware must be specific to the parent and remove it from - * the child (e.g. an AutoProxyCreator will not work properly). Unfortunately there might still be a a - * BeanPostProcessor with a dependency that itself is BeanFactoryAware, but we can't legislate for that here. + * Assume that a BeanPostProcessor that is BeanFactoryAware must be specific to + * the parent and remove it from the child (e.g. an AutoProxyCreator will not work + * properly). Unfortunately there might still be a a BeanPostProcessor with a + * dependency that itself is BeanFactoryAware, but we can't legislate for that + * here. */ beanPostProcessorExcludeClasses.add(BeanFactoryAware.class); } /** - * Flag to indicate that configuration such as bean post processors and custom editors should be copied from the - * parent context. Defaults to true. - * + * Flag to indicate that configuration such as bean post processors and custom editors + * should be copied from the parent context. Defaults to true. * @param copyConfiguration the flag value to set */ public void setCopyConfiguration(boolean copyConfiguration) { @@ -93,9 +95,8 @@ public abstract class AbstractApplicationContextFactory implements ApplicationCo } /** - * Protected access for subclasses to the flag determining whether configuration should be copied from parent - * context. - * + * Protected access for subclasses to the flag determining whether configuration + * should be copied from parent context. * @return the flag value */ protected final boolean isCopyConfiguration() { @@ -103,9 +104,9 @@ public abstract class AbstractApplicationContextFactory implements ApplicationCo } /** - * Determines which bean factory post processors (like property placeholders) should be copied from the parent - * context. Defaults to {@link PropertySourcesPlaceholderConfigurer} and {@link CustomEditorConfigurer}. - * + * Determines which bean factory post processors (like property placeholders) should + * be copied from the parent context. Defaults to + * {@link PropertySourcesPlaceholderConfigurer} and {@link CustomEditorConfigurer}. * @param beanFactoryPostProcessorClasses array of post processor types to be copied */ @@ -118,11 +119,11 @@ public abstract class AbstractApplicationContextFactory implements ApplicationCo } /** - * Determines by exclusion which bean post processors should be copied from the parent context. Defaults to - * {@link BeanFactoryAware} (so any post processors that have a reference to the parent bean factory are not copied - * into the child). Note that these classes do not themselves have to be {@link BeanPostProcessor} implementations - * or sub-interfaces. - * + * Determines by exclusion which bean post processors should be copied from the parent + * context. Defaults to {@link BeanFactoryAware} (so any post processors that have a + * reference to the parent bean factory are not copied into the child). Note that + * these classes do not themselves have to be {@link BeanPostProcessor} + * implementations or sub-interfaces. * @param beanPostProcessorExcludeClasses the classes to set */ public void setBeanPostProcessorExcludeClasses(Class[] beanPostProcessorExcludeClasses) { @@ -134,9 +135,8 @@ public abstract class AbstractApplicationContextFactory implements ApplicationCo } /** - * Protected access to the list of bean factory post processor classes that should be copied over to the context - * from the parent. - * + * Protected access to the list of bean factory post processor classes that should be + * copied over to the context from the parent. * @return the classes for post processors that were nominated for copying */ protected final Collection> getBeanFactoryPostProcessorClasses() { @@ -177,11 +177,11 @@ public abstract class AbstractApplicationContextFactory implements ApplicationCo Object... resources); /** - * Extension point for special subclasses that want to do more complex things with the context prior to refresh. The - * default implementation does nothing. - * + * Extension point for special subclasses that want to do more complex things with the + * context prior to refresh. The default implementation does nothing. * @param parent the parent for the new application context - * @param context the new application context before it is refreshed, but after bean factory is initialized + * @param context the new application context before it is refreshed, but after bean + * factory is initialized * * @see AbstractApplicationContextFactory#setBeanFactoryPostProcessorClasses(Class[]) */ @@ -189,10 +189,9 @@ public abstract class AbstractApplicationContextFactory implements ApplicationCo } /** - * Extension point for special subclasses that want to do more complex things with the bean factory prior to - * refresh. The default implementation copies all configuration from the parent according to the - * {@link #setCopyConfiguration(boolean) flag} set. - * + * Extension point for special subclasses that want to do more complex things with the + * bean factory prior to refresh. The default implementation copies all configuration + * from the parent according to the {@link #setCopyConfiguration(boolean) flag} set. * @param parent the parent bean factory for the new context (will never be null) * @param beanFactory the new bean factory before bean definitions are loaded * @@ -205,15 +204,15 @@ public abstract class AbstractApplicationContextFactory implements ApplicationCo List parentPostProcessors = new ArrayList<>(); List childPostProcessors = new ArrayList<>(); - childPostProcessors.addAll(beanFactory instanceof AbstractBeanFactory ? ((AbstractBeanFactory) beanFactory) - .getBeanPostProcessors() : new ArrayList<>()); - parentPostProcessors.addAll(parent instanceof AbstractBeanFactory ? ((AbstractBeanFactory) parent) - .getBeanPostProcessors() : new ArrayList<>()); + childPostProcessors.addAll(beanFactory instanceof AbstractBeanFactory + ? ((AbstractBeanFactory) beanFactory).getBeanPostProcessors() : new ArrayList<>()); + parentPostProcessors.addAll(parent instanceof AbstractBeanFactory + ? ((AbstractBeanFactory) parent).getBeanPostProcessors() : new ArrayList<>()); try { - Class applicationContextAwareProcessorClass = - ClassUtils.forName("org.springframework.context.support.ApplicationContextAwareProcessor", - parent.getBeanClassLoader()); + Class applicationContextAwareProcessorClass = ClassUtils.forName( + "org.springframework.context.support.ApplicationContextAwareProcessor", + parent.getBeanClassLoader()); for (BeanPostProcessor beanPostProcessor : new ArrayList<>(parentPostProcessors)) { if (applicationContextAwareProcessorClass.isAssignableFrom(beanPostProcessor.getClass())) { @@ -243,8 +242,8 @@ public abstract class AbstractApplicationContextFactory implements ApplicationCo beanFactory.copyConfigurationFrom(parent); - List beanPostProcessors = beanFactory instanceof AbstractBeanFactory ? ((AbstractBeanFactory) beanFactory) - .getBeanPostProcessors() : new ArrayList<>(); + List beanPostProcessors = beanFactory instanceof AbstractBeanFactory + ? ((AbstractBeanFactory) beanFactory).getBeanPostProcessors() : new ArrayList<>(); beanPostProcessors.clear(); beanPostProcessors.addAll(aggregatedPostProcessors); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ApplicationContextFactory.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ApplicationContextFactory.java index af862552b..1cab43fef 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ApplicationContextFactory.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ApplicationContextFactory.java @@ -21,14 +21,13 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.ConfigurableApplicationContext; /** - * Factory for the creation of {@link ApplicationContext}s. This interface - * is primarily useful when creating a new {@link ApplicationContext} per - * execution of a {@link Job}. - * + * Factory for the creation of {@link ApplicationContext}s. This interface is primarily + * useful when creating a new {@link ApplicationContext} per execution of a {@link Job}. + * * @author Lucas Ward */ public interface ApplicationContextFactory { ConfigurableApplicationContext createApplicationContext(); - + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ApplicationContextJobFactory.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ApplicationContextJobFactory.java index 0efb7189e..34b486e92 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ApplicationContextJobFactory.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ApplicationContextJobFactory.java @@ -21,8 +21,8 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.ConfigurableApplicationContext; /** - * A {@link JobFactory} that creates its own {@link ApplicationContext} and - * pulls a bean out when asked to create a {@link Job}. + * A {@link JobFactory} that creates its own {@link ApplicationContext} and pulls a bean + * out when asked to create a {@link Job}. * * @author Dave Syer * @@ -32,10 +32,9 @@ public class ApplicationContextJobFactory implements JobFactory { private final Job job; /** - * @param jobName the id of the {@link Job} in the application context to be - * created - * @param applicationContextFactory a factory for an application context - * containing a job with the job name provided + * @param jobName the id of the {@link Job} in the application context to be created + * @param applicationContextFactory a factory for an application context containing a + * job with the job name provided */ public ApplicationContextJobFactory(String jobName, ApplicationContextFactory applicationContextFactory) { @SuppressWarnings("resource") @@ -44,8 +43,8 @@ public class ApplicationContextJobFactory implements JobFactory { } /** - * Create an {@link ApplicationContext} from the factory provided and pull - * out a bean with the name given during initialization. + * Create an {@link ApplicationContext} from the factory provided and pull out a bean + * with the name given during initialization. * * @see org.springframework.batch.core.configuration.JobFactory#createJob() */ diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/AutomaticJobRegistrar.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/AutomaticJobRegistrar.java index 2c6412755..e1da66ab1 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/AutomaticJobRegistrar.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/AutomaticJobRegistrar.java @@ -32,18 +32,17 @@ import org.springframework.core.Ordered; import org.springframework.util.Assert; /** - * Loads and unloads {@link Job Jobs} when the application context is created and destroyed. Each resource provided is - * loaded as an application context with the current context as its parent, and then all the jobs from the child context - * are registered under their bean names. A {@link JobRegistry} is required. + * Loads and unloads {@link Job Jobs} when the application context is created and + * destroyed. Each resource provided is loaded as an application context with the current + * context as its parent, and then all the jobs from the child context are registered + * under their bean names. A {@link JobRegistry} is required. * * @author Lucas Ward * @author Dave Syer * @author Mahmoud Ben Hassine - * * @since 2.1 */ -public class AutomaticJobRegistrar implements Ordered, SmartLifecycle, ApplicationContextAware, - InitializingBean { +public class AutomaticJobRegistrar implements Ordered, SmartLifecycle, ApplicationContextAware, InitializingBean { private Collection applicationContextFactories = new ArrayList<>(); @@ -62,9 +61,8 @@ public class AutomaticJobRegistrar implements Ordered, SmartLifecycle, Applicati private int order = Ordered.LOWEST_PRECEDENCE; /** - * The enclosing application context, which can be used to check if {@link ApplicationContextEvent events} come - * from the expected source. - * + * The enclosing application context, which can be used to check if + * {@link ApplicationContextEvent events} come from the expected source. * @param applicationContext the enclosing application context if there is one * @see ApplicationContextAware#setApplicationContext(ApplicationContext) */ @@ -75,8 +73,8 @@ public class AutomaticJobRegistrar implements Ordered, SmartLifecycle, Applicati /** * Add some factories to the set that will be used to load contexts and jobs. - * - * @param applicationContextFactory the {@link ApplicationContextFactory} values to use + * @param applicationContextFactory the {@link ApplicationContextFactory} values to + * use */ public void addApplicationContextFactory(ApplicationContextFactory applicationContextFactory) { if (applicationContextFactory instanceof ApplicationContextAware) { @@ -87,8 +85,8 @@ public class AutomaticJobRegistrar implements Ordered, SmartLifecycle, Applicati /** * Add some factories to the set that will be used to load contexts and jobs. - * - * @param applicationContextFactories the {@link ApplicationContextFactory} values to use + * @param applicationContextFactories the {@link ApplicationContextFactory} values to + * use */ public void setApplicationContextFactories(ApplicationContextFactory[] applicationContextFactories) { for (ApplicationContextFactory applicationContextFactory : applicationContextFactories) { @@ -98,7 +96,6 @@ public class AutomaticJobRegistrar implements Ordered, SmartLifecycle, Applicati /** * The job loader that will be used to load and manage jobs. - * * @param jobLoader the {@link JobLoader} to set */ public void setJobLoader(JobLoader jobLoader) { @@ -142,7 +139,8 @@ public class AutomaticJobRegistrar implements Ordered, SmartLifecycle, Applicati } /** - * Take all the contexts from the factories provided and pass them to the {@link JobLoader}. + * Take all the contexts from the factories provided and pass them to the + * {@link JobLoader}. * * @see Lifecycle#start() */ @@ -166,7 +164,6 @@ public class AutomaticJobRegistrar implements Ordered, SmartLifecycle, Applicati /** * Check if this component has been started. - * * @return true if started successfully and not stopped * @see Lifecycle#isRunning() */ diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ClasspathXmlApplicationContextsFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ClasspathXmlApplicationContextsFactoryBean.java index 2c94fe92b..38696035e 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ClasspathXmlApplicationContextsFactoryBean.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ClasspathXmlApplicationContextsFactoryBean.java @@ -30,14 +30,15 @@ import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; import org.springframework.core.io.Resource; /** - * A convenient factory for creating a set of {@link ApplicationContextFactory} - * components from a set of {@link Resource resources}. + * A convenient factory for creating a set of {@link ApplicationContextFactory} components + * from a set of {@link Resource resources}. * * @author Dave Syer * @author Mahmoud Ben Hassine * */ -public class ClasspathXmlApplicationContextsFactoryBean implements FactoryBean, ApplicationContextAware { +public class ClasspathXmlApplicationContextsFactoryBean + implements FactoryBean, ApplicationContextAware { private List resources = new ArrayList<>(); @@ -50,13 +51,10 @@ public class ClasspathXmlApplicationContextsFactoryBean implements FactoryBeanclasspath*:/config/*-context.xml). - * + * A set of resources to load using a {@link GenericApplicationContextFactory}. Each + * resource should be a Spring configuration file which is loaded into an application + * context whose parent is the current context. In a configuration file the resources + * can be given as a pattern (e.g. classpath*:/config/*-context.xml). * @param resources array of resources to use */ public void setResources(Resource[] resources) { @@ -64,10 +62,8 @@ public class ClasspathXmlApplicationContextsFactoryBean implements FactoryBean[] beanPostProcessorExcludeClasses) { @@ -101,9 +95,8 @@ public class ClasspathXmlApplicationContextsFactoryBean implements FactoryBean contexts = new ConcurrentHashMap<>(); @@ -68,7 +69,6 @@ public class DefaultJobLoader implements JobLoader, InitializingBean { /** * Creates a job loader with the job registry provided. - * * @param jobRegistry a {@link JobRegistry} */ public DefaultJobLoader(JobRegistry jobRegistry) { @@ -77,7 +77,6 @@ public class DefaultJobLoader implements JobLoader, InitializingBean { /** * Creates a job loader with the job and step registries provided. - * * @param jobRegistry a {@link JobRegistry} * @param stepRegistry a {@link StepRegistry} (can be {@code null}) */ @@ -88,7 +87,6 @@ public class DefaultJobLoader implements JobLoader, InitializingBean { /** * The {@link JobRegistry} to use for jobs created. - * * @param jobRegistry the job registry */ public void setJobRegistry(JobRegistry jobRegistry) { @@ -97,7 +95,6 @@ public class DefaultJobLoader implements JobLoader, InitializingBean { /** * The {@link StepRegistry} to use for the steps of created jobs. - * * @param stepRegistry the step registry */ public void setStepRegistry(StepRegistry stepRegistry) { @@ -105,8 +102,7 @@ public class DefaultJobLoader implements JobLoader, InitializingBean { } /** - * Unregister all the jobs and close all the contexts created by this - * loader. + * Unregister all the jobs and close all the contexts created by this loader. * * @see JobLoader#clear() */ @@ -217,11 +213,10 @@ public class DefaultJobLoader implements JobLoader, InitializingBean { } /** - * Returns all the {@link Step} instances defined by the specified {@link StepLocator}. - *
- * The specified jobApplicationContext is used to collect additional steps that - * are not exposed by the step locator - * + * Returns all the {@link Step} instances defined by the specified + * {@link StepLocator}.
+ * The specified jobApplicationContext is used to collect additional steps + * that are not exposed by the step locator * @param stepLocator the given step locator * @param jobApplicationContext the application context of the job * @return all the {@link Step} defined by the given step locator and context @@ -234,8 +229,10 @@ public class DefaultJobLoader implements JobLoader, InitializingBean { result.add(stepLocator.getStep(stepName)); } - // Because some steps are referenced by name, we need to look in the context to see if there - // are more Step instances defined. Right now they are registered as being available in the + // Because some steps are referenced by name, we need to look in the context to + // see if there + // are more Step instances defined. Right now they are registered as being + // available in the // context of the job but we have no idea if they are linked to that Job or not. final Map allSteps = jobApplicationContext.getBeansOfType(Step.class); for (Map.Entry entry : allSteps.entrySet()) { @@ -247,10 +244,9 @@ public class DefaultJobLoader implements JobLoader, InitializingBean { } /** - * Registers the specified {@link Job} defined in the specified {@link ConfigurableApplicationContext}. - *
+ * Registers the specified {@link Job} defined in the specified + * {@link ConfigurableApplicationContext}.
* Makes sure to update the {@link StepRegistry} if it is available. - * * @param context the context in which the job is defined * @param job the job to register * @throws DuplicateJobException if that job is already registered @@ -270,10 +266,9 @@ public class DefaultJobLoader implements JobLoader, InitializingBean { /** * Unregisters the job identified by the specified jobName. - * * @param jobName the name of the job to unregister */ - private void doUnregister(String jobName) { + private void doUnregister(String jobName) { jobRegistry.unregister(jobName); if (stepRegistry != null) { stepRegistry.unregisterStepsFromJob(jobName); @@ -285,4 +280,5 @@ public class DefaultJobLoader implements JobLoader, InitializingBean { public void afterPropertiesSet() { Assert.notNull(jobRegistry, "Job registry could not be null."); } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/GenericApplicationContextFactory.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/GenericApplicationContextFactory.java index 4fd69ea6a..6e263c100 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/GenericApplicationContextFactory.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/GenericApplicationContextFactory.java @@ -34,28 +34,31 @@ import java.util.Arrays; import java.util.List; /** - * {@link ApplicationContextFactory} implementation that takes a parent context and a path to the context to create. - * When createApplicationContext method is called, the child {@link ApplicationContext} will be returned. The child - * context is not re-created every time it is requested, it is lazily initialized and cached. Clients should ensure that + * {@link ApplicationContextFactory} implementation that takes a parent context and a path + * to the context to create. When createApplicationContext method is called, the child + * {@link ApplicationContext} will be returned. The child context is not re-created every + * time it is requested, it is lazily initialized and cached. Clients should ensure that * it is closed when it is no longer needed. - * + * */ public class GenericApplicationContextFactory extends AbstractApplicationContextFactory { /** - * Create an application context factory for the resource specified. The resource can be an actual {@link Resource}, - * in which case it will be interpreted as an XML file, or it can be a @Configuration class, or a package name. - * All types must be the same (mixing XML with a java package for example is not allowed and will result in an - * {@link java.lang.IllegalArgumentException}). - * - * @param resources some resources (XML configuration files, @Configuration classes or java packages to scan) + * Create an application context factory for the resource specified. The resource can + * be an actual {@link Resource}, in which case it will be interpreted as an XML file, + * or it can be a @Configuration class, or a package name. All types must be the + * same (mixing XML with a java package for example is not allowed and will result in + * an {@link java.lang.IllegalArgumentException}). + * @param resources some resources (XML configuration files, @Configuration + * classes or java packages to scan) */ public GenericApplicationContextFactory(Object... resources) { super(resources); } /** - * @see AbstractApplicationContextFactory#createApplicationContext(ConfigurableApplicationContext, Object...) + * @see AbstractApplicationContextFactory#createApplicationContext(ConfigurableApplicationContext, + * Object...) */ @Override protected ConfigurableApplicationContext createApplicationContext(ConfigurableApplicationContext parent, @@ -63,23 +66,26 @@ public class GenericApplicationContextFactory extends AbstractApplicationContext ConfigurableApplicationContext context; if (allObjectsOfType(resources, Resource.class)) { - context = new ResourceXmlApplicationContext(parent, resources); - } else if (allObjectsOfType(resources, Class.class)) { - context = new ResourceAnnotationApplicationContext(parent, resources); - } else if (allObjectsOfType(resources, String.class)) { - context = new ResourceAnnotationApplicationContext(parent, resources); - } else { + context = new ResourceXmlApplicationContext(parent, resources); + } + else if (allObjectsOfType(resources, Class.class)) { + context = new ResourceAnnotationApplicationContext(parent, resources); + } + else if (allObjectsOfType(resources, String.class)) { + context = new ResourceAnnotationApplicationContext(parent, resources); + } + else { List> types = new ArrayList<>(); for (Object resource : resources) { types.add(resource.getClass()); } - throw new IllegalArgumentException("No application context could be created for resource types: " - + Arrays.toString(types.toArray())); + throw new IllegalArgumentException( + "No application context could be created for resource types: " + Arrays.toString(types.toArray())); } return context; } - + private boolean allObjectsOfType(Object[] objects, Class type) { for (Object object : objects) { if (!type.isInstance(object)) { @@ -140,29 +146,32 @@ public class GenericApplicationContextFactory extends AbstractApplicationContext class ResourceXmlApplicationContextHelper extends ApplicationContextHelper { - ResourceXmlApplicationContextHelper(ConfigurableApplicationContext parent, GenericApplicationContext context, Object... config) { + ResourceXmlApplicationContextHelper(ConfigurableApplicationContext parent, + GenericApplicationContext context, Object... config) { super(parent, context, config); } @Override protected String generateId(Object... configs) { Resource[] resources = Arrays.copyOfRange(configs, 0, configs.length, Resource[].class); - try { - List uris = new ArrayList<>(); - for (Resource resource : resources) { - uris.add(resource.getURI().toString()); - } - return StringUtils.collectionToCommaDelimitedString(uris); - } - catch (IOException e) { - return Arrays.toString(resources); - } + try { + List uris = new ArrayList<>(); + for (Resource resource : resources) { + uris.add(resource.getURI().toString()); + } + return StringUtils.collectionToCommaDelimitedString(uris); + } + catch (IOException e) { + return Arrays.toString(resources); + } } + @Override protected void loadConfiguration(Object... configs) { Resource[] resources = Arrays.copyOfRange(configs, 0, configs.length, Resource[].class); load(resources); } + } helper = new ResourceXmlApplicationContextHelper(parent, this, resources); refresh(); @@ -189,7 +198,8 @@ public class GenericApplicationContextFactory extends AbstractApplicationContext class ResourceAnnotationApplicationContextHelper extends ApplicationContextHelper { - public ResourceAnnotationApplicationContextHelper(ConfigurableApplicationContext parent, GenericApplicationContext context, Object... config) { + public ResourceAnnotationApplicationContextHelper(ConfigurableApplicationContext parent, + GenericApplicationContext context, Object... config) { super(parent, context, config); } @@ -207,6 +217,7 @@ public class GenericApplicationContextFactory extends AbstractApplicationContext return Arrays.toString(configs); } } + @Override protected void loadConfiguration(Object... configs) { if (allObjectsOfType(configs, Class.class)) { @@ -218,6 +229,7 @@ public class GenericApplicationContextFactory extends AbstractApplicationContext scan(pkgs); } } + } helper = new ResourceAnnotationApplicationContextHelper(parent, this, resources); refresh(); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/GroupAwareJob.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/GroupAwareJob.java index 3ceb7e157..a5cbbfe0e 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/GroupAwareJob.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/GroupAwareJob.java @@ -23,14 +23,13 @@ import org.springframework.lang.Nullable; import org.springframework.util.ClassUtils; /** - * A {@link Job} that can optionally prepend a group name to another job's name, - * to make it fit a naming convention for type or origin. E.g. the source job - * might be overnightJob and the group - * financeDepartment, which would result in a {@link Job} with - * identical functionality but named financeDepartment.overnightJob - * . The use of a "." separator for elements is deliberate, since it is a "safe" - * character in a
URL. - * + * A {@link Job} that can optionally prepend a group name to another job's name, to make + * it fit a naming convention for type or origin. E.g. the source job might be + * overnightJob and the group financeDepartment, which would + * result in a {@link Job} with identical functionality but named + * financeDepartment.overnightJob . The use of a "." separator for elements + * is deliberate, since it is a "safe" character in a + * URL. * * @author Dave Syer * @author Mahmoud Ben Hassine @@ -39,8 +38,8 @@ import org.springframework.util.ClassUtils; public class GroupAwareJob implements Job { /** - * The separator between group and delegate job names in the final name - * given to this job. + * The separator between group and delegate job names in the final name given to this + * job. */ private static final String SEPARATOR = "."; @@ -50,7 +49,6 @@ public class GroupAwareJob implements Job { /** * Create a new {@link Job} with the delegate and no group name. - * * @param delegate a delegate for the features of a regular Job */ public GroupAwareJob(Job delegate) { @@ -59,7 +57,6 @@ public class GroupAwareJob implements Job { /** * Create a new {@link Job} with the given group name and delegate. - * * @param groupName the group name to prepend (can be {@code null}) * @param delegate a delegate for the features of a regular Job */ @@ -75,14 +72,13 @@ public class GroupAwareJob implements Job { } /** - * Concatenates the group name and the delegate job name (joining with a - * "."). + * Concatenates the group name and the delegate job name (joining with a "."). * * @see org.springframework.batch.core.Job#getName() */ @Override public String getName() { - return groupName==null ? delegate.getName() : groupName + SEPARATOR + delegate.getName(); + return groupName == null ? delegate.getName() : groupName + SEPARATOR + delegate.getName(); } @Override diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobFactoryRegistrationListener.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobFactoryRegistrationListener.java index 9df2959a8..9cf3705ab 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobFactoryRegistrationListener.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobFactoryRegistrationListener.java @@ -24,11 +24,10 @@ import org.springframework.batch.core.configuration.JobFactory; import org.springframework.batch.core.configuration.JobRegistry; /** - * Generic service that can bind and unbind a {@link JobFactory} in a - * {@link JobRegistry}. - * + * Generic service that can bind and unbind a {@link JobFactory} in a {@link JobRegistry}. + * * @author Dave Syer - * + * */ public class JobFactoryRegistrationListener { @@ -37,9 +36,7 @@ public class JobFactoryRegistrationListener { private JobRegistry jobRegistry; /** - * Public setter for a {@link JobRegistry} to use for all the bind and - * unbind events. - * + * Public setter for a {@link JobRegistry} to use for all the bind and unbind events. * @param jobRegistry {@link JobRegistry} */ public void setJobRegistry(JobRegistry jobRegistry) { @@ -47,8 +44,7 @@ public class JobFactoryRegistrationListener { } /** - * Take the {@link JobFactory} provided and register it with the - * {@link JobRegistry}. + * Take the {@link JobFactory} provided and register it with the {@link JobRegistry}. * @param jobFactory a {@link JobFactory} * @param params not needed by this listener. * @throws Exception if there is a problem diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobLoader.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobLoader.java index b997e6237..d0df080c5 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobLoader.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobLoader.java @@ -22,36 +22,30 @@ import org.springframework.batch.core.configuration.DuplicateJobException; /** * @author Dave Syer - * * @since 2.1 */ public interface JobLoader { /** * Load an application context and register all the jobs. - * * @param factory a factory for an application context (containing jobs) * @return a collection of the jobs created - * - * @throws DuplicateJobException if a job with the same name was already - * registered + * @throws DuplicateJobException if a job with the same name was already registered */ Collection load(ApplicationContextFactory factory) throws DuplicateJobException; /** - * Load an application context and register all the jobs, having first - * unregistered them if already registered. Implementations should also take - * care to close and clean up the application context previously created if - * possible (either from this factory or from one with the same jobs). - * + * Load an application context and register all the jobs, having first unregistered + * them if already registered. Implementations should also take care to close and + * clean up the application context previously created if possible (either from this + * factory or from one with the same jobs). * @param factory a factory for an application context (containing jobs) * @return a collection of the jobs created */ Collection reload(ApplicationContextFactory factory); /** - * Unregister all the jobs and close all the contexts created by this - * loader. + * Unregister all the jobs and close all the contexts created by this loader. */ void clear(); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobRegistryBeanPostProcessor.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobRegistryBeanPostProcessor.java index 4eb2a2625..67ff99555 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobRegistryBeanPostProcessor.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/JobRegistryBeanPostProcessor.java @@ -37,15 +37,15 @@ import org.springframework.util.Assert; /** * A {@link BeanPostProcessor} that registers {@link Job} beans with a - * {@link JobRegistry}. Include a bean of this type along with your job - * configuration, and use the same {@link JobRegistry} as a {@link JobLocator} - * when you need to locate a {@link Job} to launch. + * {@link JobRegistry}. Include a bean of this type along with your job configuration, and + * use the same {@link JobRegistry} as a {@link JobLocator} when you need to locate a + * {@link Job} to launch. * * @author Dave Syer * */ -public class JobRegistryBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware, InitializingBean, -DisposableBean { +public class JobRegistryBeanPostProcessor + implements BeanPostProcessor, BeanFactoryAware, InitializingBean, DisposableBean { private static Log logger = LogFactory.getLog(JobRegistryBeanPostProcessor.class); @@ -59,13 +59,11 @@ DisposableBean { private DefaultListableBeanFactory beanFactory; /** - * The group name for jobs registered by this component. Optional (defaults - * to null, which means that jobs are registered with their bean names). - * Useful where there is a hierarchy of application contexts all - * contributing to the same {@link JobRegistry}: child contexts can then - * define an instance with a unique group name to avoid clashes between job - * names. - * + * The group name for jobs registered by this component. Optional (defaults to null, + * which means that jobs are registered with their bean names). Useful where there is + * a hierarchy of application contexts all contributing to the same + * {@link JobRegistry}: child contexts can then define an instance with a unique group + * name to avoid clashes between job names. * @param groupName the groupName to set */ public void setGroupName(String groupName) { @@ -74,7 +72,6 @@ DisposableBean { /** * Injection setter for {@link JobRegistry}. - * * @param jobRegistry the jobConfigurationRegistry to set */ public void setJobRegistry(JobRegistry jobRegistry) { @@ -84,8 +81,7 @@ DisposableBean { /* * (non-Javadoc) * - * @see - * org.springframework.beans.factory.BeanFactoryAware#setBeanFactory(org + * @see org.springframework.beans.factory.BeanFactoryAware#setBeanFactory(org * .springframework.beans.factory.BeanFactory) */ @Override @@ -106,8 +102,8 @@ DisposableBean { } /** - * Unregister all the {@link Job} instances that were registered by this - * post processor. + * Unregister all the {@link Job} instances that were registered by this post + * processor. * @see org.springframework.beans.factory.DisposableBean#destroy() */ @Override @@ -137,7 +133,7 @@ DisposableBean { if (beanFactory != null && beanFactory.containsBean(beanName)) { groupName = getGroupName(beanFactory.getBeanDefinition(beanName), job); } - job = groupName==null ? job : new GroupAwareJob(groupName, job); + job = groupName == null ? job : new GroupAwareJob(groupName, job); ReferenceJobFactory jobFactory = new ReferenceJobFactory(job); String name = jobFactory.getJobName(); if (logger.isDebugEnabled()) { @@ -155,10 +151,9 @@ DisposableBean { } /** - * Determine a group name for the job to be registered. Default - * implementation just returns the {@link #setGroupName(String) groupName} - * configured. Provides an extension point for specialised subclasses. - * + * Determine a group name for the job to be registered. Default implementation just + * returns the {@link #setGroupName(String) groupName} configured. Provides an + * extension point for specialised subclasses. * @param beanDefinition the bean definition for the job * @param job the job * @return a group name for the job (or null if not needed) @@ -177,4 +172,5 @@ DisposableBean { public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/MapJobRegistry.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/MapJobRegistry.java index 590aaa463..3e55bedc0 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/MapJobRegistry.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/MapJobRegistry.java @@ -40,7 +40,8 @@ public class MapJobRegistry implements JobRegistry { /** * The map holding the registered job factories. */ - // The "final" ensures that it is visible and initialized when the constructor resolves. + // The "final" ensures that it is visible and initialized when the constructor + // resolves. private final ConcurrentMap map = new ConcurrentHashMap<>(); @Override @@ -50,8 +51,7 @@ public class MapJobRegistry implements JobRegistry { Assert.notNull(name, "Job configuration must have a name."); JobFactory previousValue = map.putIfAbsent(name, jobFactory); if (previousValue != null) { - throw new DuplicateJobException("A job configuration with this name [" + name - + "] was already registered"); + throw new DuplicateJobException("A job configuration with this name [" + name + "] was already registered"); } } @@ -66,7 +66,8 @@ public class MapJobRegistry implements JobRegistry { JobFactory factory = map.get(name); if (factory == null) { throw new NoSuchJobException("No job configuration with the name [" + name + "] was registered"); - } else { + } + else { return factory.createJob(); } } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/MapStepRegistry.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/MapStepRegistry.java index b54e4ca50..262c6b9e7 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/MapStepRegistry.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/MapStepRegistry.java @@ -44,15 +44,14 @@ public class MapStepRegistry implements StepRegistry { Assert.notNull(jobName, "The job name cannot be null."); Assert.notNull(steps, "The job steps cannot be null."); - final Map jobSteps = new HashMap<>(); for (Step step : steps) { jobSteps.put(step.getName(), step); } final Object previousValue = map.putIfAbsent(jobName, jobSteps); if (previousValue != null) { - throw new DuplicateJobException("A job configuration with this name [" + jobName - + "] was already registered"); + throw new DuplicateJobException( + "A job configuration with this name [" + jobName + "] was already registered"); } } @@ -68,13 +67,15 @@ public class MapStepRegistry implements StepRegistry { Assert.notNull(stepName, "The step name cannot be null."); if (!map.containsKey(jobName)) { throw new NoSuchJobException("No job configuration with the name [" + jobName + "] was registered"); - } else { + } + else { final Map jobSteps = map.get(jobName); if (jobSteps.containsKey(stepName)) { return jobSteps.get(stepName); - } else { - throw new NoSuchStepException("The step called [" + stepName + "] does not exist in the job [" + - jobName + "]"); + } + else { + throw new NoSuchStepException( + "The step called [" + stepName + "] does not exist in the job [" + jobName + "]"); } } } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ReferenceJobFactory.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ReferenceJobFactory.java index 7d8ab4fc0..bb8fda56a 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ReferenceJobFactory.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/ReferenceJobFactory.java @@ -19,8 +19,8 @@ import org.springframework.batch.core.Job; import org.springframework.batch.core.configuration.JobFactory; /** - * A {@link JobFactory} that just keeps a reference to a {@link Job}. It never - * modifies its {@link Job}. + * A {@link JobFactory} that just keeps a reference to a {@link Job}. It never modifies + * its {@link Job}. * * @author Dave Syer * diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractFlowParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractFlowParser.java index 9317edbf0..90283ce9d 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractFlowParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractFlowParser.java @@ -131,10 +131,9 @@ public abstract class AbstractFlowParser extends AbstractSingleBeanDefinitionPar private String jobFactoryRef; /** - * Convenience method for subclasses to set the job factory reference if it - * is available (null is fine, but the quality of error reports is better if - * it is available). - * + * Convenience method for subclasses to set the job factory reference if it is + * available (null is fine, but the quality of error reports is better if it is + * available). * @param jobFactoryRef name of the ref */ protected void setJobFactoryRef(String jobFactoryRef) { @@ -186,9 +185,8 @@ public abstract class AbstractFlowParser extends AbstractSingleBeanDefinitionPar stepExists = true; } else if (nodeName.equals(SPLIT_ELE)) { - stateTransitions.addAll(splitParser - .parse(child, new ParserContext(parserContext.getReaderContext(), parserContext - .getDelegate(), builder.getBeanDefinition()))); + stateTransitions.addAll(splitParser.parse(child, new ParserContext(parserContext.getReaderContext(), + parserContext.getDelegate(), builder.getBeanDefinition()))); stepExists = true; } @@ -203,8 +201,8 @@ public abstract class AbstractFlowParser extends AbstractSingleBeanDefinitionPar String flowName = (String) builder.getRawBeanDefinition().getAttribute("flowName"); if (!stepExists && !StringUtils.hasText(element.getAttribute("parent"))) { - parserContext.getReaderContext().error("The flow [" + flowName + "] must contain at least one step, flow or split", - element); + parserContext.getReaderContext() + .error("The flow [" + flowName + "] must contain at least one step, flow or split", element); } // Ensure that all elements are reachable @@ -224,7 +222,6 @@ public abstract class AbstractFlowParser extends AbstractSingleBeanDefinitionPar /** * Find all of the elements that are pointed to by this element. - * * @param element The parent element * @return a collection of reachable element names */ @@ -253,9 +250,9 @@ public abstract class AbstractFlowParser extends AbstractSingleBeanDefinitionPar /** * Find all of the elements reachable from the startElement. - * * @param startElement name of the element to start from - * @param reachableElementMap Map of elements that can be reached from the startElement + * @param reachableElementMap Map of elements that can be reached from the + * startElement * @param accumulator a collection of reachable element names */ protected void findAllReachableElements(String startElement, Map> reachableElementMap, @@ -277,8 +274,7 @@ public abstract class AbstractFlowParser extends AbstractSingleBeanDefinitionPar * @param stateDef The bean definition for the current state * @param element the <step/gt; element to parse * @return a collection of - * {@link org.springframework.batch.core.job.flow.support.StateTransition} - * references + * {@link org.springframework.batch.core.job.flow.support.StateTransition} references */ public static Collection getNextElements(ParserContext parserContext, BeanDefinition stateDef, Element element) { @@ -287,13 +283,11 @@ public abstract class AbstractFlowParser extends AbstractSingleBeanDefinitionPar /** * @param parserContext the parser context for the bean factory - * @param stepId the id of the current state if it is a step state, null - * otherwise + * @param stepId the id of the current state if it is a step state, null otherwise * @param stateDef The bean definition for the current state * @param element the <step/gt; element to parse * @return a collection of - * {@link org.springframework.batch.core.job.flow.support.StateTransition} - * references + * {@link org.springframework.batch.core.job.flow.support.StateTransition} references */ public static Collection getNextElements(ParserContext parserContext, String stepId, BeanDefinition stateDef, Element element) { @@ -328,9 +322,8 @@ public abstract class AbstractFlowParser extends AbstractSingleBeanDefinitionPar } } else if (hasNextAttribute) { - parserContext.getReaderContext().error( - "The <" + element.getNodeName() + "/> may not contain a '" + NEXT_ATTR - + "' attribute and a transition element", element); + parserContext.getReaderContext().error("The <" + element.getNodeName() + "/> may not contain a '" + + NEXT_ATTR + "' attribute and a transition element", element); } return list; @@ -357,8 +350,7 @@ public abstract class AbstractFlowParser extends AbstractSingleBeanDefinitionPar * @param stateDef The bean definition for the current state * @param parserContext the parser context for the bean factory * @return a collection of - * {@link org.springframework.batch.core.job.flow.support.StateTransition} - * references + * {@link org.springframework.batch.core.job.flow.support.StateTransition} references */ private static Collection parseTransitionElement(Element transitionElement, String stateId, BeanDefinition stateDef, ParserContext parserContext) { @@ -373,24 +365,24 @@ public abstract class AbstractFlowParser extends AbstractSingleBeanDefinitionPar boolean abandon = stateId != null && StringUtils.hasText(restartAttribute) && !restartAttribute.equals(stateId); String exitCodeAttribute = transitionElement.getAttribute(EXIT_CODE_ATTR); - return createTransition(status, onAttribute, nextAttribute, exitCodeAttribute, stateDef, parserContext, abandon); + return createTransition(status, onAttribute, nextAttribute, exitCodeAttribute, stateDef, parserContext, + abandon); } /** * @param status The batch status that this transition will set. Use * BatchStatus.UNKNOWN if not applicable. - * @param on The pattern that this transition should match. Use null for - * "no restriction" (same as "*"). + * @param on The pattern that this transition should match. Use null for "no + * restriction" (same as "*"). * @param next The state to which this transition should go. Use null if not * applicable. - * @param exitCode The exit code that this transition will set. Use null to - * default to batchStatus. + * @param exitCode The exit code that this transition will set. Use null to default to + * batchStatus. * @param stateDef The bean definition for the current state * @param parserContext the parser context for the bean factory * @param abandon the abandon flag to be used by the transition. * @return a collection of - * {@link org.springframework.batch.core.job.flow.support.StateTransition} - * references + * {@link org.springframework.batch.core.job.flow.support.StateTransition} references */ protected static Collection createTransition(FlowExecutionStatus status, String on, String next, String exitCode, BeanDefinition stateDef, ParserContext parserContext, boolean abandon) { @@ -409,8 +401,7 @@ public abstract class AbstractFlowParser extends AbstractSingleBeanDefinitionPar endBuilder.addConstructorArgValue(exitCodeExists ? exitCode : status.getName()); String endName = (status == FlowExecutionStatus.STOPPED ? STOP_ELE - : status == FlowExecutionStatus.FAILED ? FAIL_ELE : END_ELE) - + (endCounter++); + : status == FlowExecutionStatus.FAILED ? FAIL_ELE : END_ELE) + (endCounter++); endBuilder.addConstructorArgValue(endName); endBuilder.addConstructorArgValue(abandon); @@ -456,11 +447,11 @@ public abstract class AbstractFlowParser extends AbstractSingleBeanDefinitionPar /** * Strip the namespace from the element name if it exists. */ - private static String stripNamespace(String elementName){ - if(elementName.startsWith("batch:")){ + private static String stripNamespace(String elementName) { + if (elementName.startsWith("batch:")) { return elementName.substring(6); } - else{ + else { return elementName; } } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractListenerParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractListenerParser.java index 0701cfad9..8b6e93c11 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractListenerParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractListenerParser.java @@ -55,7 +55,8 @@ public abstract class AbstractListenerParser { } public void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { - builder.addPropertyValue("delegate", parseListenerElement(element, parserContext, builder.getRawBeanDefinition())); + builder.addPropertyValue("delegate", + parseListenerElement(element, parserContext, builder.getRawBeanDefinition())); ManagedMap metaDataMap = new ManagedMap<>(); for (String metaDataPropertyName : getMethodNameAttributes()) { @@ -67,7 +68,8 @@ public abstract class AbstractListenerParser { builder.addPropertyValue("metaDataMap", metaDataMap); } - public static BeanMetadataElement parseListenerElement(Element element, ParserContext parserContext, BeanDefinition enclosing) { + public static BeanMetadataElement parseListenerElement(Element element, ParserContext parserContext, + BeanDefinition enclosing) { String listenerRef = element.getAttribute(REF_ATTR); List beanElements = DomUtils.getChildElementsByTagName(element, BEAN_ELE); List refElements = DomUtils.getChildElementsByTagName(element, REF_ELE); @@ -79,8 +81,8 @@ public abstract class AbstractListenerParser { } else if (beanElements.size() == 1) { Element beanElement = beanElements.get(0); - BeanDefinitionHolder beanDefinitionHolder = parserContext.getDelegate().parseBeanDefinitionElement( - beanElement, enclosing); + BeanDefinitionHolder beanDefinitionHolder = parserContext.getDelegate() + .parseBeanDefinitionElement(beanElement, enclosing); parserContext.getDelegate().decorateBeanDefinitionIfRequired(beanElement, beanDefinitionHolder); return beanDefinitionHolder; } @@ -117,8 +119,8 @@ public abstract class AbstractListenerParser { } String id = element.getAttribute(ID_ATTR); - parserContext.getReaderContext().error( - "The <" + element.getTagName() + (StringUtils.hasText(id) ? " id=\"" + id + "\"" : "") + parserContext.getReaderContext() + .error("The <" + element.getTagName() + (StringUtils.hasText(id) ? " id=\"" + id + "\"" : "") + "/> element must have exactly one of: '" + REF_ATTR + "' attribute, <" + BEAN_ELE + "/> attribute, or <" + REF_ELE + "/> element. Found: " + found + ".", element); } @@ -133,7 +135,8 @@ public abstract class AbstractListenerParser { } /** - * @return The {@link Class} for the implementation of {@link AbstractListenerFactoryBean}. + * @return The {@link Class} for the implementation of + * {@link AbstractListenerFactoryBean}. */ protected abstract Class> getBeanClass(); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractStepParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractStepParser.java index 4c3ad681f..d8972ad37 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractStepParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractStepParser.java @@ -1,303 +1,307 @@ -/* - * Copyright 2006-2022 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.configuration.xml; - -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import org.springframework.batch.core.listener.StepListenerMetaData; -import org.springframework.beans.MutablePropertyValues; -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.config.BeanDefinitionHolder; -import org.springframework.beans.factory.config.RuntimeBeanReference; -import org.springframework.beans.factory.config.TypedStringValue; -import org.springframework.beans.factory.support.AbstractBeanDefinition; -import org.springframework.beans.factory.support.BeanDefinitionBuilder; -import org.springframework.beans.factory.support.GenericBeanDefinition; -import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate; -import org.springframework.beans.factory.xml.ParserContext; -import org.springframework.util.StringUtils; -import org.springframework.util.xml.DomUtils; - -/** - * Internal parser for the <step/> elements inside a job. A step element - * references a bean definition for a - * {@link org.springframework.batch.core.Step} and goes on to (optionally) list - * a set of transitions from that step to others with <next on="pattern" - * to="stepName"/>. Used by the {@link JobParser}. - * - * @author Dave Syer - * @author Thomas Risberg - * @author Josh Long - * @see JobParser - * @since 2.0 - */ -public abstract class AbstractStepParser { - - /** - * The ID attribute for the step parser. - */ - protected static final String ID_ATTR = "id"; - - private static final String PARENT_ATTR = "parent"; - - private static final String REF_ATTR = "ref"; - - private static final String ALLOW_START_ATTR = "allow-start-if-complete"; - - private static final String TASKLET_ELE = "tasklet"; - - private static final String PARTITION_ELE = "partition"; - - private static final String JOB_ELE = "job"; - - private static final String JOB_PARAMS_EXTRACTOR_ATTR = "job-parameters-extractor"; - - private static final String JOB_LAUNCHER_ATTR = "job-launcher"; - - private static final String STEP_ATTR = "step"; - - private static final String STEP_ELE = STEP_ATTR; - - private static final String PARTITIONER_ATTR = "partitioner"; - - private static final String AGGREGATOR_ATTR = "aggregator"; - - private static final String HANDLER_ATTR = "handler"; - - private static final String HANDLER_ELE = "handler"; - - private static final String TASK_EXECUTOR_ATTR = "task-executor"; - - private static final String GRID_SIZE_ATTR = "grid-size"; - - private static final String FLOW_ELE = "flow"; - - private static final String JOB_REPO_ATTR = "job-repository"; - - private static final StepListenerParser stepListenerParser = new StepListenerParser(StepListenerMetaData.stepExecutionListenerMetaData()); - - /** - * @param stepElement The <step/> element - * @param parserContext instance of {@link ParserContext}. - * @param jobFactoryRef the reference to the {@link JobParserJobFactoryBean} - * from the enclosing tag. Use 'null' if unknown. - * @return {@link AbstractBeanDefinition} for the stepElement. - */ - protected AbstractBeanDefinition parseStep(Element stepElement, ParserContext parserContext, String jobFactoryRef) { - - BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(); - AbstractBeanDefinition bd = builder.getRawBeanDefinition(); - - // look at all nested elements - NodeList children = stepElement.getChildNodes(); - - for (int i = 0; i < children.getLength(); i++) { - Node nd = children.item(i); - - if (nd instanceof Element) { - Element nestedElement = (Element) nd; - String name = nestedElement.getLocalName(); - - if (TASKLET_ELE.equals(name)) { - boolean stepUnderspecified = CoreNamespaceUtils.isUnderspecified(stepElement); - new TaskletParser().parseTasklet(stepElement, nestedElement, bd, parserContext, stepUnderspecified); - } - else if (FLOW_ELE.equals(name)) { - boolean stepUnderspecified = CoreNamespaceUtils.isUnderspecified(stepElement); - parseFlow(stepElement, nestedElement, bd, parserContext, stepUnderspecified); - } - else if (PARTITION_ELE.equals(name)) { - boolean stepUnderspecified = CoreNamespaceUtils.isUnderspecified(stepElement); - parsePartition(stepElement, nestedElement, bd, parserContext, stepUnderspecified, jobFactoryRef); - } - else if (JOB_ELE.equals(name)) { - boolean stepUnderspecified = CoreNamespaceUtils.isUnderspecified(stepElement); - parseJob(stepElement, nestedElement, bd, parserContext, stepUnderspecified); - } - else if ("description".equals(name)) { - bd.setDescription(nestedElement.getTextContent()); - } - - // nested bean reference/declaration - else { - String ns = nestedElement.getNamespaceURI(); - Object value = null; - boolean skip = false; - - // Spring NS - if ((ns == null && name.equals(BeanDefinitionParserDelegate.BEAN_ELEMENT)) - || ns.equals(BeanDefinitionParserDelegate.BEANS_NAMESPACE_URI)) { - BeanDefinitionHolder holder = parserContext.getDelegate().parseBeanDefinitionElement(nestedElement); - value = parserContext.getDelegate().decorateBeanDefinitionIfRequired(nestedElement, holder); - } - // Spring Batch transitions - else if (ns.equals("http://www.springframework.org/schema/batch")) { - // don't parse - skip = true; - } - // Custom NS - else { - value = parserContext.getDelegate().parseCustomElement(nestedElement); - } - - if (!skip) { - bd.setBeanClass(StepParserStepFactoryBean.class); - bd.setAttribute("isNamespaceStep", true); - builder.addPropertyValue("tasklet", value); - } - } - } - } - - String parentRef = stepElement.getAttribute(PARENT_ATTR); - if (StringUtils.hasText(parentRef)) { - bd.setParentName(parentRef); - } - - String isAbstract = stepElement.getAttribute("abstract"); - if (StringUtils.hasText(isAbstract)) { - bd.setAbstract(Boolean.valueOf(isAbstract)); - } - - String jobRepositoryRef = stepElement.getAttribute(JOB_REPO_ATTR); - if (StringUtils.hasText(jobRepositoryRef)) { - builder.addPropertyReference("jobRepository", jobRepositoryRef); - } - - if (StringUtils.hasText(jobFactoryRef)) { - bd.setAttribute("jobParserJobFactoryBeanRef", jobFactoryRef); - } - - //add the allow parser here - String isAllowStart = stepElement.getAttribute(ALLOW_START_ATTR); - if (StringUtils.hasText(isAllowStart)) { - //check if the value is already set from an inner element - if (!bd.getPropertyValues().contains("allowStartIfComplete")) { - //set the value as a property - bd.getPropertyValues().add("allowStartIfComplete", Boolean.valueOf(isAllowStart)); - }//end if - } - - stepListenerParser.handleListenersElement(stepElement, bd, parserContext); - return bd; - } - - private void parsePartition(Element stepElement, Element partitionElement, AbstractBeanDefinition bd, ParserContext parserContext, boolean stepUnderspecified, String jobFactoryRef ) { - - bd.setBeanClass(StepParserStepFactoryBean.class); - bd.setAttribute("isNamespaceStep", true); - String stepRef = partitionElement.getAttribute(STEP_ATTR); - String partitionerRef = partitionElement.getAttribute(PARTITIONER_ATTR); - String aggregatorRef = partitionElement.getAttribute(AGGREGATOR_ATTR); - String handlerRef = partitionElement.getAttribute(HANDLER_ATTR); - - if (!StringUtils.hasText(partitionerRef)) { - parserContext.getReaderContext().error("You must specify a partitioner", partitionElement); - return; - } - - MutablePropertyValues propertyValues = bd.getPropertyValues(); - - propertyValues.addPropertyValue("partitioner", new RuntimeBeanReference(partitionerRef)); - if (StringUtils.hasText(aggregatorRef)) { - propertyValues.addPropertyValue("stepExecutionAggregator", new RuntimeBeanReference(aggregatorRef)); - } - - boolean customHandler = false; - if (!StringUtils.hasText(handlerRef)) { - Element handlerElement = DomUtils.getChildElementByTagName(partitionElement, HANDLER_ELE); - if (handlerElement != null) { - String taskExecutorRef = handlerElement.getAttribute(TASK_EXECUTOR_ATTR); - if (StringUtils.hasText(taskExecutorRef)) { - propertyValues.addPropertyValue("taskExecutor", new RuntimeBeanReference(taskExecutorRef)); - } - String gridSize = handlerElement.getAttribute(GRID_SIZE_ATTR); - if (StringUtils.hasText(gridSize)) { - propertyValues.addPropertyValue("gridSize", new TypedStringValue(gridSize)); - } - } - } else { - customHandler = true; - BeanDefinition partitionHandler = BeanDefinitionBuilder.genericBeanDefinition().getRawBeanDefinition(); - partitionHandler.setParentName(handlerRef); - propertyValues.addPropertyValue("partitionHandler", partitionHandler); - } - - Element inlineStepElement = DomUtils.getChildElementByTagName(partitionElement, STEP_ELE); - if (inlineStepElement == null && !StringUtils.hasText(stepRef) && !customHandler) { - parserContext.getReaderContext().error("You must specify a step", partitionElement); - return; - } - - if (StringUtils.hasText(stepRef)) { - propertyValues.addPropertyValue("step", new RuntimeBeanReference(stepRef)); - } else if( inlineStepElement!=null) { - AbstractBeanDefinition stepDefinition = parseStep(inlineStepElement, parserContext, jobFactoryRef); - stepDefinition.getPropertyValues().addPropertyValue("name", stepElement.getAttribute(ID_ATTR)); - propertyValues.addPropertyValue("step", stepDefinition ); - } - - } - - private void parseJob(Element stepElement, Element jobElement, AbstractBeanDefinition bd, ParserContext parserContext, boolean stepUnderspecified) { - - bd.setBeanClass(StepParserStepFactoryBean.class); - bd.setAttribute("isNamespaceStep", true); - String jobRef = jobElement.getAttribute(REF_ATTR); - - if (!StringUtils.hasText(jobRef)) { - parserContext.getReaderContext().error("You must specify a job", jobElement); - return; - } - - MutablePropertyValues propertyValues = bd.getPropertyValues(); - propertyValues.addPropertyValue("job", new RuntimeBeanReference(jobRef)); - - String jobParametersExtractor = jobElement.getAttribute(JOB_PARAMS_EXTRACTOR_ATTR); - String jobLauncher = jobElement.getAttribute(JOB_LAUNCHER_ATTR); - - if (StringUtils.hasText(jobParametersExtractor)) { - propertyValues.addPropertyValue("jobParametersExtractor", new RuntimeBeanReference(jobParametersExtractor)); - } - if (StringUtils.hasText(jobLauncher)) { - propertyValues.addPropertyValue("jobLauncher", new RuntimeBeanReference(jobLauncher)); - } - - } - - - private void parseFlow(Element stepElement, Element flowElement, AbstractBeanDefinition bd, - ParserContext parserContext, boolean stepUnderspecified) { - - bd.setBeanClass(StepParserStepFactoryBean.class); - bd.setAttribute("isNamespaceStep", true); - String flowRef = flowElement.getAttribute(PARENT_ATTR); - String idAttribute = stepElement.getAttribute(ID_ATTR); - - BeanDefinition flowDefinition = new GenericBeanDefinition(); - flowDefinition.setParentName(flowRef); - MutablePropertyValues propertyValues = flowDefinition.getPropertyValues(); - if (StringUtils.hasText(idAttribute)) { - propertyValues.addPropertyValue("name", idAttribute); - } - - bd.getPropertyValues().addPropertyValue("flow", flowDefinition); - - } - -} +/* + * Copyright 2006-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.configuration.xml; + +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import org.springframework.batch.core.listener.StepListenerMetaData; +import org.springframework.beans.MutablePropertyValues; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.BeanDefinitionHolder; +import org.springframework.beans.factory.config.RuntimeBeanReference; +import org.springframework.beans.factory.config.TypedStringValue; +import org.springframework.beans.factory.support.AbstractBeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.GenericBeanDefinition; +import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate; +import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.util.StringUtils; +import org.springframework.util.xml.DomUtils; + +/** + * Internal parser for the <step/> elements inside a job. A step element references + * a bean definition for a {@link org.springframework.batch.core.Step} and goes on to + * (optionally) list a set of transitions from that step to others with <next + * on="pattern" to="stepName"/>. Used by the {@link JobParser}. + * + * @author Dave Syer + * @author Thomas Risberg + * @author Josh Long + * @see JobParser + * @since 2.0 + */ +public abstract class AbstractStepParser { + + /** + * The ID attribute for the step parser. + */ + protected static final String ID_ATTR = "id"; + + private static final String PARENT_ATTR = "parent"; + + private static final String REF_ATTR = "ref"; + + private static final String ALLOW_START_ATTR = "allow-start-if-complete"; + + private static final String TASKLET_ELE = "tasklet"; + + private static final String PARTITION_ELE = "partition"; + + private static final String JOB_ELE = "job"; + + private static final String JOB_PARAMS_EXTRACTOR_ATTR = "job-parameters-extractor"; + + private static final String JOB_LAUNCHER_ATTR = "job-launcher"; + + private static final String STEP_ATTR = "step"; + + private static final String STEP_ELE = STEP_ATTR; + + private static final String PARTITIONER_ATTR = "partitioner"; + + private static final String AGGREGATOR_ATTR = "aggregator"; + + private static final String HANDLER_ATTR = "handler"; + + private static final String HANDLER_ELE = "handler"; + + private static final String TASK_EXECUTOR_ATTR = "task-executor"; + + private static final String GRID_SIZE_ATTR = "grid-size"; + + private static final String FLOW_ELE = "flow"; + + private static final String JOB_REPO_ATTR = "job-repository"; + + private static final StepListenerParser stepListenerParser = new StepListenerParser( + StepListenerMetaData.stepExecutionListenerMetaData()); + + /** + * @param stepElement The <step/> element + * @param parserContext instance of {@link ParserContext}. + * @param jobFactoryRef the reference to the {@link JobParserJobFactoryBean} from the + * enclosing tag. Use 'null' if unknown. + * @return {@link AbstractBeanDefinition} for the stepElement. + */ + protected AbstractBeanDefinition parseStep(Element stepElement, ParserContext parserContext, String jobFactoryRef) { + + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(); + AbstractBeanDefinition bd = builder.getRawBeanDefinition(); + + // look at all nested elements + NodeList children = stepElement.getChildNodes(); + + for (int i = 0; i < children.getLength(); i++) { + Node nd = children.item(i); + + if (nd instanceof Element) { + Element nestedElement = (Element) nd; + String name = nestedElement.getLocalName(); + + if (TASKLET_ELE.equals(name)) { + boolean stepUnderspecified = CoreNamespaceUtils.isUnderspecified(stepElement); + new TaskletParser().parseTasklet(stepElement, nestedElement, bd, parserContext, stepUnderspecified); + } + else if (FLOW_ELE.equals(name)) { + boolean stepUnderspecified = CoreNamespaceUtils.isUnderspecified(stepElement); + parseFlow(stepElement, nestedElement, bd, parserContext, stepUnderspecified); + } + else if (PARTITION_ELE.equals(name)) { + boolean stepUnderspecified = CoreNamespaceUtils.isUnderspecified(stepElement); + parsePartition(stepElement, nestedElement, bd, parserContext, stepUnderspecified, jobFactoryRef); + } + else if (JOB_ELE.equals(name)) { + boolean stepUnderspecified = CoreNamespaceUtils.isUnderspecified(stepElement); + parseJob(stepElement, nestedElement, bd, parserContext, stepUnderspecified); + } + else if ("description".equals(name)) { + bd.setDescription(nestedElement.getTextContent()); + } + + // nested bean reference/declaration + else { + String ns = nestedElement.getNamespaceURI(); + Object value = null; + boolean skip = false; + + // Spring NS + if ((ns == null && name.equals(BeanDefinitionParserDelegate.BEAN_ELEMENT)) + || ns.equals(BeanDefinitionParserDelegate.BEANS_NAMESPACE_URI)) { + BeanDefinitionHolder holder = parserContext.getDelegate() + .parseBeanDefinitionElement(nestedElement); + value = parserContext.getDelegate().decorateBeanDefinitionIfRequired(nestedElement, holder); + } + // Spring Batch transitions + else if (ns.equals("http://www.springframework.org/schema/batch")) { + // don't parse + skip = true; + } + // Custom NS + else { + value = parserContext.getDelegate().parseCustomElement(nestedElement); + } + + if (!skip) { + bd.setBeanClass(StepParserStepFactoryBean.class); + bd.setAttribute("isNamespaceStep", true); + builder.addPropertyValue("tasklet", value); + } + } + } + } + + String parentRef = stepElement.getAttribute(PARENT_ATTR); + if (StringUtils.hasText(parentRef)) { + bd.setParentName(parentRef); + } + + String isAbstract = stepElement.getAttribute("abstract"); + if (StringUtils.hasText(isAbstract)) { + bd.setAbstract(Boolean.valueOf(isAbstract)); + } + + String jobRepositoryRef = stepElement.getAttribute(JOB_REPO_ATTR); + if (StringUtils.hasText(jobRepositoryRef)) { + builder.addPropertyReference("jobRepository", jobRepositoryRef); + } + + if (StringUtils.hasText(jobFactoryRef)) { + bd.setAttribute("jobParserJobFactoryBeanRef", jobFactoryRef); + } + + // add the allow parser here + String isAllowStart = stepElement.getAttribute(ALLOW_START_ATTR); + if (StringUtils.hasText(isAllowStart)) { + // check if the value is already set from an inner element + if (!bd.getPropertyValues().contains("allowStartIfComplete")) { + // set the value as a property + bd.getPropertyValues().add("allowStartIfComplete", Boolean.valueOf(isAllowStart)); + } // end if + } + + stepListenerParser.handleListenersElement(stepElement, bd, parserContext); + return bd; + } + + private void parsePartition(Element stepElement, Element partitionElement, AbstractBeanDefinition bd, + ParserContext parserContext, boolean stepUnderspecified, String jobFactoryRef) { + + bd.setBeanClass(StepParserStepFactoryBean.class); + bd.setAttribute("isNamespaceStep", true); + String stepRef = partitionElement.getAttribute(STEP_ATTR); + String partitionerRef = partitionElement.getAttribute(PARTITIONER_ATTR); + String aggregatorRef = partitionElement.getAttribute(AGGREGATOR_ATTR); + String handlerRef = partitionElement.getAttribute(HANDLER_ATTR); + + if (!StringUtils.hasText(partitionerRef)) { + parserContext.getReaderContext().error("You must specify a partitioner", partitionElement); + return; + } + + MutablePropertyValues propertyValues = bd.getPropertyValues(); + + propertyValues.addPropertyValue("partitioner", new RuntimeBeanReference(partitionerRef)); + if (StringUtils.hasText(aggregatorRef)) { + propertyValues.addPropertyValue("stepExecutionAggregator", new RuntimeBeanReference(aggregatorRef)); + } + + boolean customHandler = false; + if (!StringUtils.hasText(handlerRef)) { + Element handlerElement = DomUtils.getChildElementByTagName(partitionElement, HANDLER_ELE); + if (handlerElement != null) { + String taskExecutorRef = handlerElement.getAttribute(TASK_EXECUTOR_ATTR); + if (StringUtils.hasText(taskExecutorRef)) { + propertyValues.addPropertyValue("taskExecutor", new RuntimeBeanReference(taskExecutorRef)); + } + String gridSize = handlerElement.getAttribute(GRID_SIZE_ATTR); + if (StringUtils.hasText(gridSize)) { + propertyValues.addPropertyValue("gridSize", new TypedStringValue(gridSize)); + } + } + } + else { + customHandler = true; + BeanDefinition partitionHandler = BeanDefinitionBuilder.genericBeanDefinition().getRawBeanDefinition(); + partitionHandler.setParentName(handlerRef); + propertyValues.addPropertyValue("partitionHandler", partitionHandler); + } + + Element inlineStepElement = DomUtils.getChildElementByTagName(partitionElement, STEP_ELE); + if (inlineStepElement == null && !StringUtils.hasText(stepRef) && !customHandler) { + parserContext.getReaderContext().error("You must specify a step", partitionElement); + return; + } + + if (StringUtils.hasText(stepRef)) { + propertyValues.addPropertyValue("step", new RuntimeBeanReference(stepRef)); + } + else if (inlineStepElement != null) { + AbstractBeanDefinition stepDefinition = parseStep(inlineStepElement, parserContext, jobFactoryRef); + stepDefinition.getPropertyValues().addPropertyValue("name", stepElement.getAttribute(ID_ATTR)); + propertyValues.addPropertyValue("step", stepDefinition); + } + + } + + private void parseJob(Element stepElement, Element jobElement, AbstractBeanDefinition bd, + ParserContext parserContext, boolean stepUnderspecified) { + + bd.setBeanClass(StepParserStepFactoryBean.class); + bd.setAttribute("isNamespaceStep", true); + String jobRef = jobElement.getAttribute(REF_ATTR); + + if (!StringUtils.hasText(jobRef)) { + parserContext.getReaderContext().error("You must specify a job", jobElement); + return; + } + + MutablePropertyValues propertyValues = bd.getPropertyValues(); + propertyValues.addPropertyValue("job", new RuntimeBeanReference(jobRef)); + + String jobParametersExtractor = jobElement.getAttribute(JOB_PARAMS_EXTRACTOR_ATTR); + String jobLauncher = jobElement.getAttribute(JOB_LAUNCHER_ATTR); + + if (StringUtils.hasText(jobParametersExtractor)) { + propertyValues.addPropertyValue("jobParametersExtractor", new RuntimeBeanReference(jobParametersExtractor)); + } + if (StringUtils.hasText(jobLauncher)) { + propertyValues.addPropertyValue("jobLauncher", new RuntimeBeanReference(jobLauncher)); + } + + } + + private void parseFlow(Element stepElement, Element flowElement, AbstractBeanDefinition bd, + ParserContext parserContext, boolean stepUnderspecified) { + + bd.setBeanClass(StepParserStepFactoryBean.class); + bd.setAttribute("isNamespaceStep", true); + String flowRef = flowElement.getAttribute(PARENT_ATTR); + String idAttribute = stepElement.getAttribute(ID_ATTR); + + BeanDefinition flowDefinition = new GenericBeanDefinition(); + flowDefinition.setParentName(flowRef); + MutablePropertyValues propertyValues = flowDefinition.getPropertyValues(); + if (StringUtils.hasText(idAttribute)) { + propertyValues.addPropertyValue("name", idAttribute); + } + + bd.getPropertyValues().addPropertyValue("flow", flowDefinition); + + } + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/BeanDefinitionUtils.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/BeanDefinitionUtils.java index 33efd7903..336bd4396 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/BeanDefinitionUtils.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/BeanDefinitionUtils.java @@ -1,49 +1,52 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.configuration.xml; - -import org.springframework.beans.PropertyValue; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; - -/** - * @author Dan Garrette - * @since 2.0.1 - */ -public class BeanDefinitionUtils { - - /** - * @param beanName a bean definition name - * @param propertyName the name of the property - * @param beanFactory a {@link BeanFactory} - * @return The {@link PropertyValue} for the property of the bean. Search - * parent hierarchy if necessary. Return null if none is found. - */ - public static PropertyValue getPropertyValue(String beanName, String propertyName, ConfigurableListableBeanFactory beanFactory) { - return beanFactory.getMergedBeanDefinition(beanName).getPropertyValues().getPropertyValue(propertyName); - } - - /** - * @param beanName a bean definition name - * @param attributeName the name of the property - * @param beanFactory a {@link BeanFactory} - * @return The value for the attribute of the bean. Search parent hierarchy - * if necessary. Return null if none is found. - */ - public static Object getAttribute(String beanName, String attributeName, ConfigurableListableBeanFactory beanFactory) { - return beanFactory.getMergedBeanDefinition(beanName).getAttribute(attributeName); - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.configuration.xml; + +import org.springframework.beans.PropertyValue; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; + +/** + * @author Dan Garrette + * @since 2.0.1 + */ +public class BeanDefinitionUtils { + + /** + * @param beanName a bean definition name + * @param propertyName the name of the property + * @param beanFactory a {@link BeanFactory} + * @return The {@link PropertyValue} for the property of the bean. Search parent + * hierarchy if necessary. Return null if none is found. + */ + public static PropertyValue getPropertyValue(String beanName, String propertyName, + ConfigurableListableBeanFactory beanFactory) { + return beanFactory.getMergedBeanDefinition(beanName).getPropertyValues().getPropertyValue(propertyName); + } + + /** + * @param beanName a bean definition name + * @param attributeName the name of the property + * @param beanFactory a {@link BeanFactory} + * @return The value for the attribute of the bean. Search parent hierarchy if + * necessary. Return null if none is found. + */ + public static Object getAttribute(String beanName, String attributeName, + ConfigurableListableBeanFactory beanFactory) { + return beanFactory.getMergedBeanDefinition(beanName).getAttribute(attributeName); + } + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/ChunkElementParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/ChunkElementParser.java index ff9327cde..95988cf7d 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/ChunkElementParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/ChunkElementParser.java @@ -40,7 +40,7 @@ import org.springframework.util.xml.DomUtils; /** * Internal parser for the <chunk/> element inside a step. - * + * * @author Thomas Risberg * @since 2.0 */ @@ -71,10 +71,11 @@ public class ChunkElementParser { * @param bd {@link AbstractBeanDefinition} instance of the containing bean. * @param element the element to parse * @param parserContext the context to use - * @param underspecified if true, a fatal error will not be raised if attribute - * or element is missing. + * @param underspecified if true, a fatal error will not be raised if attribute or + * element is missing. */ - protected void parse(Element element, AbstractBeanDefinition bd, ParserContext parserContext, boolean underspecified) { + protected void parse(Element element, AbstractBeanDefinition bd, ParserContext parserContext, + boolean underspecified) { MutablePropertyValues propertyValues = bd.getPropertyValues(); @@ -111,21 +112,24 @@ public class ChunkElementParser { if (!underspecified && propertyValues.contains("commitInterval") == propertyValues.contains("chunkCompletionPolicy")) { if (propertyValues.contains("commitInterval")) { - parserContext.getReaderContext().error( - "The <" + element.getNodeName() + "/> element must contain either '" + COMMIT_INTERVAL_ATTR - + "' " + "or '" + CHUNK_COMPLETION_POLICY_ATTR + "', but not both.", element); + parserContext.getReaderContext() + .error("The <" + element.getNodeName() + "/> element must contain either '" + + COMMIT_INTERVAL_ATTR + "' " + "or '" + CHUNK_COMPLETION_POLICY_ATTR + + "', but not both.", element); } else { - parserContext.getReaderContext().error( - "The <" + element.getNodeName() + "/> element must contain either '" + COMMIT_INTERVAL_ATTR - + "' " + "or '" + CHUNK_COMPLETION_POLICY_ATTR + "'.", element); + parserContext + .getReaderContext().error( + "The <" + element.getNodeName() + "/> element must contain either '" + + COMMIT_INTERVAL_ATTR + "' " + "or '" + CHUNK_COMPLETION_POLICY_ATTR + "'.", + element); } } String skipLimit = element.getAttribute("skip-limit"); - ManagedMap skippableExceptions = - new ExceptionElementParser().parse(element, parserContext, "skippable-exception-classes"); + ManagedMap skippableExceptions = new ExceptionElementParser().parse(element, + parserContext, "skippable-exception-classes"); if (StringUtils.hasText(skipLimit)) { if (skippableExceptions == null) { skippableExceptions = new ManagedMap<>(); @@ -134,9 +138,10 @@ public class ChunkElementParser { propertyValues.addPropertyValue("skipLimit", skipLimit); } if (skippableExceptions != null) { - List exceptionClassElements = DomUtils.getChildElementsByTagName(element, "skippable-exception-classes"); + List exceptionClassElements = DomUtils.getChildElementsByTagName(element, + "skippable-exception-classes"); - if(!CollectionUtils.isEmpty(exceptionClassElements)) { + if (!CollectionUtils.isEmpty(exceptionClassElements)) { skippableExceptions.setMergeEnabled(exceptionClassElements.get(0).hasAttribute(MERGE_ATTR) && Boolean.valueOf(exceptionClassElements.get(0).getAttribute(MERGE_ATTR))); } @@ -149,8 +154,8 @@ public class ChunkElementParser { underspecified); String retryLimit = element.getAttribute("retry-limit"); - ManagedMap retryableExceptions = - new ExceptionElementParser().parse(element, parserContext, "retryable-exception-classes"); + ManagedMap retryableExceptions = new ExceptionElementParser().parse(element, + parserContext, "retryable-exception-classes"); if (StringUtils.hasText(retryLimit)) { if (retryableExceptions == null) { retryableExceptions = new ManagedMap<>(); @@ -159,9 +164,10 @@ public class ChunkElementParser { propertyValues.addPropertyValue("retryLimit", retryLimit); } if (retryableExceptions != null) { - List exceptionClassElements = DomUtils.getChildElementsByTagName(element, "retryable-exception-classes"); + List exceptionClassElements = DomUtils.getChildElementsByTagName(element, + "retryable-exception-classes"); - if(!CollectionUtils.isEmpty(exceptionClassElements)) { + if (!CollectionUtils.isEmpty(exceptionClassElements)) { retryableExceptions.setMergeEnabled(exceptionClassElements.get(0).hasAttribute(MERGE_ATTR) && Boolean.valueOf(exceptionClassElements.get(0).getAttribute(MERGE_ATTR))); } @@ -199,50 +205,52 @@ public class ChunkElementParser { /** * Handle the ItemReader, ItemProcessor, and ItemWriter attributes/elements. */ - private void handleItemHandler(AbstractBeanDefinition enclosing, String handlerName, String propertyName, String adapterClassName, boolean required, - Element element, ParserContext parserContext, MutablePropertyValues propertyValues, boolean underspecified) { + private void handleItemHandler(AbstractBeanDefinition enclosing, String handlerName, String propertyName, + String adapterClassName, boolean required, Element element, ParserContext parserContext, + MutablePropertyValues propertyValues, boolean underspecified) { String refName = element.getAttribute(handlerName); List children = DomUtils.getChildElementsByTagName(element, handlerName); if (children.size() == 1) { if (StringUtils.hasText(refName)) { - parserContext.getReaderContext().error( - "The <" + element.getNodeName() + "/> element may not have both a '" + handlerName - + "' attribute and a <" + handlerName + "/> element.", element); + parserContext.getReaderContext() + .error("The <" + element.getNodeName() + "/> element may not have both a '" + handlerName + + "' attribute and a <" + handlerName + "/> element.", element); } - handleItemHandlerElement(enclosing, propertyName, adapterClassName, propertyValues, children.get(0), parserContext); + handleItemHandlerElement(enclosing, propertyName, adapterClassName, propertyValues, children.get(0), + parserContext); } else if (children.size() > 1) { - parserContext.getReaderContext().error( - "The <" + handlerName + "/> element may not appear more than once in a single <" - + element.getNodeName() + "/>.", element); + parserContext.getReaderContext().error("The <" + handlerName + + "/> element may not appear more than once in a single <" + element.getNodeName() + "/>.", + element); } else if (StringUtils.hasText(refName)) { propertyValues.addPropertyValue(propertyName, new RuntimeBeanReference(refName)); } else if (required && !underspecified) { - parserContext.getReaderContext().error( - "The <" + element.getNodeName() + "/> element has neither a '" + handlerName - + "' attribute nor a <" + handlerName + "/> element.", element); + parserContext.getReaderContext().error("The <" + element.getNodeName() + "/> element has neither a '" + + handlerName + "' attribute nor a <" + handlerName + "/> element.", element); } } /** - * Handle the <reader/>, <processor/>, or <writer/> that - * is defined within the item handler. + * Handle the <reader/>, <processor/>, or <writer/> that is defined + * within the item handler. */ - private void handleItemHandlerElement(AbstractBeanDefinition enclosing, String propertyName, String adapterClassName, - MutablePropertyValues propertyValues, Element element, ParserContext parserContext) { + private void handleItemHandlerElement(AbstractBeanDefinition enclosing, String propertyName, + String adapterClassName, MutablePropertyValues propertyValues, Element element, + ParserContext parserContext) { List beanElements = DomUtils.getChildElementsByTagName(element, BEAN_ELE); List refElements = DomUtils.getChildElementsByTagName(element, REF_ELE); if (beanElements.size() + refElements.size() != 1) { - parserContext.getReaderContext().error( - "The <" + element.getNodeName() + "/> must have exactly one of either a <" + BEAN_ELE - + "/> element or a <" + REF_ELE + "/> element.", element); + parserContext.getReaderContext() + .error("The <" + element.getNodeName() + "/> must have exactly one of either a <" + BEAN_ELE + + "/> element or a <" + REF_ELE + "/> element.", element); } else if (beanElements.size() == 1) { Element beanElement = beanElements.get(0); - BeanDefinitionHolder beanDefinitionHolder = parserContext.getDelegate().parseBeanDefinitionElement( - beanElement, enclosing); + BeanDefinitionHolder beanDefinitionHolder = parserContext.getDelegate() + .parseBeanDefinitionElement(beanElement, enclosing); parserContext.getDelegate().decorateBeanDefinitionIfRequired(beanElement, beanDefinitionHolder); propertyValues.addPropertyValue(propertyName, beanDefinitionHolder); @@ -256,8 +264,7 @@ public class ChunkElementParser { } /** - * Handle the adapter-method attribute by using an - * AbstractMethodInvokingDelegator + * Handle the adapter-method attribute by using an AbstractMethodInvokingDelegator */ private void handleAdapterMethodAttribute(String propertyName, String adapterClassName, MutablePropertyValues stepPvs, Element element) { @@ -296,8 +303,8 @@ public class ChunkElementParser { } } - private void handleRetryListenerElements(ParserContext parserContext, Element element, ManagedList beans, - BeanDefinition enclosing) { + private void handleRetryListenerElements(ParserContext parserContext, Element element, + ManagedList beans, BeanDefinition enclosing) { List listenerElements = DomUtils.getChildElementsByTagName(element, "listener"); if (listenerElements != null) { for (Element listenerElement : listenerElements) { @@ -306,7 +313,8 @@ public class ChunkElementParser { } } - private void handleStreamsElement(Element element, MutablePropertyValues propertyValues, ParserContext parserContext) { + private void handleStreamsElement(Element element, MutablePropertyValues propertyValues, + ParserContext parserContext) { Element streamsElement = DomUtils.getChildElementByTagName(element, "streams"); if (streamsElement != null) { ManagedList streamBeans = new ManagedList<>(); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespaceHandler.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespaceHandler.java index 5c461f9a2..a695822c7 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespaceHandler.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespaceHandler.java @@ -19,8 +19,6 @@ import org.springframework.beans.factory.xml.NamespaceHandler; import org.springframework.beans.factory.xml.NamespaceHandlerSupport; /** - * - * * @author Dave Syer * */ diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespacePostProcessor.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespacePostProcessor.java index 2df8de324..a325951a8 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespacePostProcessor.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespacePostProcessor.java @@ -1,153 +1,150 @@ -/* - * Copyright 2006-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.configuration.xml; - -import org.springframework.batch.core.repository.JobRepository; -import org.springframework.batch.core.step.AbstractStep; -import org.springframework.beans.BeansException; -import org.springframework.beans.MutablePropertyValues; -import org.springframework.beans.PropertyValue; -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.config.BeanFactoryPostProcessor; -import org.springframework.beans.factory.config.BeanPostProcessor; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.beans.factory.config.RuntimeBeanReference; -import org.springframework.beans.factory.support.AbstractBeanDefinition; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.transaction.PlatformTransactionManager; - -/** - * Post-process jobs and steps defined using the batch namespace to inject - * dependencies. - * - * @author Dan Garrette - * @since 2.0.1 - */ -public class CoreNamespacePostProcessor implements BeanPostProcessor, BeanFactoryPostProcessor, ApplicationContextAware { - - private static final String DEFAULT_JOB_REPOSITORY_NAME = "jobRepository"; - - private static final String DEFAULT_TRANSACTION_MANAGER_NAME = "transactionManager"; - - private static final String JOB_FACTORY_PROPERTY_NAME = "jobParserJobFactoryBeanRef"; - - private static final String JOB_REPOSITORY_PROPERTY_NAME = "jobRepository"; - - private ApplicationContext applicationContext; - - @Override - public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { - for (String beanName : beanFactory.getBeanDefinitionNames()) { - injectJobRepositoryIntoSteps(beanName, beanFactory); - overrideStepClass(beanName, beanFactory); - } - } - - /** - * Automatically inject job-repository from a job into its steps. Only - * inject if the step is an AbstractStep or StepParserStepFactoryBean. - * - * @param beanName - * @param beanFactory - */ - private void injectJobRepositoryIntoSteps(String beanName, ConfigurableListableBeanFactory beanFactory) { - BeanDefinition bd = beanFactory.getBeanDefinition(beanName); - if (bd.hasAttribute(JOB_FACTORY_PROPERTY_NAME)) { - MutablePropertyValues pvs = bd.getPropertyValues(); - if (beanFactory.isTypeMatch(beanName, AbstractStep.class)) { - String jobName = (String) bd.getAttribute(JOB_FACTORY_PROPERTY_NAME); - PropertyValue jobRepository = BeanDefinitionUtils.getPropertyValue(jobName, - JOB_REPOSITORY_PROPERTY_NAME, beanFactory); - if (jobRepository != null) { - // Set the job's JobRepository onto the step - pvs.addPropertyValue(jobRepository); - } - else { - // No JobRepository found, so inject the default - RuntimeBeanReference jobRepositoryBeanRef = new RuntimeBeanReference(DEFAULT_JOB_REPOSITORY_NAME); - pvs.addPropertyValue(JOB_REPOSITORY_PROPERTY_NAME, jobRepositoryBeanRef); - } - } - } - } - - /** - * If any of the beans in the parent hierarchy is a <step/> with a - * <tasklet/>, then the bean class must be - * {@link StepParserStepFactoryBean}. - * - * @param beanName - * @param beanFactory - */ - private void overrideStepClass(String beanName, ConfigurableListableBeanFactory beanFactory) { - BeanDefinition bd = beanFactory.getBeanDefinition(beanName); - Object isNamespaceStep = BeanDefinitionUtils - .getAttribute(beanName, "isNamespaceStep", beanFactory); - if (isNamespaceStep != null && (Boolean) isNamespaceStep) { - ((AbstractBeanDefinition) bd).setBeanClass(StepParserStepFactoryBean.class); - } - } - - @Override - public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { - return injectDefaults(bean); - } - - /** - * Inject defaults into factory beans. - *
    - *
  • Inject "jobRepository" into any {@link JobParserJobFactoryBean} - * without a jobRepository. - *
  • Inject "transactionManager" into any - * {@link StepParserStepFactoryBean} without a transactionManager. - *
- * - * @param bean - * @return - */ - private Object injectDefaults(Object bean) { - if (bean instanceof JobParserJobFactoryBean) { - JobParserJobFactoryBean fb = (JobParserJobFactoryBean) bean; - JobRepository jobRepository = fb.getJobRepository(); - if (jobRepository == null) { - fb.setJobRepository((JobRepository) applicationContext.getBean(DEFAULT_JOB_REPOSITORY_NAME)); - } - } else if (bean instanceof StepParserStepFactoryBean) { - StepParserStepFactoryBean fb = (StepParserStepFactoryBean) bean; - JobRepository jobRepository = fb.getJobRepository(); - if (jobRepository == null) { - fb.setJobRepository((JobRepository) applicationContext.getBean(DEFAULT_JOB_REPOSITORY_NAME)); - } - PlatformTransactionManager transactionManager = fb.getTransactionManager(); - if (transactionManager == null && fb.requiresTransactionManager()) { - fb.setTransactionManager((PlatformTransactionManager) applicationContext - .getBean(DEFAULT_TRANSACTION_MANAGER_NAME)); - } - } - return bean; - } - - @Override - public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { - return bean; - } - - @Override - public void setApplicationContext(ApplicationContext applicationContext) { - this.applicationContext = applicationContext; - } -} +/* + * Copyright 2006-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.configuration.xml; + +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.core.step.AbstractStep; +import org.springframework.beans.BeansException; +import org.springframework.beans.MutablePropertyValues; +import org.springframework.beans.PropertyValue; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.config.RuntimeBeanReference; +import org.springframework.beans.factory.support.AbstractBeanDefinition; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.transaction.PlatformTransactionManager; + +/** + * Post-process jobs and steps defined using the batch namespace to inject dependencies. + * + * @author Dan Garrette + * @since 2.0.1 + */ +public class CoreNamespacePostProcessor + implements BeanPostProcessor, BeanFactoryPostProcessor, ApplicationContextAware { + + private static final String DEFAULT_JOB_REPOSITORY_NAME = "jobRepository"; + + private static final String DEFAULT_TRANSACTION_MANAGER_NAME = "transactionManager"; + + private static final String JOB_FACTORY_PROPERTY_NAME = "jobParserJobFactoryBeanRef"; + + private static final String JOB_REPOSITORY_PROPERTY_NAME = "jobRepository"; + + private ApplicationContext applicationContext; + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { + for (String beanName : beanFactory.getBeanDefinitionNames()) { + injectJobRepositoryIntoSteps(beanName, beanFactory); + overrideStepClass(beanName, beanFactory); + } + } + + /** + * Automatically inject job-repository from a job into its steps. Only inject if the + * step is an AbstractStep or StepParserStepFactoryBean. + * @param beanName + * @param beanFactory + */ + private void injectJobRepositoryIntoSteps(String beanName, ConfigurableListableBeanFactory beanFactory) { + BeanDefinition bd = beanFactory.getBeanDefinition(beanName); + if (bd.hasAttribute(JOB_FACTORY_PROPERTY_NAME)) { + MutablePropertyValues pvs = bd.getPropertyValues(); + if (beanFactory.isTypeMatch(beanName, AbstractStep.class)) { + String jobName = (String) bd.getAttribute(JOB_FACTORY_PROPERTY_NAME); + PropertyValue jobRepository = BeanDefinitionUtils.getPropertyValue(jobName, + JOB_REPOSITORY_PROPERTY_NAME, beanFactory); + if (jobRepository != null) { + // Set the job's JobRepository onto the step + pvs.addPropertyValue(jobRepository); + } + else { + // No JobRepository found, so inject the default + RuntimeBeanReference jobRepositoryBeanRef = new RuntimeBeanReference(DEFAULT_JOB_REPOSITORY_NAME); + pvs.addPropertyValue(JOB_REPOSITORY_PROPERTY_NAME, jobRepositoryBeanRef); + } + } + } + } + + /** + * If any of the beans in the parent hierarchy is a <step/> with a + * <tasklet/>, then the bean class must be {@link StepParserStepFactoryBean}. + * @param beanName + * @param beanFactory + */ + private void overrideStepClass(String beanName, ConfigurableListableBeanFactory beanFactory) { + BeanDefinition bd = beanFactory.getBeanDefinition(beanName); + Object isNamespaceStep = BeanDefinitionUtils.getAttribute(beanName, "isNamespaceStep", beanFactory); + if (isNamespaceStep != null && (Boolean) isNamespaceStep) { + ((AbstractBeanDefinition) bd).setBeanClass(StepParserStepFactoryBean.class); + } + } + + @Override + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + return injectDefaults(bean); + } + + /** + * Inject defaults into factory beans. + *
    + *
  • Inject "jobRepository" into any {@link JobParserJobFactoryBean} without a + * jobRepository. + *
  • Inject "transactionManager" into any {@link StepParserStepFactoryBean} without + * a transactionManager. + *
+ * @param bean + * @return + */ + private Object injectDefaults(Object bean) { + if (bean instanceof JobParserJobFactoryBean) { + JobParserJobFactoryBean fb = (JobParserJobFactoryBean) bean; + JobRepository jobRepository = fb.getJobRepository(); + if (jobRepository == null) { + fb.setJobRepository((JobRepository) applicationContext.getBean(DEFAULT_JOB_REPOSITORY_NAME)); + } + } + else if (bean instanceof StepParserStepFactoryBean) { + StepParserStepFactoryBean fb = (StepParserStepFactoryBean) bean; + JobRepository jobRepository = fb.getJobRepository(); + if (jobRepository == null) { + fb.setJobRepository((JobRepository) applicationContext.getBean(DEFAULT_JOB_REPOSITORY_NAME)); + } + PlatformTransactionManager transactionManager = fb.getTransactionManager(); + if (transactionManager == null && fb.requiresTransactionManager()) { + fb.setTransactionManager( + (PlatformTransactionManager) applicationContext.getBean(DEFAULT_TRANSACTION_MANAGER_NAME)); + } + } + return bean; + } + + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + return bean; + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) { + this.applicationContext = applicationContext; + } + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespaceUtils.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespaceUtils.java index 8003a2331..9705c9afc 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespaceUtils.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespaceUtils.java @@ -59,7 +59,6 @@ public class CoreNamespaceUtils { /** * Create the beans based on the content of the source. - * * @param parserContext The parser context to be used. * @param source The source for the auto registration. */ @@ -72,7 +71,8 @@ public class CoreNamespaceUtils { } private static void checkForStepScope(ParserContext parserContext, Object source) { - checkForScope(parserContext, source, XML_CONFIG_STEP_SCOPE_PROCESSOR_CLASS_NAME, STEP_SCOPE_PROCESSOR_BEAN_NAME); + checkForScope(parserContext, source, XML_CONFIG_STEP_SCOPE_PROCESSOR_CLASS_NAME, + STEP_SCOPE_PROCESSOR_BEAN_NAME); } private static void checkForJobScope(ParserContext parserContext, Object source) { @@ -85,14 +85,14 @@ public class CoreNamespaceUtils { String[] beanNames = parserContext.getRegistry().getBeanDefinitionNames(); for (String beanName : beanNames) { BeanDefinition bd = parserContext.getRegistry().getBeanDefinition(beanName); - if (scopeClassName.equals(bd.getBeanClassName()) || JAVA_CONFIG_SCOPE_CLASS_NAME.equals(bd.getBeanClassName())) { + if (scopeClassName.equals(bd.getBeanClassName()) + || JAVA_CONFIG_SCOPE_CLASS_NAME.equals(bd.getBeanClassName())) { foundScope = true; break; } } if (!foundScope) { - BeanDefinitionBuilder stepScopeBuilder = BeanDefinitionBuilder - .genericBeanDefinition(scopeClassName); + BeanDefinitionBuilder stepScopeBuilder = BeanDefinitionBuilder.genericBeanDefinition(scopeClassName); AbstractBeanDefinition abd = stepScopeBuilder.getBeanDefinition(); abd.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); abd.setSource(source); @@ -102,15 +102,15 @@ public class CoreNamespaceUtils { /** * Register a {@link Comparator} to be used to sort {@link StateTransition}s - * * @param parserContext */ private static void addStateTransitionComparator(ParserContext parserContext) { BeanDefinitionRegistry registry = parserContext.getRegistry(); if (!stateTransitionComparatorAlreadyDefined(registry)) { - AbstractBeanDefinition defaultStateTransitionComparator = BeanDefinitionBuilder.genericBeanDefinition( - DefaultStateTransitionComparator.class).getBeanDefinition(); - registry.registerBeanDefinition(DefaultStateTransitionComparator.STATE_TRANSITION_COMPARATOR, defaultStateTransitionComparator); + AbstractBeanDefinition defaultStateTransitionComparator = BeanDefinitionBuilder + .genericBeanDefinition(DefaultStateTransitionComparator.class).getBeanDefinition(); + registry.registerBeanDefinition(DefaultStateTransitionComparator.STATE_TRANSITION_COMPARATOR, + defaultStateTransitionComparator); } } @@ -120,14 +120,13 @@ public class CoreNamespaceUtils { /** * Register a RangePropertyEditor if one does not already exist. - * * @param parserContext */ private static void addRangePropertyEditor(ParserContext parserContext) { BeanDefinitionRegistry registry = parserContext.getRegistry(); if (!rangeArrayEditorAlreadyDefined(registry)) { - AbstractBeanDefinition customEditorConfigurer = BeanDefinitionBuilder.genericBeanDefinition( - CUSTOM_EDITOR_CONFIGURER_CLASS_NAME).getBeanDefinition(); + AbstractBeanDefinition customEditorConfigurer = BeanDefinitionBuilder + .genericBeanDefinition(CUSTOM_EDITOR_CONFIGURER_CLASS_NAME).getBeanDefinition(); customEditorConfigurer.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); ManagedMap editors = new ManagedMap<>(); editors.put(RANGE_ARRAY_CLASS_NAME, RANGE_ARRAY_EDITOR_CLASS_NAME); @@ -166,8 +165,8 @@ public class CoreNamespaceUtils { private static void addCoreNamespacePostProcessor(ParserContext parserContext) { BeanDefinitionRegistry registry = parserContext.getRegistry(); if (!coreNamespaceBeanPostProcessorAlreadyDefined(registry)) { - AbstractBeanDefinition postProcessorBeanDef = BeanDefinitionBuilder.genericBeanDefinition( - CORE_NAMESPACE_POST_PROCESSOR_CLASS_NAME).getBeanDefinition(); + AbstractBeanDefinition postProcessorBeanDef = BeanDefinitionBuilder + .genericBeanDefinition(CORE_NAMESPACE_POST_PROCESSOR_CLASS_NAME).getBeanDefinition(); postProcessorBeanDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); registry.registerBeanDefinition(CORE_NAMESPACE_POST_PROCESSOR_CLASS_NAME, postProcessorBeanDef); } @@ -184,9 +183,8 @@ public class CoreNamespaceUtils { } /** - * Should this element be treated as incomplete? If it has a parent or is - * abstract, then it may not have all properties. - * + * Should this element be treated as incomplete? If it has a parent or is abstract, + * then it may not have all properties. * @param element to be evaluated. * @return TRUE if the element is abstract or has a parent */ @@ -204,12 +202,11 @@ public class CoreNamespaceUtils { } /** - * Check that the schema location declared in the source file being parsed - * matches the Spring Batch version. (The old 2.0 schema is not 100% - * compatible with the new parser, so it is an error to explicitly define - * 2.0. It might be an error to declare spring-batch.xsd as an alias, but - * you are only going to find that out when one of the sub parses breaks.) - * + * Check that the schema location declared in the source file being parsed matches the + * Spring Batch version. (The old 2.0 schema is not 100% compatible with the new + * parser, so it is an error to explicitly define 2.0. It might be an error to declare + * spring-batch.xsd as an alias, but you are only going to find that out when one of + * the sub parses breaks.) * @param element the element that is to be parsed next * @return true if we find a schema declaration that matches */ diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/DecisionParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/DecisionParser.java index 4e2e1c308..64a989b2d 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/DecisionParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/DecisionParser.java @@ -24,38 +24,37 @@ import org.springframework.beans.factory.xml.ParserContext; import org.w3c.dom.Element; /** - * Internal parser for the <decision/> elements inside a job. A decision - * element references a bean definition for a - * {@link org.springframework.batch.core.job.flow.JobExecutionDecider} - * and goes on to list a set of transitions to other states with <next - * on="pattern" to="stepName"/>. Used by the {@link JobParser}. - * + * Internal parser for the <decision/> elements inside a job. A decision element + * references a bean definition for a + * {@link org.springframework.batch.core.job.flow.JobExecutionDecider} and goes on to list + * a set of transitions to other states with <next on="pattern" to="stepName"/>. + * Used by the {@link JobParser}. + * * @see JobParser - * * @author Dave Syer - * + * */ public class DecisionParser { /** * Parse the decision and turn it into a list of transitions. - * * @param element the <decision/gt; element to parse * @param parserContext the parser context for the bean factory - * @return a collection of bean definitions for - * {@link org.springframework.batch.core.job.flow.support.StateTransition} - * instances objects + * @return a collection of bean definitions for + * {@link org.springframework.batch.core.job.flow.support.StateTransition} instances + * objects */ public Collection parse(Element element, ParserContext parserContext) { String refAttribute = element.getAttribute("decider"); String idAttribute = element.getAttribute("id"); - BeanDefinitionBuilder stateBuilder = - BeanDefinitionBuilder.genericBeanDefinition("org.springframework.batch.core.job.flow.support.state.DecisionState"); + BeanDefinitionBuilder stateBuilder = BeanDefinitionBuilder + .genericBeanDefinition("org.springframework.batch.core.job.flow.support.state.DecisionState"); stateBuilder.addConstructorArgValue(new RuntimeBeanReference(refAttribute)); stateBuilder.addConstructorArgValue(idAttribute); return InlineFlowParser.getNextElements(parserContext, stateBuilder.getBeanDefinition(), element); } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/ExceptionElementParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/ExceptionElementParser.java index aba04df02..0d2c02407 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/ExceptionElementParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/ExceptionElementParser.java @@ -26,7 +26,8 @@ import org.w3c.dom.Element; public class ExceptionElementParser { - public ManagedMap parse(Element element, ParserContext parserContext, String exceptionListName) { + public ManagedMap parse(Element element, ParserContext parserContext, + String exceptionListName) { List children = DomUtils.getChildElementsByTagName(element, exceptionListName); if (children.size() == 1) { ManagedMap map = new ManagedMap<>(); @@ -37,9 +38,9 @@ public class ExceptionElementParser { return map; } else if (children.size() > 1) { - parserContext.getReaderContext().error( - "The <" + exceptionListName + "/> element may not appear more than once in a single <" - + element.getNodeName() + "/>.", element); + parserContext.getReaderContext().error("The <" + exceptionListName + + "/> element may not appear more than once in a single <" + element.getNodeName() + "/>.", + element); } return null; } @@ -51,4 +52,5 @@ public class ExceptionElementParser { map.put(new TypedStringValue(className, Class.class), include); } } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/FlowElementParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/FlowElementParser.java index 06fb7176d..1a524b367 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/FlowElementParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/FlowElementParser.java @@ -27,11 +27,10 @@ import org.w3c.dom.Element; /** * Internal parser for the <flow/> elements inside a job. - * + * * @see JobParser - * * @author Dave Syer - * + * */ public class FlowElementParser { @@ -41,12 +40,11 @@ public class FlowElementParser { /** * Parse the flow and turn it into a list of transitions. - * * @param element the <flow/gt; element to parse * @param parserContext the parser context for the bean factory * @return a collection of bean definitions for - * {@link org.springframework.batch.core.job.flow.support.StateTransition} - * instances objects + * {@link org.springframework.batch.core.job.flow.support.StateTransition} instances + * objects */ public Collection parse(Element element, ParserContext parserContext) { @@ -65,4 +63,5 @@ public class FlowElementParser { return InlineFlowParser.getNextElements(parserContext, stateBuilder.getBeanDefinition(), element); } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/InlineFlowParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/InlineFlowParser.java index 8d1560230..6a9157960 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/InlineFlowParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/InlineFlowParser.java @@ -28,15 +28,15 @@ import org.w3c.dom.Element; * */ public class InlineFlowParser extends AbstractFlowParser { + private final String flowName; /** - * Construct a {@link InlineFlowParser} with the specified name and using the - * provided job repository ref. - * + * Construct a {@link InlineFlowParser} with the specified name and using the provided + * job repository ref. * @param flowName the name of the flow - * @param jobFactoryRef the reference to the {@link JobParserJobFactoryBean} - * from the enclosing tag + * @param jobFactoryRef the reference to the {@link JobParserJobFactoryBean} from the + * enclosing tag */ public InlineFlowParser(String flowName, String jobFactoryRef) { this.flowName = flowName; @@ -57,10 +57,12 @@ public class InlineFlowParser extends AbstractFlowParser { protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { builder.getRawBeanDefinition().setAttribute("flowName", flowName); builder.addPropertyValue("name", flowName); - builder.addPropertyValue("stateTransitionComparator", new RuntimeBeanReference(DefaultStateTransitionComparator.STATE_TRANSITION_COMPARATOR)); + builder.addPropertyValue("stateTransitionComparator", + new RuntimeBeanReference(DefaultStateTransitionComparator.STATE_TRANSITION_COMPARATOR)); super.doParse(element, parserContext, builder); builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); parserContext.popAndRegisterContainingComponent(); } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/InlineStepParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/InlineStepParser.java index e8e8fa998..f342c1af1 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/InlineStepParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/InlineStepParser.java @@ -26,14 +26,12 @@ import org.springframework.beans.factory.xml.ParserContext; import org.w3c.dom.Element; /** - * Internal parser for the <step/> elements inside a job. A step element - * references a bean definition for a - * {@link org.springframework.batch.core.Step} and goes on to (optionally) list - * a set of transitions from that step to others with <next on="pattern" - * to="stepName"/>. Used by the {@link JobParser}. - * + * Internal parser for the <step/> elements inside a job. A step element references + * a bean definition for a {@link org.springframework.batch.core.Step} and goes on to + * (optionally) list a set of transitions from that step to others with <next + * on="pattern" to="stepName"/>. Used by the {@link JobParser}. + * * @see JobParser - * * @author Dave Syer * @author Thomas Risberg * @since 2.0 @@ -42,14 +40,13 @@ public class InlineStepParser extends AbstractStepParser { /** * Parse the step and turn it into a list of transitions. - * * @param element the <step/gt; element to parse * @param parserContext the parser context for the bean factory - * @param jobFactoryRef the reference to the {@link JobParserJobFactoryBean} - * from the enclosing tag + * @param jobFactoryRef the reference to the {@link JobParserJobFactoryBean} from the + * enclosing tag * @return a collection of bean definitions for - * {@link org.springframework.batch.core.job.flow.support.StateTransition} - * instances objects + * {@link org.springframework.batch.core.job.flow.support.StateTransition} instances + * objects */ public Collection parse(Element element, ParserContext parserContext, String jobFactoryRef) { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobExecutionListenerParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobExecutionListenerParser.java index ddd61ff0a..56300a742 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobExecutionListenerParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobExecutionListenerParser.java @@ -22,8 +22,8 @@ import org.springframework.batch.core.listener.JobListenerMetaData; import org.springframework.batch.core.listener.ListenerMetaData; /** - * Parser for a step listener element. Builds a {@link JobListenerFactoryBean} - * using attributes from the configuration. + * Parser for a step listener element. Builds a {@link JobListenerFactoryBean} using + * attributes from the configuration. * * @author Dan Garrette * @since 2.0 diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobParser.java index c6c009d33..0a75ac4d6 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobParser.java @@ -32,11 +32,11 @@ import org.springframework.util.xml.DomUtils; import org.w3c.dom.Element; /** - * Parser for the <job/> element in the Batch namespace. Sets up and returns - * a bean definition for a {@link org.springframework.batch.core.Job}. - * + * Parser for the <job/> element in the Batch namespace. Sets up and returns a bean + * definition for a {@link org.springframework.batch.core.Job}. + * * @author Dave Syer - * + * */ public class JobParser extends AbstractSingleBeanDefinitionParser { @@ -57,9 +57,9 @@ public class JobParser extends AbstractSingleBeanDefinitionParser { /** * Create a bean definition for a - * {@link org.springframework.batch.core.job.flow.FlowJob}. Nested step - * elements are delegated to an {@link InlineStepParser}. - * + * {@link org.springframework.batch.core.job.flow.FlowJob}. Nested step elements are + * delegated to an {@link InlineStepParser}. + * * @see AbstractSingleBeanDefinitionParser#doParse(Element, ParserContext, * BeanDefinitionBuilder) */ @@ -68,9 +68,10 @@ public class JobParser extends AbstractSingleBeanDefinitionParser { if (!CoreNamespaceUtils.namespaceMatchesVersion(element)) { parserContext.getReaderContext().error( - "You are using a version of the spring-batch XSD that is not compatible with Spring Batch 3.0." + - " Please upgrade your schema declarations (or use the spring-batch.xsd alias if you are " + - "feeling lucky).", element); + "You are using a version of the spring-batch XSD that is not compatible with Spring Batch 3.0." + + " Please upgrade your schema declarations (or use the spring-batch.xsd alias if you are " + + "feeling lucky).", + element); return; } @@ -110,9 +111,9 @@ public class JobParser extends AbstractSingleBeanDefinitionParser { if (isAbstract) { for (String tagName : Arrays.asList("step", "decision", "split")) { if (!DomUtils.getChildElementsByTagName(element, tagName).isEmpty()) { - parserContext.getReaderContext().error( - "The <" + tagName + "/> element may not appear on a with abstract=\"true\" [" - + jobName + "]", element); + parserContext.getReaderContext().error("The <" + tagName + + "/> element may not appear on a with abstract=\"true\" [" + jobName + "]", + element); } } } @@ -144,15 +145,14 @@ public class JobParser extends AbstractSingleBeanDefinitionParser { parserContext.popAndRegisterContainingComponent(); } else if (listenersElements.size() > 1) { - parserContext.getReaderContext().error( - "The '' element may not appear more than once in a single .", element); + parserContext.getReaderContext() + .error("The '' element may not appear more than once in a single .", element); } } /** * Parse the element to retrieve {@link BeanMetadataElement}. - * * @param element The {@link Element} to be parsed. * @param parserContext The {@link ParserContext}. * @return The {@link BeanMetadataElement} extracted from the element parameter. @@ -166,8 +166,8 @@ public class JobParser extends AbstractSingleBeanDefinitionParser { return new RuntimeBeanReference(refAttribute); } else if (beanElement != null) { - BeanDefinitionHolder beanDefinitionHolder = parserContext.getDelegate().parseBeanDefinitionElement( - beanElement); + BeanDefinitionHolder beanDefinitionHolder = parserContext.getDelegate() + .parseBeanDefinitionElement(beanElement); parserContext.getDelegate().decorateBeanDefinitionIfRequired(beanElement, beanDefinitionHolder); return beanDefinitionHolder; } @@ -175,8 +175,8 @@ public class JobParser extends AbstractSingleBeanDefinitionParser { return (BeanMetadataElement) parserContext.getDelegate().parsePropertySubElement(refElement, null); } - parserContext.getReaderContext().error( - "One of ref attribute or a nested bean definition or ref element must be specified", element); + parserContext.getReaderContext() + .error("One of ref attribute or a nested bean definition or ref element must be specified", element); return null; } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobParserJobFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobParserJobFactoryBean.java index 0dadac05b..547aeb25c 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobParserJobFactoryBean.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobParserJobFactoryBean.java @@ -1,172 +1,168 @@ -/* - * Copyright 2006-2022 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.configuration.xml; - -import org.springframework.batch.core.JobExecutionListener; -import org.springframework.batch.core.JobParametersIncrementer; -import org.springframework.batch.core.JobParametersValidator; -import org.springframework.batch.core.job.flow.Flow; -import org.springframework.batch.core.job.flow.FlowJob; -import org.springframework.batch.core.repository.JobRepository; -import org.springframework.beans.factory.FactoryBean; -import org.springframework.beans.factory.SmartFactoryBean; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; - -/** - * This {@link FactoryBean} is used by the batch namespace parser to create - * {@link FlowJob} objects. It stores all of the properties that are - * configurable on the <job/>. - * - * @author Dan Garrette - * @author Dave Syer - * @since 2.0.1 - */ -public class JobParserJobFactoryBean implements SmartFactoryBean { - - private String name; - - private Boolean restartable; - - private JobRepository jobRepository; - - private JobParametersValidator jobParametersValidator; - - private JobExecutionListener[] jobExecutionListeners; - - private JobParametersIncrementer jobParametersIncrementer; - - private Flow flow; - - /** - * Constructor for the factory bean that initializes the name. - * - * @param name The name to be used by the factory bean. - */ - public JobParserJobFactoryBean(String name) { - this.name = name; - } - - @Override - public final FlowJob getObject() throws Exception { - Assert.isTrue(StringUtils.hasText(name), "The job must have an id."); - FlowJob flowJob = new FlowJob(name); - - if (restartable != null) { - flowJob.setRestartable(restartable); - } - - if (jobRepository != null) { - flowJob.setJobRepository(jobRepository); - } - - if (jobParametersValidator != null) { - flowJob.setJobParametersValidator(jobParametersValidator); - } - - if (jobExecutionListeners != null) { - flowJob.setJobExecutionListeners(jobExecutionListeners); - } - - if (jobParametersIncrementer != null) { - flowJob.setJobParametersIncrementer(jobParametersIncrementer); - } - - if (flow != null) { - flowJob.setFlow(flow); - } - - flowJob.afterPropertiesSet(); - return flowJob; - } - - /** - * Set the restartable flag for the factory bean. - * - * @param restartable The restartable flag to be used by the factory bean. - */ - public void setRestartable(Boolean restartable) { - this.restartable = restartable; - } - - /** - * Set the {@link JobRepository} for the factory bean. - * - * @param jobRepository The {@link JobRepository} to be used by the factory bean. - */ - public void setJobRepository(JobRepository jobRepository) { - this.jobRepository = jobRepository; - } - - /** - * Set the {@link JobParametersValidator} for the factory bean. - * - * @param jobParametersValidator The {@link JobParametersValidator} to be used by the factory bean. - */ - public void setJobParametersValidator(JobParametersValidator jobParametersValidator) { - this.jobParametersValidator = jobParametersValidator; - } - - /** - * @return The {@link JobRepository} used by the factory bean. - */ - public JobRepository getJobRepository() { - return this.jobRepository; - } - - public void setJobExecutionListeners(JobExecutionListener[] jobExecutionListeners) { - this.jobExecutionListeners = jobExecutionListeners; - } - - /** - * Set the {@link JobParametersIncrementer} for the factory bean. - * - * @param jobParametersIncrementer The {@link JobParametersIncrementer} to be used by the factory bean. - */ - public void setJobParametersIncrementer(JobParametersIncrementer jobParametersIncrementer) { - this.jobParametersIncrementer = jobParametersIncrementer; - } - - /** - * Set the flow for the factory bean. - * - * @param flow The {@link Flow} to be used by the factory bean. - */ - public void setFlow(Flow flow) { - this.flow = flow; - } - - @Override - public Class getObjectType() { - return FlowJob.class; - } - - @Override - public boolean isSingleton() { - return true; - } - - @Override - public boolean isEagerInit() { - return true; - } - - @Override - public boolean isPrototype() { - return false; - } - -} +/* + * Copyright 2006-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.configuration.xml; + +import org.springframework.batch.core.JobExecutionListener; +import org.springframework.batch.core.JobParametersIncrementer; +import org.springframework.batch.core.JobParametersValidator; +import org.springframework.batch.core.job.flow.Flow; +import org.springframework.batch.core.job.flow.FlowJob; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.SmartFactoryBean; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +/** + * This {@link FactoryBean} is used by the batch namespace parser to create + * {@link FlowJob} objects. It stores all of the properties that are configurable on the + * <job/>. + * + * @author Dan Garrette + * @author Dave Syer + * @since 2.0.1 + */ +public class JobParserJobFactoryBean implements SmartFactoryBean { + + private String name; + + private Boolean restartable; + + private JobRepository jobRepository; + + private JobParametersValidator jobParametersValidator; + + private JobExecutionListener[] jobExecutionListeners; + + private JobParametersIncrementer jobParametersIncrementer; + + private Flow flow; + + /** + * Constructor for the factory bean that initializes the name. + * @param name The name to be used by the factory bean. + */ + public JobParserJobFactoryBean(String name) { + this.name = name; + } + + @Override + public final FlowJob getObject() throws Exception { + Assert.isTrue(StringUtils.hasText(name), "The job must have an id."); + FlowJob flowJob = new FlowJob(name); + + if (restartable != null) { + flowJob.setRestartable(restartable); + } + + if (jobRepository != null) { + flowJob.setJobRepository(jobRepository); + } + + if (jobParametersValidator != null) { + flowJob.setJobParametersValidator(jobParametersValidator); + } + + if (jobExecutionListeners != null) { + flowJob.setJobExecutionListeners(jobExecutionListeners); + } + + if (jobParametersIncrementer != null) { + flowJob.setJobParametersIncrementer(jobParametersIncrementer); + } + + if (flow != null) { + flowJob.setFlow(flow); + } + + flowJob.afterPropertiesSet(); + return flowJob; + } + + /** + * Set the restartable flag for the factory bean. + * @param restartable The restartable flag to be used by the factory bean. + */ + public void setRestartable(Boolean restartable) { + this.restartable = restartable; + } + + /** + * Set the {@link JobRepository} for the factory bean. + * @param jobRepository The {@link JobRepository} to be used by the factory bean. + */ + public void setJobRepository(JobRepository jobRepository) { + this.jobRepository = jobRepository; + } + + /** + * Set the {@link JobParametersValidator} for the factory bean. + * @param jobParametersValidator The {@link JobParametersValidator} to be used by the + * factory bean. + */ + public void setJobParametersValidator(JobParametersValidator jobParametersValidator) { + this.jobParametersValidator = jobParametersValidator; + } + + /** + * @return The {@link JobRepository} used by the factory bean. + */ + public JobRepository getJobRepository() { + return this.jobRepository; + } + + public void setJobExecutionListeners(JobExecutionListener[] jobExecutionListeners) { + this.jobExecutionListeners = jobExecutionListeners; + } + + /** + * Set the {@link JobParametersIncrementer} for the factory bean. + * @param jobParametersIncrementer The {@link JobParametersIncrementer} to be used by + * the factory bean. + */ + public void setJobParametersIncrementer(JobParametersIncrementer jobParametersIncrementer) { + this.jobParametersIncrementer = jobParametersIncrementer; + } + + /** + * Set the flow for the factory bean. + * @param flow The {@link Flow} to be used by the factory bean. + */ + public void setFlow(Flow flow) { + this.flow = flow; + } + + @Override + public Class getObjectType() { + return FlowJob.class; + } + + @Override + public boolean isSingleton() { + return true; + } + + @Override + public boolean isEagerInit() { + return true; + } + + @Override + public boolean isPrototype() { + return false; + } + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobRepositoryParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobRepositoryParser.java index b2a36074e..2665df482 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobRepositoryParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobRepositoryParser.java @@ -27,8 +27,8 @@ import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** - * Parser for the <job-repository/> element in the Batch namespace. Sets up - * and returns a JobRepositoryFactoryBean. + * Parser for the <job-repository/> element in the Batch namespace. Sets up and + * returns a JobRepositoryFactoryBean. * * @author Thomas Risberg * @since 2.0 @@ -65,7 +65,7 @@ public class JobRepositoryParser extends AbstractSingleBeanDefinitionParser { CoreNamespaceUtils.autoregisterBeansForNamespace(parserContext, element); String dataSource = element.getAttribute("data-source"); - + String jdbcOperations = element.getAttribute("jdbc-operations"); String transactionManager = element.getAttribute("transaction-manager"); @@ -88,8 +88,8 @@ public class JobRepositoryParser extends AbstractSingleBeanDefinitionParser { builder.addPropertyReference("jdbcOperations", jdbcOperations); } if (StringUtils.hasText(isolationLevelForCreate)) { - builder.addPropertyValue("isolationLevelForCreate", DefaultTransactionDefinition.PREFIX_ISOLATION - + isolationLevelForCreate); + builder.addPropertyValue("isolationLevelForCreate", + DefaultTransactionDefinition.PREFIX_ISOLATION + isolationLevelForCreate); } if (StringUtils.hasText(tablePrefix)) { builder.addPropertyValue("tablePrefix", tablePrefix); @@ -107,4 +107,5 @@ public class JobRepositoryParser extends AbstractSingleBeanDefinitionParser { builder.setRole(BeanDefinition.ROLE_SUPPORT); } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/SimpleFlowFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/SimpleFlowFactoryBean.java index 8b490b206..52723b952 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/SimpleFlowFactoryBean.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/SimpleFlowFactoryBean.java @@ -35,10 +35,10 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; /** - * Convenience factory for SimpleFlow instances for use in XML namespace. It - * replaces the states in the input with proxies that have a unique name formed - * from the flow name and the original state name (unless the name is already in - * that form, in which case it is not modified). + * Convenience factory for SimpleFlow instances for use in XML namespace. It replaces the + * states in the input with proxies that have a unique name formed from the flow name and + * the original state name (unless the name is already in that form, in which case it is + * not modified). * * @author Dave Syer * @author Michael Minella @@ -72,7 +72,6 @@ public class SimpleFlowFactoryBean implements FactoryBean, Initializ /** * The name of the flow that is created by this factory. - * * @param name the value of the name */ public void setName(String name) { @@ -81,10 +80,8 @@ public class SimpleFlowFactoryBean implements FactoryBean, Initializ } /** - * The raw state transitions for the flow. They will be transformed into - * proxies that have the same behavior but unique names prefixed with the - * flow name. - * + * The raw state transitions for the flow. They will be transformed into proxies that + * have the same behavior but unique names prefixed with the flow name. * @param stateTransitions the list of transitions */ public void setStateTransitions(List stateTransitions) { @@ -93,19 +90,20 @@ public class SimpleFlowFactoryBean implements FactoryBean, Initializ /** * Check mandatory properties (name). - * * @throws Exception thrown if error occurs. */ @Override public void afterPropertiesSet() throws Exception { Assert.hasText(name, "The flow must have a name"); - if(flowType == null) { + if (flowType == null) { flowType = SimpleFlow.class; } } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.springframework.beans.factory.FactoryBean#getObject() */ @Override @@ -135,10 +133,9 @@ public class SimpleFlowFactoryBean implements FactoryBean, Initializ } /** - * Convenience method to get a state that proxies the input but with a - * different name, appropriate to this flow. If the state is a StepState - * then the step name is also changed. - * + * Convenience method to get a state that proxies the input but with a different name, + * appropriate to this flow. If the state is a StepState then the step name is also + * changed. * @param state * @return */ @@ -157,14 +154,12 @@ public class SimpleFlowFactoryBean implements FactoryBean, Initializ /** * Provides an extension point to provide alternative {@link StepState} * implementations within a {@link SimpleFlow} - * * @param state The state that will be used to create the StepState * @param oldName The name to be replaced * @param stateName The name for the new State * @return a state for the requested data */ - protected State createNewStepState(State state, String oldName, - String stateName) { + protected State createNewStepState(State state, String oldName, String stateName) { return new StepState(stateName, ((StepState) state).getStep(oldName)); } @@ -179,13 +174,14 @@ public class SimpleFlowFactoryBean implements FactoryBean, Initializ } /** - * A State that proxies a delegate and changes its name but leaves its - * behavior unchanged. + * A State that proxies a delegate and changes its name but leaves its behavior + * unchanged. * * @author Dave Syer * */ public static class DelegateState extends AbstractState implements FlowHolder { + private final State state; private DelegateState(String name, State state) { @@ -212,7 +208,7 @@ public class SimpleFlowFactoryBean implements FactoryBean, Initializ @Override public Collection getFlows() { - return (state instanceof FlowHolder) ? ((FlowHolder)state).getFlows() : Collections.emptyList(); + return (state instanceof FlowHolder) ? ((FlowHolder) state).getFlows() : Collections.emptyList(); } } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/SplitParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/SplitParser.java index e364fcc40..7684f9d9b 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/SplitParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/SplitParser.java @@ -33,14 +33,13 @@ import org.w3c.dom.Element; /** * Internal parser for the <split/> elements inside a job. A split element - * optionally references a bean definition for a {@link TaskExecutor} and goes - * on to list a set of transitions to other states with <next on="pattern" - * to="stepName"/>. Used by the {@link JobParser}. - * + * optionally references a bean definition for a {@link TaskExecutor} and goes on to list + * a set of transitions to other states with <next on="pattern" to="stepName"/>. + * Used by the {@link JobParser}. + * * @see JobParser - * * @author Dave Syer - * + * */ public class SplitParser { @@ -49,11 +48,9 @@ public class SplitParser { private final String jobFactoryRef; /** - * Construct a {@link InlineFlowParser} using the provided job repository - * ref. - * - * @param jobFactoryRef the reference to the {@link JobParserJobFactoryBean} - * from the enclosing tag + * Construct a {@link InlineFlowParser} using the provided job repository ref. + * @param jobFactoryRef the reference to the {@link JobParserJobFactoryBean} from the + * enclosing tag */ public SplitParser(String jobFactoryRef) { this.jobFactoryRef = jobFactoryRef; @@ -61,12 +58,11 @@ public class SplitParser { /** * Parse the split and turn it into a list of transitions. - * * @param element the <split/gt; element to parse * @param parserContext the parser context for the bean factory * @return a collection of bean definitions for - * {@link org.springframework.batch.core.job.flow.support.StateTransition} - * instances objects + * {@link org.springframework.batch.core.job.flow.support.StateTransition} instances + * objects */ public Collection parse(Element element, ParserContext parserContext) { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StandaloneStepParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StandaloneStepParser.java index 364eaf5cb..90517d6bf 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StandaloneStepParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StandaloneStepParser.java @@ -20,10 +20,9 @@ import org.springframework.beans.factory.xml.ParserContext; import org.w3c.dom.Element; /** - * Internal parser for the <step/> elements for a job. A step element - * references a bean definition for a - * {@link org.springframework.batch.core.Step}. - * + * Internal parser for the <step/> elements for a job. A step element references a + * bean definition for a {@link org.springframework.batch.core.Step}. + * * @author Dave Syer * @author Thomas Risberg * @since 2.0 @@ -32,7 +31,6 @@ public class StandaloneStepParser extends AbstractStepParser { /** * Parse the step and turn it into a list of transitions. - * * @param element the <step/gt; element to parse * @param parserContext the parser context for the bean factory * @return {@link AbstractBeanDefinition} instance. @@ -40,4 +38,5 @@ public class StandaloneStepParser extends AbstractStepParser { public AbstractBeanDefinition parse(Element element, ParserContext parserContext) { return parseStep(element, parserContext, null); } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepListenerParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepListenerParser.java index 11792aee2..c095262db 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepListenerParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepListenerParser.java @@ -1,93 +1,93 @@ -/* - * Copyright 2006-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.configuration.xml; - -import java.util.List; - -import org.springframework.batch.core.listener.AbstractListenerFactoryBean; -import org.springframework.batch.core.listener.ListenerMetaData; -import org.springframework.batch.core.listener.StepListenerFactoryBean; -import org.springframework.batch.core.listener.StepListenerMetaData; -import org.springframework.beans.MutablePropertyValues; -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.parsing.CompositeComponentDefinition; -import org.springframework.beans.factory.support.ManagedList; -import org.springframework.beans.factory.xml.ParserContext; -import org.springframework.util.xml.DomUtils; -import org.w3c.dom.Element; - -/** - * Parser for a step listener element. Builds a {@link StepListenerFactoryBean} - * using attributes from the configuration. - * - * @author Dan Garrette - * @since 2.0 - * @see AbstractListenerParser - */ -public class StepListenerParser extends AbstractListenerParser { - - private static final String LISTENERS_ELE = "listeners"; - - private static final String MERGE_ATTR = "merge"; - - private final ListenerMetaData[] listenerMetaData; - - public StepListenerParser() { - this(StepListenerMetaData.values()); - } - - public StepListenerParser(ListenerMetaData[] listenerMetaData) { - this.listenerMetaData = listenerMetaData; - } - - @Override - protected Class> getBeanClass() { - return StepListenerFactoryBean.class; - } - - @Override - protected ListenerMetaData[] getMetaDataValues() { - return listenerMetaData; - } - - @SuppressWarnings("unchecked") - public void handleListenersElement(Element stepElement, BeanDefinition beanDefinition, - ParserContext parserContext) { - MutablePropertyValues propertyValues = beanDefinition.getPropertyValues(); - List listenersElements = DomUtils.getChildElementsByTagName(stepElement, LISTENERS_ELE); - if (listenersElements.size() == 1) { - Element listenersElement = listenersElements.get(0); - CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(listenersElement.getTagName(), - parserContext.extractSource(stepElement)); - parserContext.pushContainingComponent(compositeDef); - ManagedList listenerBeans = new ManagedList<>(); - if (propertyValues.contains("listeners")) { - listenerBeans = (ManagedList) propertyValues.getPropertyValue("listeners").getValue(); - } - listenerBeans.setMergeEnabled(listenersElement.hasAttribute(MERGE_ATTR) - && Boolean.valueOf(listenersElement.getAttribute(MERGE_ATTR))); - List listenerElements = DomUtils.getChildElementsByTagName(listenersElement, "listener"); - if (listenerElements != null) { - for (Element listenerElement : listenerElements) { - listenerBeans.add(parse(listenerElement, parserContext)); - } - } - propertyValues.addPropertyValue("listeners", listenerBeans); - parserContext.popAndRegisterContainingComponent(); - } - } - -} +/* + * Copyright 2006-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.configuration.xml; + +import java.util.List; + +import org.springframework.batch.core.listener.AbstractListenerFactoryBean; +import org.springframework.batch.core.listener.ListenerMetaData; +import org.springframework.batch.core.listener.StepListenerFactoryBean; +import org.springframework.batch.core.listener.StepListenerMetaData; +import org.springframework.beans.MutablePropertyValues; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.parsing.CompositeComponentDefinition; +import org.springframework.beans.factory.support.ManagedList; +import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.util.xml.DomUtils; +import org.w3c.dom.Element; + +/** + * Parser for a step listener element. Builds a {@link StepListenerFactoryBean} using + * attributes from the configuration. + * + * @author Dan Garrette + * @since 2.0 + * @see AbstractListenerParser + */ +public class StepListenerParser extends AbstractListenerParser { + + private static final String LISTENERS_ELE = "listeners"; + + private static final String MERGE_ATTR = "merge"; + + private final ListenerMetaData[] listenerMetaData; + + public StepListenerParser() { + this(StepListenerMetaData.values()); + } + + public StepListenerParser(ListenerMetaData[] listenerMetaData) { + this.listenerMetaData = listenerMetaData; + } + + @Override + protected Class> getBeanClass() { + return StepListenerFactoryBean.class; + } + + @Override + protected ListenerMetaData[] getMetaDataValues() { + return listenerMetaData; + } + + @SuppressWarnings("unchecked") + public void handleListenersElement(Element stepElement, BeanDefinition beanDefinition, + ParserContext parserContext) { + MutablePropertyValues propertyValues = beanDefinition.getPropertyValues(); + List listenersElements = DomUtils.getChildElementsByTagName(stepElement, LISTENERS_ELE); + if (listenersElements.size() == 1) { + Element listenersElement = listenersElements.get(0); + CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(listenersElement.getTagName(), + parserContext.extractSource(stepElement)); + parserContext.pushContainingComponent(compositeDef); + ManagedList listenerBeans = new ManagedList<>(); + if (propertyValues.contains("listeners")) { + listenerBeans = (ManagedList) propertyValues.getPropertyValue("listeners").getValue(); + } + listenerBeans.setMergeEnabled(listenersElement.hasAttribute(MERGE_ATTR) + && Boolean.valueOf(listenersElement.getAttribute(MERGE_ATTR))); + List listenerElements = DomUtils.getChildElementsByTagName(listenersElement, "listener"); + if (listenerElements != null) { + for (Element listenerElement : listenerElements) { + listenerBeans.add(parse(listenerElement, parserContext)); + } + } + propertyValues.addPropertyValue("listeners", listenerBeans); + parserContext.popAndRegisterContainingComponent(); + } + } + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBean.java index 7ae07be56..6ba064cd5 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBean.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBean.java @@ -77,9 +77,11 @@ import org.springframework.transaction.interceptor.DefaultTransactionAttribute; import org.springframework.util.Assert; /** - * This {@link FactoryBean} is used by the batch namespace parser to create {@link Step} objects. Stores all of the - * properties that are configurable on the <step/> (and its inner <tasklet/>). Based on which properties are - * configured, the {@link #getObject()} method will delegate to the appropriate class for generating the {@link Step}. + * This {@link FactoryBean} is used by the batch namespace parser to create {@link Step} + * objects. Stores all of the properties that are configurable on the <step/> (and + * its inner <tasklet/>). Based on which properties are configured, the + * {@link #getObject()} method will delegate to the appropriate class for generating the + * {@link Step}. * * @author Dan Garrette * @author Josh Long @@ -224,8 +226,8 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN @Override public Step getObject() throws Exception { if (hasChunkElement) { - Assert.isNull(tasklet, "Step [" + name - + "] has both a element and a 'ref' attribute referencing a Tasklet."); + Assert.isNull(tasklet, + "Step [" + name + "] has both a element and a 'ref' attribute referencing a Tasklet."); validateFaultTolerantSettings(); @@ -269,7 +271,7 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN builder.repository(jobRepository); builder.transactionManager(transactionManager); for (Object listener : stepExecutionListeners) { - if(listener instanceof StepExecutionListener) { + if (listener instanceof StepExecutionListener) { builder.listener((StepExecutionListener) listener); } } @@ -277,7 +279,6 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN /** * Create a partition {@link Step}. - * * @return The {@link Step}. */ protected Step createPartitionStep() { @@ -307,7 +308,6 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN /** * Creates a fault tolerant {@link Step}. - * * @return The {@link Step}. */ protected Step createFaultTolerantStep() { @@ -341,7 +341,7 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN if (skipPolicy != null) { builder.skipPolicy(skipPolicy); } - else if (skipLimit!=null) { + else if (skipLimit != null) { builder.skipLimit(skipLimit); for (Class type : skippableExceptionClasses.keySet()) { if (skippableExceptionClasses.get(type)) { @@ -392,7 +392,6 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN /** * Creates a new {@link FaultTolerantStepBuilder}. - * * @param stepName The name of the step used by the created builder. * @return The {@link FaultTolerantStepBuilder}. */ @@ -414,7 +413,6 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN /** * Creates a new {@link TaskletStep}. - * * @return The {@link TaskletStep}. */ protected Step createSimpleStep() { @@ -455,8 +453,8 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN } /** - * Set the state of the {@link AbstractTaskletStepBuilder} using the values that were established for the factory bean. - * + * Set the state of the {@link AbstractTaskletStepBuilder} using the values that were + * established for the factory bean. * @param builder The {@link AbstractTaskletStepBuilder} to be modified. */ @SuppressWarnings("serial") @@ -504,7 +502,6 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN /** * Create a new {@link org.springframework.batch.core.job.flow.FlowStep}. - * * @return The {@link org.springframework.batch.core.job.flow.FlowStep}. */ protected Step createFlowStep() { @@ -538,12 +535,13 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN } /** - * Check if a field is present then a second is also. If the twoWayDependency flag is set then the opposite must - * also be true: if the second value is present, the first must also be. - * + * Check if a field is present then a second is also. If the twoWayDependency flag is + * set then the opposite must also be true: if the second value is present, the first + * must also be. * @param dependentName the name of the first field * @param dependentValue the value of the first field - * @param name the name of the other field (which should be absent if the first is present) + * @param name the name of the other field (which should be absent if the first is + * present) * @param value the value of the other field * @param twoWayDependency true if both depend on each other * @throws IllegalArgumentException if either condition is violated @@ -562,7 +560,6 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN /** * Is the object non-null (or if an Integer, non-zero)? - * * @param o an object * @return true if the object has a value */ @@ -580,7 +577,8 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN } /** - * @return true if the step is configured with any components that require fault tolerance + * @return true if the step is configured with any components that require fault + * tolerance */ protected boolean isFaultTolerant() { return backOffPolicy != null || skipPolicy != null || retryPolicy != null || isPositive(skipLimit) @@ -610,7 +608,8 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN // ========================================================= /** - * Set the bean name property, which will become the name of the {@link Step} when it is created. + * Set the bean name property, which will become the name of the {@link Step} when it + * is created. * * @see org.springframework.beans.factory.BeanNameAware#setBeanName(java.lang.String) */ @@ -717,9 +716,8 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN // ========================================================= /** - * Public setter for the flag to indicate that the step should be replayed on a restart, even if successful the - * first time. - * + * Public setter for the flag to indicate that the step should be replayed on a + * restart, even if successful the first time. * @param allowStartIfComplete the shouldAllowStartIfComplete to set */ public void setAllowStartIfComplete(boolean allowStartIfComplete) { @@ -736,7 +734,6 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN /** * Public setter for {@link JobRepository}. - * * @param jobRepository {@link JobRepository} instance to be used by the step. */ public void setJobRepository(JobRepository jobRepository) { @@ -745,8 +742,8 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN /** * The number of times that the step should be allowed to start - * - * @param startLimit int containing the number of times a step should be allowed to start. + * @param startLimit int containing the number of times a step should be allowed to + * start. */ public void setStartLimit(int startLimit) { this.startLimit = startLimit; @@ -754,7 +751,6 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN /** * A preconfigured {@link Tasklet} to use. - * * @param tasklet {@link Tasklet} instance to be used by step. */ public void setTasklet(Tasklet tasklet) { @@ -766,8 +762,8 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN } /** - * @return transactionManager instance of {@link PlatformTransactionManager} - * used by the step. + * @return transactionManager instance of {@link PlatformTransactionManager} used by + * the step. */ public PlatformTransactionManager getTransactionManager() { return transactionManager; @@ -785,9 +781,8 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN // ========================================================= /** - * The listeners to inject into the {@link Step}. Any instance of {@link StepListener} can be used, and will then - * receive callbacks at the appropriate stage in the step. - * + * The listeners to inject into the {@link Step}. Any instance of {@link StepListener} + * can be used, and will then receive callbacks at the appropriate stage in the step. * @param listeners an array of listeners */ @SuppressWarnings("unchecked") @@ -822,7 +817,6 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN /** * Exception classes that may not cause a rollback if encountered in the right place. - * * @param noRollbackExceptionClasses the noRollbackExceptionClasses to set */ public void setNoRollbackExceptionClasses(Collection> noRollbackExceptionClasses) { @@ -856,7 +850,6 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN /** * A backoff policy to be applied to retry process. - * * @param backOffPolicy the {@link BackOffPolicy} to set */ public void setBackOffPolicy(BackOffPolicy backOffPolicy) { @@ -864,9 +857,8 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN } /** - * A retry policy to apply when exceptions occur. If this is specified then the retry limit and retryable exceptions - * will be ignored. - * + * A retry policy to apply when exceptions occur. If this is specified then the retry + * limit and retryable exceptions will be ignored. * @param retryPolicy the {@link RetryPolicy} to set */ public void setRetryPolicy(RetryPolicy retryPolicy) { @@ -881,9 +873,8 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN } /** - * A key generator that can be used to compare items with previously recorded items in a retry. Only used if the - * reader is a transactional queue. - * + * A key generator that can be used to compare items with previously recorded items in + * a retry. Only used if the reader is a transactional queue. * @param keyGenerator the {@link KeyGenerator} to set */ public void setKeyGenerator(KeyGenerator keyGenerator) { @@ -895,14 +886,14 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN // ========================================================= /** - * Public setter for the capacity of the cache in the retry policy. If more items than this fail without being - * skipped or recovered an exception will be thrown. This is to guard against inadvertent infinite loops generated - * by item identity problems.
+ * Public setter for the capacity of the cache in the retry policy. If more items than + * this fail without being skipped or recovered an exception will be thrown. This is + * to guard against inadvertent infinite loops generated by item identity + * problems.
*
- * The default value should be high enough and more for most purposes. To breach the limit in a single-threaded step - * typically you have to have this many failures in a single transaction. Defaults to the value in the - * {@link MapRetryContextCache}.
- * + * The default value should be high enough and more for most purposes. To breach the + * limit in a single-threaded step typically you have to have this many failures in a + * single transaction. Defaults to the value in the {@link MapRetryContextCache}.
* @param cacheCapacity the cache capacity to set (greater than 0 else ignored) */ public void setCacheCapacity(int cacheCapacity) { @@ -910,10 +901,10 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN } /** - * Public setter for the {@link CompletionPolicy} applying to the chunk level. A transaction will be committed when - * this policy decides to complete. Defaults to a {@link SimpleCompletionPolicy} with chunk size equal to the - * commitInterval property. - * + * Public setter for the {@link CompletionPolicy} applying to the chunk level. A + * transaction will be committed when this policy decides to complete. Defaults to a + * {@link SimpleCompletionPolicy} with chunk size equal to the commitInterval + * property. * @param chunkCompletionPolicy the chunkCompletionPolicy to set */ public void setChunkCompletionPolicy(CompletionPolicy chunkCompletionPolicy) { @@ -922,7 +913,6 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN /** * Set the commit interval. Either set this or the chunkCompletionPolicy but not both. - * * @param commitInterval 1 by default */ public void setCommitInterval(int commitInterval) { @@ -937,9 +927,9 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN } /** - * Flag to signal that the reader is transactional (usually a JMS consumer) so that items are re-presented after a - * rollback. The default is false and readers are assumed to be forward-only. - * + * Flag to signal that the reader is transactional (usually a JMS consumer) so that + * items are re-presented after a rollback. The default is false and readers are + * assumed to be forward-only. * @param isReaderTransactionalQueue the value of the flag */ public void setIsReaderTransactionalQueue(boolean isReaderTransactionalQueue) { @@ -947,9 +937,9 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN } /** - * Flag to signal that the processor is transactional, in which case it should be called for every item in every - * transaction. If false then we can cache the processor results between transactions in the case of a rollback. - * + * Flag to signal that the processor is transactional, in which case it should be + * called for every item in every transaction. If false then we can cache the + * processor results between transactions in the case of a rollback. * @param processorTransactional the value to set */ public void setProcessorTransactional(Boolean processorTransactional) { @@ -957,9 +947,9 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN } /** - * Public setter for the retry limit. Each item can be retried up to this limit. Note this limit includes the - * initial attempt to process the item, therefore retryLimit == 1 by default. - * + * Public setter for the retry limit. Each item can be retried up to this limit. Note + * this limit includes the initial attempt to process the item, therefore + * retryLimit == 1 by default. * @param retryLimit the retry limit to set, must be greater or equal to 1. */ public void setRetryLimit(int retryLimit) { @@ -967,10 +957,10 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN } /** - * Public setter for a limit that determines skip policy. If this value is positive then an exception in chunk - * processing will cause the item to be skipped and no exception propagated until the limit is reached. If it is - * zero then all exceptions will be propagated from the chunk and cause the step to abort. - * + * Public setter for a limit that determines skip policy. If this value is positive + * then an exception in chunk processing will cause the item to be skipped and no + * exception propagated until the limit is reached. If it is zero then all exceptions + * will be propagated from the chunk and cause the step to abort. * @param skipLimit the value to set. Default is 0 (never skip). */ public void setSkipLimit(int skipLimit) { @@ -978,8 +968,8 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN } /** - * Public setter for a skip policy. If this value is set then the skip limit and skippable exceptions are ignored. - * + * Public setter for a skip policy. If this value is set then the skip limit and + * skippable exceptions are ignored. * @param skipPolicy the {@link SkipPolicy} to set */ public void setSkipPolicy(SkipPolicy skipPolicy) { @@ -987,9 +977,8 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN } /** - * Public setter for the {@link TaskExecutor}. If this is set, then it will be used to execute the chunk processing - * inside the {@link Step}. - * + * Public setter for the {@link TaskExecutor}. If this is set, then it will be used to + * execute the chunk processing inside the {@link Step}. * @param taskExecutor the taskExecutor to set */ public void setTaskExecutor(TaskExecutor taskExecutor) { @@ -997,9 +986,9 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN } /** - * Public setter for the throttle limit. This limits the number of tasks queued for concurrent processing to prevent - * thread pools from being overwhelmed. Defaults to {@link TaskExecutorRepeatTemplate#DEFAULT_THROTTLE_LIMIT}. - * + * Public setter for the throttle limit. This limits the number of tasks queued for + * concurrent processing to prevent thread pools from being overwhelmed. Defaults to + * {@link TaskExecutorRepeatTemplate#DEFAULT_THROTTLE_LIMIT}. * @param throttleLimit the throttle limit to set. */ public void setThrottleLimit(Integer throttleLimit) { @@ -1033,7 +1022,6 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN /** * Public setter for the {@link RetryListener}s. - * * @param retryListeners the {@link RetryListener}s to set */ public void setRetryListeners(RetryListener... retryListeners) { @@ -1041,11 +1029,11 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN } /** - * Public setter for exception classes that when raised won't crash the job but will result in transaction rollback - * and the item which handling caused the exception will be skipped. - * - * @param exceptionClasses {@link Map} containing the {@link Throwable}s as - * the keys and the values are {@link Boolean}s, that if true the item is skipped. + * Public setter for exception classes that when raised won't crash the job but will + * result in transaction rollback and the item which handling caused the exception + * will be skipped. + * @param exceptionClasses {@link Map} containing the {@link Throwable}s as the keys + * and the values are {@link Boolean}s, that if true the item is skipped. */ public void setSkippableExceptionClasses(Map, Boolean> exceptionClasses) { this.skippableExceptionClasses = exceptionClasses; @@ -1053,7 +1041,6 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN /** * Public setter for exception classes that will retry the item when raised. - * * @param retryableExceptionClasses the retryableExceptionClasses to set */ public void setRetryableExceptionClasses(Map, Boolean> retryableExceptionClasses) { @@ -1061,9 +1048,8 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN } /** - * The streams to inject into the {@link Step}. Any instance of {@link ItemStream} can be used, and will then - * receive callbacks at the appropriate stage in the step. - * + * The streams to inject into the {@link Step}. Any instance of {@link ItemStream} can + * be used, and will then receive callbacks at the appropriate stage in the step. * @param streams an array of listeners */ public void setStreams(ItemStream[] streams) { @@ -1101,4 +1087,5 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN protected boolean hasPartitionElement() { return this.partitionHandler != null; } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/TaskletParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/TaskletParser.java index 6db4f597f..d9b555aa7 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/TaskletParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/TaskletParser.java @@ -34,11 +34,10 @@ import org.w3c.dom.Element; /** * Parse a tasklet element for a step. - * + * * @author Dave Syer - * * @since 2.1 - * + * */ public class TaskletParser { @@ -90,8 +89,8 @@ public class TaskletParser { } else if (beanElements.size() == 1) { Element beanElement = beanElements.get(0); - BeanDefinitionHolder beanDefinitionHolder = parserContext.getDelegate().parseBeanDefinitionElement( - beanElement, bd); + BeanDefinitionHolder beanDefinitionHolder = parserContext.getDelegate() + .parseBeanDefinitionElement(beanElement, bd); parserContext.getDelegate().decorateBeanDefinitionIfRequired(beanElement, beanDefinitionHolder); bme = beanDefinitionHolder; } @@ -168,10 +167,10 @@ public class TaskletParser { } if (error != null) { - parserContext.getReaderContext().error( - "The <" + taskletElement.getTagName() + "/> element " + error + " one of: '" + TASKLET_REF_ATTR - + "' attribute, <" + CHUNK_ELE + "/> element, <" + BEAN_ELE + "/> attribute, or <" - + REF_ELE + "/> element. Found: " + found + ".", taskletElement); + parserContext.getReaderContext() + .error("The <" + taskletElement.getTagName() + "/> element " + error + " one of: '" + + TASKLET_REF_ATTR + "' attribute, <" + CHUNK_ELE + "/> element, <" + BEAN_ELE + + "/> attribute, or <" + REF_ELE + "/> element. Found: " + found + ".", taskletElement); } } @@ -217,14 +216,14 @@ public class TaskletParser { propertyValues.addPropertyValue(propertyName, list); } else if (children.size() > 1) { - parserContext.getReaderContext().error( - "The <" + exceptionListName + "/> element may not appear more than once in a single <" - + element.getNodeName() + "/>.", element); + parserContext.getReaderContext().error("The <" + exceptionListName + + "/> element may not appear more than once in a single <" + element.getNodeName() + "/>.", + element); } } - private void addExceptionClasses(String elementName, Element exceptionClassesElement, ManagedList list, - ParserContext parserContext) { + private void addExceptionClasses(String elementName, Element exceptionClassesElement, + ManagedList list, ParserContext parserContext) { for (Element child : DomUtils.getChildElementsByTagName(exceptionClassesElement, elementName)) { String className = child.getAttribute("class"); list.add(new TypedStringValue(className, Class.class)); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/TopLevelFlowParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/TopLevelFlowParser.java index 69f3fb9b1..0ddaa3fb4 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/TopLevelFlowParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/TopLevelFlowParser.java @@ -41,7 +41,8 @@ public class TopLevelFlowParser extends AbstractFlowParser { String flowName = element.getAttribute(ID_ATTR); builder.getRawBeanDefinition().setAttribute("flowName", flowName); builder.addPropertyValue("name", flowName); - builder.addPropertyValue("stateTransitionComparator", new RuntimeBeanReference(DefaultStateTransitionComparator.STATE_TRANSITION_COMPARATOR)); + builder.addPropertyValue("stateTransitionComparator", + new RuntimeBeanReference(DefaultStateTransitionComparator.STATE_TRANSITION_COMPARATOR)); String abstractAttr = element.getAttribute(ABSTRACT_ATTR); if (StringUtils.hasText(abstractAttr)) { builder.setAbstract(abstractAttr.equals("true")); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/TopLevelStepParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/TopLevelStepParser.java index c2d85c0b5..19f5fffb8 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/TopLevelStepParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/TopLevelStepParser.java @@ -21,12 +21,11 @@ import org.springframework.beans.factory.xml.ParserContext; import org.w3c.dom.Element; /** - * Parser for the <step/> top level element in the Batch namespace. Sets up - * and returns a bean definition for a - * {@link org.springframework.batch.core.Step}. - * + * Parser for the <step/> top level element in the Batch namespace. Sets up and + * returns a bean definition for a {@link org.springframework.batch.core.Step}. + * * @author Thomas Risberg - * + * */ public class TopLevelStepParser extends AbstractBeanDefinitionParser { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/converter/DefaultJobParametersConverter.java b/spring-batch-core/src/main/java/org/springframework/batch/core/converter/DefaultJobParametersConverter.java index 6ab74eb41..2e0d71be8 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/converter/DefaultJobParametersConverter.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/converter/DefaultJobParametersConverter.java @@ -36,12 +36,11 @@ import java.util.Map.Entry; import java.util.Properties; /** - * Converter for {@link JobParameters} instances using a simple naming - * convention for property keys. Key names that are prefixed with a - are - * considered non-identifying and will not contribute to the identity of a - * {@link JobInstance}. Key names ending with "(<type>)" where - * type is one of string, date, long are converted to the corresponding type. - * The default type is string. E.g. + * Converter for {@link JobParameters} instances using a simple naming convention for + * property keys. Key names that are prefixed with a - are considered non-identifying and + * will not contribute to the identity of a {@link JobInstance}. Key names ending with + * "(<type>)" where type is one of string, date, long are converted to the + * corresponding type. The default type is string. E.g. * *
  * schedule.date(date)=2007/12/11
@@ -53,8 +52,8 @@ import java.util.Properties;
  *
  * 
* - * If you need to be able to parse and format local-specific dates and numbers, - * you can inject formatters ({@link #setDateFormat(DateFormat)} and + * If you need to be able to parse and format local-specific dates and numbers, you can + * inject formatters ({@link #setDateFormat(DateFormat)} and * {@link #setNumberFormat(NumberFormat)}). * * @author Dave Syer @@ -97,11 +96,9 @@ public class DefaultJobParametersConverter implements JobParametersConverter { private final NumberFormat longNumberFormat = new DecimalFormat("#"); /** - * Check for suffix on keys and use those to decide how to convert the - * value. - * - * @throws IllegalArgumentException if a number or date is passed in that - * cannot be parsed, or cast to the correct type. + * Check for suffix on keys and use those to decide how to convert the value. + * @throws IllegalArgumentException if a number or date is passed in that cannot be + * parsed, or cast to the correct type. * * @see org.springframework.batch.core.converter.JobParametersConverter#getJobParameters(java.util.Properties) */ @@ -120,9 +117,10 @@ public class DefaultJobParametersConverter implements JobParametersConverter { String value = (String) entry.getValue(); boolean identifying = isIdentifyingKey(key); - if(!identifying) { + if (!identifying) { key = key.replaceFirst(NON_IDENTIFYING_FLAG, ""); - } else if(identifying && key.startsWith(IDENTIFYING_FLAG)) { + } + else if (identifying && key.startsWith(IDENTIFYING_FLAG)) { key = key.replaceFirst("\\" + IDENTIFYING_FLAG, ""); } @@ -133,9 +131,9 @@ public class DefaultJobParametersConverter implements JobParametersConverter { date = dateFormat.parse(value); } catch (ParseException ex) { - String suffix = (dateFormat instanceof SimpleDateFormat) ? ", use " - + ((SimpleDateFormat) dateFormat).toPattern() : ""; - throw new IllegalArgumentException("Date format is invalid: [" + value + "]" + suffix); + String suffix = (dateFormat instanceof SimpleDateFormat) + ? ", use " + ((SimpleDateFormat) dateFormat).toPattern() : ""; + throw new IllegalArgumentException("Date format is invalid: [" + value + "]" + suffix); } } propertiesBuilder.addDate(StringUtils.replace(key, DATE_TYPE, ""), date, identifying); @@ -169,7 +167,7 @@ public class DefaultJobParametersConverter implements JobParametersConverter { private boolean isIdentifyingKey(String key) { boolean identifying = true; - if(key.startsWith(NON_IDENTIFYING_FLAG)) { + if (key.startsWith(NON_IDENTIFYING_FLAG)) { identifying = false; } @@ -185,19 +183,18 @@ public class DefaultJobParametersConverter implements JobParametersConverter { return numberFormat.parse(value); } catch (ParseException ex) { - String suffix = (numberFormat instanceof DecimalFormat) ? ", use " - + ((DecimalFormat) numberFormat).toPattern() : ""; - throw new IllegalArgumentException("Number format is invalid: [" + value + "], use " + suffix); + String suffix = (numberFormat instanceof DecimalFormat) + ? ", use " + ((DecimalFormat) numberFormat).toPattern() : ""; + throw new IllegalArgumentException("Number format is invalid: [" + value + "], use " + suffix); } } } /** - * Use the same suffixes to create properties (omitting the string suffix - * because it is the default). Non-identifying parameters will be prefixed - * with the {@link #NON_IDENTIFYING_FLAG}. However, since parameters are - * identifying by default, they will not be prefixed with the - * {@link #IDENTIFYING_FLAG}. + * Use the same suffixes to create properties (omitting the string suffix because it + * is the default). Non-identifying parameters will be prefixed with the + * {@link #NON_IDENTIFYING_FLAG}. However, since parameters are identifying by + * default, they will not be prefixed with the {@link #IDENTIFYING_FLAG}. * * @see org.springframework.batch.core.converter.JobParametersConverter#getProperties(org.springframework.batch.core.JobParameters) */ @@ -216,7 +213,7 @@ public class DefaultJobParametersConverter implements JobParametersConverter { JobParameter jobParameter = entry.getValue(); Object value = jobParameter.getValue(); if (value != null) { - key = (!jobParameter.isIdentifying()? NON_IDENTIFYING_FLAG : "") + key; + key = (!jobParameter.isIdentifying() ? NON_IDENTIFYING_FLAG : "") + key; if (jobParameter.getType() == ParameterType.DATE) { synchronized (dateFormat) { result.setProperty(key + DATE_TYPE, dateFormat.format(value)); @@ -228,7 +225,7 @@ public class DefaultJobParametersConverter implements JobParametersConverter { } } else if (jobParameter.getType() == ParameterType.DOUBLE) { - result.setProperty(key + DOUBLE_TYPE, decimalFormat((Double)value)); + result.setProperty(key + DOUBLE_TYPE, decimalFormat((Double) value)); } else { result.setProperty(key, "" + value); @@ -253,7 +250,6 @@ public class DefaultJobParametersConverter implements JobParametersConverter { /** * Public setter for injecting a date format. - * * @param dateFormat a {@link DateFormat}, defaults to "yyyy/MM/dd" */ public void setDateFormat(DateFormat dateFormat) { @@ -261,12 +257,12 @@ public class DefaultJobParametersConverter implements JobParametersConverter { } /** - * Public setter for the {@link NumberFormat}. Used to parse longs and - * doubles, so must not contain decimal place (e.g. use "#" or "#,###"). - * + * Public setter for the {@link NumberFormat}. Used to parse longs and doubles, so + * must not contain decimal place (e.g. use "#" or "#,###"). * @param numberFormat the {@link NumberFormat} to set */ public void setNumberFormat(NumberFormat numberFormat) { this.numberFormat = numberFormat; } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/converter/JobParametersConverter.java b/spring-batch-core/src/main/java/org/springframework/batch/core/converter/JobParametersConverter.java index 5bc3b86a9..f7a6eb1c0 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/converter/JobParametersConverter.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/converter/JobParametersConverter.java @@ -23,34 +23,31 @@ import org.springframework.batch.core.JobParametersBuilder; import org.springframework.lang.Nullable; /** - * A factory for {@link JobParameters} instances. A job can be executed with - * many possible runtime parameters, which identify the instance of the job. - * This converter allows job parameters to be converted to and from Properties. - * + * A factory for {@link JobParameters} instances. A job can be executed with many possible + * runtime parameters, which identify the instance of the job. This converter allows job + * parameters to be converted to and from Properties. + * * @author Dave Syer * @author Mahmoud Ben Hassine - * * @see JobParametersBuilder - * + * */ public interface JobParametersConverter { /** - * Get a new {@link JobParameters} instance. If given null, or an empty - * properties, an empty JobParameters will be returned. - * + * Get a new {@link JobParameters} instance. If given null, or an empty properties, an + * empty JobParameters will be returned. * @param properties the runtime parameters in the form of String literals. - * @return a {@link JobParameters} properties converted to the correct - * types. + * @return a {@link JobParameters} properties converted to the correct types. */ JobParameters getJobParameters(@Nullable Properties properties); /** - * The inverse operation: get a {@link Properties} instance. If given null - * or empty JobParameters, an empty Properties should be returned. - * + * The inverse operation: get a {@link Properties} instance. If given null or empty + * JobParameters, an empty Properties should be returned. * @param params the {@link JobParameters} instance to be converted. * @return a representation of the parameters as properties */ Properties getProperties(@Nullable JobParameters params); + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/converter/package-info.java b/spring-batch-core/src/main/java/org/springframework/batch/core/converter/package-info.java index 3330b0f30..8948cd221 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/converter/package-info.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/converter/package-info.java @@ -1,6 +1,6 @@ /** - * Support classes for implementations of the batch APIs. Things like converters and resource location and management - * concerns. + * Support classes for implementations of the batch APIs. Things like converters and + * resource location and management concerns. * * @author Michael Minella * @author Mahmoud Ben Hassine diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/explore/JobExplorer.java b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/JobExplorer.java index 586ad67be..e1c364f89 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/explore/JobExplorer.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/JobExplorer.java @@ -26,9 +26,9 @@ import org.springframework.batch.item.ExecutionContext; import org.springframework.lang.Nullable; /** - * Entry point for browsing executions of running or historical jobs and steps. - * Since the data may be re-hydrated from persistent storage, it may not contain - * volatile fields that would have been present when the execution was active. + * Entry point for browsing executions of running or historical jobs and steps. Since the + * data may be re-hydrated from persistent storage, it may not contain volatile fields + * that would have been present when the execution was active. * * @author Dave Syer * @author Michael Minella @@ -39,9 +39,8 @@ import org.springframework.lang.Nullable; public interface JobExplorer { /** - * Fetch {@link JobInstance} values in descending order of creation (and - * therefore usually of first execution). - * + * Fetch {@link JobInstance} values in descending order of creation (and therefore + * usually of first execution). * @param jobName the name of the job to query * @param start the start index of the instances to return * @param count the maximum number of instances to return @@ -62,12 +61,10 @@ public interface JobExplorer { } /** - * Retrieve a {@link JobExecution} by its id. The complete object graph for - * this execution should be returned (unless otherwise indicated) including - * the parent {@link JobInstance} and associated {@link ExecutionContext} - * and {@link StepExecution} instances (also including their execution - * contexts). - * + * Retrieve a {@link JobExecution} by its id. The complete object graph for this + * execution should be returned (unless otherwise indicated) including the parent + * {@link JobInstance} and associated {@link ExecutionContext} and + * {@link StepExecution} instances (also including their execution contexts). * @param executionId the job execution id * @return the {@link JobExecution} with this id, or null if not found */ @@ -75,11 +72,10 @@ public interface JobExplorer { JobExecution getJobExecution(@Nullable Long executionId); /** - * Retrieve a {@link StepExecution} by its id and parent - * {@link JobExecution} id. The execution context for the step should be - * available in the result, and the parent job execution should have its - * primitive properties, but may not contain the job instance information. - * + * Retrieve a {@link StepExecution} by its id and parent {@link JobExecution} id. The + * execution context for the step should be available in the result, and the parent + * job execution should have its primitive properties, but may not contain the job + * instance information. * @param jobExecutionId the parent job execution id * @param stepExecutionId the step execution id * @return the {@link StepExecution} with this id, or null if not found @@ -97,11 +93,10 @@ public interface JobExplorer { JobInstance getJobInstance(@Nullable Long instanceId); /** - * Retrieve job executions by their job instance. The corresponding step - * executions may not be fully hydrated (e.g. their execution context may be - * missing), depending on the implementation. Use - * {@link #getStepExecution(Long, Long)} to hydrate them in that case. - * + * Retrieve job executions by their job instance. The corresponding step executions + * may not be fully hydrated (e.g. their execution context may be missing), depending + * on the implementation. Use {@link #getStepExecution(Long, Long)} to hydrate them in + * that case. * @param jobInstance the {@link JobInstance} to query * @return the set of all executions for the specified {@link JobInstance} */ @@ -122,11 +117,10 @@ public interface JobExplorer { } /** - * Retrieve running job executions. The corresponding step executions may - * not be fully hydrated (e.g. their execution context may be missing), - * depending on the implementation. Use - * {@link #getStepExecution(Long, Long)} to hydrate them in that case. - * + * Retrieve running job executions. The corresponding step executions may not be fully + * hydrated (e.g. their execution context may be missing), depending on the + * implementation. Use {@link #getStepExecution(Long, Long)} to hydrate them in that + * case. * @param jobName the name of the job * @return the set of running executions for jobs with the specified name */ @@ -135,15 +129,13 @@ public interface JobExplorer { /** * Query the repository for all unique {@link JobInstance} names (sorted * alphabetically). - * * @return the set of job names that have been executed */ List getJobNames(); - + /** - * Fetch {@link JobInstance} values in descending order of creation (and - * there for usually of first execution) with a 'like'/wildcard criteria. - * + * Fetch {@link JobInstance} values in descending order of creation (and there for + * usually of first execution) with a 'like'/wildcard criteria. * @param jobName the name of the job to query for. * @param start the start index of the instances to return. * @param count the maximum number of instances to return. @@ -152,15 +144,13 @@ public interface JobExplorer { List findJobInstancesByJobName(String jobName, int start, int count); /** - * Query the repository for the number of unique {@link JobInstance}s - * associated with the supplied job name. - * + * Query the repository for the number of unique {@link JobInstance}s associated with + * the supplied job name. * @param jobName the name of the job to query for - * @return the number of {@link JobInstance}s that exist within the - * associated job repository - * - * @throws NoSuchJobException thrown when there is no {@link JobInstance} - * for the jobName specified. + * @return the number of {@link JobInstance}s that exist within the associated job + * repository + * @throws NoSuchJobException thrown when there is no {@link JobInstance} for the + * jobName specified. */ int getJobInstanceCount(@Nullable String jobName) throws NoSuchJobException; diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/AbstractJobExplorerFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/AbstractJobExplorerFactoryBean.java index c4918d736..71ded02e8 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/AbstractJobExplorerFactoryBean.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/explore/support/AbstractJobExplorerFactoryBean.java @@ -24,12 +24,10 @@ import org.springframework.batch.core.repository.dao.StepExecutionDao; import org.springframework.beans.factory.FactoryBean; /** - * A {@link FactoryBean} that automates the creation of a - * {@link SimpleJobExplorer}. Declares abstract methods for providing DAO - * object implementations. + * A {@link FactoryBean} that automates the creation of a {@link SimpleJobExplorer}. + * Declares abstract methods for providing DAO object implementations. * * @see JobExplorerFactoryBean - * * @author Dave Syer * @author Mahmoud Ben Hassine * @since 2.0 @@ -38,35 +36,30 @@ public abstract class AbstractJobExplorerFactoryBean implements FactoryBean findJobInstancesByJobName(String jobName, int start, int count) { return jobInstanceDao.findJobInstancesByName(jobName, start, count); } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/AbstractJob.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/AbstractJob.java index 148baefd3..dad6e100a 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/AbstractJob.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/AbstractJob.java @@ -59,17 +59,17 @@ import org.springframework.util.Assert; import org.springframework.util.ClassUtils; /** - * Abstract implementation of the {@link Job} interface. Common dependencies - * such as a {@link JobRepository}, {@link JobExecutionListener}s, and various - * configuration parameters are set here. Therefore, common error handling and - * listener calling activities are abstracted away from implementations. + * Abstract implementation of the {@link Job} interface. Common dependencies such as a + * {@link JobRepository}, {@link JobExecutionListener}s, and various configuration + * parameters are set here. Therefore, common error handling and listener calling + * activities are abstracted away from implementations. * * @author Lucas Ward * @author Dave Syer * @author Mahmoud Ben Hassine */ -public abstract class AbstractJob implements Job, StepLocator, BeanNameAware, -InitializingBean, Observation.KeyValuesProviderAware { +public abstract class AbstractJob implements Job, StepLocator, BeanNameAware, InitializingBean, + Observation.KeyValuesProviderAware { protected static final Log logger = LogFactory.getLog(AbstractJob.class); @@ -97,9 +97,7 @@ InitializingBean, Observation.KeyValuesProviderAware } /** - * Convenience constructor to immediately add name (which is mandatory but - * not final). - * + * Convenience constructor to immediately add name (which is mandatory but not final). * @param name name of the job */ public AbstractJob(String name) { @@ -110,12 +108,9 @@ InitializingBean, Observation.KeyValuesProviderAware /** * A validator for job parameters. Defaults to a vanilla * {@link DefaultJobParametersValidator}. - * - * @param jobParametersValidator - * a validator instance + * @param jobParametersValidator a validator instance */ - public void setJobParametersValidator( - JobParametersValidator jobParametersValidator) { + public void setJobParametersValidator(JobParametersValidator jobParametersValidator) { this.jobParametersValidator = jobParametersValidator; } @@ -130,11 +125,11 @@ InitializingBean, Observation.KeyValuesProviderAware } /** - * Set the name property if it is not already set. Because of the order of - * the callbacks in a Spring container the name property will be set first - * if it is present. Care is needed with bean definition inheritance - if a - * parent bean has a name, then its children need an explicit name as well, - * otherwise they will not be unique. + * Set the name property if it is not already set. Because of the order of the + * callbacks in a Spring container the name property will be set first if it is + * present. Care is needed with bean definition inheritance - if a parent bean has a + * name, then its children need an explicit name as well, otherwise they will not be + * unique. * * @see org.springframework.beans.factory.BeanNameAware#setBeanName(java.lang.String) */ @@ -146,9 +141,8 @@ InitializingBean, Observation.KeyValuesProviderAware } /** - * Set the name property. Always overrides the default value if this object - * is a Spring bean. - * + * Set the name property. Always overrides the default value if this object is a + * Spring bean. * @param name the name to be associated with the job. * * @see #setBeanName(java.lang.String) @@ -168,9 +162,8 @@ InitializingBean, Observation.KeyValuesProviderAware } /** - * Retrieve the step with the given name. If there is no Step with the given - * name, then return null. - * + * Retrieve the step with the given name. If there is no Step with the given name, + * then return null. * @param stepName name of the step * @return the Step */ @@ -179,7 +172,6 @@ InitializingBean, Observation.KeyValuesProviderAware /** * Retrieve the step names. - * * @return the step names */ @Override @@ -191,11 +183,9 @@ InitializingBean, Observation.KeyValuesProviderAware } /** - * Boolean flag to prevent categorically a job from restarting, even if it - * has failed previously. - * - * @param restartable - * the value of the flag to set (default true) + * Boolean flag to prevent categorically a job from restarting, even if it has failed + * previously. + * @param restartable the value of the flag to set (default true) */ public void setRestartable(boolean restartable) { this.restartable = restartable; @@ -211,12 +201,9 @@ InitializingBean, Observation.KeyValuesProviderAware /** * Public setter for the {@link JobParametersIncrementer}. - * - * @param jobParametersIncrementer - * the {@link JobParametersIncrementer} to set + * @param jobParametersIncrementer the {@link JobParametersIncrementer} to set */ - public void setJobParametersIncrementer( - JobParametersIncrementer jobParametersIncrementer) { + public void setJobParametersIncrementer(JobParametersIncrementer jobParametersIncrementer) { this.jobParametersIncrementer = jobParametersIncrementer; } @@ -232,11 +219,9 @@ InitializingBean, Observation.KeyValuesProviderAware } /** - * Public setter for injecting {@link JobExecutionListener}s. They will all - * be given the listener callbacks at the appropriate point in the job. - * - * @param listeners - * the listeners to set. + * Public setter for injecting {@link JobExecutionListener}s. They will all be given + * the listener callbacks at the appropriate point in the job. + * @param listeners the listeners to set. */ public void setJobExecutionListeners(JobExecutionListener[] listeners) { for (int i = 0; i < listeners.length; i++) { @@ -245,21 +230,16 @@ InitializingBean, Observation.KeyValuesProviderAware } /** - * Register a single listener for the {@link JobExecutionListener} - * callbacks. - * - * @param listener - * a {@link JobExecutionListener} + * Register a single listener for the {@link JobExecutionListener} callbacks. + * @param listener a {@link JobExecutionListener} */ public void registerJobExecutionListener(JobExecutionListener listener) { this.listener.register(listener); } /** - * Public setter for the {@link JobRepository} that is needed to manage the - * state of the batch meta domain (jobs, steps, executions) during the life - * of a job. - * + * Public setter for the {@link JobRepository} that is needed to manage the state of + * the batch meta domain (jobs, steps, executions) during the life of a job. * @param jobRepository repository to use during the job execution */ public void setJobRepository(JobRepository jobRepository) { @@ -269,7 +249,6 @@ InitializingBean, Observation.KeyValuesProviderAware /** * Convenience method for subclasses to access the job repository. - * * @return the jobRepository */ protected JobRepository getJobRepository() { @@ -277,28 +256,22 @@ InitializingBean, Observation.KeyValuesProviderAware } /** - * Extension point for subclasses allowing them to concentrate on processing - * logic and ignore listeners and repository calls. Implementations usually - * are concerned with the ordering of steps, and delegate actual step - * processing to {@link #handleStep(Step, JobExecution)}. - * - * @param execution - * the current {@link JobExecution} - * - * @throws JobExecutionException - * to signal a fatal batch framework error (not a business or - * validation exception) + * Extension point for subclasses allowing them to concentrate on processing logic and + * ignore listeners and repository calls. Implementations usually are concerned with + * the ordering of steps, and delegate actual step processing to + * {@link #handleStep(Step, JobExecution)}. + * @param execution the current {@link JobExecution} + * @throws JobExecutionException to signal a fatal batch framework error (not a + * business or validation exception) */ - abstract protected void doExecute(JobExecution execution) - throws JobExecutionException; + abstract protected void doExecute(JobExecution execution) throws JobExecutionException; /** - * Run the specified job, handling all listener and repository calls, and - * delegating the actual processing to {@link #doExecute(JobExecution)}. + * Run the specified job, handling all listener and repository calls, and delegating + * the actual processing to {@link #doExecute(JobExecution)}. * * @see Job#execute(JobExecution) - * @throws StartLimitExceededException - * if start limit of one of the steps was exceeded + * @throws StartLimitExceededException if start limit of one of the steps was exceeded */ @Override public final void execute(JobExecution execution) { @@ -311,12 +284,12 @@ InitializingBean, Observation.KeyValuesProviderAware JobSynchronizationManager.register(execution); String activeJobMeterName = "job.active"; - LongTaskTimer longTaskTimer = BatchMetrics.createLongTaskTimer(activeJobMeterName, "Active jobs", - Tag.of(BatchMetrics.METRICS_PREFIX + activeJobMeterName + ".name", execution.getJobInstance().getJobName())); + LongTaskTimer longTaskTimer = BatchMetrics.createLongTaskTimer(activeJobMeterName, "Active jobs", Tag.of( + BatchMetrics.METRICS_PREFIX + activeJobMeterName + ".name", execution.getJobInstance().getJobName())); LongTaskTimer.Sample longTaskTimerSample = longTaskTimer.start(); - Observation observation = BatchMetrics.createObservation(BatchJobObservation.BATCH_JOB_OBSERVATION.getName(), new BatchJobContext(execution)) - .contextualName(execution.getJobInstance().getJobName()) - .keyValuesProvider(this.keyValuesProvider) + Observation observation = BatchMetrics + .createObservation(BatchJobObservation.BATCH_JOB_OBSERVATION.getName(), new BatchJobContext(execution)) + .contextualName(execution.getJobInstance().getJobName()).keyValuesProvider(this.keyValuesProvider) .start(); try (Observation.Scope scope = observation.openScope()) { @@ -334,10 +307,12 @@ InitializingBean, Observation.KeyValuesProviderAware if (logger.isDebugEnabled()) { logger.debug("Job execution complete: " + execution); } - } catch (RepeatException e) { + } + catch (RepeatException e) { throw e.getCause(); } - } else { + } + else { // The job was already stopped before we even got this far. Deal // with it in the same way as any other interruption. @@ -349,10 +324,10 @@ InitializingBean, Observation.KeyValuesProviderAware } - } catch (JobInterruptedException e) { + } + catch (JobInterruptedException e) { if (logger.isInfoEnabled()) { - logger.info("Encountered interruption executing job: " - + e.getMessage()); + logger.info("Encountered interruption executing job: " + e.getMessage()); } if (logger.isDebugEnabled()) { logger.debug("Full exception", e); @@ -360,18 +335,20 @@ InitializingBean, Observation.KeyValuesProviderAware execution.setExitStatus(getDefaultExitStatusForFailure(e, execution)); execution.setStatus(BatchStatus.max(BatchStatus.STOPPED, e.getStatus())); execution.addFailureException(e); - } catch (Throwable t) { + } + catch (Throwable t) { logger.error("Encountered fatal error executing job", t); execution.setExitStatus(getDefaultExitStatusForFailure(t, execution)); execution.setStatus(BatchStatus.FAILED); execution.addFailureException(t); - } finally { + } + finally { try { if (execution.getStatus().isLessThanOrEqualTo(BatchStatus.STOPPED) && execution.getStepExecutions().isEmpty()) { ExitStatus exitStatus = execution.getExitStatus(); - ExitStatus newExitStatus = - ExitStatus.NOOP.addExitDescription("All steps already completed or no steps configured for this job."); + ExitStatus newExitStatus = ExitStatus.NOOP + .addExitDescription("All steps already completed or no steps configured for this job."); execution.setExitStatus(exitStatus.and(newExitStatus)); } stopObservation(execution, observation); @@ -380,12 +357,14 @@ InitializingBean, Observation.KeyValuesProviderAware try { listener.afterJob(execution); - } catch (Exception e) { + } + catch (Exception e) { logger.error("Exception encountered in afterJob callback", e); } jobRepository.update(execution); - } finally { + } + finally { JobSynchronizationManager.release(); } @@ -407,53 +386,43 @@ InitializingBean, Observation.KeyValuesProviderAware } /** - * Convenience method for subclasses to delegate the handling of a specific - * step in the context of the current {@link JobExecution}. Clients of this - * method do not need access to the {@link JobRepository}, nor do they need - * to worry about populating the execution context on a restart, nor - * detecting the interrupted state (in job or step execution). - * - * @param step - * the {@link Step} to execute - * @param execution - * the current {@link JobExecution} + * Convenience method for subclasses to delegate the handling of a specific step in + * the context of the current {@link JobExecution}. Clients of this method do not need + * access to the {@link JobRepository}, nor do they need to worry about populating the + * execution context on a restart, nor detecting the interrupted state (in job or step + * execution). + * @param step the {@link Step} to execute + * @param execution the current {@link JobExecution} * @return the {@link StepExecution} corresponding to this step - * - * @throws JobInterruptedException - * if the {@link JobExecution} has been interrupted, and in - * particular if {@link BatchStatus#ABANDONED} or - * {@link BatchStatus#STOPPING} is detected - * @throws StartLimitExceededException - * if the start limit has been exceeded for this step - * @throws JobRestartException - * if the job is in an inconsistent state from an earlier - * failure + * @throws JobInterruptedException if the {@link JobExecution} has been interrupted, + * and in particular if {@link BatchStatus#ABANDONED} or {@link BatchStatus#STOPPING} + * is detected + * @throws StartLimitExceededException if the start limit has been exceeded for this + * step + * @throws JobRestartException if the job is in an inconsistent state from an earlier + * failure */ protected final StepExecution handleStep(Step step, JobExecution execution) - throws JobInterruptedException, JobRestartException, - StartLimitExceededException { + throws JobInterruptedException, JobRestartException, StartLimitExceededException { return stepHandler.handleStep(step, execution); } /** * Default mapping from throwable to {@link ExitStatus}. - * * @param ex the cause of the failure * @param execution the {@link JobExecution} instance. * @return an {@link ExitStatus} */ protected ExitStatus getDefaultExitStatusForFailure(Throwable ex, JobExecution execution) { ExitStatus exitStatus; - if (ex instanceof JobInterruptedException - || ex.getCause() instanceof JobInterruptedException) { - exitStatus = ExitStatus.STOPPED - .addExitDescription(JobInterruptedException.class.getName()); - } else if (ex instanceof NoSuchJobException - || ex.getCause() instanceof NoSuchJobException) { - exitStatus = new ExitStatus(ExitCodeMapper.NO_SUCH_JOB, ex - .getClass().getName()); - } else { + if (ex instanceof JobInterruptedException || ex.getCause() instanceof JobInterruptedException) { + exitStatus = ExitStatus.STOPPED.addExitDescription(JobInterruptedException.class.getName()); + } + else if (ex instanceof NoSuchJobException || ex.getCause() instanceof NoSuchJobException) { + exitStatus = new ExitStatus(ExitCodeMapper.NO_SUCH_JOB, ex.getClass().getName()); + } + else { exitStatus = ExitStatus.FAILED.addExitDescription(ex); } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/CompositeJobParametersValidator.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/CompositeJobParametersValidator.java index 9c327cc39..86ba78749 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/CompositeJobParametersValidator.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/CompositeJobParametersValidator.java @@ -25,8 +25,8 @@ import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** - * Composite {@link JobParametersValidator} that passes the job parameters through a sequence of - * injected JobParametersValidators + * Composite {@link JobParametersValidator} that passes the job parameters through a + * sequence of injected JobParametersValidators * * @author Morten Andersen-Gott * @author Mahmoud Ben Hassine @@ -39,7 +39,6 @@ public class CompositeJobParametersValidator implements JobParametersValidator, /** * Validates the JobParameters according to the injected JobParameterValidators * Validation stops and exception is thrown on first validation error - * * @param parameters some {@link JobParameters} * @throws JobParametersInvalidException if the parameters are invalid */ @@ -52,7 +51,8 @@ public class CompositeJobParametersValidator implements JobParametersValidator, /** * Public setter for the validators - * @param validators list of validators to be used by the CompositeJobParametersValidator. + * @param validators list of validators to be used by the + * CompositeJobParametersValidator. */ public void setValidators(List validators) { this.validators = validators; @@ -64,6 +64,4 @@ public class CompositeJobParametersValidator implements JobParametersValidator, Assert.notEmpty(validators, "The 'validators' may not be empty"); } - - } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/DefaultJobParametersValidator.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/DefaultJobParametersValidator.java index 23c228429..c20410ae9 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/DefaultJobParametersValidator.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/DefaultJobParametersValidator.java @@ -1,152 +1,144 @@ -/* - * Copyright 2012-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.job; - -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; - -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersInvalidException; -import org.springframework.batch.core.JobParametersValidator; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.lang.Nullable; -import org.springframework.util.Assert; - -/** - * Default implementation of {@link JobParametersValidator}. - * - * @author Dave Syer - * @author Mahmoud Ben Hassine - * - */ -public class DefaultJobParametersValidator implements JobParametersValidator, InitializingBean { - - private Collection requiredKeys; - - private Collection optionalKeys; - - /** - * Convenient default constructor for unconstrained validation. - */ - public DefaultJobParametersValidator() { - this(new String[0], new String[0]); - } - - /** - * Create a new validator with the required and optional job parameter keys - * provided. - * - * @see DefaultJobParametersValidator#setOptionalKeys(String[]) - * @see DefaultJobParametersValidator#setRequiredKeys(String[]) - * - * @param requiredKeys the required keys - * @param optionalKeys the optional keys - */ - public DefaultJobParametersValidator(String[] requiredKeys, String[] optionalKeys) { - super(); - setRequiredKeys(requiredKeys); - setOptionalKeys(optionalKeys); - } - - /** - * Check that there are no overlaps between required and optional keys. - * @throws IllegalStateException if there is an overlap - */ - @Override - public void afterPropertiesSet() throws IllegalStateException { - for (String key : requiredKeys) { - Assert.state(!optionalKeys.contains(key), "Optional keys cannot be required: " + key); - } - } - - /** - * Check the parameters meet the specification provided. If optional keys - * are explicitly specified then all keys must be in that list, or in the - * required list. Otherwise all keys that are specified as required must be - * present. - * - * @see JobParametersValidator#validate(JobParameters) - * - * @throws JobParametersInvalidException if the parameters are not valid - */ - @Override - public void validate(@Nullable JobParameters parameters) throws JobParametersInvalidException { - - if (parameters == null) { - throw new JobParametersInvalidException("The JobParameters can not be null"); - } - - Set keys = parameters.getParameters().keySet(); - - // If there are explicit optional keys then all keys must be in that - // group, or in the required group. - if (!optionalKeys.isEmpty()) { - - Collection missingKeys = new HashSet<>(); - for (String key : keys) { - if (!optionalKeys.contains(key) && !requiredKeys.contains(key)) { - missingKeys.add(key); - } - } - if (!missingKeys.isEmpty()) { - throw new JobParametersInvalidException( - "The JobParameters contains keys that are not explicitly optional or required: " + missingKeys); - } - - } - - Collection missingKeys = new HashSet<>(); - for (String key : requiredKeys) { - if (!keys.contains(key)) { - missingKeys.add(key); - } - } - if (!missingKeys.isEmpty()) { - throw new JobParametersInvalidException("The JobParameters do not contain required keys: " + missingKeys); - } - - } - - /** - * The keys that are required in the parameters. The default is empty, - * meaning that all parameters are optional, unless optional keys are - * explicitly specified. - * - * @param requiredKeys the required key values - * - * @see #setOptionalKeys(String[]) - */ - public final void setRequiredKeys(String[] requiredKeys) { - this.requiredKeys = new HashSet<>(Arrays.asList(requiredKeys)); - } - - /** - * The keys that are optional in the parameters. If any keys are explicitly - * optional, then to be valid all other keys must be explicitly required. - * The default is empty, meaning that all parameters that are not required - * are optional. - * - * @param optionalKeys the optional key values - * - * @see #setRequiredKeys(String[]) - */ - public final void setOptionalKeys(String[] optionalKeys) { - this.optionalKeys = new HashSet<>(Arrays.asList(optionalKeys)); - } - -} +/* + * Copyright 2012-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.job; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.JobParametersInvalidException; +import org.springframework.batch.core.JobParametersValidator; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; + +/** + * Default implementation of {@link JobParametersValidator}. + * + * @author Dave Syer + * @author Mahmoud Ben Hassine + * + */ +public class DefaultJobParametersValidator implements JobParametersValidator, InitializingBean { + + private Collection requiredKeys; + + private Collection optionalKeys; + + /** + * Convenient default constructor for unconstrained validation. + */ + public DefaultJobParametersValidator() { + this(new String[0], new String[0]); + } + + /** + * Create a new validator with the required and optional job parameter keys provided. + * + * @see DefaultJobParametersValidator#setOptionalKeys(String[]) + * @see DefaultJobParametersValidator#setRequiredKeys(String[]) + * @param requiredKeys the required keys + * @param optionalKeys the optional keys + */ + public DefaultJobParametersValidator(String[] requiredKeys, String[] optionalKeys) { + super(); + setRequiredKeys(requiredKeys); + setOptionalKeys(optionalKeys); + } + + /** + * Check that there are no overlaps between required and optional keys. + * @throws IllegalStateException if there is an overlap + */ + @Override + public void afterPropertiesSet() throws IllegalStateException { + for (String key : requiredKeys) { + Assert.state(!optionalKeys.contains(key), "Optional keys cannot be required: " + key); + } + } + + /** + * Check the parameters meet the specification provided. If optional keys are + * explicitly specified then all keys must be in that list, or in the required list. + * Otherwise all keys that are specified as required must be present. + * + * @see JobParametersValidator#validate(JobParameters) + * @throws JobParametersInvalidException if the parameters are not valid + */ + @Override + public void validate(@Nullable JobParameters parameters) throws JobParametersInvalidException { + + if (parameters == null) { + throw new JobParametersInvalidException("The JobParameters can not be null"); + } + + Set keys = parameters.getParameters().keySet(); + + // If there are explicit optional keys then all keys must be in that + // group, or in the required group. + if (!optionalKeys.isEmpty()) { + + Collection missingKeys = new HashSet<>(); + for (String key : keys) { + if (!optionalKeys.contains(key) && !requiredKeys.contains(key)) { + missingKeys.add(key); + } + } + if (!missingKeys.isEmpty()) { + throw new JobParametersInvalidException( + "The JobParameters contains keys that are not explicitly optional or required: " + missingKeys); + } + + } + + Collection missingKeys = new HashSet<>(); + for (String key : requiredKeys) { + if (!keys.contains(key)) { + missingKeys.add(key); + } + } + if (!missingKeys.isEmpty()) { + throw new JobParametersInvalidException("The JobParameters do not contain required keys: " + missingKeys); + } + + } + + /** + * The keys that are required in the parameters. The default is empty, meaning that + * all parameters are optional, unless optional keys are explicitly specified. + * @param requiredKeys the required key values + * + * @see #setOptionalKeys(String[]) + */ + public final void setRequiredKeys(String[] requiredKeys) { + this.requiredKeys = new HashSet<>(Arrays.asList(requiredKeys)); + } + + /** + * The keys that are optional in the parameters. If any keys are explicitly optional, + * then to be valid all other keys must be explicitly required. The default is empty, + * meaning that all parameters that are not required are optional. + * @param optionalKeys the optional key values + * + * @see #setRequiredKeys(String[]) + */ + public final void setOptionalKeys(String[] optionalKeys) { + this.optionalKeys = new HashSet<>(Arrays.asList(optionalKeys)); + } + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/SimpleJob.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/SimpleJob.java index 1ac8cef78..d285ca702 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/SimpleJob.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/SimpleJob.java @@ -32,9 +32,9 @@ import org.springframework.batch.core.step.StepLocator; /** * Simple implementation of {@link Job} interface providing the ability to run a - * {@link JobExecution}. Sequentially executes a job by iterating through its - * list of steps. Any {@link Step} that fails will fail the job. The job is - * considered complete when all steps have been executed. + * {@link JobExecution}. Sequentially executes a job by iterating through its list of + * steps. Any {@link Step} that fails will fail the job. The job is considered complete + * when all steps have been executed. * * @author Lucas Ward * @author Dave Syer @@ -62,7 +62,6 @@ public class SimpleJob extends AbstractJob { /** * Public setter for the steps in this job. Overrides any calls to * {@link #addStep(Step)}. - * * @param steps the steps to execute */ public void setSteps(List steps) { @@ -72,7 +71,6 @@ public class SimpleJob extends AbstractJob { /** * Convenience method for clients to inspect the steps for this job. - * * @return the step names for this job */ @Override @@ -81,8 +79,8 @@ public class SimpleJob extends AbstractJob { for (Step step : steps) { names.add(step.getName()); - if(step instanceof StepLocator) { - names.addAll(((StepLocator)step).getStepNames()); + if (step instanceof StepLocator) { + names.addAll(((StepLocator) step).getStepNames()); } } return names; @@ -90,7 +88,6 @@ public class SimpleJob extends AbstractJob { /** * Convenience method for adding a single step to the job. - * * @param step a {@link Step} to add */ public void addStep(Step step) { @@ -100,17 +97,17 @@ public class SimpleJob extends AbstractJob { /* * (non-Javadoc) * - * @see - * org.springframework.batch.core.job.AbstractJob#getStep(java.lang.String) + * @see org.springframework.batch.core.job.AbstractJob#getStep(java.lang.String) */ @Override public Step getStep(String stepName) { for (Step step : this.steps) { if (step.getName().equals(stepName)) { return step; - } else if(step instanceof StepLocator) { - Step result = ((StepLocator)step).getStep(stepName); - if(result != null) { + } + else if (step instanceof StepLocator) { + Step result = ((StepLocator) step).getStep(stepName); + if (result != null) { return result; } } @@ -119,17 +116,16 @@ public class SimpleJob extends AbstractJob { } /** - * Handler of steps sequentially as provided, checking each one for success - * before moving to the next. Returns the last {@link StepExecution} - * successfully processed if it exists, and null if none were processed. - * + * Handler of steps sequentially as provided, checking each one for success before + * moving to the next. Returns the last {@link StepExecution} successfully processed + * if it exists, and null if none were processed. * @param execution the current {@link JobExecution} * * @see AbstractJob#handleStep(Step, JobExecution) */ @Override - protected void doExecute(JobExecution execution) throws JobInterruptedException, JobRestartException, - StartLimitExceededException { + protected void doExecute(JobExecution execution) + throws JobInterruptedException, JobRestartException, StartLimitExceededException { StepExecution stepExecution = null; for (Step step : steps) { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/SimpleStepHandler.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/SimpleStepHandler.java index 27b784714..930ab7f0c 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/SimpleStepHandler.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/SimpleStepHandler.java @@ -1,239 +1,240 @@ -/* - * Copyright 2006-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.core.job; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobInstance; -import org.springframework.batch.core.JobInterruptedException; -import org.springframework.batch.core.StartLimitExceededException; -import org.springframework.batch.core.Step; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.repository.JobRepository; -import org.springframework.batch.core.repository.JobRestartException; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.util.Assert; - -/** - * Implementation of {@link StepHandler} that manages repository and restart - * concerns. - * - * @author Dave Syer - * - */ -public class SimpleStepHandler implements StepHandler, InitializingBean { - - private static final Log logger = LogFactory.getLog(SimpleStepHandler.class); - - private JobRepository jobRepository; - - private ExecutionContext executionContext; - - /** - * Convenient default constructor for configuration usage. - */ - public SimpleStepHandler() { - this(null); - } - - /** - * @param jobRepository a {@link org.springframework.batch.core.repository.JobRepository} - */ - public SimpleStepHandler(JobRepository jobRepository) { - this(jobRepository, new ExecutionContext()); - } - - /** - * @param jobRepository a {@link org.springframework.batch.core.repository.JobRepository} - * @param executionContext the {@link org.springframework.batch.item.ExecutionContext} for the current Step - */ - public SimpleStepHandler(JobRepository jobRepository, ExecutionContext executionContext) { - this.jobRepository = jobRepository; - this.executionContext = executionContext; - } - - /** - * Check mandatory properties (jobRepository). - * - * @see InitializingBean#afterPropertiesSet() - */ - @Override - public void afterPropertiesSet() throws Exception { - Assert.state(jobRepository != null, "A JobRepository must be provided"); - } - - /** - * @return the used jobRepository - */ - protected JobRepository getJobRepository() { - return this.jobRepository; - } - - /** - * @param jobRepository the jobRepository to set - */ - public void setJobRepository(JobRepository jobRepository) { - this.jobRepository = jobRepository; - } - - /** - * A context containing values to be added to the step execution before it - * is handled. - * - * @param executionContext the execution context to set - */ - public void setExecutionContext(ExecutionContext executionContext) { - this.executionContext = executionContext; - } - - @Override - public StepExecution handleStep(Step step, JobExecution execution) throws JobInterruptedException, - JobRestartException, StartLimitExceededException { - if (execution.isStopping()) { - throw new JobInterruptedException("JobExecution interrupted."); - } - - JobInstance jobInstance = execution.getJobInstance(); - - StepExecution lastStepExecution = jobRepository.getLastStepExecution(jobInstance, step.getName()); - if (stepExecutionPartOfExistingJobExecution(execution, lastStepExecution)) { - // If the last execution of this step was in the same job, it's - // probably intentional so we want to run it again... - if (logger.isInfoEnabled()) { - logger.info(String.format("Duplicate step [%s] detected in execution of job=[%s]. " - + "If either step fails, both will be executed again on restart.", step.getName(), jobInstance - .getJobName())); - } - lastStepExecution = null; - } - StepExecution currentStepExecution = lastStepExecution; - - if (shouldStart(lastStepExecution, execution, step)) { - - currentStepExecution = execution.createStepExecution(step.getName()); - - boolean isRestart = (lastStepExecution != null && !lastStepExecution.getStatus().equals( - BatchStatus.COMPLETED)); - - if (isRestart) { - currentStepExecution.setExecutionContext(lastStepExecution.getExecutionContext()); - - if(lastStepExecution.getExecutionContext().containsKey("batch.executed")) { - currentStepExecution.getExecutionContext().remove("batch.executed"); - } - } - else { - currentStepExecution.setExecutionContext(new ExecutionContext(executionContext)); - } - - jobRepository.add(currentStepExecution); - - if (logger.isInfoEnabled()) { - logger.info("Executing step: [" + step.getName() + "]"); - } - try { - step.execute(currentStepExecution); - currentStepExecution.getExecutionContext().put("batch.executed", true); - } - catch (JobInterruptedException e) { - // Ensure that the job gets the message that it is stopping - // and can pass it on to other steps that are executing - // concurrently. - execution.setStatus(BatchStatus.STOPPING); - throw e; - } - - jobRepository.updateExecutionContext(execution); - - if (currentStepExecution.getStatus() == BatchStatus.STOPPING - || currentStepExecution.getStatus() == BatchStatus.STOPPED) { - // Ensure that the job gets the message that it is stopping - execution.setStatus(BatchStatus.STOPPING); - throw new JobInterruptedException("Job interrupted by step execution"); - } - - } - - return currentStepExecution; - } - - /** - * Detect whether a step execution belongs to this job execution. - * @param jobExecution the current job execution - * @param stepExecution an existing step execution - * @return true if the {@link org.springframework.batch.core.StepExecution} is part of the {@link org.springframework.batch.core.JobExecution} - */ - private boolean stepExecutionPartOfExistingJobExecution(JobExecution jobExecution, StepExecution stepExecution) { - return stepExecution != null && stepExecution.getJobExecutionId() != null - && stepExecution.getJobExecutionId().equals(jobExecution.getId()); - } - - /** - * Given a step and configuration, return true if the step should start, - * false if it should not, and throw an exception if the job should finish. - * @param lastStepExecution the last step execution - * @param jobExecution the {@link JobExecution} instance to be evaluated. - * @param step the {@link Step} instance to be evaluated. - * @return true if step should start, false if it should not. - * - * @throws StartLimitExceededException if the start limit has been exceeded - * for this step - * @throws JobRestartException if the job is in an inconsistent state from - * an earlier failure - */ - protected boolean shouldStart(StepExecution lastStepExecution, JobExecution jobExecution, Step step) - throws JobRestartException, StartLimitExceededException { - - BatchStatus stepStatus; - if (lastStepExecution == null) { - stepStatus = BatchStatus.STARTING; - } - else { - stepStatus = lastStepExecution.getStatus(); - } - - if (stepStatus == BatchStatus.UNKNOWN) { - throw new JobRestartException("Cannot restart step from UNKNOWN status. " - + "The last execution ended with a failure that could not be rolled back, " - + "so it may be dangerous to proceed. Manual intervention is probably necessary."); - } - - if ((stepStatus == BatchStatus.COMPLETED && !step.isAllowStartIfComplete()) - || stepStatus == BatchStatus.ABANDONED) { - // step is complete, false should be returned, indicating that the - // step should not be started - if (logger.isInfoEnabled()) { - logger.info("Step already complete or not restartable, so no action to execute: " + lastStepExecution); - } - return false; - } - - if (jobRepository.getStepExecutionCount(jobExecution.getJobInstance(), step.getName()) < step.getStartLimit()) { - // step start count is less than start max, return true - return true; - } - else { - // start max has been exceeded, throw an exception. - throw new StartLimitExceededException("Maximum start limit exceeded for step: " + step.getName() - + "StartMax: " + step.getStartLimit()); - } - } - -} +/* + * Copyright 2006-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.core.job; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobInstance; +import org.springframework.batch.core.JobInterruptedException; +import org.springframework.batch.core.StartLimitExceededException; +import org.springframework.batch.core.Step; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.core.repository.JobRestartException; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.util.Assert; + +/** + * Implementation of {@link StepHandler} that manages repository and restart concerns. + * + * @author Dave Syer + * + */ +public class SimpleStepHandler implements StepHandler, InitializingBean { + + private static final Log logger = LogFactory.getLog(SimpleStepHandler.class); + + private JobRepository jobRepository; + + private ExecutionContext executionContext; + + /** + * Convenient default constructor for configuration usage. + */ + public SimpleStepHandler() { + this(null); + } + + /** + * @param jobRepository a + * {@link org.springframework.batch.core.repository.JobRepository} + */ + public SimpleStepHandler(JobRepository jobRepository) { + this(jobRepository, new ExecutionContext()); + } + + /** + * @param jobRepository a + * {@link org.springframework.batch.core.repository.JobRepository} + * @param executionContext the {@link org.springframework.batch.item.ExecutionContext} + * for the current Step + */ + public SimpleStepHandler(JobRepository jobRepository, ExecutionContext executionContext) { + this.jobRepository = jobRepository; + this.executionContext = executionContext; + } + + /** + * Check mandatory properties (jobRepository). + * + * @see InitializingBean#afterPropertiesSet() + */ + @Override + public void afterPropertiesSet() throws Exception { + Assert.state(jobRepository != null, "A JobRepository must be provided"); + } + + /** + * @return the used jobRepository + */ + protected JobRepository getJobRepository() { + return this.jobRepository; + } + + /** + * @param jobRepository the jobRepository to set + */ + public void setJobRepository(JobRepository jobRepository) { + this.jobRepository = jobRepository; + } + + /** + * A context containing values to be added to the step execution before it is handled. + * @param executionContext the execution context to set + */ + public void setExecutionContext(ExecutionContext executionContext) { + this.executionContext = executionContext; + } + + @Override + public StepExecution handleStep(Step step, JobExecution execution) + throws JobInterruptedException, JobRestartException, StartLimitExceededException { + if (execution.isStopping()) { + throw new JobInterruptedException("JobExecution interrupted."); + } + + JobInstance jobInstance = execution.getJobInstance(); + + StepExecution lastStepExecution = jobRepository.getLastStepExecution(jobInstance, step.getName()); + if (stepExecutionPartOfExistingJobExecution(execution, lastStepExecution)) { + // If the last execution of this step was in the same job, it's + // probably intentional so we want to run it again... + if (logger.isInfoEnabled()) { + logger.info(String.format( + "Duplicate step [%s] detected in execution of job=[%s]. " + + "If either step fails, both will be executed again on restart.", + step.getName(), jobInstance.getJobName())); + } + lastStepExecution = null; + } + StepExecution currentStepExecution = lastStepExecution; + + if (shouldStart(lastStepExecution, execution, step)) { + + currentStepExecution = execution.createStepExecution(step.getName()); + + boolean isRestart = (lastStepExecution != null + && !lastStepExecution.getStatus().equals(BatchStatus.COMPLETED)); + + if (isRestart) { + currentStepExecution.setExecutionContext(lastStepExecution.getExecutionContext()); + + if (lastStepExecution.getExecutionContext().containsKey("batch.executed")) { + currentStepExecution.getExecutionContext().remove("batch.executed"); + } + } + else { + currentStepExecution.setExecutionContext(new ExecutionContext(executionContext)); + } + + jobRepository.add(currentStepExecution); + + if (logger.isInfoEnabled()) { + logger.info("Executing step: [" + step.getName() + "]"); + } + try { + step.execute(currentStepExecution); + currentStepExecution.getExecutionContext().put("batch.executed", true); + } + catch (JobInterruptedException e) { + // Ensure that the job gets the message that it is stopping + // and can pass it on to other steps that are executing + // concurrently. + execution.setStatus(BatchStatus.STOPPING); + throw e; + } + + jobRepository.updateExecutionContext(execution); + + if (currentStepExecution.getStatus() == BatchStatus.STOPPING + || currentStepExecution.getStatus() == BatchStatus.STOPPED) { + // Ensure that the job gets the message that it is stopping + execution.setStatus(BatchStatus.STOPPING); + throw new JobInterruptedException("Job interrupted by step execution"); + } + + } + + return currentStepExecution; + } + + /** + * Detect whether a step execution belongs to this job execution. + * @param jobExecution the current job execution + * @param stepExecution an existing step execution + * @return true if the {@link org.springframework.batch.core.StepExecution} is part of + * the {@link org.springframework.batch.core.JobExecution} + */ + private boolean stepExecutionPartOfExistingJobExecution(JobExecution jobExecution, StepExecution stepExecution) { + return stepExecution != null && stepExecution.getJobExecutionId() != null + && stepExecution.getJobExecutionId().equals(jobExecution.getId()); + } + + /** + * Given a step and configuration, return true if the step should start, false if it + * should not, and throw an exception if the job should finish. + * @param lastStepExecution the last step execution + * @param jobExecution the {@link JobExecution} instance to be evaluated. + * @param step the {@link Step} instance to be evaluated. + * @return true if step should start, false if it should not. + * @throws StartLimitExceededException if the start limit has been exceeded for this + * step + * @throws JobRestartException if the job is in an inconsistent state from an earlier + * failure + */ + protected boolean shouldStart(StepExecution lastStepExecution, JobExecution jobExecution, Step step) + throws JobRestartException, StartLimitExceededException { + + BatchStatus stepStatus; + if (lastStepExecution == null) { + stepStatus = BatchStatus.STARTING; + } + else { + stepStatus = lastStepExecution.getStatus(); + } + + if (stepStatus == BatchStatus.UNKNOWN) { + throw new JobRestartException("Cannot restart step from UNKNOWN status. " + + "The last execution ended with a failure that could not be rolled back, " + + "so it may be dangerous to proceed. Manual intervention is probably necessary."); + } + + if ((stepStatus == BatchStatus.COMPLETED && !step.isAllowStartIfComplete()) + || stepStatus == BatchStatus.ABANDONED) { + // step is complete, false should be returned, indicating that the + // step should not be started + if (logger.isInfoEnabled()) { + logger.info("Step already complete or not restartable, so no action to execute: " + lastStepExecution); + } + return false; + } + + if (jobRepository.getStepExecutionCount(jobExecution.getJobInstance(), step.getName()) < step.getStartLimit()) { + // step start count is less than start max, return true + return true; + } + else { + // start max has been exceeded, throw an exception. + throw new StartLimitExceededException( + "Maximum start limit exceeded for step: " + step.getName() + "StartMax: " + step.getStartLimit()); + } + } + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/StepHandler.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/StepHandler.java index a34641c41..ebe18808e 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/StepHandler.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/StepHandler.java @@ -1,56 +1,53 @@ -/* - * Copyright 2006-2009 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.core.job; - -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobInterruptedException; -import org.springframework.batch.core.StartLimitExceededException; -import org.springframework.batch.core.Step; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.repository.JobRestartException; - -/** - * Strategy interface for handling a {@link Step} on behalf of a {@link Job}. - * - * @author Dave Syer - * - */ -public interface StepHandler { - - /** - * Handle a step and return the execution for it. Does not save the - * {@link JobExecution}, but should manage the persistence of the - * {@link StepExecution} if required (e.g. at least it needs to be added to - * a repository before the step can be executed). - * - * @param step a {@link Step} - * @param jobExecution a {@link JobExecution} - * @return an execution of the step - * - * @throws JobInterruptedException if there is an interruption - * @throws JobRestartException if there is a problem restarting a failed - * step - * @throws StartLimitExceededException if the step exceeds its start limit - * - * @see Job#execute(JobExecution) - * @see Step#execute(StepExecution) - */ - StepExecution handleStep(Step step, JobExecution jobExecution) throws JobInterruptedException, JobRestartException, - StartLimitExceededException; - -} +/* + * Copyright 2006-2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.core.job; + +import org.springframework.batch.core.Job; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobInterruptedException; +import org.springframework.batch.core.StartLimitExceededException; +import org.springframework.batch.core.Step; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.repository.JobRestartException; + +/** + * Strategy interface for handling a {@link Step} on behalf of a {@link Job}. + * + * @author Dave Syer + * + */ +public interface StepHandler { + + /** + * Handle a step and return the execution for it. Does not save the + * {@link JobExecution}, but should manage the persistence of the + * {@link StepExecution} if required (e.g. at least it needs to be added to a + * repository before the step can be executed). + * @param step a {@link Step} + * @param jobExecution a {@link JobExecution} + * @return an execution of the step + * @throws JobInterruptedException if there is an interruption + * @throws JobRestartException if there is a problem restarting a failed step + * @throws StartLimitExceededException if the step exceeds its start limit + * + * @see Job#execute(JobExecution) + * @see Step#execute(StepExecution) + */ + StepExecution handleStep(Step step, JobExecution jobExecution) + throws JobInterruptedException, JobRestartException, StartLimitExceededException; + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/FlowBuilder.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/FlowBuilder.java index 04cec5d67..6116e0df3 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/FlowBuilder.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/FlowBuilder.java @@ -41,14 +41,13 @@ import org.springframework.batch.core.job.flow.support.state.StepState; import org.springframework.core.task.TaskExecutor; /** - * A builder for a flow of steps that can be executed as a job or as part of a job. Steps can be linked together with - * conditional transitions that depend on the exit status of the previous step. + * A builder for a flow of steps that can be executed as a job or as part of a job. Steps + * can be linked together with conditional transitions that depend on the exit status of + * the previous step. * * @author Dave Syer * @author Michael Minella - * * @since 2.2 - * * @param the type of object returned by the builder (by default a Flow) * */ @@ -95,9 +94,8 @@ public class FlowBuilder { } /** - * Validate the current state of the builder and build a flow. Subclasses may override this to build an object of a - * different type that itself depends on the flow. - * + * Validate the current state of the builder and build a flow. Subclasses may override + * this to build an object of a different type that itself depends on the flow. * @return a flow */ public Q build() { @@ -107,9 +105,8 @@ public class FlowBuilder { } /** - * Transition to the next step on successful completion of the current step. All other outcomes are treated as - * failures. - * + * Transition to the next step on successful completion of the current step. All other + * outcomes are treated as failures. * @param step the next step * @return this to enable chaining */ @@ -119,8 +116,8 @@ public class FlowBuilder { } /** - * Start a flow. If some steps are already registered, just a synonym for {@link #from(Step)}. - * + * Start a flow. If some steps are already registered, just a synonym for + * {@link #from(Step)}. * @param step the step to start with * @return this to enable chaining */ @@ -130,9 +127,8 @@ public class FlowBuilder { } /** - * Go back to a previously registered step and start a new path. If no steps are registered yet just a synonym for - * {@link #start(Step)}. - * + * Go back to a previously registered step and start a new path. If no steps are + * registered yet just a synonym for {@link #start(Step)}. * @param step the step to start from (already registered) * @return this to enable chaining */ @@ -142,9 +138,8 @@ public class FlowBuilder { } /** - * Transition to the decider on successful completion of the current step. All other outcomes are treated as - * failures. - * + * Transition to the decider on successful completion of the current step. All other + * outcomes are treated as failures. * @param decider the JobExecutionDecider to determine the next step to execute * @return this to enable chaining */ @@ -155,7 +150,6 @@ public class FlowBuilder { /** * If a flow should start with a decision use this as the first state. - * * @param decider the to start from * @return a builder to enable chaining */ @@ -166,7 +160,6 @@ public class FlowBuilder { /** * Start again from a decision that was already registered. - * * @param decider the decider to start from (already registered) * @return a builder to enable chaining */ @@ -177,7 +170,6 @@ public class FlowBuilder { /** * Go next on successful completion to a subflow. - * * @param flow the flow to go to * @return a builder to enable chaining */ @@ -188,7 +180,6 @@ public class FlowBuilder { /** * Start again from a subflow that was already registered. - * * @param flow the flow to start from (already registered) * @return a builder to enable chaining */ @@ -199,7 +190,6 @@ public class FlowBuilder { /** * If a flow should start with a subflow use this as the first state. - * * @param flow the flow to start from * @return a builder to enable chaining */ @@ -217,10 +207,10 @@ public class FlowBuilder { } /** - * Start a transition to a new state if the exit status from the previous state matches the pattern given. - * Successful completion normally results in an exit status equal to (or starting with by convention) "COMPLETED". - * See {@link ExitStatus} for commonly used values. - * + * Start a transition to a new state if the exit status from the previous state + * matches the pattern given. Successful completion normally results in an exit status + * equal to (or starting with by convention) "COMPLETED". See {@link ExitStatus} for + * commonly used values. * @param pattern the pattern of exit status on which to take this transition * @return a builder to enable fluent chaining */ @@ -229,9 +219,9 @@ public class FlowBuilder { } /** - * A synonym for {@link #build()} which callers might find useful. Subclasses can override build to create an object - * of the desired type (e.g. a parent builder or an actual flow). - * + * A synonym for {@link #build()} which callers might find useful. Subclasses can + * override build to create an object of the desired type (e.g. a parent builder or an + * actual flow). * @return the result of the builder */ public final Q end() { @@ -292,8 +282,8 @@ public class FlowBuilder { } else if (input instanceof JobExecutionDecider) { if (!states.containsKey(input)) { - states.put(input, new DecisionState((JobExecutionDecider) input, prefix + "decision" - + (decisionCounter++))); + states.put(input, + new DecisionState((JobExecutionDecider) input, prefix + "decision" + (decisionCounter++))); } result = states.get(input); } @@ -331,7 +321,8 @@ public class FlowBuilder { tos.put(currentState.getName(), currentState); } Map copy = new HashMap<>(tos); - // Find all the states that are really end states but not explicitly declared as such + // Find all the states that are really end states but not explicitly declared as + // such for (String to : copy.keySet()) { if (!froms.contains(to)) { currentState = copy.get(to); @@ -414,7 +405,6 @@ public class FlowBuilder { * A builder for continuing a flow from a decision state. * * @author Dave Syer - * * @param the result of the builder's build() */ public static class UnterminatedFlowBuilder { @@ -426,10 +416,10 @@ public class FlowBuilder { } /** - * Start a transition to a new state if the exit status from the previous state matches the pattern given. - * Successful completion normally results in an exit status equal to (or starting with by convention) - * "COMPLETED". See {@link ExitStatus} for commonly used values. - * + * Start a transition to a new state if the exit status from the previous state + * matches the pattern given. Successful completion normally results in an exit + * status equal to (or starting with by convention) "COMPLETED". See + * {@link ExitStatus} for commonly used values. * @param pattern the pattern of exit status on which to take this transition * @return a TransitionBuilder */ @@ -443,7 +433,6 @@ public class FlowBuilder { * A builder for transitions within a flow. * * @author Dave Syer - * * @param the result of the parent builder's build() */ public static class TransitionBuilder { @@ -459,7 +448,6 @@ public class FlowBuilder { /** * Specify the next step. - * * @param step the next step after this transition * @return a FlowBuilder */ @@ -472,7 +460,6 @@ public class FlowBuilder { /** * Specify the next state as a complete flow. - * * @param flow the next flow after this transition * @return a FlowBuilder */ @@ -485,7 +472,6 @@ public class FlowBuilder { /** * Specify the next state as a decision. - * * @param decider the decider to determine the next step * @return a FlowBuilder */ @@ -498,7 +484,6 @@ public class FlowBuilder { /** * Signal the successful end of the flow. - * * @return a FlowBuilder */ public FlowBuilder stop() { @@ -508,7 +493,6 @@ public class FlowBuilder { /** * Stop the flow and provide a flow to start with if the flow is restarted. - * * @param flow the flow to restart with * @return a FlowBuilder */ @@ -520,7 +504,6 @@ public class FlowBuilder { /** * Stop the flow and provide a decider to start with if the flow is restarted. - * * @param decider a decider to restart with * @return a FlowBuilder */ @@ -532,7 +515,6 @@ public class FlowBuilder { /** * Stop the flow and provide a step to start with if the flow is restarted. - * * @param restart the step to restart with * @return a FlowBuilder */ @@ -544,7 +526,6 @@ public class FlowBuilder { /** * Signal the successful end of the flow. - * * @return a FlowBuilder */ public FlowBuilder end() { @@ -554,7 +535,6 @@ public class FlowBuilder { /** * Signal the end of the flow with the status provided. - * * @param status {@link String} containing the status. * @return a FlowBuilder */ @@ -565,34 +545,36 @@ public class FlowBuilder { /** * Signal the end of the flow with an error condition. - * * @return a FlowBuilder */ public FlowBuilder fail() { parent.fail(pattern); return parent; } + } /** - * A builder for building a split state. Example (builder is a {@link FlowBuilder}): + * A builder for building a split state. Example (builder is a + * {@link FlowBuilder}): * *
 	 * Flow splitFlow = builder.start(flow1).split(new SyncTaskExecutor()).add(flow2).build();
 	 * 
* - * where flow1 and flow2 will be executed (one after the other because of the task - * executor that was added). Another example + * where flow1 and flow2 will be executed (one after the + * other because of the task executor that was added). Another example * *
 	 * Flow splitFlow = builder.start(step1).split(new SimpleAsyncTaskExecutor()).add(flow).build();
 	 * 
* - * In this example, a flow consisting of step1 will be executed in parallel with flow. + * In this example, a flow consisting of step1 will be executed in + * parallel with flow. * - * Note: Adding a split to a chain of states is not supported. For example, the following configuration - * is not supported. Instead, the configuration would need to create a flow3 that was the split flow and assemble - * them separately. + * Note: Adding a split to a chain of states is not supported. For example, + * the following configuration is not supported. Instead, the configuration would need + * to create a flow3 that was the split flow and assemble them separately. * *
 	 * // instead of this
@@ -618,7 +600,6 @@ public class FlowBuilder {
 	 *
 	 * @author Dave Syer
 	 * @author Michael Minella
-	 *
 	 * @param  the result of the parent builder's build()
 	 */
 	public static class SplitBuilder {
@@ -637,8 +618,8 @@ public class FlowBuilder {
 		}
 
 		/**
-		 * Add flows to the split, in addition to the current state already present in the parent builder.
-		 *
+		 * Add flows to the split, in addition to the current state already present in the
+		 * parent builder.
 		 * @param flows more flows to add to the split
 		 * @return the parent builder
 		 */
@@ -652,7 +633,8 @@ public class FlowBuilder {
 				FlowBuilder stateBuilder = new FlowBuilder<>(name + "_" + (counter++));
 				stateBuilder.currentState = one;
 				flow = stateBuilder.build();
-			} else if (one instanceof FlowState && parent.states.size() == 1) {
+			}
+			else if (one instanceof FlowState && parent.states.size() == 1) {
 				list.add(((FlowState) one).getFlows().iterator().next());
 			}
 
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/FlowBuilderException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/FlowBuilderException.java
index 11c00a751..999ae7b1e 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/FlowBuilderException.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/FlowBuilderException.java
@@ -17,7 +17,6 @@ package org.springframework.batch.core.job.builder;
 
 /**
  * @author Dave Syer
- * 
  * @since 2.2
  *
  */
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/FlowJobBuilder.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/FlowJobBuilder.java
index ec26ec760..883f35c1a 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/FlowJobBuilder.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/FlowJobBuilder.java
@@ -22,11 +22,10 @@ import org.springframework.batch.core.job.flow.FlowJob;
 import org.springframework.batch.core.step.builder.StepBuilderException;
 
 /**
- * A job builder for {@link FlowJob} instances. A flow job delegates processing to a nested flow composed of steps and
- * conditional transitions between steps.
- * 
+ * A job builder for {@link FlowJob} instances. A flow job delegates processing to a
+ * nested flow composed of steps and conditional transitions between steps.
+ *
  * @author Dave Syer
- * 
  * @since 2.2
  */
 public class FlowJobBuilder extends JobBuilderHelper {
@@ -34,8 +33,8 @@ public class FlowJobBuilder extends JobBuilderHelper {
 	private Flow flow;
 
 	/**
-	 * Create a new builder initialized with any properties in the parent. The parent is copied, so it can be re-used.
-	 * 
+	 * Create a new builder initialized with any properties in the parent. The parent is
+	 * copied, so it can be re-used.
 	 * @param parent a parent helper containing common job properties
 	 */
 	public FlowJobBuilder(JobBuilderHelper parent) {
@@ -43,8 +42,8 @@ public class FlowJobBuilder extends JobBuilderHelper {
 	}
 
 	/**
-	 * Start a job with this flow, but expect to transition from there to other flows or steps.
-	 * 
+	 * Start a job with this flow, but expect to transition from there to other flows or
+	 * steps.
 	 * @param flow the flow to start with
 	 * @return a builder to enable fluent chaining
 	 */
@@ -53,8 +52,8 @@ public class FlowJobBuilder extends JobBuilderHelper {
 	}
 
 	/**
-	 * Start a job with this step, but expect to transition from there to other flows or steps.
-	 * 
+	 * Start a job with this step, but expect to transition from there to other flows or
+	 * steps.
 	 * @param step the step to start with
 	 * @return a builder to enable fluent chaining
 	 */
@@ -64,7 +63,6 @@ public class FlowJobBuilder extends JobBuilderHelper {
 
 	/**
 	 * Provide a single flow to execute as the job.
-	 * 
 	 * @param flow the flow to execute
 	 * @return this for fluent chaining
 	 */
@@ -75,7 +73,6 @@ public class FlowJobBuilder extends JobBuilderHelper {
 
 	/**
 	 * Build a job that executes the flow provided, normally composed of other steps.
-	 * 
 	 * @return a flow job
 	 */
 	public Job build() {
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/JobBuilder.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/JobBuilder.java
index eb412148f..4ead859e8 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/JobBuilder.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/JobBuilder.java
@@ -22,7 +22,6 @@ import org.springframework.batch.core.job.flow.Flow;
  * Convenience for building jobs of various kinds.
  *
  * @author Dave Syer
- *
  * @since 2.2
  *
  */
@@ -30,7 +29,6 @@ public class JobBuilder extends JobBuilderHelper {
 
 	/**
 	 * Create a new builder for a job with the given name.
-	 *
 	 * @param name the name of the job
 	 */
 	public JobBuilder(String name) {
@@ -39,7 +37,6 @@ public class JobBuilder extends JobBuilderHelper {
 
 	/**
 	 * Create a new job builder that will execute a step or sequence of steps.
-	 *
 	 * @param step a step to execute
 	 * @return a {@link SimpleJobBuilder}
 	 */
@@ -49,7 +46,6 @@ public class JobBuilder extends JobBuilderHelper {
 
 	/**
 	 * Create a new job builder that will execute a flow.
-	 *
 	 * @param flow a flow to execute
 	 * @return a {@link SimpleJobBuilder}
 	 */
@@ -59,11 +55,11 @@ public class JobBuilder extends JobBuilderHelper {
 
 	/**
 	 * Create a new job builder that will execute a step or sequence of steps.
-	 *
 	 * @param step a step to execute
 	 * @return a {@link SimpleJobBuilder}
 	 */
 	public JobFlowBuilder flow(Step step) {
 		return new FlowJobBuilder(this).start(step);
 	}
+
 }
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/JobBuilderException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/JobBuilderException.java
index 1e2742193..751647c08 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/JobBuilderException.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/JobBuilderException.java
@@ -17,7 +17,6 @@ package org.springframework.batch.core.job.builder;
 
 /**
  * @author Dave Syer
- * 
  * @since 2.2
  *
  */
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/JobBuilderHelper.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/JobBuilderHelper.java
index b1ed7c2ac..3a6651a26 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/JobBuilderHelper.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/JobBuilderHelper.java
@@ -36,11 +36,11 @@ import org.springframework.batch.core.repository.JobRepository;
 import org.springframework.batch.support.ReflectionUtils;
 
 /**
- * A base class and utility for other job builders providing access to common properties like job repository.
- * 
+ * A base class and utility for other job builders providing access to common properties
+ * like job repository.
+ *
  * @author Dave Syer
  * @author Mahmoud Ben Hassine
- * 
  * @since 2.2
  */
 public abstract class JobBuilderHelper> {
@@ -55,8 +55,8 @@ public abstract class JobBuilderHelper> {
 	}
 
 	/**
-	 * Create a new builder initialized with any properties in the parent. The parent is copied, so it can be re-used.
-	 * 
+	 * Create a new builder initialized with any properties in the parent. The parent is
+	 * copied, so it can be re-used.
 	 * @param parent a parent helper containing common step properties
 	 */
 	protected JobBuilderHelper(JobBuilderHelper parent) {
@@ -65,7 +65,6 @@ public abstract class JobBuilderHelper> {
 
 	/**
 	 * Add a job parameters validator.
-	 * 
 	 * @param jobParametersValidator a job parameters validator
 	 * @return this to enable fluent chaining
 	 */
@@ -78,7 +77,6 @@ public abstract class JobBuilderHelper> {
 
 	/**
 	 * Add a job parameters incrementer.
-	 * 
 	 * @param jobParametersIncrementer a job parameters incrementer
 	 * @return this to enable fluent chaining
 	 */
@@ -91,7 +89,6 @@ public abstract class JobBuilderHelper> {
 
 	/**
 	 * Sets the job repository for the job.
-	 * 
 	 * @param jobRepository the job repository (mandatory)
 	 * @return this to enable fluent chaining
 	 */
@@ -104,7 +101,6 @@ public abstract class JobBuilderHelper> {
 
 	/**
 	 * Registers objects using the annotation based listener configuration.
-	 *
 	 * @param listener the object that has a method configured with listener annotation
 	 * @return this for fluent chaining
 	 */
@@ -113,7 +109,7 @@ public abstract class JobBuilderHelper> {
 		jobExecutionListenerMethods.addAll(ReflectionUtils.findMethod(listener.getClass(), BeforeJob.class));
 		jobExecutionListenerMethods.addAll(ReflectionUtils.findMethod(listener.getClass(), AfterJob.class));
 
-		if(jobExecutionListenerMethods.size() > 0) {
+		if (jobExecutionListenerMethods.size() > 0) {
 			JobListenerFactoryBean factory = new JobListenerFactoryBean();
 			factory.setDelegate(listener);
 			properties.addJobExecutionListener((JobExecutionListener) factory.getObject());
@@ -126,7 +122,6 @@ public abstract class JobBuilderHelper> {
 
 	/**
 	 * Register a job execution listener.
-	 * 
 	 * @param listener a job execution listener
 	 * @return this to enable fluent chaining
 	 */
@@ -139,7 +134,6 @@ public abstract class JobBuilderHelper> {
 
 	/**
 	 * Set a flag to prevent restart an execution of this job even if it has failed.
-	 * 
 	 * @return this to enable fluent chaining
 	 */
 	public B preventRestart() {
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/JobFlowBuilder.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/JobFlowBuilder.java
index e95db4fcc..57b4337ae 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/JobFlowBuilder.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/JobFlowBuilder.java
@@ -52,8 +52,9 @@ public class JobFlowBuilder extends FlowBuilder {
 	}
 
 	/**
-	 * Build a flow and inject it into the parent builder. The parent builder is then returned so it can be enhanced
-	 * before building an actual job.  Normally called explicitly via {@link #end()}.
+	 * Build a flow and inject it into the parent builder. The parent builder is then
+	 * returned so it can be enhanced before building an actual job. Normally called
+	 * explicitly via {@link #end()}.
 	 *
 	 * @see org.springframework.batch.core.job.builder.FlowBuilder#build()
 	 */
@@ -61,7 +62,7 @@ public class JobFlowBuilder extends FlowBuilder {
 	public FlowJobBuilder build() {
 		Flow flow = flow();
 
-		if(flow instanceof InitializingBean) {
+		if (flow instanceof InitializingBean) {
 			try {
 				((InitializingBean) flow).afterPropertiesSet();
 			}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/SimpleJobBuilder.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/SimpleJobBuilder.java
index 9a827f8be..f881e66cf 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/SimpleJobBuilder.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/SimpleJobBuilder.java
@@ -27,9 +27,8 @@ import org.springframework.util.Assert;
 
 /**
  * @author Dave Syer
- * 
  * @since 2.2
- * 
+ *
  */
 public class SimpleJobBuilder extends JobBuilderHelper {
 
@@ -38,8 +37,8 @@ public class SimpleJobBuilder extends JobBuilderHelper {
 	private JobFlowBuilder builder;
 
 	/**
-	 * Create a new builder initialized with any properties in the parent. The parent is copied, so it can be re-used.
-	 * 
+	 * Create a new builder initialized with any properties in the parent. The parent is
+	 * copied, so it can be re-used.
 	 * @param parent the parent to use
 	 */
 	public SimpleJobBuilder(JobBuilderHelper parent) {
@@ -64,7 +63,6 @@ public class SimpleJobBuilder extends JobBuilderHelper {
 
 	/**
 	 * Start the job with this step.
-	 * 
 	 * @param step a step to start with
 	 * @return this for fluent chaining
 	 */
@@ -80,7 +78,6 @@ public class SimpleJobBuilder extends JobBuilderHelper {
 
 	/**
 	 * Branch into a flow conditional on the outcome of the current step.
-	 * 
 	 * @param pattern a pattern for the exit status of the current step
 	 * @return a builder for fluent chaining
 	 */
@@ -98,9 +95,8 @@ public class SimpleJobBuilder extends JobBuilderHelper {
 	}
 
 	/**
-	 * Start with this decider. Returns a flow builder and when the flow is ended a job builder will be returned to
-	 * continue the job configuration if needed.
-	 * 
+	 * Start with this decider. Returns a flow builder and when the flow is ended a job
+	 * builder will be returned to continue the job configuration if needed.
 	 * @param decider a decider to execute first
 	 * @return builder for fluent chaining
 	 */
@@ -121,9 +117,9 @@ public class SimpleJobBuilder extends JobBuilderHelper {
 	}
 
 	/**
-	 * Continue with this decider if the previous step was successful. Returns a flow builder and when the flow is ended
-	 * a job builder will be returned to continue the job configuration if needed.
-	 * 
+	 * Continue with this decider if the previous step was successful. Returns a flow
+	 * builder and when the flow is ended a job builder will be returned to continue the
+	 * job configuration if needed.
 	 * @param decider a decider to execute next
 	 * @return builder for fluent chaining
 	 */
@@ -147,7 +143,6 @@ public class SimpleJobBuilder extends JobBuilderHelper {
 
 	/**
 	 * Continue or end a job with this step if the previous step was successful.
-	 * 
 	 * @param step a step to execute next
 	 * @return this for fluent chaining
 	 */
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/Flow.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/Flow.java
index 9688ae012..ca1d57aa3 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/Flow.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/Flow.java
@@ -29,9 +29,8 @@ public interface Flow {
 	String getName();
 
 	/**
-	 * Retrieve the State with the given name. If there is no State with the
-	 * given name, then return null.
-	 * 
+	 * Retrieve the State with the given name. If there is no State with the given name,
+	 * then return null.
 	 * @param stateName the name of the state to retrieve
 	 * @return the State
 	 */
@@ -40,7 +39,6 @@ public interface Flow {
 	/**
 	 * @param executor the {@link FlowExecutor} instance to use for the flow execution.
 	 * @return a {@link FlowExecution} containing the exit status of the flow.
-	 *
 	 * @throws FlowExecutionException thrown if error occurs during flow execution.
 	 */
 	FlowExecution start(FlowExecutor executor) throws FlowExecutionException;
@@ -49,14 +47,12 @@ public interface Flow {
 	 * @param stateName the name of the state to resume on.
 	 * @param executor the context to be passed into each state executed.
 	 * @return a {@link FlowExecution} containing the exit status of the flow.
-	 *
 	 * @throws FlowExecutionException thrown if error occurs during flow execution.
 	 */
 	FlowExecution resume(String stateName, FlowExecutor executor) throws FlowExecutionException;
 
 	/**
-	 * Convenient accessor for clients needing to explore the states of this
-	 * flow.
+	 * Convenient accessor for clients needing to explore the states of this flow.
 	 * @return the states
 	 */
 	Collection getStates();
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowExecution.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowExecution.java
index af6ae4d1b..d50a56087 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowExecution.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowExecution.java
@@ -15,7 +15,6 @@
  */
 package org.springframework.batch.core.job.flow;
 
-
 /**
  * @author Dave Syer
  * @since 2.0
@@ -23,11 +22,13 @@ package org.springframework.batch.core.job.flow;
 public class FlowExecution implements Comparable {
 
 	private final String name;
+
 	private final FlowExecutionStatus status;
 
 	/**
 	 * @param name the flow name to be associated with the FlowExecution.
-	 * @param status the {@link FlowExecutionStatus} to be associated with the FlowExecution.
+	 * @param status the {@link FlowExecutionStatus} to be associated with the
+	 * FlowExecution.
 	 */
 	public FlowExecution(String name, FlowExecutionStatus status) {
 		this.name = name;
@@ -49,11 +50,9 @@ public class FlowExecution implements Comparable {
 	}
 
 	/**
-	 * Create an ordering on {@link FlowExecution} instances by comparing their
-	 * statuses.
+	 * Create an ordering on {@link FlowExecution} instances by comparing their statuses.
 	 *
 	 * @see Comparable#compareTo(Object)
-	 *
 	 * @param other the {@link FlowExecution} instance to compare with this instance.
 	 * @return negative, zero or positive as per the contract
 	 */
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowExecutionStatus.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowExecutionStatus.java
index b16d4e43e..caa8aa7d1 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowExecutionStatus.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowExecutionStatus.java
@@ -84,7 +84,6 @@ public class FlowExecutionStatus implements Comparable {
 		return name.startsWith(FAILED.getName());
 	}
 
-
 	/**
 	 * @return true if this status represents the end of a flow
 	 */
@@ -98,12 +97,12 @@ public class FlowExecutionStatus implements Comparable {
 	private boolean isComplete() {
 		return name.startsWith(COMPLETED.getName());
 	}
+
 	/**
-	 * Create an ordering on {@link FlowExecutionStatus} instances by comparing
-	 * their statuses.
+	 * Create an ordering on {@link FlowExecutionStatus} instances by comparing their
+	 * statuses.
 	 *
 	 * @see Comparable#compareTo(Object)
-	 *
 	 * @param other instance of {@link FlowExecutionStatus} to compare this instance with.
 	 * @return negative, zero or positive as per the contract
 	 */
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowExecutor.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowExecutor.java
index db1176724..4f24417f3 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowExecutor.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowExecutor.java
@@ -24,9 +24,9 @@ import org.springframework.batch.core.repository.JobRestartException;
 import org.springframework.lang.Nullable;
 
 /**
- * Context and execution strategy for {@link FlowJob} to allow it to delegate
- * its execution step by step.
- * 
+ * Context and execution strategy for {@link FlowJob} to allow it to delegate its
+ * execution step by step.
+ *
  * @author Dave Syer
  * @author Mahmoud Ben Hassine
  * @since 2.0
@@ -56,7 +56,6 @@ public interface FlowExecutor {
 	/**
 	 * Chance to clean up resources at the end of a flow (whether it completed
 	 * successfully or not).
-	 * 
 	 * @param result the final {@link FlowExecution}
 	 */
 	void close(FlowExecution result);
@@ -67,9 +66,7 @@ public interface FlowExecutor {
 	void abandonStepExecution();
 
 	/**
-	 * Handle any status changes that might be needed in the
-	 * {@link JobExecution}.
-	 *
+	 * Handle any status changes that might be needed in the {@link JobExecution}.
 	 * @param status status to update the {@link JobExecution} to.
 	 */
 	void updateJobExecutionStatus(FlowExecutionStatus status);
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowHolder.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowHolder.java
index 8675dc0de..17ae62b62 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowHolder.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowHolder.java
@@ -19,12 +19,12 @@ import java.util.Collection;
 
 /**
  * Convenient interface for components that contain nested flows.
- * 
+ *
  * @author Dave Syer
  *
  */
 public interface FlowHolder {
-	
+
 	Collection getFlows();
 
 }
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowJob.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowJob.java
index 6a762b303..3118c9768 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowJob.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowJob.java
@@ -1,147 +1,145 @@
-/*
- * Copyright 2006-2019 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.batch.core.job.flow;
-
-import java.util.Collection;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-import org.springframework.batch.core.Job;
-import org.springframework.batch.core.JobExecution;
-import org.springframework.batch.core.JobExecutionException;
-import org.springframework.batch.core.Step;
-import org.springframework.batch.core.job.AbstractJob;
-import org.springframework.batch.core.job.SimpleStepHandler;
-import org.springframework.batch.core.step.StepHolder;
-import org.springframework.batch.core.step.StepLocator;
-
-/**
- * Implementation of the {@link Job} interface that allows for complex flows of
- * steps, rather than requiring sequential execution. In general, this job
- * implementation was designed to be used behind a parser, allowing for a
- * namespace to abstract away details.
- *
- * @author Dave Syer
- * @author Mahmoud Ben Hassine
- * @since 2.0
- */
-public class FlowJob extends AbstractJob {
-
-	protected Flow flow;
-
-	private Map stepMap = new ConcurrentHashMap<>();
-
-	private volatile boolean initialized = false;
-
-	/**
-	 * Create a {@link FlowJob} with null name and no flow (invalid state).
-	 */
-	public FlowJob() {
-		super();
-	}
-
-	/**
-	 * Create a {@link FlowJob} with provided name and no flow (invalid state).
-	 *
-	 * @param name the name to be associated with the FlowJob.
-	 */
-	public FlowJob(String name) {
-		super(name);
-	}
-
-	/**
-	 * Public setter for the flow.
-	 *
-	 * @param flow the flow to set
-	 */
-	public void setFlow(Flow flow) {
-		this.flow = flow;
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	@Override
-	public Step getStep(String stepName) {
-		if (!initialized) {
-			init();
-		}
-		return stepMap.get(stepName);
-	}
-
-	/**
-	 * Initialize the step names
-	 */
-	private void init() {
-		findSteps(flow, stepMap);
-	}
-
-	/**
-	 * @param flow
-	 * @param map
-	 */
-	private void findSteps(Flow flow, Map map) {
-
-		for (State state : flow.getStates()) {
-			if (state instanceof StepLocator) {
-				StepLocator locator = (StepLocator) state;
-				for (String name : locator.getStepNames()) {
-					map.put(name, locator.getStep(name));
-				}
-			} else if (state instanceof StepHolder) {
-				Step step = ((StepHolder) state).getStep();
-				String name = step.getName();
-				stepMap.put(name, step);
-			}
-			else if (state instanceof FlowHolder) {
-				for (Flow subflow : ((FlowHolder) state).getFlows()) {
-					findSteps(subflow, map);
-				}
-			}
-		}
-
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	@Override
-	public Collection getStepNames() {
-		if (!initialized) {
-			init();
-		}
-		return stepMap.keySet();
-	}
-
-	/**
-	 * @see AbstractJob#doExecute(JobExecution)
-	 */
-	@Override
-	protected void doExecute(final JobExecution execution) throws JobExecutionException {
-		try {
-			JobFlowExecutor executor = new JobFlowExecutor(getJobRepository(),
-					new SimpleStepHandler(getJobRepository()), execution);
-			executor.updateJobExecutionStatus(flow.start(executor).getStatus());
-		}
-		catch (FlowExecutionException e) {
-			if (e.getCause() instanceof JobExecutionException) {
-				throw (JobExecutionException) e.getCause();
-			}
-			throw new JobExecutionException("Flow execution ended unexpectedly", e);
-		}
-	}
-
-}
+/*
+ * Copyright 2006-2019 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.batch.core.job.flow;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.springframework.batch.core.Job;
+import org.springframework.batch.core.JobExecution;
+import org.springframework.batch.core.JobExecutionException;
+import org.springframework.batch.core.Step;
+import org.springframework.batch.core.job.AbstractJob;
+import org.springframework.batch.core.job.SimpleStepHandler;
+import org.springframework.batch.core.step.StepHolder;
+import org.springframework.batch.core.step.StepLocator;
+
+/**
+ * Implementation of the {@link Job} interface that allows for complex flows of steps,
+ * rather than requiring sequential execution. In general, this job implementation was
+ * designed to be used behind a parser, allowing for a namespace to abstract away details.
+ *
+ * @author Dave Syer
+ * @author Mahmoud Ben Hassine
+ * @since 2.0
+ */
+public class FlowJob extends AbstractJob {
+
+	protected Flow flow;
+
+	private Map stepMap = new ConcurrentHashMap<>();
+
+	private volatile boolean initialized = false;
+
+	/**
+	 * Create a {@link FlowJob} with null name and no flow (invalid state).
+	 */
+	public FlowJob() {
+		super();
+	}
+
+	/**
+	 * Create a {@link FlowJob} with provided name and no flow (invalid state).
+	 * @param name the name to be associated with the FlowJob.
+	 */
+	public FlowJob(String name) {
+		super(name);
+	}
+
+	/**
+	 * Public setter for the flow.
+	 * @param flow the flow to set
+	 */
+	public void setFlow(Flow flow) {
+		this.flow = flow;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Step getStep(String stepName) {
+		if (!initialized) {
+			init();
+		}
+		return stepMap.get(stepName);
+	}
+
+	/**
+	 * Initialize the step names
+	 */
+	private void init() {
+		findSteps(flow, stepMap);
+	}
+
+	/**
+	 * @param flow
+	 * @param map
+	 */
+	private void findSteps(Flow flow, Map map) {
+
+		for (State state : flow.getStates()) {
+			if (state instanceof StepLocator) {
+				StepLocator locator = (StepLocator) state;
+				for (String name : locator.getStepNames()) {
+					map.put(name, locator.getStep(name));
+				}
+			}
+			else if (state instanceof StepHolder) {
+				Step step = ((StepHolder) state).getStep();
+				String name = step.getName();
+				stepMap.put(name, step);
+			}
+			else if (state instanceof FlowHolder) {
+				for (Flow subflow : ((FlowHolder) state).getFlows()) {
+					findSteps(subflow, map);
+				}
+			}
+		}
+
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Collection getStepNames() {
+		if (!initialized) {
+			init();
+		}
+		return stepMap.keySet();
+	}
+
+	/**
+	 * @see AbstractJob#doExecute(JobExecution)
+	 */
+	@Override
+	protected void doExecute(final JobExecution execution) throws JobExecutionException {
+		try {
+			JobFlowExecutor executor = new JobFlowExecutor(getJobRepository(),
+					new SimpleStepHandler(getJobRepository()), execution);
+			executor.updateJobExecutionStatus(flow.start(executor).getStatus());
+		}
+		catch (FlowExecutionException e) {
+			if (e.getCause() instanceof JobExecutionException) {
+				throw (JobExecutionException) e.getCause();
+			}
+			throw new JobExecutionException("Flow execution ended unexpectedly", e);
+		}
+	}
+
+}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowStep.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowStep.java
index 93953d0a9..de1ca1b5c 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowStep.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowStep.java
@@ -1,104 +1,101 @@
-/*
- * Copyright 2009-2012 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.batch.core.job.flow;
-
-import org.springframework.batch.core.JobExecutionException;
-import org.springframework.batch.core.Step;
-import org.springframework.batch.core.StepExecution;
-import org.springframework.batch.core.job.SimpleStepHandler;
-import org.springframework.batch.core.job.StepHandler;
-import org.springframework.batch.core.repository.JobRepository;
-import org.springframework.batch.core.step.AbstractStep;
-import org.springframework.util.Assert;
-
-/**
- * A {@link Step} implementation that delegates to a {@link Flow}. Useful for
- * logical grouping of steps, and especially for partitioning with multiple
- * steps per execution. If the flow has steps then when the {@link FlowStep}
- * executes, all steps including the parent {@link FlowStep} will have
- * executions in the {@link JobRepository} (one for the parent and one each for
- * the flow steps).
- * 
- * @author Dave Syer
- * 
- */
-public class FlowStep extends AbstractStep {
-
-	private Flow flow;
-
-	/**
-	 * Default constructor convenient for configuration purposes.
-	 */
-	public FlowStep() {
-		super(null);
-	}
-
-	/**
-	 * Constructor for a {@link FlowStep} that sets the flow and of the step
-	 * explicitly.
-	 *
-	 * @param flow the {@link Flow} instance to be associated with this step.
-	 */
-	public FlowStep(Flow flow) {
-		super(flow.getName());
-	}
-
-	/**
-	 * Public setter for the flow.
-	 * 
-	 * @param flow the flow to set
-	 */
-	public void setFlow(Flow flow) {
-		this.flow = flow;
-	}
-
-	/**
-	 * Ensure that the flow is set.
-	 * @see AbstractStep#afterPropertiesSet()
-	 */
-	@Override
-	public void afterPropertiesSet() throws Exception {
-		Assert.state(flow != null, "A Flow must be provided");
-		if (getName()==null) {
-			setName(flow.getName());
-		}
-		super.afterPropertiesSet();
-	}
-
-	/**
-	 * Delegate to the flow provided for the execution of the step.
-	 * 
-	 * @see AbstractStep#doExecute(StepExecution)
-	 */
-	@Override
-	protected void doExecute(StepExecution stepExecution) throws Exception {
-		try {
-			stepExecution.getExecutionContext().put(STEP_TYPE_KEY, this.getClass().getName());
-			StepHandler stepHandler = new SimpleStepHandler(getJobRepository(), stepExecution.getExecutionContext());
-			FlowExecutor executor = new JobFlowExecutor(getJobRepository(), stepHandler, stepExecution.getJobExecution());
-			executor.updateJobExecutionStatus(flow.start(executor).getStatus());
-			stepExecution.upgradeStatus(executor.getJobExecution().getStatus());
-			stepExecution.setExitStatus(executor.getJobExecution().getExitStatus());
-		}
-		catch (FlowExecutionException e) {
-			if (e.getCause() instanceof JobExecutionException) {
-				throw (JobExecutionException) e.getCause();
-			}
-			throw new JobExecutionException("Flow execution ended unexpectedly", e);
-		}
-	}
-
-}
+/*
+ * Copyright 2009-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.batch.core.job.flow;
+
+import org.springframework.batch.core.JobExecutionException;
+import org.springframework.batch.core.Step;
+import org.springframework.batch.core.StepExecution;
+import org.springframework.batch.core.job.SimpleStepHandler;
+import org.springframework.batch.core.job.StepHandler;
+import org.springframework.batch.core.repository.JobRepository;
+import org.springframework.batch.core.step.AbstractStep;
+import org.springframework.util.Assert;
+
+/**
+ * A {@link Step} implementation that delegates to a {@link Flow}. Useful for logical
+ * grouping of steps, and especially for partitioning with multiple steps per execution.
+ * If the flow has steps then when the {@link FlowStep} executes, all steps including the
+ * parent {@link FlowStep} will have executions in the {@link JobRepository} (one for the
+ * parent and one each for the flow steps).
+ *
+ * @author Dave Syer
+ *
+ */
+public class FlowStep extends AbstractStep {
+
+	private Flow flow;
+
+	/**
+	 * Default constructor convenient for configuration purposes.
+	 */
+	public FlowStep() {
+		super(null);
+	}
+
+	/**
+	 * Constructor for a {@link FlowStep} that sets the flow and of the step explicitly.
+	 * @param flow the {@link Flow} instance to be associated with this step.
+	 */
+	public FlowStep(Flow flow) {
+		super(flow.getName());
+	}
+
+	/**
+	 * Public setter for the flow.
+	 * @param flow the flow to set
+	 */
+	public void setFlow(Flow flow) {
+		this.flow = flow;
+	}
+
+	/**
+	 * Ensure that the flow is set.
+	 * @see AbstractStep#afterPropertiesSet()
+	 */
+	@Override
+	public void afterPropertiesSet() throws Exception {
+		Assert.state(flow != null, "A Flow must be provided");
+		if (getName() == null) {
+			setName(flow.getName());
+		}
+		super.afterPropertiesSet();
+	}
+
+	/**
+	 * Delegate to the flow provided for the execution of the step.
+	 *
+	 * @see AbstractStep#doExecute(StepExecution)
+	 */
+	@Override
+	protected void doExecute(StepExecution stepExecution) throws Exception {
+		try {
+			stepExecution.getExecutionContext().put(STEP_TYPE_KEY, this.getClass().getName());
+			StepHandler stepHandler = new SimpleStepHandler(getJobRepository(), stepExecution.getExecutionContext());
+			FlowExecutor executor = new JobFlowExecutor(getJobRepository(), stepHandler,
+					stepExecution.getJobExecution());
+			executor.updateJobExecutionStatus(flow.start(executor).getStatus());
+			stepExecution.upgradeStatus(executor.getJobExecution().getStatus());
+			stepExecution.setExitStatus(executor.getJobExecution().getExitStatus());
+		}
+		catch (FlowExecutionException e) {
+			if (e.getCause() instanceof JobExecutionException) {
+				throw (JobExecutionException) e.getCause();
+			}
+			throw new JobExecutionException("Flow execution ended unexpectedly", e);
+		}
+	}
+
+}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/JobExecutionDecider.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/JobExecutionDecider.java
index 64cc0dea1..c66d216a9 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/JobExecutionDecider.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/JobExecutionDecider.java
@@ -20,11 +20,11 @@ import org.springframework.batch.core.StepExecution;
 import org.springframework.lang.Nullable;
 
 /**
- * Interface allowing for programmatic access to the decision on what the status
- * of a flow should be.  For example, if some condition that's stored in the 
- * database indicates that the job should stop for a manual check, a decider
- * implementation could check that value to determine the status of the flow. 
- * 
+ * Interface allowing for programmatic access to the decision on what the status of a flow
+ * should be. For example, if some condition that's stored in the database indicates that
+ * the job should stop for a manual check, a decider implementation could check that value
+ * to determine the status of the flow.
+ *
  * @author Dave Syer
  * @author Mahmoud Ben Hassine
  * @since 2.0
@@ -33,9 +33,8 @@ public interface JobExecutionDecider {
 
 	/**
 	 * Strategy for branching an execution based on the state of an ongoing
-	 * {@link JobExecution}. The return value will be used as a status to
-	 * determine the next step in the job.
-	 * 
+	 * {@link JobExecution}. The return value will be used as a status to determine the
+	 * next step in the job.
 	 * @param jobExecution a job execution
 	 * @param stepExecution the latest step execution (may be {@code null})
 	 * @return the exit status code
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/JobFlowExecutor.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/JobFlowExecutor.java
index 6a3003cbd..e9d8fecb3 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/JobFlowExecutor.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/JobFlowExecutor.java
@@ -1,154 +1,156 @@
-/*
- * Copyright 2006-2018 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.batch.core.job.flow;
-
-import org.springframework.batch.core.BatchStatus;
-import org.springframework.batch.core.ExitStatus;
-import org.springframework.batch.core.JobExecution;
-import org.springframework.batch.core.JobInterruptedException;
-import org.springframework.batch.core.StartLimitExceededException;
-import org.springframework.batch.core.Step;
-import org.springframework.batch.core.StepExecution;
-import org.springframework.batch.core.job.StepHandler;
-import org.springframework.batch.core.repository.JobRepository;
-import org.springframework.batch.core.repository.JobRestartException;
-import org.springframework.lang.Nullable;
-
-/**
- * Implementation of {@link FlowExecutor} for use in components that need to
- * execute a flow related to a {@link JobExecution}.
- *
- * @author Dave Syer
- * @author Michael Minella
- * @author Mahmoud Ben Hassine
- *
- */
-public class JobFlowExecutor implements FlowExecutor {
-
-	private final ThreadLocal stepExecutionHolder = new ThreadLocal<>();
-
-	private final JobExecution execution;
-
-	protected ExitStatus exitStatus = ExitStatus.EXECUTING;
-
-	private final StepHandler stepHandler;
-
-	private final JobRepository jobRepository;
-
-	/**
-	 * @param jobRepository instance of {@link JobRepository}.
-	 * @param stepHandler instance of {@link StepHandler}.
-	 * @param execution instance of {@link JobExecution}.
-	 */
-	public JobFlowExecutor(JobRepository jobRepository, StepHandler stepHandler, JobExecution execution) {
-		this.jobRepository = jobRepository;
-		this.stepHandler = stepHandler;
-		this.execution = execution;
-		stepExecutionHolder.set(null);
-	}
-
-	@Override
-	public String executeStep(Step step) throws JobInterruptedException, JobRestartException,
-	StartLimitExceededException {
-		boolean isRerun = isStepRestart(step);
-		StepExecution stepExecution = stepHandler.handleStep(step, execution);
-		stepExecutionHolder.set(stepExecution);
-
-		if (stepExecution == null) {
-			return  ExitStatus.COMPLETED.getExitCode();
-		}
-		if (stepExecution.isTerminateOnly()) {
-			throw new JobInterruptedException("Step requested termination: "+stepExecution, stepExecution.getStatus());
-		}
-
-		if(isRerun) {
-			stepExecution.getExecutionContext().put("batch.restart", true);
-		}
-
-		return stepExecution.getExitStatus().getExitCode();
-	}
-
-	private boolean isStepRestart(Step step) {
-		int count = jobRepository.getStepExecutionCount(execution.getJobInstance(), step.getName());
-
-		return count > 0;
-	}
-
-	@Override
-	public void abandonStepExecution() {
-		StepExecution lastStepExecution = stepExecutionHolder.get();
-		if (lastStepExecution != null && lastStepExecution.getStatus().isGreaterThan(BatchStatus.STOPPING)) {
-			lastStepExecution.upgradeStatus(BatchStatus.ABANDONED);
-			jobRepository.update(lastStepExecution);
-		}
-	}
-
-	@Override
-	public void updateJobExecutionStatus(FlowExecutionStatus status) {
-		execution.setStatus(findBatchStatus(status));
-		exitStatus = exitStatus.and(new ExitStatus(status.getName()));
-		execution.setExitStatus(exitStatus);
-	}
-
-	@Override
-	public JobExecution getJobExecution() {
-		return execution;
-	}
-
-	@Override
-	@Nullable
-	public StepExecution getStepExecution() {
-		return stepExecutionHolder.get();
-	}
-
-	@Override
-	public void close(FlowExecution result) {
-		stepExecutionHolder.set(null);
-	}
-
-	@Override
-	public boolean isRestart() {
-		if (getStepExecution() != null && getStepExecution().getStatus() == BatchStatus.ABANDONED) {
-			/*
-			 * This is assumed to be the last step execution and it was marked
-			 * abandoned, so we are in a restart of a stopped step.
-			 */
-			// TODO: mark the step execution in some more definitive way?
-			return true;
-		}
-		return execution.getStepExecutions().isEmpty();
-	}
-
-	@Override
-	public void addExitStatus(String code) {
-		exitStatus = exitStatus.and(new ExitStatus(code));
-	}
-
-	/**
-	 * @param status {@link FlowExecutionStatus} to convert.
-	 * @return A {@link BatchStatus} appropriate for the {@link FlowExecutionStatus} provided
-	 */
-	protected BatchStatus findBatchStatus(FlowExecutionStatus status) {
-		for (BatchStatus batchStatus : BatchStatus.values()) {
-			if (status.getName().startsWith(batchStatus.toString())) {
-				return batchStatus;
-			}
-		}
-		return BatchStatus.UNKNOWN;
-	}
-
-}
+/*
+ * Copyright 2006-2018 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.batch.core.job.flow;
+
+import org.springframework.batch.core.BatchStatus;
+import org.springframework.batch.core.ExitStatus;
+import org.springframework.batch.core.JobExecution;
+import org.springframework.batch.core.JobInterruptedException;
+import org.springframework.batch.core.StartLimitExceededException;
+import org.springframework.batch.core.Step;
+import org.springframework.batch.core.StepExecution;
+import org.springframework.batch.core.job.StepHandler;
+import org.springframework.batch.core.repository.JobRepository;
+import org.springframework.batch.core.repository.JobRestartException;
+import org.springframework.lang.Nullable;
+
+/**
+ * Implementation of {@link FlowExecutor} for use in components that need to execute a
+ * flow related to a {@link JobExecution}.
+ *
+ * @author Dave Syer
+ * @author Michael Minella
+ * @author Mahmoud Ben Hassine
+ *
+ */
+public class JobFlowExecutor implements FlowExecutor {
+
+	private final ThreadLocal stepExecutionHolder = new ThreadLocal<>();
+
+	private final JobExecution execution;
+
+	protected ExitStatus exitStatus = ExitStatus.EXECUTING;
+
+	private final StepHandler stepHandler;
+
+	private final JobRepository jobRepository;
+
+	/**
+	 * @param jobRepository instance of {@link JobRepository}.
+	 * @param stepHandler instance of {@link StepHandler}.
+	 * @param execution instance of {@link JobExecution}.
+	 */
+	public JobFlowExecutor(JobRepository jobRepository, StepHandler stepHandler, JobExecution execution) {
+		this.jobRepository = jobRepository;
+		this.stepHandler = stepHandler;
+		this.execution = execution;
+		stepExecutionHolder.set(null);
+	}
+
+	@Override
+	public String executeStep(Step step)
+			throws JobInterruptedException, JobRestartException, StartLimitExceededException {
+		boolean isRerun = isStepRestart(step);
+		StepExecution stepExecution = stepHandler.handleStep(step, execution);
+		stepExecutionHolder.set(stepExecution);
+
+		if (stepExecution == null) {
+			return ExitStatus.COMPLETED.getExitCode();
+		}
+		if (stepExecution.isTerminateOnly()) {
+			throw new JobInterruptedException("Step requested termination: " + stepExecution,
+					stepExecution.getStatus());
+		}
+
+		if (isRerun) {
+			stepExecution.getExecutionContext().put("batch.restart", true);
+		}
+
+		return stepExecution.getExitStatus().getExitCode();
+	}
+
+	private boolean isStepRestart(Step step) {
+		int count = jobRepository.getStepExecutionCount(execution.getJobInstance(), step.getName());
+
+		return count > 0;
+	}
+
+	@Override
+	public void abandonStepExecution() {
+		StepExecution lastStepExecution = stepExecutionHolder.get();
+		if (lastStepExecution != null && lastStepExecution.getStatus().isGreaterThan(BatchStatus.STOPPING)) {
+			lastStepExecution.upgradeStatus(BatchStatus.ABANDONED);
+			jobRepository.update(lastStepExecution);
+		}
+	}
+
+	@Override
+	public void updateJobExecutionStatus(FlowExecutionStatus status) {
+		execution.setStatus(findBatchStatus(status));
+		exitStatus = exitStatus.and(new ExitStatus(status.getName()));
+		execution.setExitStatus(exitStatus);
+	}
+
+	@Override
+	public JobExecution getJobExecution() {
+		return execution;
+	}
+
+	@Override
+	@Nullable
+	public StepExecution getStepExecution() {
+		return stepExecutionHolder.get();
+	}
+
+	@Override
+	public void close(FlowExecution result) {
+		stepExecutionHolder.set(null);
+	}
+
+	@Override
+	public boolean isRestart() {
+		if (getStepExecution() != null && getStepExecution().getStatus() == BatchStatus.ABANDONED) {
+			/*
+			 * This is assumed to be the last step execution and it was marked abandoned,
+			 * so we are in a restart of a stopped step.
+			 */
+			// TODO: mark the step execution in some more definitive way?
+			return true;
+		}
+		return execution.getStepExecutions().isEmpty();
+	}
+
+	@Override
+	public void addExitStatus(String code) {
+		exitStatus = exitStatus.and(new ExitStatus(code));
+	}
+
+	/**
+	 * @param status {@link FlowExecutionStatus} to convert.
+	 * @return A {@link BatchStatus} appropriate for the {@link FlowExecutionStatus}
+	 * provided
+	 */
+	protected BatchStatus findBatchStatus(FlowExecutionStatus status) {
+		for (BatchStatus batchStatus : BatchStatus.values()) {
+			if (status.getName().startsWith(batchStatus.toString())) {
+				return batchStatus;
+			}
+		}
+		return BatchStatus.UNKNOWN;
+	}
+
+}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/State.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/State.java
index 659e47f21..c6a0a5e11 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/State.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/State.java
@@ -23,20 +23,17 @@ public interface State {
 
 	/**
 	 * The name of the state. Should be unique within a flow.
-	 * 
 	 * @return the name of this state
 	 */
 	String getName();
 
 	/**
-	 * Handle some business or processing logic and return a status that can be
-	 * used to drive a flow to the next {@link State}. The status can be any
-	 * string, but special meaning is assigned to the static constants in
-	 * {@link FlowExecution}. The context can be used by implementations to do
-	 * whatever they need to do. The same context will be passed to all
-	 * {@link State} instances, so implementations should be careful that the
-	 * context is thread-safe, or used in a thread-safe manner.
-	 * 
+	 * Handle some business or processing logic and return a status that can be used to
+	 * drive a flow to the next {@link State}. The status can be any string, but special
+	 * meaning is assigned to the static constants in {@link FlowExecution}. The context
+	 * can be used by implementations to do whatever they need to do. The same context
+	 * will be passed to all {@link State} instances, so implementations should be careful
+	 * that the context is thread-safe, or used in a thread-safe manner.
 	 * @param executor the context passed in by the caller
 	 * @return a status for the execution
 	 * @throws Exception if anything goes wrong
@@ -44,10 +41,8 @@ public interface State {
 	FlowExecutionStatus handle(FlowExecutor executor) throws Exception;
 
 	/**
-	 * Inquire as to whether a {@link State} is an end state. Implementations
-	 * should return false if processing can continue, even if that would
-	 * require a restart.
-	 * 
+	 * Inquire as to whether a {@link State} is an end state. Implementations should
+	 * return false if processing can continue, even if that would require a restart.
 	 * @return true if this {@link State} is the end of processing
 	 */
 	boolean isEndState();
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/DefaultStateTransitionComparator.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/DefaultStateTransitionComparator.java
index 2b36e74c1..1d43ccc1a 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/DefaultStateTransitionComparator.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/DefaultStateTransitionComparator.java
@@ -20,19 +20,21 @@ import org.springframework.util.StringUtils;
 import java.util.Comparator;
 
 /**
- * Sorts by decreasing specificity of pattern, based on just counting
- * wildcards (with * taking precedence over ?). If wildcard counts are equal
- * then falls back to alphabetic comparison. Hence * > foo* > ??? >
- * fo? > foo.
+ * Sorts by decreasing specificity of pattern, based on just counting wildcards (with *
+ * taking precedence over ?). If wildcard counts are equal then falls back to alphabetic
+ * comparison. Hence * > foo* > ??? > fo? > foo.
  *
  * @see Comparator
  * @author Michael Minella
  * @since 3.0
  */
 public class DefaultStateTransitionComparator implements Comparator {
+
 	public static final String STATE_TRANSITION_COMPARATOR = "batch_state_transition_comparator";
 
-	/* (non-Javadoc)
+	/*
+	 * (non-Javadoc)
+	 *
 	 * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
 	 */
 	@Override
@@ -59,4 +61,5 @@ public class DefaultStateTransitionComparator implements Comparator> transitionMap = new HashMap<>();
-
-	private Map stateMap = new HashMap<>();
-
-	private List stateTransitions = new ArrayList<>();
-
-	private final String name;
-
-	private Comparator stateTransitionComparator;
-
-	public void setStateTransitionComparator(Comparator stateTransitionComparator) {
-		this.stateTransitionComparator = stateTransitionComparator;
-	}
-
-	/**
-	 * Create a flow with the given name.
-	 *
-	 * @param name the name of the flow
-	 */
-	public SimpleFlow(String name) {
-		this.name = name;
-	}
-
-	public State getStartState() {
-		return this.startState;
-	}
-
-	/**
-	 * Get the name for this flow.
-	 *
-	 * @see Flow#getName()
-	 */
-	@Override
-	public String getName() {
-		return name;
-	}
-
-	/**
-	 * Public setter for the stateTransitions.
-	 *
-	 * @param stateTransitions the stateTransitions to set
-	 */
-	public void setStateTransitions(List stateTransitions) {
-
-		this.stateTransitions = stateTransitions;
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	@Override
-	public State getState(String stateName) {
-		return stateMap.get(stateName);
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	@Override
-	public Collection getStates() {
-		return new HashSet<>(stateMap.values());
-	}
-
-	/**
-	 * Locate start state and pre-populate data structures needed for execution.
-	 *
-	 * @see InitializingBean#afterPropertiesSet()
-	 */
-	@Override
-	public void afterPropertiesSet() throws Exception {
-		if (startState == null) {
-			initializeTransitions();
-		}
-	}
-
-	/**
-	 * @see Flow#start(FlowExecutor)
-	 */
-	@Override
-	public FlowExecution start(FlowExecutor executor) throws FlowExecutionException {
-		if (startState == null) {
-			initializeTransitions();
-		}
-		State state = startState;
-		String stateName = state.getName();
-		return resume(stateName, executor);
-	}
-
-	/**
-	 * @see Flow#resume(String, FlowExecutor)
-	 */
-	@Override
-	public FlowExecution resume(String stateName, FlowExecutor executor) throws FlowExecutionException {
-
-		FlowExecutionStatus status = FlowExecutionStatus.UNKNOWN;
-		State state = stateMap.get(stateName);
-
-		if (logger.isDebugEnabled()) {
-			logger.debug("Resuming state="+stateName+" with status="+status);
-		}
-		StepExecution stepExecution = null;
-
-		// Terminate if there are no more states
-		while (isFlowContinued(state, status, stepExecution)) {
-			stateName = state.getName();
-
-			try {
-				if (logger.isDebugEnabled()) {
-					logger.debug("Handling state="+stateName);
-				}
-				status = state.handle(executor);
-				stepExecution = executor.getStepExecution();
-			}
-			catch (FlowExecutionException e) {
-				executor.close(new FlowExecution(stateName, status));
-				throw e;
-			}
-			catch (Exception e) {
-				executor.close(new FlowExecution(stateName, status));
-				throw new FlowExecutionException(String.format("Ended flow=%s at state=%s with exception", name,
-																	  stateName), e);
-			}
-
-			if (logger.isDebugEnabled()) {
-				logger.debug("Completed state="+stateName+" with status="+status);
-			}
-
-			state = nextState(stateName, status, stepExecution);
-		}
-
-		FlowExecution result = new FlowExecution(stateName, status);
-		executor.close(result);
-		return result;
-
-	}
-
-	protected Map> getTransitionMap() {
-		return transitionMap;
-	}
-
-	protected Map getStateMap() {
-		return stateMap;
-	}
-
-	/**
-	 * @param stateName the name of the next state.
-	 * @param status {@link FlowExecutionStatus} instance.
-	 * @param stepExecution {@link StepExecution} instance.
-	 * @return the next {@link Step} (or null if this is the end)
-	 * @throws FlowExecutionException thrown if error occurs during nextState processing.
-	 */
-	protected State nextState(String stateName, FlowExecutionStatus status, StepExecution stepExecution) throws FlowExecutionException {
-		Set set = transitionMap.get(stateName);
-
-		if (set == null) {
-			throw new FlowExecutionException(String.format("No transitions found in flow=%s for state=%s", getName(),
-																  stateName));
-		}
-
-		String next = null;
-		String exitCode = status.getName();
-
-		for (StateTransition stateTransition : set) {
-			if (stateTransition.matches(exitCode) || (exitCode.equals("PENDING") && stateTransition.matches("STOPPED"))) {
-				if (stateTransition.isEnd()) {
-					// End of job
-					return null;
-				}
-				next = stateTransition.getNext();
-				break;
-			}
-		}
-
-		if (next == null) {
-			throw new FlowExecutionException(String.format("Next state not found in flow=%s for state=%s with exit status=%s", getName(), stateName, status.getName()));
-		}
-
-		if (!stateMap.containsKey(next)) {
-			throw new FlowExecutionException(String.format("Next state not specified in flow=%s for next=%s",
-																  getName(), next));
-		}
-
-		return stateMap.get(next);
-
-	}
-
-	protected boolean isFlowContinued(State state, FlowExecutionStatus status, StepExecution stepExecution) {
-		boolean continued = true;
-
-		continued = state != null && status!=FlowExecutionStatus.STOPPED;
-
-		if(stepExecution != null) {
-			Boolean reRun = (Boolean) stepExecution.getExecutionContext().get("batch.restart");
-			Boolean executed = (Boolean) stepExecution.getExecutionContext().get("batch.executed");
-
-			if((executed == null || !executed) && reRun != null && reRun && status == FlowExecutionStatus.STOPPED && !state.getName().endsWith(stepExecution.getStepName()) ) {
-				continued = true;
-			}
-		}
-
-		return continued;
-	}
-
-	/**
-	 * Analyse the transitions provided and generate all the information needed
-	 * to execute the flow.
-	 */
-	private void initializeTransitions() {
-		startState = null;
-		transitionMap.clear();
-		stateMap.clear();
-		boolean hasEndStep = false;
-
-		if (stateTransitions.isEmpty()) {
-			throw new IllegalArgumentException("No start state was found. You must specify at least one step in a job.");
-		}
-
-		for (StateTransition stateTransition : stateTransitions) {
-			State state = stateTransition.getState();
-			String stateName = state.getName();
-			stateMap.put(stateName, state);
-		}
-
-		for (StateTransition stateTransition : stateTransitions) {
-
-			State state = stateTransition.getState();
-
-			if (!stateTransition.isEnd()) {
-
-				String next = stateTransition.getNext();
-
-				if (!stateMap.containsKey(next)) {
-					throw new IllegalArgumentException("Missing state for [" + stateTransition + "]");
-				}
-
-			}
-			else {
-				hasEndStep = true;
-			}
-
-			String name = state.getName();
-
-			Set set = transitionMap.get(name);
-			if (set == null) {
-				// If no comparator is provided, we will maintain the order of insertion
-				if(stateTransitionComparator == null) {
-					set = new LinkedHashSet<>();
-				} else {
-					set = new TreeSet<>(stateTransitionComparator);
-				}
-
-				transitionMap.put(name, set);
-			}
-			set.add(stateTransition);
-
-		}
-
-		if (!hasEndStep) {
-			throw new IllegalArgumentException(
-													  "No end state was found.  You must specify at least one transition with no next state.");
-		}
-
-		startState = stateTransitions.get(0).getState();
-
-	}
-}
+/*
+ * Copyright 2006-2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.batch.core.job.flow.support;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.springframework.batch.core.Step;
+import org.springframework.batch.core.StepExecution;
+import org.springframework.batch.core.job.flow.Flow;
+import org.springframework.batch.core.job.flow.FlowExecution;
+import org.springframework.batch.core.job.flow.FlowExecutionException;
+import org.springframework.batch.core.job.flow.FlowExecutionStatus;
+import org.springframework.batch.core.job.flow.FlowExecutor;
+import org.springframework.batch.core.job.flow.State;
+import org.springframework.beans.factory.InitializingBean;
+
+/**
+ * A {@link Flow} that branches conditionally depending on the exit status of the last
+ * {@link State}. The input parameters are the state transitions (in no particular order).
+ * The start state name can be specified explicitly (and must exist in the set of
+ * transitions), or computed from the existing transitions, if unambiguous.
+ *
+ * @author Dave Syer
+ * @author Michael Minella
+ * @author Mahmoud Ben Hassine
+ * @since 2.0
+ */
+public class SimpleFlow implements Flow, InitializingBean {
+
+	private static final Log logger = LogFactory.getLog(SimpleFlow.class);
+
+	private State startState;
+
+	private Map> transitionMap = new HashMap<>();
+
+	private Map stateMap = new HashMap<>();
+
+	private List stateTransitions = new ArrayList<>();
+
+	private final String name;
+
+	private Comparator stateTransitionComparator;
+
+	public void setStateTransitionComparator(Comparator stateTransitionComparator) {
+		this.stateTransitionComparator = stateTransitionComparator;
+	}
+
+	/**
+	 * Create a flow with the given name.
+	 * @param name the name of the flow
+	 */
+	public SimpleFlow(String name) {
+		this.name = name;
+	}
+
+	public State getStartState() {
+		return this.startState;
+	}
+
+	/**
+	 * Get the name for this flow.
+	 *
+	 * @see Flow#getName()
+	 */
+	@Override
+	public String getName() {
+		return name;
+	}
+
+	/**
+	 * Public setter for the stateTransitions.
+	 * @param stateTransitions the stateTransitions to set
+	 */
+	public void setStateTransitions(List stateTransitions) {
+
+		this.stateTransitions = stateTransitions;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public State getState(String stateName) {
+		return stateMap.get(stateName);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Collection getStates() {
+		return new HashSet<>(stateMap.values());
+	}
+
+	/**
+	 * Locate start state and pre-populate data structures needed for execution.
+	 *
+	 * @see InitializingBean#afterPropertiesSet()
+	 */
+	@Override
+	public void afterPropertiesSet() throws Exception {
+		if (startState == null) {
+			initializeTransitions();
+		}
+	}
+
+	/**
+	 * @see Flow#start(FlowExecutor)
+	 */
+	@Override
+	public FlowExecution start(FlowExecutor executor) throws FlowExecutionException {
+		if (startState == null) {
+			initializeTransitions();
+		}
+		State state = startState;
+		String stateName = state.getName();
+		return resume(stateName, executor);
+	}
+
+	/**
+	 * @see Flow#resume(String, FlowExecutor)
+	 */
+	@Override
+	public FlowExecution resume(String stateName, FlowExecutor executor) throws FlowExecutionException {
+
+		FlowExecutionStatus status = FlowExecutionStatus.UNKNOWN;
+		State state = stateMap.get(stateName);
+
+		if (logger.isDebugEnabled()) {
+			logger.debug("Resuming state=" + stateName + " with status=" + status);
+		}
+		StepExecution stepExecution = null;
+
+		// Terminate if there are no more states
+		while (isFlowContinued(state, status, stepExecution)) {
+			stateName = state.getName();
+
+			try {
+				if (logger.isDebugEnabled()) {
+					logger.debug("Handling state=" + stateName);
+				}
+				status = state.handle(executor);
+				stepExecution = executor.getStepExecution();
+			}
+			catch (FlowExecutionException e) {
+				executor.close(new FlowExecution(stateName, status));
+				throw e;
+			}
+			catch (Exception e) {
+				executor.close(new FlowExecution(stateName, status));
+				throw new FlowExecutionException(
+						String.format("Ended flow=%s at state=%s with exception", name, stateName), e);
+			}
+
+			if (logger.isDebugEnabled()) {
+				logger.debug("Completed state=" + stateName + " with status=" + status);
+			}
+
+			state = nextState(stateName, status, stepExecution);
+		}
+
+		FlowExecution result = new FlowExecution(stateName, status);
+		executor.close(result);
+		return result;
+
+	}
+
+	protected Map> getTransitionMap() {
+		return transitionMap;
+	}
+
+	protected Map getStateMap() {
+		return stateMap;
+	}
+
+	/**
+	 * @param stateName the name of the next state.
+	 * @param status {@link FlowExecutionStatus} instance.
+	 * @param stepExecution {@link StepExecution} instance.
+	 * @return the next {@link Step} (or null if this is the end)
+	 * @throws FlowExecutionException thrown if error occurs during nextState processing.
+	 */
+	protected State nextState(String stateName, FlowExecutionStatus status, StepExecution stepExecution)
+			throws FlowExecutionException {
+		Set set = transitionMap.get(stateName);
+
+		if (set == null) {
+			throw new FlowExecutionException(
+					String.format("No transitions found in flow=%s for state=%s", getName(), stateName));
+		}
+
+		String next = null;
+		String exitCode = status.getName();
+
+		for (StateTransition stateTransition : set) {
+			if (stateTransition.matches(exitCode)
+					|| (exitCode.equals("PENDING") && stateTransition.matches("STOPPED"))) {
+				if (stateTransition.isEnd()) {
+					// End of job
+					return null;
+				}
+				next = stateTransition.getNext();
+				break;
+			}
+		}
+
+		if (next == null) {
+			throw new FlowExecutionException(
+					String.format("Next state not found in flow=%s for state=%s with exit status=%s", getName(),
+							stateName, status.getName()));
+		}
+
+		if (!stateMap.containsKey(next)) {
+			throw new FlowExecutionException(
+					String.format("Next state not specified in flow=%s for next=%s", getName(), next));
+		}
+
+		return stateMap.get(next);
+
+	}
+
+	protected boolean isFlowContinued(State state, FlowExecutionStatus status, StepExecution stepExecution) {
+		boolean continued = true;
+
+		continued = state != null && status != FlowExecutionStatus.STOPPED;
+
+		if (stepExecution != null) {
+			Boolean reRun = (Boolean) stepExecution.getExecutionContext().get("batch.restart");
+			Boolean executed = (Boolean) stepExecution.getExecutionContext().get("batch.executed");
+
+			if ((executed == null || !executed) && reRun != null && reRun && status == FlowExecutionStatus.STOPPED
+					&& !state.getName().endsWith(stepExecution.getStepName())) {
+				continued = true;
+			}
+		}
+
+		return continued;
+	}
+
+	/**
+	 * Analyse the transitions provided and generate all the information needed to execute
+	 * the flow.
+	 */
+	private void initializeTransitions() {
+		startState = null;
+		transitionMap.clear();
+		stateMap.clear();
+		boolean hasEndStep = false;
+
+		if (stateTransitions.isEmpty()) {
+			throw new IllegalArgumentException(
+					"No start state was found. You must specify at least one step in a job.");
+		}
+
+		for (StateTransition stateTransition : stateTransitions) {
+			State state = stateTransition.getState();
+			String stateName = state.getName();
+			stateMap.put(stateName, state);
+		}
+
+		for (StateTransition stateTransition : stateTransitions) {
+
+			State state = stateTransition.getState();
+
+			if (!stateTransition.isEnd()) {
+
+				String next = stateTransition.getNext();
+
+				if (!stateMap.containsKey(next)) {
+					throw new IllegalArgumentException("Missing state for [" + stateTransition + "]");
+				}
+
+			}
+			else {
+				hasEndStep = true;
+			}
+
+			String name = state.getName();
+
+			Set set = transitionMap.get(name);
+			if (set == null) {
+				// If no comparator is provided, we will maintain the order of insertion
+				if (stateTransitionComparator == null) {
+					set = new LinkedHashSet<>();
+				}
+				else {
+					set = new TreeSet<>(stateTransitionComparator);
+				}
+
+				transitionMap.put(name, set);
+			}
+			set.add(stateTransition);
+
+		}
+
+		if (!hasEndStep) {
+			throw new IllegalArgumentException(
+					"No end state was found.  You must specify at least one transition with no next state.");
+		}
+
+		startState = stateTransitions.get(0).getState();
+
+	}
+
+}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/StateTransition.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/StateTransition.java
index 7f9709e4e..8fdd62cc1 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/StateTransition.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/StateTransition.java
@@ -23,10 +23,10 @@ import org.springframework.util.Assert;
 import org.springframework.util.StringUtils;
 
 /**
- * Value object representing a potential transition from one {@link State} to
- * another. The originating State name and the next {@link State} to execute are
- * linked by a pattern for the {@link ExitStatus#getExitCode() exit code} of an
- * execution of the originating State.
+ * Value object representing a potential transition from one {@link State} to another. The
+ * originating State name and the next {@link State} to execute are linked by a pattern
+ * for the {@link ExitStatus#getExitCode() exit code} of an execution of the originating
+ * State.
  *
  * @author Dave Syer
  * @author Michael Minella
@@ -49,12 +49,9 @@ public final class StateTransition {
 	}
 
 	/**
-	 * Create a new end state {@link StateTransition} specification. This
-	 * transition explicitly goes unconditionally to an end state (i.e. no more
-	 * executions).
-	 *
-	 * @param state the {@link State} used to generate the outcome for this
-	 * transition
+	 * Create a new end state {@link StateTransition} specification. This transition
+	 * explicitly goes unconditionally to an end state (i.e. no more executions).
+	 * @param state the {@link State} used to generate the outcome for this transition
 	 * @return {@link StateTransition} that was created.
 	 */
 	public static StateTransition createEndStateTransition(State state) {
@@ -62,14 +59,11 @@ public final class StateTransition {
 	}
 
 	/**
-	 * Create a new end state {@link StateTransition} specification. This
-	 * transition explicitly goes to an end state (i.e. no more processing) if
-	 * the outcome matches the pattern.
-	 *
-	 * @param state the {@link State} used to generate the outcome for this
-	 * transition
-	 * @param pattern the pattern to match in the exit status of the
-	 * {@link State}
+	 * Create a new end state {@link StateTransition} specification. This transition
+	 * explicitly goes to an end state (i.e. no more processing) if the outcome matches
+	 * the pattern.
+	 * @param state the {@link State} used to generate the outcome for this transition
+	 * @param pattern the pattern to match in the exit status of the {@link State}
 	 * @return {@link StateTransition} that was created.
 	 */
 	public static StateTransition createEndStateTransition(State state, String pattern) {
@@ -77,25 +71,22 @@ public final class StateTransition {
 	}
 
 	/**
-	 * Convenience method to switch the origin and destination of a transition,
-	 * creating a new instance.
-	 *
+	 * Convenience method to switch the origin and destination of a transition, creating a
+	 * new instance.
 	 * @param stateTransition an existing state transition
 	 * @param state the new state for the origin
 	 * @param next the new name for the destination
-	 *
 	 * @return {@link StateTransition} that was created.
 	 */
-	public static StateTransition switchOriginAndDestination(StateTransition stateTransition, State state, String next) {
+	public static StateTransition switchOriginAndDestination(StateTransition stateTransition, State state,
+			String next) {
 		return createStateTransition(state, stateTransition.pattern, next);
 	}
 
 	/**
-	 * Create a new state {@link StateTransition} specification with a wildcard
-	 * pattern that matches all outcomes.
-	 *
-	 * @param state the {@link State} used to generate the outcome for this
-	 * transition
+	 * Create a new state {@link StateTransition} specification with a wildcard pattern
+	 * that matches all outcomes.
+	 * @param state the {@link State} used to generate the outcome for this transition
 	 * @param next the name of the next {@link State} to execute
 	 * @return {@link StateTransition} that was created.
 	 */
@@ -104,13 +95,11 @@ public final class StateTransition {
 	}
 
 	/**
-	 * Create a new {@link StateTransition} specification from one {@link State}
-	 * to another (by name).
-	 *
-	 * @param state the {@link State} used to generate the outcome for this
-	 * transition
-	 * @param pattern the pattern to match in the exit status of the
-	 * {@link State} (can be {@code null})
+	 * Create a new {@link StateTransition} specification from one {@link State} to
+	 * another (by name).
+	 * @param state the {@link State} used to generate the outcome for this transition
+	 * @param pattern the pattern to match in the exit status of the {@link State} (can be
+	 * {@code null})
 	 * @param next the name of the next {@link State} to execute (can be {@code null})
 	 * @return {@link StateTransition} that was created.
 	 */
@@ -153,9 +142,8 @@ public final class StateTransition {
 	}
 
 	/**
-	 * Check if the provided status matches the pattern, signalling that the
-	 * next State should be executed.
-	 *
+	 * Check if the provided status matches the pattern, signalling that the next State
+	 * should be executed.
 	 * @param status the status to compare
 	 * @return true if the pattern matches this status
 	 */
@@ -165,7 +153,6 @@ public final class StateTransition {
 
 	/**
 	 * Check for a special next State signalling the end of a job.
-	 *
 	 * @return true if this transition goes nowhere (there is no next)
 	 */
 	public boolean isEnd() {
@@ -179,8 +166,8 @@ public final class StateTransition {
 	 */
 	@Override
 	public String toString() {
-		return String.format("StateTransition: [state=%s, pattern=%s, next=%s]",
-				state == null ? null : state.getName(), pattern, next);
+		return String.format("StateTransition: [state=%s, pattern=%s, next=%s]", state == null ? null : state.getName(),
+				pattern, next);
 	}
 
 }
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/AbstractState.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/AbstractState.java
index b7301ef4c..fc0a8eb6d 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/AbstractState.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/AbstractState.java
@@ -19,7 +19,6 @@ import org.springframework.batch.core.job.flow.FlowExecutionStatus;
 import org.springframework.batch.core.job.flow.FlowExecutor;
 import org.springframework.batch.core.job.flow.State;
 
-
 /**
  * @author Dave Syer
  * @since 2.0
@@ -40,12 +39,14 @@ public abstract class AbstractState implements State {
 		return name;
 	}
 
-	/* (non-Javadoc)
+	/*
+	 * (non-Javadoc)
+	 *
 	 * @see java.lang.Object#toString()
 	 */
 	@Override
 	public String toString() {
-		return getClass().getSimpleName()+": name=["+name+"]";
+		return getClass().getSimpleName() + ": name=[" + name + "]";
 	}
 
 	@Override
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/DecisionState.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/DecisionState.java
index 63f9b594c..35cbbcca5 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/DecisionState.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/DecisionState.java
@@ -31,7 +31,8 @@ public class DecisionState extends AbstractState {
 	private final JobExecutionDecider decider;
 
 	/**
-	 * @param decider the {@link JobExecutionDecider} instance to make the status decision.
+	 * @param decider the {@link JobExecutionDecider} instance to make the status
+	 * decision.
 	 * @param name the name of the decision state.
 	 */
 	public DecisionState(JobExecutionDecider decider, String name) {
@@ -44,7 +45,9 @@ public class DecisionState extends AbstractState {
 		return decider.decide(executor.getJobExecution(), executor.getStepExecution());
 	}
 
-	/* (non-Javadoc)
+	/*
+	 * (non-Javadoc)
+	 *
 	 * @see org.springframework.batch.core.job.flow.State#isEndState()
 	 */
 	@Override
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/EndState.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/EndState.java
index 04c450eaa..053b5c8a4 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/EndState.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/EndState.java
@@ -23,8 +23,8 @@ import org.springframework.batch.core.job.flow.FlowExecutor;
 import org.springframework.batch.core.job.flow.State;
 
 /**
- * {@link State} implementation for ending a job if it is in progress and
- * continuing if just starting.
+ * {@link State} implementation for ending a job if it is in progress and continuing if
+ * just starting.
  *
  * @author Dave Syer
  * @since 2.0
@@ -58,8 +58,8 @@ public class EndState extends AbstractState {
 	 * @param status The {@link FlowExecutionStatus} to end with
 	 * @param name The name of the state
 	 * @param code The exit status to save
-	 * @param abandon flag to indicate that previous step execution can be
-	 * marked as abandoned (if there is one)
+	 * @param abandon flag to indicate that previous step execution can be marked as
+	 * abandoned (if there is one)
 	 *
 	 */
 	public EndState(FlowExecutionStatus status, String code, String name, boolean abandon) {
@@ -101,22 +101,21 @@ public class EndState extends AbstractState {
 			if (status.isStop()) {
 				if (!executor.isRestart()) {
 					/*
-					 * If there are step executions, then we are not at the
-					 * beginning of a restart.
+					 * If there are step executions, then we are not at the beginning of a
+					 * restart.
 					 */
 					if (abandon) {
 						/*
-						 * Only if instructed to do so, upgrade the status of
-						 * last step execution so it is not replayed on a
-						 * restart...
+						 * Only if instructed to do so, upgrade the status of last step
+						 * execution so it is not replayed on a restart...
 						 */
 						executor.abandonStepExecution();
 					}
 				}
 				else {
 					/*
-					 * If we are a stop state and we got this far then it must
-					 * be a restart, so return COMPLETED.
+					 * If we are a stop state and we got this far then it must be a
+					 * restart, so return COMPLETED.
 					 */
 					return FlowExecutionStatus.COMPLETED;
 				}
@@ -131,7 +130,6 @@ public class EndState extends AbstractState {
 
 	/**
 	 * Performs any logic to update the exit status for the current flow.
-	 *
 	 * @param executor {@link FlowExecutor} for the current flow
 	 * @param code The exit status to save
 	 */
@@ -158,4 +156,5 @@ public class EndState extends AbstractState {
 	public String toString() {
 		return super.toString() + " status=[" + status + "]";
 	}
+
 }
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/FlowExecutionAggregator.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/FlowExecutionAggregator.java
index eb28126d7..cd5a124ef 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/FlowExecutionAggregator.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/FlowExecutionAggregator.java
@@ -21,9 +21,9 @@ import org.springframework.batch.core.job.flow.FlowExecution;
 import org.springframework.batch.core.job.flow.FlowExecutionStatus;
 
 /**
- * Strategy interface for aggregating {@link FlowExecution} instances into a
- * single exit status.
- * 
+ * Strategy interface for aggregating {@link FlowExecution} instances into a single exit
+ * status.
+ *
  * @author Dave Syer
  * @since 2.0
  */
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/FlowState.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/FlowState.java
index 617a97565..dd17ab8b9 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/FlowState.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/FlowState.java
@@ -56,7 +56,9 @@ public class FlowState extends AbstractState implements FlowHolder {
 		return flow.start(executor).getStatus();
 	}
 
-	/* (non-Javadoc)
+	/*
+	 * (non-Javadoc)
+	 *
 	 * @see org.springframework.batch.core.job.flow.State#isEndState()
 	 */
 	@Override
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/MaxValueFlowExecutionAggregator.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/MaxValueFlowExecutionAggregator.java
index 2382af0dd..a395b2dca 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/MaxValueFlowExecutionAggregator.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/MaxValueFlowExecutionAggregator.java
@@ -24,8 +24,7 @@ import org.springframework.batch.core.job.flow.FlowExecutionStatus;
 /**
  * Implementation of the {@link FlowExecutionAggregator} interface that aggregates
  * {@link FlowExecutionStatus}', using the status with the high precedence as the
- * aggregate status.  See {@link FlowExecutionStatus} for details on status
- * precedence.
+ * aggregate status. See {@link FlowExecutionStatus} for details on status precedence.
  *
  * @author Dave Syer
  * @since 2.0
@@ -33,9 +32,9 @@ import org.springframework.batch.core.job.flow.FlowExecutionStatus;
 public class MaxValueFlowExecutionAggregator implements FlowExecutionAggregator {
 
 	/**
-	 * Aggregate all of the {@link FlowExecutionStatus}es of the
-	 * {@link FlowExecution}s into one status. The aggregate status will be the
-	 * status with the highest precedence.
+	 * Aggregate all of the {@link FlowExecutionStatus}es of the {@link FlowExecution}s
+	 * into one status. The aggregate status will be the status with the highest
+	 * precedence.
 	 *
 	 * @see FlowExecutionAggregator#aggregate(Collection)
 	 */
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/SplitState.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/SplitState.java
index 0e945bce6..790afb728 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/SplitState.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/SplitState.java
@@ -34,8 +34,8 @@ import org.springframework.core.task.TaskExecutor;
 import org.springframework.core.task.TaskRejectedException;
 
 /**
- * A {@link State} implementation that splits a {@link Flow} into multiple
- * parallel subflows.
+ * A {@link State} implementation that splits a {@link Flow} into multiple parallel
+ * subflows.
  *
  * @author Dave Syer
  * @since 2.0
@@ -74,8 +74,8 @@ public class SplitState extends AbstractState implements FlowHolder {
 	}
 
 	/**
-	 * Execute the flows in parallel by passing them to the {@link TaskExecutor}
-	 * and wait for all of them to finish before proceeding.
+	 * Execute the flows in parallel by passing them to the {@link TaskExecutor} and wait
+	 * for all of them to finish before proceeding.
 	 *
 	 * @see State#handle(FlowExecutor)
 	 */
@@ -89,11 +89,11 @@ public class SplitState extends AbstractState implements FlowHolder {
 		for (final Flow flow : flows) {
 
 			final FutureTask task = new FutureTask<>(new Callable() {
-                @Override
-                public FlowExecution call() throws Exception {
-                    return flow.start(executor);
-                }
-            });
+				@Override
+				public FlowExecution call() throws Exception {
+					return flow.start(executor);
+				}
+			});
 
 			tasks.add(task);
 
@@ -118,7 +118,8 @@ public class SplitState extends AbstractState implements FlowHolder {
 				Throwable cause = e.getCause();
 				if (cause instanceof Exception) {
 					throw (Exception) cause;
-				} else {
+				}
+				else {
 					throw e;
 				}
 			}
@@ -140,4 +141,5 @@ public class SplitState extends AbstractState implements FlowHolder {
 	public boolean isEndState() {
 		return false;
 	}
+
 }
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/StepState.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/StepState.java
index bde475e47..f9d10cec8 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/StepState.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/StepState.java
@@ -1,115 +1,123 @@
-/*
- * Copyright 2006-2019 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.batch.core.job.flow.support.state;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import org.springframework.batch.core.Step;
-import org.springframework.batch.core.job.flow.FlowExecutionStatus;
-import org.springframework.batch.core.job.flow.FlowExecutor;
-import org.springframework.batch.core.job.flow.State;
-import org.springframework.batch.core.step.NoSuchStepException;
-import org.springframework.batch.core.step.StepHolder;
-import org.springframework.batch.core.step.StepLocator;
-
-/**
- * {@link State} implementation that delegates to a {@link FlowExecutor} to
- * execute the specified {@link Step}.
- *
- * @author Dave Syer
- * @author Michael Minella
- * @author Mahmoud Ben Hassine
- * @since 2.0
- */
-public class StepState extends AbstractState implements StepLocator, StepHolder {
-
-	private final Step step;
-
-	/**
-	 * @param step the step that will be executed
-	 */
-	public StepState(Step step) {
-		super(step.getName());
-		this.step = step;
-	}
-
-	/**
-	 * @param name for the step that will be executed
-	 * @param step the step that will be executed
-	 */
-	public StepState(String name, Step step) {
-		super(name);
-		this.step = step;
-	}
-
-	@Override
-	public FlowExecutionStatus handle(FlowExecutor executor) throws Exception {
-		/*
-		 * On starting a new step, possibly upgrade the last execution to make
-		 * sure it is abandoned on restart if it failed.
-		 */
-		executor.abandonStepExecution();
-		return new FlowExecutionStatus(executor.executeStep(step));
-	}
-
-	@Override
-	public Step getStep() {
-		return step;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.springframework.batch.core.job.flow.State#isEndState()
-	 */
-	@Override
-	public boolean isEndState() {
-		return false;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.springframework.batch.core.step.StepLocator#getStepNames()
-	 */
-	@Override
-	public Collection getStepNames() {
-		List names = new ArrayList<>();
-
-		names.add(step.getName());
-
-		if(step instanceof StepLocator) {
-			names.addAll(((StepLocator)step).getStepNames());
-		}
-
-		return names;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.springframework.batch.core.step.StepLocator#getStep(java.lang.String)
-	 */
-	@Override
-	public Step getStep(String stepName) throws NoSuchStepException {
-		Step result = null;
-
-		if(step.getName().equals(stepName)) {
-			result = step;
-		} else if(step instanceof StepLocator) {
-			result = ((StepLocator) step).getStep(stepName);
-		}
-
-		return result;
-	}
-}
+/*
+ * Copyright 2006-2019 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.batch.core.job.flow.support.state;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.springframework.batch.core.Step;
+import org.springframework.batch.core.job.flow.FlowExecutionStatus;
+import org.springframework.batch.core.job.flow.FlowExecutor;
+import org.springframework.batch.core.job.flow.State;
+import org.springframework.batch.core.step.NoSuchStepException;
+import org.springframework.batch.core.step.StepHolder;
+import org.springframework.batch.core.step.StepLocator;
+
+/**
+ * {@link State} implementation that delegates to a {@link FlowExecutor} to execute the
+ * specified {@link Step}.
+ *
+ * @author Dave Syer
+ * @author Michael Minella
+ * @author Mahmoud Ben Hassine
+ * @since 2.0
+ */
+public class StepState extends AbstractState implements StepLocator, StepHolder {
+
+	private final Step step;
+
+	/**
+	 * @param step the step that will be executed
+	 */
+	public StepState(Step step) {
+		super(step.getName());
+		this.step = step;
+	}
+
+	/**
+	 * @param name for the step that will be executed
+	 * @param step the step that will be executed
+	 */
+	public StepState(String name, Step step) {
+		super(name);
+		this.step = step;
+	}
+
+	@Override
+	public FlowExecutionStatus handle(FlowExecutor executor) throws Exception {
+		/*
+		 * On starting a new step, possibly upgrade the last execution to make sure it is
+		 * abandoned on restart if it failed.
+		 */
+		executor.abandonStepExecution();
+		return new FlowExecutionStatus(executor.executeStep(step));
+	}
+
+	@Override
+	public Step getStep() {
+		return step;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.springframework.batch.core.job.flow.State#isEndState()
+	 */
+	@Override
+	public boolean isEndState() {
+		return false;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.springframework.batch.core.step.StepLocator#getStepNames()
+	 */
+	@Override
+	public Collection getStepNames() {
+		List names = new ArrayList<>();
+
+		names.add(step.getName());
+
+		if (step instanceof StepLocator) {
+			names.addAll(((StepLocator) step).getStepNames());
+		}
+
+		return names;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.springframework.batch.core.step.StepLocator#getStep(java.lang.String)
+	 */
+	@Override
+	public Step getStep(String stepName) throws NoSuchStepException {
+		Step result = null;
+
+		if (step.getName().equals(stepName)) {
+			result = step;
+		}
+		else if (step instanceof StepLocator) {
+			result = ((StepLocator) step).getStep(stepName);
+		}
+
+		return result;
+	}
+
+}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobExecutionNotFailedException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobExecutionNotFailedException.java
index 31fc309e1..29788479b 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobExecutionNotFailedException.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobExecutionNotFailedException.java
@@ -18,18 +18,17 @@ package org.springframework.batch.core.launch;
 import org.springframework.batch.core.JobExecutionException;
 
 /**
- * Checked exception to indicate that user asked for a job execution to be
- * resumed when actually it didn't fail.
- * 
+ * Checked exception to indicate that user asked for a job execution to be resumed when
+ * actually it didn't fail.
+ *
  * @author Dave Syer
- * 
+ *
  */
 @SuppressWarnings("serial")
 public class JobExecutionNotFailedException extends JobExecutionException {
 
 	/**
 	 * Create an exception with the given message.
-	 *
 	 * @param msg the error message.
 	 */
 	public JobExecutionNotFailedException(String msg) {
@@ -43,4 +42,5 @@ public class JobExecutionNotFailedException extends JobExecutionException {
 	public JobExecutionNotFailedException(String msg, Throwable e) {
 		super(msg, e);
 	}
+
 }
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobExecutionNotRunningException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobExecutionNotRunningException.java
index f2aa6d527..b94b47e70 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobExecutionNotRunningException.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobExecutionNotRunningException.java
@@ -1,39 +1,39 @@
-/*
- * Copyright 2006-2007 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.batch.core.launch;
-
-import org.springframework.batch.core.JobExecutionException;
-
-/**
- * Checked exception indicating that a JobExecution that is not currently running has
- * been requested to stop.
- * 
- * @author Dave Syer
- * @since 2.0
- */
-@SuppressWarnings("serial")
-public class JobExecutionNotRunningException extends JobExecutionException {
-
-	/**
-	 * Create a {@link JobExecutionNotRunningException} with a message.
-	 * 
-	 * @param msg the message to signal cause of failure with details about the job execution
-	 */
-	public JobExecutionNotRunningException(String msg) {
-		super(msg);
-	}
-
-}
+/*
+ * Copyright 2006-2007 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.batch.core.launch;
+
+import org.springframework.batch.core.JobExecutionException;
+
+/**
+ * Checked exception indicating that a JobExecution that is not currently running has been
+ * requested to stop.
+ *
+ * @author Dave Syer
+ * @since 2.0
+ */
+@SuppressWarnings("serial")
+public class JobExecutionNotRunningException extends JobExecutionException {
+
+	/**
+	 * Create a {@link JobExecutionNotRunningException} with a message.
+	 * @param msg the message to signal cause of failure with details about the job
+	 * execution
+	 */
+	public JobExecutionNotRunningException(String msg) {
+		super(msg);
+	}
+
+}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobExecutionNotStoppedException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobExecutionNotStoppedException.java
index 4ec94b45b..a0ab2ac31 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobExecutionNotStoppedException.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobExecutionNotStoppedException.java
@@ -18,18 +18,17 @@ package org.springframework.batch.core.launch;
 import org.springframework.batch.core.JobExecutionException;
 
 /**
- * Checked exception to indicate that user asked for a job execution to be
- * aborted when hasn't been stopped.
- * 
+ * Checked exception to indicate that user asked for a job execution to be aborted when
+ * hasn't been stopped.
+ *
  * @author Dave Syer
- * 
+ *
  */
 @SuppressWarnings("serial")
 public class JobExecutionNotStoppedException extends JobExecutionException {
 
 	/**
 	 * Create an exception with the given message.
-	 *
 	 * @param msg the message.
 	 */
 	public JobExecutionNotStoppedException(String msg) {
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobInstanceAlreadyExistsException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobInstanceAlreadyExistsException.java
index 3558abba1..f354e00dd 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobInstanceAlreadyExistsException.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobInstanceAlreadyExistsException.java
@@ -18,20 +18,17 @@ package org.springframework.batch.core.launch;
 import org.springframework.batch.core.Job;
 import org.springframework.batch.core.JobExecutionException;
 
-
 /**
- * Checked exception to indicate that a required {@link Job} is not
- * available.
- * 
+ * Checked exception to indicate that a required {@link Job} is not available.
+ *
  * @author Dave Syer
- * 
+ *
  */
 @SuppressWarnings("serial")
 public class JobInstanceAlreadyExistsException extends JobExecutionException {
 
 	/**
 	 * Create an exception with the given message.
-	 *
 	 * @param msg the error message.
 	 */
 	public JobInstanceAlreadyExistsException(String msg) {
@@ -45,4 +42,5 @@ public class JobInstanceAlreadyExistsException extends JobExecutionException {
 	public JobInstanceAlreadyExistsException(String msg, Throwable e) {
 		super(msg, e);
 	}
+
 }
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobLauncher.java b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobLauncher.java
index ae2c25859..4fe68678b 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobLauncher.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobLauncher.java
@@ -24,13 +24,12 @@ import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteExcep
 import org.springframework.batch.core.repository.JobRestartException;
 
 /**
- * Simple interface for controlling jobs, including possible ad-hoc executions,
- * based on different runtime identifiers. It is extremely important to note
- * that this interface makes absolutely no guarantees about whether or not calls
- * to it are executed synchronously or asynchronously. The javadocs for specific
- * implementations should be checked to ensure callers fully understand how the
- * job will be run.
- * 
+ * Simple interface for controlling jobs, including possible ad-hoc executions, based on
+ * different runtime identifiers. It is extremely important to note that this interface
+ * makes absolutely no guarantees about whether or not calls to it are executed
+ * synchronously or asynchronously. The javadocs for specific implementations should be
+ * checked to ensure callers fully understand how the job will be run.
+ *
  * @author Lucas Ward
  * @author Dave Syer
  */
@@ -38,30 +37,26 @@ import org.springframework.batch.core.repository.JobRestartException;
 public interface JobLauncher {
 
 	/**
-	 * Start a job execution for the given {@link Job} and {@link JobParameters}
-	 * . If a {@link JobExecution} was able to be created successfully, it will
-	 * always be returned by this method, regardless of whether or not the
-	 * execution was successful. If there is a past {@link JobExecution} which
-	 * has paused, the same {@link JobExecution} is returned instead of a new
-	 * one created. A exception will only be thrown if there is a failure to
-	 * start the job. If the job encounters some error while processing, the
-	 * JobExecution will be returned, and the status will need to be inspected.
-	 *
+	 * Start a job execution for the given {@link Job} and {@link JobParameters} . If a
+	 * {@link JobExecution} was able to be created successfully, it will always be
+	 * returned by this method, regardless of whether or not the execution was successful.
+	 * If there is a past {@link JobExecution} which has paused, the same
+	 * {@link JobExecution} is returned instead of a new one created. A exception will
+	 * only be thrown if there is a failure to start the job. If the job encounters some
+	 * error while processing, the JobExecution will be returned, and the status will need
+	 * to be inspected.
 	 * @param job the job to be executed.
 	 * @param jobParameters the parameters passed to this execution of the job.
-	 * @return the {@link JobExecution} if it returns synchronously. If the
-	 * implementation is asynchronous, the status might well be unknown.
-	 * 
-	 * @throws JobExecutionAlreadyRunningException if the JobInstance identified
-	 * by the properties already has an execution running.
-	 * @throws IllegalArgumentException if the job or jobInstanceProperties are
-	 * null.
-	 * @throws JobRestartException if the job has been run before and
-	 * circumstances that preclude a re-start.
-	 * @throws JobInstanceAlreadyCompleteException if the job has been run
-	 * before with the same parameters and completed successfully
-	 * @throws JobParametersInvalidException if the parameters are not valid for
-	 * this job
+	 * @return the {@link JobExecution} if it returns synchronously. If the implementation
+	 * is asynchronous, the status might well be unknown.
+	 * @throws JobExecutionAlreadyRunningException if the JobInstance identified by the
+	 * properties already has an execution running.
+	 * @throws IllegalArgumentException if the job or jobInstanceProperties are null.
+	 * @throws JobRestartException if the job has been run before and circumstances that
+	 * preclude a re-start.
+	 * @throws JobInstanceAlreadyCompleteException if the job has been run before with the
+	 * same parameters and completed successfully
+	 * @throws JobParametersInvalidException if the parameters are not valid for this job
 	 */
 	public JobExecution run(Job job, JobParameters jobParameters) throws JobExecutionAlreadyRunningException,
 			JobRestartException, JobInstanceAlreadyCompleteException, JobParametersInvalidException;
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobOperator.java b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobOperator.java
index 59ef08e6e..94ea59cdb 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobOperator.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobOperator.java
@@ -32,11 +32,10 @@ import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteExcep
 import org.springframework.batch.core.repository.JobRestartException;
 
 /**
- * Low level interface for inspecting and controlling jobs with access only to
- * primitive and collection types. Suitable for a command-line client (e.g. that
- * launches a new process for each operation), or a remote launcher like a JMX
- * console.
- * 
+ * Low level interface for inspecting and controlling jobs with access only to primitive
+ * and collection types. Suitable for a command-line client (e.g. that launches a new
+ * process for each operation), or a remote launcher like a JMX console.
+ *
  * @author Dave Syer
  * @since 2.0
  */
@@ -44,46 +43,42 @@ public interface JobOperator {
 
 	/**
 	 * List the {@link JobExecution JobExecutions} associated with a particular
-	 * {@link JobInstance}, in reverse order of creation (and therefore usually
-	 * of execution).
-	 * 
+	 * {@link JobInstance}, in reverse order of creation (and therefore usually of
+	 * execution).
 	 * @param instanceId the id of a {@link JobInstance}
-	 * @return the id values of all the {@link JobExecution JobExecutions}
-	 * associated with this instance
+	 * @return the id values of all the {@link JobExecution JobExecutions} associated with
+	 * this instance
 	 * @throws NoSuchJobInstanceException if the {@link JobInstance} associated with the
-	 * 	{@code instanceId} cannot be found.
+	 * {@code instanceId} cannot be found.
 	 */
 	List getExecutions(long instanceId) throws NoSuchJobInstanceException;
 
 	/**
-	 * List the {@link JobInstance JobInstances} for a given job name, in
-	 * reverse order of creation (and therefore usually of first execution).
-	 * 
+	 * List the {@link JobInstance JobInstances} for a given job name, in reverse order of
+	 * creation (and therefore usually of first execution).
 	 * @param jobName the job name that all the instances have
 	 * @param start the start index of the instances
 	 * @param count the maximum number of values to return
 	 * @return the id values of the {@link JobInstance JobInstances}
-	 * @throws NoSuchJobException is thrown if no {@link JobInstance}s for the jobName exist.
+	 * @throws NoSuchJobException is thrown if no {@link JobInstance}s for the jobName
+	 * exist.
 	 */
 	List getJobInstances(String jobName, int start, int count) throws NoSuchJobException;
 
 	/**
-	 * Get the id values of all the running {@link JobExecution JobExecutions}
-	 * with the given job name.
-	 * 
+	 * Get the id values of all the running {@link JobExecution JobExecutions} with the
+	 * given job name.
 	 * @param jobName the name of the job to search under
 	 * @return the id values of the running {@link JobExecution} instances
-	 * @throws NoSuchJobException if there are no {@link JobExecution
-	 * JobExecutions} with that job name
+	 * @throws NoSuchJobException if there are no {@link JobExecution JobExecutions} with
+	 * that job name
 	 */
 	Set getRunningExecutions(String jobName) throws NoSuchJobException;
 
 	/**
 	 * Get the {@link JobParameters} as an easily readable String.
-	 * 
 	 * @param executionId the id of an existing {@link JobExecution}
-	 * @return the job parameters that were used to launch the associated
-	 * instance
+	 * @return the job parameters that were used to launch the associated instance
 	 * @throws NoSuchJobExecutionException if the id was not associated with any
 	 * {@link JobExecution}
 	 */
@@ -91,127 +86,119 @@ public interface JobOperator {
 
 	/**
 	 * Start a new instance of a job with the parameters specified.
-	 * 
 	 * @param jobName the name of the {@link Job} to launch
-	 * @param parameters the parameters to launch it with (comma or newline
-	 * separated name=value pairs)
+	 * @param parameters the parameters to launch it with (comma or newline separated
+	 * name=value pairs)
 	 * @return the id of the {@link JobExecution} that is launched
-	 * @throws NoSuchJobException if there is no {@link Job} with the specified
-	 * name
-	 * @throws JobInstanceAlreadyExistsException if a job instance with this
-	 * name and parameters already exists
-	 * @throws JobParametersInvalidException thrown if any of the job parameters are invalid.
+	 * @throws NoSuchJobException if there is no {@link Job} with the specified name
+	 * @throws JobInstanceAlreadyExistsException if a job instance with this name and
+	 * parameters already exists
+	 * @throws JobParametersInvalidException thrown if any of the job parameters are
+	 * invalid.
 	 */
-	Long start(String jobName, String parameters) throws NoSuchJobException, JobInstanceAlreadyExistsException, JobParametersInvalidException;
+	Long start(String jobName, String parameters)
+			throws NoSuchJobException, JobInstanceAlreadyExistsException, JobParametersInvalidException;
 
 	/**
-	 * Restart a failed or stopped {@link JobExecution}. Fails with an exception
-	 * if the id provided does not exist or corresponds to a {@link JobInstance}
-	 * that in normal circumstances already completed successfully.
-	 * 
+	 * Restart a failed or stopped {@link JobExecution}. Fails with an exception if the id
+	 * provided does not exist or corresponds to a {@link JobInstance} that in normal
+	 * circumstances already completed successfully.
 	 * @param executionId the id of a failed or stopped {@link JobExecution}
 	 * @return the id of the {@link JobExecution} that was started
-	 * 
-	 * @throws JobInstanceAlreadyCompleteException if the job was already
-	 * successfully completed
+	 * @throws JobInstanceAlreadyCompleteException if the job was already successfully
+	 * completed
 	 * @throws NoSuchJobExecutionException if the id was not associated with any
 	 * {@link JobExecution}
 	 * @throws NoSuchJobException if the {@link JobExecution} was found, but its
 	 * corresponding {@link Job} is no longer available for launching
-	 * @throws JobRestartException if there is a non-specific error with the
-	 * restart (e.g. corrupt or inconsistent restart data)
-	 * @throws JobParametersInvalidException if the parameters are not valid for
-	 * this job
+	 * @throws JobRestartException if there is a non-specific error with the restart (e.g.
+	 * corrupt or inconsistent restart data)
+	 * @throws JobParametersInvalidException if the parameters are not valid for this job
 	 */
 	Long restart(long executionId) throws JobInstanceAlreadyCompleteException, NoSuchJobExecutionException,
 			NoSuchJobException, JobRestartException, JobParametersInvalidException;
 
 	/**
 	 * Launch the next in a sequence of {@link JobInstance} determined by the
-	 * {@link JobParametersIncrementer} attached to the specified job. If the
-	 * previous instance is still in a failed state, this method should still
-	 * create a new instance and run it with different parameters (as long as
-	 * the {@link JobParametersIncrementer} is working).
+ * {@link JobParametersIncrementer} attached to the specified job. If the previous + * instance is still in a failed state, this method should still create a new instance + * and run it with different parameters (as long as the + * {@link JobParametersIncrementer} is working).
*
- * - * The last three exception described below should be extremely unlikely, - * but cannot be ruled out entirely. It points to some other thread or - * process trying to use this method (or a similar one) at the same time. - * - * @param jobName the name of the job to launch - * @return the {@link JobExecution} id of the execution created when the job - * is launched * + * The last three exception described below should be extremely unlikely, but cannot + * be ruled out entirely. It points to some other thread or process trying to use this + * method (or a similar one) at the same time. + * @param jobName the name of the job to launch + * @return the {@link JobExecution} id of the execution created when the job is + * launched * @throws NoSuchJobException if there is no such job definition available * @throws JobParametersNotFoundException if the parameters cannot be found - * @throws JobParametersInvalidException thrown if some of the job parameters are invalid. + * @throws JobParametersInvalidException thrown if some of the job parameters are + * invalid. * @throws UnexpectedJobExecutionException if an unexpected condition arises * @throws JobRestartException thrown if a job is restarted illegally. - * @throws JobExecutionAlreadyRunningException thrown if attempting to restart a job that is already executing. - * @throws JobInstanceAlreadyCompleteException thrown if attempting to restart a completed job. + * @throws JobExecutionAlreadyRunningException thrown if attempting to restart a job + * that is already executing. + * @throws JobInstanceAlreadyCompleteException thrown if attempting to restart a + * completed job. */ Long startNextInstance(String jobName) throws NoSuchJobException, JobParametersNotFoundException, - JobRestartException, JobExecutionAlreadyRunningException, JobInstanceAlreadyCompleteException, UnexpectedJobExecutionException, JobParametersInvalidException; + JobRestartException, JobExecutionAlreadyRunningException, JobInstanceAlreadyCompleteException, + UnexpectedJobExecutionException, JobParametersInvalidException; /** - * Send a stop signal to the {@link JobExecution} with the supplied id. The - * signal is successfully sent if this method returns true, but that doesn't - * mean that the job has stopped. The only way to be sure of that is to poll - * the job execution status. - * + * Send a stop signal to the {@link JobExecution} with the supplied id. The signal is + * successfully sent if this method returns true, but that doesn't mean that the job + * has stopped. The only way to be sure of that is to poll the job execution status. * @param executionId the id of a running {@link JobExecution} - * @return true if the message was successfully sent (does not guarantee - * that the job has stopped) - * @throws NoSuchJobExecutionException if there is no {@link JobExecution} - * with the id supplied - * @throws JobExecutionNotRunningException if the {@link JobExecution} is - * not running (so cannot be stopped) + * @return true if the message was successfully sent (does not guarantee that the job + * has stopped) + * @throws NoSuchJobExecutionException if there is no {@link JobExecution} with the id + * supplied + * @throws JobExecutionNotRunningException if the {@link JobExecution} is not running + * (so cannot be stopped) */ boolean stop(long executionId) throws NoSuchJobExecutionException, JobExecutionNotRunningException; /** - * Summarise the {@link JobExecution} with the supplied id, giving details - * of status, start and end times etc. - * + * Summarise the {@link JobExecution} with the supplied id, giving details of status, + * start and end times etc. * @param executionId the id of an existing {@link JobExecution} * @return a String summarising the state of the job execution - * @throws NoSuchJobExecutionException if there is no {@link JobExecution} - * with the supplied id + * @throws NoSuchJobExecutionException if there is no {@link JobExecution} with the + * supplied id */ String getSummary(long executionId) throws NoSuchJobExecutionException; /** - * Summarise the {@link StepExecution} instances belonging to the - * {@link JobExecution} with the supplied id, giving details of status, - * start and end times etc. - * + * Summarise the {@link StepExecution} instances belonging to the {@link JobExecution} + * with the supplied id, giving details of status, start and end times etc. * @param executionId the id of an existing {@link JobExecution} - * @return a map of step execution id to String summarising the state of the - * execution - * @throws NoSuchJobExecutionException if there is no {@link JobExecution} - * with the supplied id + * @return a map of step execution id to String summarising the state of the execution + * @throws NoSuchJobExecutionException if there is no {@link JobExecution} with the + * supplied id */ Map getStepExecutionSummaries(long executionId) throws NoSuchJobExecutionException; /** * List the available job names that can be launched with * {@link #start(String, String)}. - * * @return a set of job names */ Set getJobNames(); /** - * Mark the {@link JobExecution} as ABANDONED. If a stop signal is ignored - * because the process died this is the best way to mark a job as finished - * with (as opposed to STOPPED). An abandoned job execution cannot be - * restarted by the framework. - * + * Mark the {@link JobExecution} as ABANDONED. If a stop signal is ignored because the + * process died this is the best way to mark a job as finished with (as opposed to + * STOPPED). An abandoned job execution cannot be restarted by the framework. * @param jobExecutionId the job execution id to abort * @return the {@link JobExecution} that was aborted - * @throws NoSuchJobExecutionException thrown if there is no job execution for the jobExecutionId. - * @throws JobExecutionAlreadyRunningException if the job is running (it - * should be stopped first) + * @throws NoSuchJobExecutionException thrown if there is no job execution for the + * jobExecutionId. + * @throws JobExecutionAlreadyRunningException if the job is running (it should be + * stopped first) */ JobExecution abandon(long jobExecutionId) throws NoSuchJobExecutionException, JobExecutionAlreadyRunningException; + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobParametersNotFoundException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobParametersNotFoundException.java index 6f4b978ac..2f3f94cb9 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobParametersNotFoundException.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/JobParametersNotFoundException.java @@ -18,20 +18,18 @@ package org.springframework.batch.core.launch; import org.springframework.batch.core.JobExecutionException; import org.springframework.batch.core.JobParametersIncrementer; - /** * Checked exception to indicate that a required {@link JobParametersIncrementer} is not * available. - * + * * @author Dave Syer - * + * */ @SuppressWarnings("serial") public class JobParametersNotFoundException extends JobExecutionException { /** * Create an exception with the given message. - * * @param msg the error message. */ public JobParametersNotFoundException(String msg) { @@ -45,4 +43,5 @@ public class JobParametersNotFoundException extends JobExecutionException { public JobParametersNotFoundException(String msg, Throwable e) { super(msg, e); } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/NoSuchJobException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/NoSuchJobException.java index 0713c135d..12fad9a52 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/NoSuchJobException.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/NoSuchJobException.java @@ -18,20 +18,17 @@ package org.springframework.batch.core.launch; import org.springframework.batch.core.Job; import org.springframework.batch.core.JobExecutionException; - /** - * Checked exception to indicate that a required {@link Job} is not - * available. - * + * Checked exception to indicate that a required {@link Job} is not available. + * * @author Dave Syer - * + * */ @SuppressWarnings("serial") public class NoSuchJobException extends JobExecutionException { /** * Create an exception with the given message. - * * @param msg the error message. */ public NoSuchJobException(String msg) { @@ -45,4 +42,5 @@ public class NoSuchJobException extends JobExecutionException { public NoSuchJobException(String msg, Throwable e) { super(msg, e); } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/NoSuchJobExecutionException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/NoSuchJobExecutionException.java index 96a48412b..855848573 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/NoSuchJobExecutionException.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/NoSuchJobExecutionException.java @@ -19,18 +19,16 @@ import org.springframework.batch.core.JobExecution; import org.springframework.batch.core.JobExecutionException; /** - * Checked exception to indicate that a required {@link JobExecution} is not - * available. - * + * Checked exception to indicate that a required {@link JobExecution} is not available. + * * @author Dave Syer - * + * */ @SuppressWarnings("serial") public class NoSuchJobExecutionException extends JobExecutionException { /** * Create an exception with the given message. - * * @param msg the error message. */ public NoSuchJobExecutionException(String msg) { @@ -44,4 +42,5 @@ public class NoSuchJobExecutionException extends JobExecutionException { public NoSuchJobExecutionException(String msg, Throwable e) { super(msg, e); } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/NoSuchJobInstanceException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/NoSuchJobInstanceException.java index 589bc30eb..4841d38c4 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/NoSuchJobInstanceException.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/NoSuchJobInstanceException.java @@ -21,16 +21,15 @@ import org.springframework.batch.core.JobInstance; /** * Exception that signals that the user requested an operation on a non-existent * {@link JobInstance}. - * + * * @author Dave Syer - * + * */ @SuppressWarnings("serial") public class NoSuchJobInstanceException extends JobExecutionException { /** * Create an exception with the given message. - * * @param msg the error message. */ public NoSuchJobInstanceException(String msg) { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/CommandLineJobRunner.java b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/CommandLineJobRunner.java index 5015a9e0a..2b44e4b07 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/CommandLineJobRunner.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/CommandLineJobRunner.java @@ -57,44 +57,40 @@ import org.springframework.util.StringUtils; /** *

- * Basic launcher for starting jobs from the command line. In general, it is - * assumed that this launcher will primarily be used to start a job via a script - * from an Enterprise Scheduler. Therefore, exit codes are mapped to integers so - * that schedulers can use the returned values to determine the next course of - * action. The returned values can also be useful to operations teams in - * determining what should happen upon failure. For example, a returned code of - * 5 might mean that some resource wasn't available and the job should be - * restarted. However, a code of 10 might mean that something critical has - * happened and the issue should be escalated. + * Basic launcher for starting jobs from the command line. In general, it is assumed that + * this launcher will primarily be used to start a job via a script from an Enterprise + * Scheduler. Therefore, exit codes are mapped to integers so that schedulers can use the + * returned values to determine the next course of action. The returned values can also be + * useful to operations teams in determining what should happen upon failure. For example, + * a returned code of 5 might mean that some resource wasn't available and the job should + * be restarted. However, a code of 10 might mean that something critical has happened and + * the issue should be escalated. *

* *

- * With any launch of a batch job within Spring Batch, a Spring context - * containing the {@link Job} and some execution context has to be created. This - * command line launcher can be used to load the job and its context from a - * single location. All dependencies of the launcher will then be satisfied by - * autowiring by type from the combined application context. Default values are - * provided for all fields except the {@link JobLauncher} and {@link JobLocator} - * . Therefore, if autowiring fails to set it (it should be noted that - * dependency checking is disabled because most of the fields have default - * values and thus don't require dependencies to be fulfilled via autowiring) - * then an exception will be thrown. It should also be noted that even if an - * exception is thrown by this class, it will be mapped to an integer and - * returned. + * With any launch of a batch job within Spring Batch, a Spring context containing the + * {@link Job} and some execution context has to be created. This command line launcher + * can be used to load the job and its context from a single location. All dependencies of + * the launcher will then be satisfied by autowiring by type from the combined application + * context. Default values are provided for all fields except the {@link JobLauncher} and + * {@link JobLocator} . Therefore, if autowiring fails to set it (it should be noted that + * dependency checking is disabled because most of the fields have default values and thus + * don't require dependencies to be fulfilled via autowiring) then an exception will be + * thrown. It should also be noted that even if an exception is thrown by this class, it + * will be mapped to an integer and returned. *

* *

- * Notice a property is available to set the {@link SystemExiter}. This class is - * used to exit from the main method, rather than calling System.exit() - * directly. This is because unit testing a class the calls System.exit() is - * impossible without kicking off the test within a new JVM, which it is - * possible to do, however it is a complex solution, much more so than - * strategizing the exiter. + * Notice a property is available to set the {@link SystemExiter}. This class is used to + * exit from the main method, rather than calling System.exit() directly. This is because + * unit testing a class the calls System.exit() is impossible without kicking off the test + * within a new JVM, which it is possible to do, however it is a complex solution, much + * more so than strategizing the exiter. *

* *

- * The arguments to this class can be provided on the command line (separated by - * spaces), or through stdin (separated by new line). They are as follows: + * The arguments to this class can be provided on the command line (separated by spaces), + * or through stdin (separated by new line). They are as follows: *

* * @@ -111,28 +107,26 @@ import org.springframework.util.StringUtils; *
  • -abandon: (optional) to abandon a stopped execution
  • *
  • -next: (optional) to start the next in a sequence according to the * {@link JobParametersIncrementer} in the {@link Job}
  • - *
  • jobIdentifier: the name of the job or the id of a job execution (for - * -stop, -abandon or -restart). - *
  • jobParameters: 0 to many parameters that will be used to launch a job - * specified in the form of key=value pairs. + *
  • jobIdentifier: the name of the job or the id of a job execution (for -stop, + * -abandon or -restart). + *
  • jobParameters: 0 to many parameters that will be used to launch a job specified in + * the form of key=value pairs. * * *

    - * If the -next option is used the parameters on the command line - * (if any) are appended to those retrieved from the incrementer, overriding any - * with the same key. + * If the -next option is used the parameters on the command line (if any) + * are appended to those retrieved from the incrementer, overriding any with the same key. *

    * *

    - * The combined application context must contain only one instance of - * {@link JobLauncher}. The job parameters passed in to the command line will be - * converted to {@link Properties} by assuming that each individual element is - * one parameter that is separated by an equals sign. For example, - * "vendor.id=290232". The resulting properties instance is converted to - * {@link JobParameters} using a {@link JobParametersConverter} from the - * application context (if there is one, or a - * {@link DefaultJobParametersConverter} otherwise). Below is an example - * arguments list: "

    + * The combined application context must contain only one instance of {@link JobLauncher}. + * The job parameters passed in to the command line will be converted to + * {@link Properties} by assuming that each individual element is one parameter that is + * separated by an equals sign. For example, "vendor.id=290232". The resulting properties + * instance is converted to {@link JobParameters} using a {@link JobParametersConverter} + * from the application context (if there is one, or a + * {@link DefaultJobParametersConverter} otherwise). Below is an example arguments list: " + *

    * *

    * @@ -143,12 +137,12 @@ import org.springframework.util.StringUtils; * *

    * By default, the `CommandLineJobRunner` uses a {@link DefaultJobParametersConverter} - * which implicitly converts key/value pairs to identifying job parameters. - * However, it is possible to explicitly specify which job parameters are identifying - * and which are not by prefixing them with `+` or `-` respectively. In the following - * example, `schedule.date` is an identifying job parameter while `vendor.id` is not: + * which implicitly converts key/value pairs to identifying job parameters. However, it is + * possible to explicitly specify which job parameters are identifying and which are not + * by prefixing them with `+` or `-` respectively. In the following example, + * `schedule.date` is an identifying job parameter while `vendor.id` is not: *

    - * + * *

    * * java org.springframework.batch.core.launch.support.CommandLineJobRunner testJob.xml @@ -156,18 +150,19 @@ import org.springframework.util.StringUtils; * *

    * - *

    This behaviour can be overridden by using a custom `JobParametersConverter`.

    + *

    + * This behaviour can be overridden by using a custom `JobParametersConverter`. + *

    * *

    - * Once arguments have been successfully parsed, autowiring will be used to set - * various dependencies. The {@link JobLauncher} for example, will be - * loaded this way. If none is contained in the bean factory (it searches by - * type) then a {@link BeanDefinitionStoreException} will be thrown. The same - * exception will also be thrown if there is more than one present. Assuming the - * JobLauncher has been set correctly, the jobIdentifier argument will be used - * to obtain an actual {@link Job}. If a {@link JobLocator} has been set, then - * it will be used, if not the beanFactory will be asked, using the - * jobIdentifier as the bean id. + * Once arguments have been successfully parsed, autowiring will be used to set various + * dependencies. The {@link JobLauncher} for example, will be loaded this way. If none is + * contained in the bean factory (it searches by type) then a + * {@link BeanDefinitionStoreException} will be thrown. The same exception will also be + * thrown if there is more than one present. Assuming the JobLauncher has been set + * correctly, the jobIdentifier argument will be used to obtain an actual {@link Job}. If + * a {@link JobLocator} has been set, then it will be used, if not the beanFactory will be + * asked, using the jobIdentifier as the bean id. *

    * * @author Dave Syer @@ -196,11 +191,11 @@ public class CommandLineJobRunner { private JobRepository jobRepository; - private final static List VALID_OPTS = Arrays.asList(new String [] {"-restart", "-next", "-stop", "-abandon"}); + private final static List VALID_OPTS = Arrays + .asList(new String[] { "-restart", "-next", "-stop", "-abandon" }); /** * Injection setter for the {@link JobLauncher}. - * * @param launcher the launcher to set */ public void setLauncher(JobLauncher launcher) { @@ -216,7 +211,6 @@ public class CommandLineJobRunner { /** * Injection setter for {@link JobExplorer}. - * * @param jobExplorer the {@link JobExplorer} to set */ public void setJobExplorer(JobExplorer jobExplorer) { @@ -225,7 +219,6 @@ public class CommandLineJobRunner { /** * Injection setter for the {@link ExitCodeMapper}. - * * @param exitCodeMapper the exitCodeMapper to set */ public void setExitCodeMapper(ExitCodeMapper exitCodeMapper) { @@ -233,21 +226,18 @@ public class CommandLineJobRunner { } /** - * Static setter for the {@link SystemExiter} so it can be adjusted before - * dependency injection. Typically overridden by - * {@link #setSystemExiter(SystemExiter)}. - * - * @param systemExiter {@link SystemExiter} instance to be used by CommandLineJobRunner instance. + * Static setter for the {@link SystemExiter} so it can be adjusted before dependency + * injection. Typically overridden by {@link #setSystemExiter(SystemExiter)}. + * @param systemExiter {@link SystemExiter} instance to be used by + * CommandLineJobRunner instance. */ public static void presetSystemExiter(SystemExiter systemExiter) { CommandLineJobRunner.systemExiter = systemExiter; } /** - * Retrieve the error message set by an instance of - * {@link CommandLineJobRunner} as it exits. Empty if the last job launched - * was successful. - * + * Retrieve the error message set by an instance of {@link CommandLineJobRunner} as it + * exits. Empty if the last job launched was successful. * @return the error message */ public static String getErrorMessage() { @@ -256,8 +246,8 @@ public class CommandLineJobRunner { /** * Injection setter for the {@link SystemExiter}. - * - * @param systemExiter {@link SystemExiter} instance to be used by CommandLineJobRunner instance. + * @param systemExiter {@link SystemExiter} instance to be used by + * CommandLineJobRunner instance. */ public void setSystemExiter(SystemExiter systemExiter) { CommandLineJobRunner.systemExiter = systemExiter; @@ -265,9 +255,8 @@ public class CommandLineJobRunner { /** * Injection setter for {@link JobParametersConverter}. - * - * @param jobParametersConverter instance of {@link JobParametersConverter} - * to be used by the CommandLineJobRunner instance. + * @param jobParametersConverter instance of {@link JobParametersConverter} to be used + * by the CommandLineJobRunner instance. */ public void setJobParametersConverter(JobParametersConverter jobParametersConverter) { this.jobParametersConverter = jobParametersConverter; @@ -275,7 +264,6 @@ public class CommandLineJobRunner { /** * Delegate to the exiter to (possibly) exit the VM gracefully. - * * @param status int exit code that should be reported. */ public void exit(int status) { @@ -291,9 +279,9 @@ public class CommandLineJobRunner { } /* - * Start a job by obtaining a combined classpath using the job launcher and - * job paths. If a JobLocator has been set, then use it to obtain an actual - * job, if not ask the context for it. + * Start a job by obtaining a combined classpath using the job launcher and job paths. + * If a JobLocator has been set, then use it to obtain an actual job, if not ask the + * context for it. */ @SuppressWarnings("resource") int start(String jobPath, String jobIdentifier, String[] parameters, Set opts) { @@ -303,7 +291,8 @@ public class CommandLineJobRunner { try { try { context = new AnnotationConfigApplicationContext(Class.forName(jobPath)); - } catch (ClassNotFoundException cnfe) { + } + catch (ClassNotFoundException cnfe) { context = new ClassPathXmlApplicationContext(jobPath); } @@ -317,12 +306,12 @@ public class CommandLineJobRunner { } String jobName = jobIdentifier; - - JobParameters jobParameters = jobParametersConverter.getJobParameters(StringUtils - .splitArrayElementsIntoProperties(parameters, "=")); + + JobParameters jobParameters = jobParametersConverter + .getJobParameters(StringUtils.splitArrayElementsIntoProperties(parameters, "=")); Assert.isTrue(parameters == null || parameters.length == 0 || !jobParameters.isEmpty(), "Invalid JobParameters " + Arrays.asList(parameters) - + ". If parameters are provided they should be in the form name=value (no whitespace)."); + + ". If parameters are provided they should be in the form name=value (no whitespace)."); if (opts.contains("-stop")) { List jobExecutions = getRunningJobExecutions(jobIdentifier); @@ -351,8 +340,8 @@ public class CommandLineJobRunner { if (opts.contains("-restart")) { JobExecution jobExecution = getLastFailedJobExecution(jobIdentifier); if (jobExecution == null) { - throw new JobExecutionNotFailedException("No failed or stopped execution found for job=" - + jobIdentifier); + throw new JobExecutionNotFailedException( + "No failed or stopped execution found for job=" + jobIdentifier); } jobParameters = jobExecution.getJobParameters(); jobName = jobExecution.getJobInstance().getJobName(); @@ -362,7 +351,8 @@ public class CommandLineJobRunner { if (jobLocator != null) { try { job = jobLocator.getJob(jobName); - } catch (NoSuchJobException e) { + } + catch (NoSuchJobException e) { } } if (job == null) { @@ -370,8 +360,7 @@ public class CommandLineJobRunner { } if (opts.contains("-next")) { - jobParameters = new JobParametersBuilder(jobParameters, jobExplorer) - .getNextJobParameters(job) + jobParameters = new JobParametersBuilder(jobParameters, jobExplorer).getNextJobParameters(job) .toJobParameters(); } @@ -484,34 +473,28 @@ public class CommandLineJobRunner { } /** - * Launch a batch job using a {@link CommandLineJobRunner}. Creates a new - * Spring context for the job execution, and uses a common parent for all - * such contexts. No exception are thrown from this method, rather - * exceptions are logged and an integer returned through the exit status in - * a {@link JvmSystemExiter} (which can be overridden by defining one in the - * Spring context).
    - * Parameters can be provided in the form key=value, and will be converted - * using the injected {@link JobParametersConverter}. - * + * Launch a batch job using a {@link CommandLineJobRunner}. Creates a new Spring + * context for the job execution, and uses a common parent for all such contexts. No + * exception are thrown from this method, rather exceptions are logged and an integer + * returned through the exit status in a {@link JvmSystemExiter} (which can be + * overridden by defining one in the Spring context).
    + * Parameters can be provided in the form key=value, and will be converted using the + * injected {@link JobParametersConverter}. * @param args *
      - *
    • -restart: (optional) if the job has failed or stopped and the most - * should be restarted. If specified then the jobIdentifier parameter can be - * interpreted either as the name of the job or the id of the job execution - * that failed.
    • - *
    • -next: (optional) if the job has a {@link JobParametersIncrementer} - * that can be used to launch the next instance in a sequence
    • + *
    • -restart: (optional) if the job has failed or stopped and the most should be + * restarted. If specified then the jobIdentifier parameter can be interpreted either + * as the name of the job or the id of the job execution that failed.
    • + *
    • -next: (optional) if the job has a {@link JobParametersIncrementer} that can be + * used to launch the next instance in a sequence
    • *
    • jobPath: the xml application context containing a {@link Job} - *
    • jobIdentifier: the bean id of the job or id of the failed execution - * in the case of a restart. - *
    • jobParameters: 0 to many parameters that will be used to launch a - * job. + *
    • jobIdentifier: the bean id of the job or id of the failed execution in the case + * of a restart. + *
    • jobParameters: 0 to many parameters that will be used to launch a job. *
    *

    - * The options (-restart, -next) can occur anywhere in the - * command line. + * The options (-restart, -next) can occur anywhere in the command line. *

    - * * @throws Exception is thrown if error occurs. */ public static void main(String[] args) throws Exception { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/DataFieldMaxValueJobParametersIncrementer.java b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/DataFieldMaxValueJobParametersIncrementer.java index 975c65f59..19f222487 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/DataFieldMaxValueJobParametersIncrementer.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/DataFieldMaxValueJobParametersIncrementer.java @@ -22,9 +22,9 @@ import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer import org.springframework.util.Assert; /** - * This incrementer uses a {@link DataFieldMaxValueIncrementer} to generate - * the sequence of values to use as job instance discriminator. - * + * This incrementer uses a {@link DataFieldMaxValueIncrementer} to generate the sequence + * of values to use as job instance discriminator. + * * @author Gregory D. Hopkins * @author Mahmoud Ben Hassine */ @@ -36,13 +36,13 @@ public class DataFieldMaxValueJobParametersIncrementer implements JobParametersI public static final String DEFAULT_KEY = "run.id"; private String key = DEFAULT_KEY; + private DataFieldMaxValueIncrementer dataFieldMaxValueIncrementer; /** * Create a new {@link DataFieldMaxValueJobParametersIncrementer}. - * - * @param dataFieldMaxValueIncrementer the incrementer to use to generate - * the sequence of values. Must not be {@code null}. + * @param dataFieldMaxValueIncrementer the incrementer to use to generate the sequence + * of values. Must not be {@code null}. */ public DataFieldMaxValueJobParametersIncrementer(DataFieldMaxValueIncrementer dataFieldMaxValueIncrementer) { Assert.notNull(dataFieldMaxValueIncrementer, "dataFieldMaxValueIncrementer must not be null"); @@ -52,13 +52,11 @@ public class DataFieldMaxValueJobParametersIncrementer implements JobParametersI @Override public JobParameters getNext(JobParameters jobParameters) { return new JobParametersBuilder(jobParameters == null ? new JobParameters() : jobParameters) - .addLong(this.key, this.dataFieldMaxValueIncrementer.nextLongValue()) - .toJobParameters(); + .addLong(this.key, this.dataFieldMaxValueIncrementer.nextLongValue()).toJobParameters(); } /** * Get the key. Defaults to {@link #DEFAULT_KEY}. - * * @return the key */ public String getKey() { @@ -68,7 +66,6 @@ public class DataFieldMaxValueJobParametersIncrementer implements JobParametersI /** * The name of the key to use as a job parameter. Defaults to {@link #DEFAULT_KEY}. * Must not be {@code null} or empty. - * * @param key the key to set */ public void setKey(String key) { @@ -78,7 +75,6 @@ public class DataFieldMaxValueJobParametersIncrementer implements JobParametersI /** * Get the incrementer. - * * @return the incrementer */ public DataFieldMaxValueIncrementer getDataFieldMaxValueIncrementer() { @@ -87,8 +83,8 @@ public class DataFieldMaxValueJobParametersIncrementer implements JobParametersI /** * The incrementer to generate the sequence of values. Must not be {@code null}. - * - * @param dataFieldMaxValueIncrementer the incrementer to generate the sequence of values + * @param dataFieldMaxValueIncrementer the incrementer to generate the sequence of + * values */ public void setDataFieldMaxValueIncrementer(DataFieldMaxValueIncrementer dataFieldMaxValueIncrementer) { Assert.notNull(dataFieldMaxValueIncrementer, "dataFieldMaxValueIncrementer must not be null"); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/ExitCodeMapper.java b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/ExitCodeMapper.java index 4b15bba20..9c28da39e 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/ExitCodeMapper.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/ExitCodeMapper.java @@ -17,11 +17,10 @@ package org.springframework.batch.core.launch.support; /** - * - * This interface should be implemented when an environment calling the batch - * framework has specific requirements regarding the operating system process - * return status. - * + * + * This interface should be implemented when an environment calling the batch framework + * has specific requirements regarding the operating system process return status. + * * @author Stijn Maller * @author Lucas Ward * @author Dave Syer @@ -39,11 +38,10 @@ public interface ExitCodeMapper { public static final String JOB_NOT_PROVIDED = "JOB_NOT_PROVIDED"; /** - * Convert the exit code from String into an integer that the calling - * environment as an operating system can interpret as an exit status. + * Convert the exit code from String into an integer that the calling environment as + * an operating system can interpret as an exit status. * @param exitCode The exit code which is used internally. - * @return The corresponding exit status as known by the calling - * environment. + * @return The corresponding exit status as known by the calling environment. */ public int intValue(String exitCode); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/JobRegistryBackgroundJobRunner.java b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/JobRegistryBackgroundJobRunner.java index d4eeedb6b..882cc7ed8 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/JobRegistryBackgroundJobRunner.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/JobRegistryBackgroundJobRunner.java @@ -40,20 +40,18 @@ import org.springframework.util.Assert; /** *

    - * Command line launcher for registering jobs with a {@link JobRegistry}. - * Normally this will be used in conjunction with an external trigger for the - * jobs registered, e.g. a JMX MBean wrapper for a {@link JobLauncher}, or a - * Quartz trigger. + * Command line launcher for registering jobs with a {@link JobRegistry}. Normally this + * will be used in conjunction with an external trigger for the jobs registered, e.g. a + * JMX MBean wrapper for a {@link JobLauncher}, or a Quartz trigger. *

    * *

    - * With any launch of a batch job within Spring Batch, a Spring context - * containing the {@link Job} has to be created. Using this launcher, the jobs - * are all registered with a {@link JobRegistry} defined in a parent application - * context. The jobs are then set up in child contexts. All dependencies of the - * runner will then be satisfied by autowiring by type from the parent - * application context. Default values are provided for all fields except the - * {@link JobRegistry}. Therefore, if autowiring fails to set it then an + * With any launch of a batch job within Spring Batch, a Spring context containing the + * {@link Job} has to be created. Using this launcher, the jobs are all registered with a + * {@link JobRegistry} defined in a parent application context. The jobs are then set up + * in child contexts. All dependencies of the runner will then be satisfied by autowiring + * by type from the parent application context. Default values are provided for all fields + * except the {@link JobRegistry}. Therefore, if autowiring fails to set it then an * exception will be thrown. *

    * @@ -63,9 +61,8 @@ import org.springframework.util.Assert; public class JobRegistryBackgroundJobRunner { /** - * System property key that switches the runner to "embedded" mode - * (returning immediately from the main method). Useful for testing - * purposes. + * System property key that switches the runner to "embedded" mode (returning + * immediately from the main method). Useful for testing purposes. */ public static final String EMBEDDED = JobRegistryBackgroundJobRunner.class.getSimpleName() + ".EMBEDDED"; @@ -84,7 +81,8 @@ public class JobRegistryBackgroundJobRunner { private static List errors = Collections.synchronizedList(new ArrayList<>()); /** - * @param parentContextPath the parentContextPath to be used by the JobRegistryBackgroundJobRunner. + * @param parentContextPath the parentContextPath to be used by the + * JobRegistryBackgroundJobRunner. */ public JobRegistryBackgroundJobRunner(String parentContextPath) { super(); @@ -93,7 +91,6 @@ public class JobRegistryBackgroundJobRunner { /** * A loader for the jobs that are going to be registered. - * * @param jobLoader the {@link JobLoader} to set */ public void setJobLoader(JobLoader jobLoader) { @@ -102,7 +99,6 @@ public class JobRegistryBackgroundJobRunner { /** * A job registry that can be used to create a job loader (if none is provided). - * * @param jobRegistry the {@link JobRegistry} to set */ public void setJobRegistry(JobRegistry jobRegistry) { @@ -110,8 +106,7 @@ public class JobRegistryBackgroundJobRunner { } /** - * Public getter for the startup errors encountered during parent context - * creation. + * Public getter for the startup errors encountered during parent context creation. * @return the errors */ public static List getErrors() { @@ -145,8 +140,8 @@ public class JobRegistryBackgroundJobRunner { } /** - * If there is no {@link JobLoader} then try and create one from existing - * bean definitions. + * If there is no {@link JobLoader} then try and create one from existing bean + * definitions. */ private void maybeCreateJobLoader() { @@ -172,11 +167,10 @@ public class JobRegistryBackgroundJobRunner { } /** - * Supply a list of application context locations, starting with the parent - * context, and followed by the children. The parent must contain a - * {@link JobRegistry} and the child contexts are expected to contain - * {@link Job} definitions, each of which will be registered wit the - * registry. + * Supply a list of application context locations, starting with the parent context, + * and followed by the children. The parent must contain a {@link JobRegistry} and the + * child contexts are expected to contain {@link Job} definitions, each of which will + * be registered wit the registry. * * Example usage: * @@ -184,13 +178,12 @@ public class JobRegistryBackgroundJobRunner { * $ java -classpath ... JobRegistryBackgroundJobRunner job-registry-context.xml job1.xml job2.xml ... *
  • * - * The child contexts are created only when needed though the - * {@link JobFactory} interface (but the XML is validated on startup by - * using it to create a {@link BeanFactory} which is then discarded). - * - * The parent context is created in a separate thread, and the program will - * pause for input in an infinite loop until the user hits any key. + * The child contexts are created only when needed though the {@link JobFactory} + * interface (but the XML is validated on startup by using it to create a + * {@link BeanFactory} which is then discarded). * + * The parent context is created in a separate thread, and the program will pause for + * input in an infinite loop until the user hits any key. * @param args the context locations to use (first one is for parent) * @throws Exception if anything goes wrong with the context creation */ @@ -247,8 +240,8 @@ public class JobRegistryBackgroundJobRunner { } synchronized (JobRegistryBackgroundJobRunner.class) { - System.out - .println("Started application. Interrupt (CTRL-C) or call JobRegistryBackgroundJobRunner.stop() to exit."); + System.out.println( + "Started application. Interrupt (CTRL-C) or call JobRegistryBackgroundJobRunner.stop() to exit."); JobRegistryBackgroundJobRunner.class.wait(); } launcher.destroy(); @@ -256,8 +249,8 @@ public class JobRegistryBackgroundJobRunner { } /** - * Unregister all the {@link Job} instances that were registered by this - * post processor. + * Unregister all the {@link Job} instances that were registered by this post + * processor. * @see org.springframework.beans.factory.DisposableBean#destroy() */ private void destroy() throws Exception { @@ -266,8 +259,8 @@ public class JobRegistryBackgroundJobRunner { private void run() { final ApplicationContext parent = new ClassPathXmlApplicationContext(parentContextPath); - parent.getAutowireCapableBeanFactory().autowireBeanProperties(this, - AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, false); + parent.getAutowireCapableBeanFactory().autowireBeanProperties(this, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, + false); parent.getAutowireCapableBeanFactory().initializeBean(this, getClass().getSimpleName()); this.parentContext = parent; } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/JvmSystemExiter.java b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/JvmSystemExiter.java index 41828979e..b0d9e855f 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/JvmSystemExiter.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/JvmSystemExiter.java @@ -17,9 +17,9 @@ package org.springframework.batch.core.launch.support; /** * Implementation of the {@link SystemExiter} interface that calls the standards - * System.exit method. It should be noted that there will be no unit tests for - * this class, since there is only one line of actual code, that would only be - * testable by mocking System or Runtime. + * System.exit method. It should be noted that there will be no unit tests for this class, + * since there is only one line of actual code, that would only be testable by mocking + * System or Runtime. * * @author Lucas Ward * @author Dave Syer @@ -28,9 +28,8 @@ package org.springframework.batch.core.launch.support; public class JvmSystemExiter implements SystemExiter { /** - * Delegate call to System.exit() with the argument provided. This should only - * be used in a scenario where a particular status needs to be returned to - * a Batch scheduler. + * Delegate call to System.exit() with the argument provided. This should only be used + * in a scenario where a particular status needs to be returned to a Batch scheduler. * * @see org.springframework.batch.core.launch.support.SystemExiter#exit(int) */ diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/RunIdIncrementer.java b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/RunIdIncrementer.java index e796960a6..d83ddeb85 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/RunIdIncrementer.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/RunIdIncrementer.java @@ -22,11 +22,10 @@ import org.springframework.batch.core.JobParametersIncrementer; import org.springframework.lang.Nullable; /** - * This incrementer increments a "run.id" parameter of type {@link Long} - * from the given job parameters. If the parameter does not exist, it will - * be initialized to 1. The parameter name can be configured using - * {@link #setKey(String)}. - * + * This incrementer increments a "run.id" parameter of type {@link Long} from the given + * job parameters. If the parameter does not exist, it will be initialized to 1. The + * parameter name can be configured using {@link #setKey(String)}. + * * @author Dave Syer * @author Mahmoud Ben Hassine */ @@ -37,8 +36,7 @@ public class RunIdIncrementer implements JobParametersIncrementer { private String key = RUN_ID_KEY; /** - * The name of the run id in the job parameters. Defaults to "run.id". - * + * The name of the run id in the job parameters. Defaults to "run.id". * @param key the key to set */ public void setKey(String key) { @@ -47,7 +45,6 @@ public class RunIdIncrementer implements JobParametersIncrementer { /** * Increment the run.id parameter (starting with 1). - * * @param parameters the previous job parameters * @return the next job parameters with an incremented (or initialized) run.id * @throws IllegalArgumentException if the previous value of run.id is invalid @@ -63,8 +60,7 @@ public class RunIdIncrementer implements JobParametersIncrementer { id = Long.parseLong(runIdParameter.getValue().toString()) + 1; } catch (NumberFormatException exception) { - throw new IllegalArgumentException("Invalid value for parameter " - + this.key, exception); + throw new IllegalArgumentException("Invalid value for parameter " + this.key, exception); } } return new JobParametersBuilder(params).addLong(this.key, id).toJobParameters(); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/RuntimeExceptionTranslator.java b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/RuntimeExceptionTranslator.java index 988be9bfb..6957a93c3 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/RuntimeExceptionTranslator.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/RuntimeExceptionTranslator.java @@ -24,18 +24,22 @@ import org.aopalliance.intercept.MethodInvocation; */ public class RuntimeExceptionTranslator implements MethodInterceptor { - /* (non-Javadoc) - * @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation) + /* + * (non-Javadoc) + * + * @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept. + * MethodInvocation) */ @Override public Object invoke(MethodInvocation invocation) throws Throwable { try { return invocation.proceed(); - } catch (Exception e) { + } + catch (Exception e) { if (e.getClass().getName().startsWith("java")) { throw e; } - throw new RuntimeException(e.getClass().getSimpleName()+ ": " + e.getMessage()); + throw new RuntimeException(e.getClass().getSimpleName() + ": " + e.getMessage()); } } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SimpleJobLauncher.java b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SimpleJobLauncher.java index 60a1847e9..60fe460c5 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SimpleJobLauncher.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SimpleJobLauncher.java @@ -41,28 +41,24 @@ import org.springframework.util.Assert; /** * Simple implementation of the {@link JobLauncher} interface. The Spring Core - * {@link TaskExecutor} interface is used to launch a {@link Job}. This means - * that the type of executor set is very important. If a - * {@link SyncTaskExecutor} is used, then the job will be processed - * within the same thread that called the launcher. Care should - * be taken to ensure any users of this class understand fully whether or not + * {@link TaskExecutor} interface is used to launch a {@link Job}. This means that the + * type of executor set is very important. If a {@link SyncTaskExecutor} is used, then the + * job will be processed within the same thread that called the launcher. + * Care should be taken to ensure any users of this class understand fully whether or not * the implementation of TaskExecutor used will start tasks synchronously or * asynchronously. The default setting uses a synchronous task executor. * - * There is only one required dependency of this Launcher, a - * {@link JobRepository}. The JobRepository is used to obtain a valid - * JobExecution. The Repository must be used because the provided {@link Job} - * could be a restart of an existing {@link JobInstance}, and only the - * Repository can reliably recreate it. + * There is only one required dependency of this Launcher, a {@link JobRepository}. The + * JobRepository is used to obtain a valid JobExecution. The Repository must be used + * because the provided {@link Job} could be a restart of an existing {@link JobInstance}, + * and only the Repository can reliably recreate it. * * @author Lucas Ward * @author Dave Syer * @author Will Schipp * @author Michael Minella * @author Mahmoud Ben Hassine - * * @since 1.0 - * * @see JobRepository * @see TaskExecutor */ @@ -76,20 +72,18 @@ public class SimpleJobLauncher implements JobLauncher, InitializingBean { /** * Run the provided job with the given {@link JobParameters}. The - * {@link JobParameters} will be used to determine if this is an execution - * of an existing job instance, or if a new one should be created. - * + * {@link JobParameters} will be used to determine if this is an execution of an + * existing job instance, or if a new one should be created. * @param job the job to be run. - * @param jobParameters the {@link JobParameters} for this particular - * execution. - * @return the {@link JobExecution} if it returns synchronously. If the - * implementation is asynchronous, the status might well be unknown. - * @throws JobExecutionAlreadyRunningException if the JobInstance already - * exists and has an execution already running. - * @throws JobRestartException if the execution would be a re-start, but a - * re-start is either not allowed or not needed. - * @throws JobInstanceAlreadyCompleteException if this instance has already - * completed successfully + * @param jobParameters the {@link JobParameters} for this particular execution. + * @return the {@link JobExecution} if it returns synchronously. If the implementation + * is asynchronous, the status might well be unknown. + * @throws JobExecutionAlreadyRunningException if the JobInstance already exists and + * has an execution already running. + * @throws JobRestartException if the execution would be a re-start, but a re-start is + * either not allowed or not needed. + * @throws JobInstanceAlreadyCompleteException if this instance has already completed + * successfully * @throws JobParametersInvalidException thrown if jobParameters is invalid. */ @Override @@ -107,19 +101,20 @@ public class SimpleJobLauncher implements JobLauncher, InitializingBean { throw new JobRestartException("JobInstance already exists and is not restartable"); } /* - * validate here if it has stepExecutions that are UNKNOWN, STARTING, STARTED and STOPPING - * retrieve the previous execution and check + * validate here if it has stepExecutions that are UNKNOWN, STARTING, STARTED + * and STOPPING retrieve the previous execution and check */ for (StepExecution execution : lastExecution.getStepExecutions()) { BatchStatus status = execution.getStatus(); if (status.isRunning() || status == BatchStatus.STOPPING) { - throw new JobExecutionAlreadyRunningException("A job execution for this job is already running: " - + lastExecution); - } else if (status == BatchStatus.UNKNOWN) { + throw new JobExecutionAlreadyRunningException( + "A job execution for this job is already running: " + lastExecution); + } + else if (status == BatchStatus.UNKNOWN) { throw new JobRestartException( "Cannot restart step [" + execution.getStepName() + "] from UNKNOWN status. " - + "The last execution ended with a failure that could not be rolled back, " - + "so it may be dangerous to proceed. Manual intervention is probably necessary."); + + "The last execution ended with a failure that could not be rolled back, " + + "so it may be dangerous to proceed. Manual intervention is probably necessary."); } } } @@ -129,10 +124,10 @@ public class SimpleJobLauncher implements JobLauncher, InitializingBean { job.getJobParametersValidator().validate(jobParameters); /* - * There is a very small probability that a non-restartable job can be - * restarted, but only if another process or thread manages to launch - * and fail a job execution for this instance between the last - * assertion and the next method returning successfully. + * There is a very small probability that a non-restartable job can be restarted, + * but only if another process or thread manages to launch and fail a job + * execution for this instance between the last assertion and the next method + * returning successfully. */ jobExecution = jobRepository.createJobExecution(job.getName(), jobParameters); @@ -148,17 +143,19 @@ public class SimpleJobLauncher implements JobLauncher, InitializingBean { } job.execute(jobExecution); if (logger.isInfoEnabled()) { - Duration jobExecutionDuration = BatchMetrics.calculateDuration(jobExecution.getStartTime(), jobExecution.getEndTime()); + Duration jobExecutionDuration = BatchMetrics.calculateDuration(jobExecution.getStartTime(), + jobExecution.getEndTime()); logger.info("Job: [" + job + "] completed with the following parameters: [" + jobParameters + "] and the following status: [" + jobExecution.getStatus() + "]" - + (jobExecutionDuration == null ? "" : " in " + BatchMetrics.formatDuration(jobExecutionDuration))); + + (jobExecutionDuration == null ? "" + : " in " + BatchMetrics.formatDuration(jobExecutionDuration))); } } catch (Throwable t) { if (logger.isInfoEnabled()) { logger.info("Job: [" + job - + "] failed unexpectedly and fatally with the following parameters: [" + jobParameters - + "]", t); + + "] failed unexpectedly and fatally with the following parameters: [" + + jobParameters + "]", t); } rethrow(t); } @@ -188,7 +185,6 @@ public class SimpleJobLauncher implements JobLauncher, InitializingBean { /** * Set the JobRepository. - * * @param jobRepository instance of {@link JobRepository}. */ public void setJobRepository(JobRepository jobRepository) { @@ -197,7 +193,6 @@ public class SimpleJobLauncher implements JobLauncher, InitializingBean { /** * Set the TaskExecutor. (Optional) - * * @param taskExecutor instance of {@link TaskExecutor}. */ public void setTaskExecutor(TaskExecutor taskExecutor) { @@ -205,8 +200,7 @@ public class SimpleJobLauncher implements JobLauncher, InitializingBean { } /** - * Ensure the required dependencies of a {@link JobRepository} have been - * set. + * Ensure the required dependencies of a {@link JobRepository} have been set. */ @Override public void afterPropertiesSet() throws Exception { @@ -216,4 +210,5 @@ public class SimpleJobLauncher implements JobLauncher, InitializingBean { taskExecutor = new SyncTaskExecutor(); } } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SimpleJobOperator.java b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SimpleJobOperator.java index c7aba90dd..05948f469 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SimpleJobOperator.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SimpleJobOperator.java @@ -64,15 +64,14 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.util.Assert; /** - * Simple implementation of the JobOperator interface. Due to the amount of - * functionality the implementation is combining, the following dependencies - * are required: + * Simple implementation of the JobOperator interface. Due to the amount of functionality + * the implementation is combining, the following dependencies are required: * *
      - *
    • {@link JobLauncher} - *
    • {@link JobExplorer} - *
    • {@link JobRepository} - *
    • {@link JobRegistry} + *
    • {@link JobLauncher} + *
    • {@link JobExplorer} + *
    • {@link JobRepository} + *
    • {@link JobRegistry} *
    * * @author Dave Syer @@ -150,7 +149,8 @@ public class SimpleJobOperator implements JobOperator, InitializingBean { /* * (non-Javadoc) * - * @see org.springframework.batch.core.launch.JobOperator#getExecutions(java.lang.Long) + * @see + * org.springframework.batch.core.launch.JobOperator#getExecutions(java.lang.Long) */ @Override public List getExecutions(long instanceId) throws NoSuchJobInstanceException { @@ -196,23 +196,21 @@ public class SimpleJobOperator implements JobOperator, InitializingBean { /* * (non-Javadoc) * - * @see - * org.springframework.batch.core.launch.JobOperator#getParameters(java. + * @see org.springframework.batch.core.launch.JobOperator#getParameters(java. * lang.Long) */ @Override public String getParameters(long executionId) throws NoSuchJobExecutionException { JobExecution jobExecution = findExecutionById(executionId); - return PropertiesConverter.propertiesToString(jobParametersConverter.getProperties(jobExecution - .getJobParameters())); + return PropertiesConverter + .propertiesToString(jobParametersConverter.getProperties(jobExecution.getJobParameters())); } /* * (non-Javadoc) * - * @see - * org.springframework.batch.core.launch.JobOperator#getRunningExecutions + * @see org.springframework.batch.core.launch.JobOperator#getRunningExecutions * (java.lang.String) */ @Override @@ -230,8 +228,7 @@ public class SimpleJobOperator implements JobOperator, InitializingBean { /* * (non-Javadoc) * - * @see - * org.springframework.batch.core.launch.JobOperator#getStepExecutionSummaries + * @see org.springframework.batch.core.launch.JobOperator#getStepExecutionSummaries * (java.lang.Long) */ @Override @@ -248,9 +245,7 @@ public class SimpleJobOperator implements JobOperator, InitializingBean { /* * (non-Javadoc) * - * @see - * org.springframework.batch.core.launch.JobOperator#getSummary(java.lang - * .Long) + * @see org.springframework.batch.core.launch.JobOperator#getSummary(java.lang .Long) */ @Override public String getSummary(long executionId) throws NoSuchJobExecutionException { @@ -261,11 +256,11 @@ public class SimpleJobOperator implements JobOperator, InitializingBean { /* * (non-Javadoc) * - * @see - * org.springframework.batch.core.launch.JobOperator#resume(java.lang.Long) + * @see org.springframework.batch.core.launch.JobOperator#resume(java.lang.Long) */ @Override - public Long restart(long executionId) throws JobInstanceAlreadyCompleteException, NoSuchJobExecutionException, NoSuchJobException, JobRestartException, JobParametersInvalidException { + public Long restart(long executionId) throws JobInstanceAlreadyCompleteException, NoSuchJobExecutionException, + NoSuchJobException, JobRestartException, JobParametersInvalidException { if (logger.isInfoEnabled()) { logger.info("Checking status of job execution with id=" + executionId); @@ -283,8 +278,8 @@ public class SimpleJobOperator implements JobOperator, InitializingBean { return jobLauncher.run(job, parameters).getId(); } catch (JobExecutionAlreadyRunningException e) { - throw new UnexpectedJobExecutionException(String.format(ILLEGAL_STATE_MSG, "job execution already running", - jobName, parameters), e); + throw new UnexpectedJobExecutionException( + String.format(ILLEGAL_STATE_MSG, "job execution already running", jobName, parameters), e); } } @@ -292,23 +287,23 @@ public class SimpleJobOperator implements JobOperator, InitializingBean { /* * (non-Javadoc) * - * @see - * org.springframework.batch.core.launch.JobOperator#start(java.lang.String, + * @see org.springframework.batch.core.launch.JobOperator#start(java.lang.String, * java.lang.String) */ @Override - public Long start(String jobName, String parameters) throws NoSuchJobException, JobInstanceAlreadyExistsException, JobParametersInvalidException { + public Long start(String jobName, String parameters) + throws NoSuchJobException, JobInstanceAlreadyExistsException, JobParametersInvalidException { if (logger.isInfoEnabled()) { logger.info("Checking status of job with name=" + jobName); } - JobParameters jobParameters = jobParametersConverter.getJobParameters(PropertiesConverter - .stringToProperties(parameters)); + JobParameters jobParameters = jobParametersConverter + .getJobParameters(PropertiesConverter.stringToProperties(parameters)); if (jobRepository.isJobInstanceExists(jobName, jobParameters)) { - throw new JobInstanceAlreadyExistsException(String.format( - "Cannot start a job instance that already exists with name=%s and parameters=%s", jobName, - parameters)); + throw new JobInstanceAlreadyExistsException( + String.format("Cannot start a job instance that already exists with name=%s and parameters=%s", + jobName, parameters)); } Job job = jobRegistry.getJob(jobName); @@ -319,16 +314,16 @@ public class SimpleJobOperator implements JobOperator, InitializingBean { return jobLauncher.run(job, jobParameters).getId(); } catch (JobExecutionAlreadyRunningException e) { - throw new UnexpectedJobExecutionException(String.format(ILLEGAL_STATE_MSG, "job execution already running", - jobName, parameters), e); + throw new UnexpectedJobExecutionException( + String.format(ILLEGAL_STATE_MSG, "job execution already running", jobName, parameters), e); } catch (JobRestartException e) { - throw new UnexpectedJobExecutionException(String.format(ILLEGAL_STATE_MSG, "job not restartable", jobName, - parameters), e); + throw new UnexpectedJobExecutionException( + String.format(ILLEGAL_STATE_MSG, "job not restartable", jobName, parameters), e); } catch (JobInstanceAlreadyCompleteException e) { - throw new UnexpectedJobExecutionException(String.format(ILLEGAL_STATE_MSG, "job already complete", jobName, - parameters), e); + throw new UnexpectedJobExecutionException( + String.format(ILLEGAL_STATE_MSG, "job already complete", jobName, parameters), e); } } @@ -339,16 +334,14 @@ public class SimpleJobOperator implements JobOperator, InitializingBean { * @see JobOperator#startNextInstance(String ) */ @Override - public Long startNextInstance(String jobName) throws NoSuchJobException, - UnexpectedJobExecutionException, JobParametersInvalidException { + public Long startNextInstance(String jobName) + throws NoSuchJobException, UnexpectedJobExecutionException, JobParametersInvalidException { if (logger.isInfoEnabled()) { logger.info("Locating parameters for next instance of job with name=" + jobName); } Job job = jobRegistry.getJob(jobName); - JobParameters parameters = new JobParametersBuilder(jobExplorer) - .getNextJobParameters(job) - .toJobParameters(); + JobParameters parameters = new JobParametersBuilder(jobExplorer).getNextJobParameters(job).toJobParameters(); if (logger.isInfoEnabled()) { logger.info(String.format("Attempting to launch job with name=%s and parameters=%s", jobName, parameters)); } @@ -356,16 +349,16 @@ public class SimpleJobOperator implements JobOperator, InitializingBean { return jobLauncher.run(job, parameters).getId(); } catch (JobExecutionAlreadyRunningException e) { - throw new UnexpectedJobExecutionException(String.format(ILLEGAL_STATE_MSG, "job already running", jobName, - parameters), e); + throw new UnexpectedJobExecutionException( + String.format(ILLEGAL_STATE_MSG, "job already running", jobName, parameters), e); } catch (JobRestartException e) { - throw new UnexpectedJobExecutionException(String.format(ILLEGAL_STATE_MSG, "job not restartable", jobName, - parameters), e); + throw new UnexpectedJobExecutionException( + String.format(ILLEGAL_STATE_MSG, "job not restartable", jobName, parameters), e); } catch (JobInstanceAlreadyCompleteException e) { - throw new UnexpectedJobExecutionException(String.format(ILLEGAL_STATE_MSG, "job instance already complete", - jobName, parameters), e); + throw new UnexpectedJobExecutionException( + String.format(ILLEGAL_STATE_MSG, "job instance already complete", jobName, parameters), e); } } @@ -373,8 +366,7 @@ public class SimpleJobOperator implements JobOperator, InitializingBean { /* * (non-Javadoc) * - * @see - * org.springframework.batch.core.launch.JobOperator#stop(java.lang.Long) + * @see org.springframework.batch.core.launch.JobOperator#stop(java.lang.Long) */ @Override @Transactional @@ -386,45 +378,48 @@ public class SimpleJobOperator implements JobOperator, InitializingBean { // the step implementation will check this status at chunk boundaries. BatchStatus status = jobExecution.getStatus(); if (!(status == BatchStatus.STARTED || status == BatchStatus.STARTING)) { - throw new JobExecutionNotRunningException("JobExecution must be running so that it can be stopped: "+jobExecution); + throw new JobExecutionNotRunningException( + "JobExecution must be running so that it can be stopped: " + jobExecution); } jobExecution.setStatus(BatchStatus.STOPPING); jobRepository.update(jobExecution); try { Job job = jobRegistry.getJob(jobExecution.getJobInstance().getJobName()); - if (job instanceof StepLocator) {//can only process as StepLocator is the only way to get the step object - //get the current stepExecution + if (job instanceof StepLocator) {// can only process as StepLocator is the + // only way to get the step object + // get the current stepExecution for (StepExecution stepExecution : jobExecution.getStepExecutions()) { if (stepExecution.getStatus().isRunning()) { try { - //have the step execution that's running -> need to 'stop' it - Step step = ((StepLocator)job).getStep(stepExecution.getStepName()); + // have the step execution that's running -> need to 'stop' it + Step step = ((StepLocator) job).getStep(stepExecution.getStepName()); if (step instanceof TaskletStep) { - Tasklet tasklet = ((TaskletStep)step).getTasklet(); + Tasklet tasklet = ((TaskletStep) step).getTasklet(); if (tasklet instanceof StoppableTasklet) { StepSynchronizationManager.register(stepExecution); - ((StoppableTasklet)tasklet).stop(); + ((StoppableTasklet) tasklet).stop(); StepSynchronizationManager.release(); } } } catch (NoSuchStepException e) { - logger.warn("Step not found",e); + logger.warn("Step not found", e); } } } } } catch (NoSuchJobException e) { - logger.warn("Cannot find Job object in the job registry. StoppableTasklet#stop() will not be called",e); + logger.warn("Cannot find Job object in the job registry. StoppableTasklet#stop() will not be called", e); } return true; } @Override - public JobExecution abandon(long jobExecutionId) throws NoSuchJobExecutionException, JobExecutionAlreadyRunningException { + public JobExecution abandon(long jobExecutionId) + throws NoSuchJobExecutionException, JobExecutionAlreadyRunningException { JobExecution jobExecution = findExecutionById(jobExecutionId); if (jobExecution.getStatus().isLessThan(BatchStatus.STOPPING)) { @@ -450,4 +445,5 @@ public class SimpleJobOperator implements JobOperator, InitializingBean { return jobExecution; } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SimpleJvmExitCodeMapper.java b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SimpleJvmExitCodeMapper.java index a5db65960..7341b746d 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SimpleJvmExitCodeMapper.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SimpleJvmExitCodeMapper.java @@ -24,9 +24,9 @@ import org.apache.commons.logging.LogFactory; import org.springframework.batch.core.ExitStatus; /** - * An implementation of {@link ExitCodeMapper} that can be configured through a - * map from batch exit codes (String) to integer results. Some default entries - * are set up to recognise common cases. Any that are injected are added to these. + * An implementation of {@link ExitCodeMapper} that can be configured through a map from + * batch exit codes (String) to integer results. Some default entries are set up to + * recognise common cases. Any that are injected are added to these. * * @author Stijn Maller * @author Lucas Ward @@ -53,18 +53,17 @@ public class SimpleJvmExitCodeMapper implements ExitCodeMapper { /** * Supply the ExitCodeMappings - * @param exitCodeMap A set of mappings between environment specific exit - * codes and batch framework internal exit codes + * @param exitCodeMap A set of mappings between environment specific exit codes and + * batch framework internal exit codes */ public void setMapping(Map exitCodeMap) { mapping.putAll(exitCodeMap); } /** - * Get the operating system exit status that matches a certain Batch - * Framework exit code - * @param exitCode The exit code of the Batch Job as known by the Batch - * Framework + * Get the operating system exit status that matches a certain Batch Framework exit + * code + * @param exitCode The exit code of the Batch Job as known by the Batch Framework * @return The exitCode of the Batch Job as known by the JVM */ @Override diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SystemExiter.java b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SystemExiter.java index a49efa3fd..a384c4480 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SystemExiter.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SystemExiter.java @@ -16,11 +16,10 @@ package org.springframework.batch.core.launch.support; /** - * Interface for exiting the JVM. This abstraction is only - * useful in order to allow classes that make System.exit calls - * to be testable, since calling System.exit during a unit - * test would cause the entire jvm to finish. - * + * Interface for exiting the JVM. This abstraction is only useful in order to allow + * classes that make System.exit calls to be testable, since calling System.exit during a + * unit test would cause the entire jvm to finish. + * * @author Lucas Ward * */ @@ -28,12 +27,11 @@ public interface SystemExiter { /** * Terminate the currently running Java Virtual Machine. - * * @param status exit status. - * @throws SecurityException - * if a security manager exists and its checkExit - * method doesn't allow exit with the specified status. - * @see System#exit(int) + * @throws SecurityException if a security manager exists and its + * checkExit method doesn't allow exit with the specified status. + * @see System#exit(int) */ void exit(int status); + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/AbstractListenerFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/AbstractListenerFactoryBean.java index 39a8568c4..83b56eb29 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/AbstractListenerFactoryBean.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/AbstractListenerFactoryBean.java @@ -39,26 +39,25 @@ import static org.springframework.batch.support.MethodInvokerUtils.getMethodInvo import static org.springframework.batch.support.MethodInvokerUtils.getMethodInvokerForInterface; /** - * {@link FactoryBean} implementation that builds a listener based on the - * various lifecycle methods or annotations that are provided. There are three - * possible ways of having a method called as part of a listener lifecycle: + * {@link FactoryBean} implementation that builds a listener based on the various + * lifecycle methods or annotations that are provided. There are three possible ways of + * having a method called as part of a listener lifecycle: * *
      - *
    • Interface implementation: By implementing any of the subclasses of a - * listener interface, methods on said interface will be called + *
    • Interface implementation: By implementing any of the subclasses of a listener + * interface, methods on said interface will be called *
    • Annotations: Annotating a method will result in registration. - *
    • String name of the method to be called, which is tied to a - * {@link ListenerMetaData} value in the metaDataMap. + *
    • String name of the method to be called, which is tied to a {@link ListenerMetaData} + * value in the metaDataMap. *
    * - * It should be noted that methods obtained by name or annotation that don't - * match the listener method signatures to which they belong will cause errors. - * However, it is acceptable to have no parameters at all. If the same method is - * marked in more than one way. (i.e. the method name is given and it is - * annotated) the method will only be called once. However, if the same class - * has multiple methods tied to a particular listener, each method will be - * called. Also note that the same annotations cannot be applied to two separate - * methods in a single class. + * It should be noted that methods obtained by name or annotation that don't match the + * listener method signatures to which they belong will cause errors. However, it is + * acceptable to have no parameters at all. If the same method is marked in more than one + * way. (i.e. the method name is given and it is annotated) the method will only be called + * once. However, if the same class has multiple methods tied to a particular listener, + * each method will be called. Also note that the same annotations cannot be applied to + * two separate methods in a single class. * * @author Lucas Ward * @author Dan Garrette @@ -111,7 +110,7 @@ public abstract class AbstractListenerFactoryBean implements FactoryBean implements FactoryBean listenerType, ListenerMetaData[] metaDataValues) { if (target == null) { @@ -224,8 +222,11 @@ public abstract class AbstractListenerFactoryBean implements FactoryBean implements FactoryBean listeners) { @@ -49,7 +48,6 @@ public class CompositeChunkListener implements ChunkListener { /** * Convenience constructor for setting the {@link ChunkListener}s. - * * @param listeners array of {@link ChunkListener}. */ public CompositeChunkListener(ChunkListener... listeners) { @@ -58,7 +56,6 @@ public class CompositeChunkListener implements ChunkListener { /** * Public setter for the listeners. - * * @param listeners list of {@link ChunkListener}. */ public void setListeners(List listeners) { @@ -67,7 +64,6 @@ public class CompositeChunkListener implements ChunkListener { /** * Register additional listener. - * * @param chunkListener instance of {@link ChunkListener}. */ public void register(ChunkListener chunkListener) { @@ -88,8 +84,8 @@ public class CompositeChunkListener implements ChunkListener { } /** - * Call the registered listeners in order, respecting and prioritizing those - * that implement {@link Ordered}. + * Call the registered listeners in order, respecting and prioritizing those that + * implement {@link Ordered}. * * @see org.springframework.batch.core.ChunkListener#beforeChunk(ChunkContext context) */ @@ -104,7 +100,8 @@ public class CompositeChunkListener implements ChunkListener { /** * Call the registered listeners in reverse order. * - * @see org.springframework.batch.core.ChunkListener#afterChunkError(ChunkContext context) + * @see org.springframework.batch.core.ChunkListener#afterChunkError(ChunkContext + * context) */ @Override public void afterChunkError(ChunkContext context) { @@ -113,4 +110,5 @@ public class CompositeChunkListener implements ChunkListener { listener.afterChunkError(context); } } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/CompositeItemProcessListener.java b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/CompositeItemProcessListener.java index 944972fa6..86ff47092 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/CompositeItemProcessListener.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/CompositeItemProcessListener.java @@ -33,8 +33,8 @@ public class CompositeItemProcessListener implements ItemProcessListener> itemProcessorListeners) { this.listeners.setItems(itemProcessorListeners); @@ -42,16 +42,16 @@ public class CompositeItemProcessListener implements ItemProcessListener itemProcessorListener) { listeners.add(itemProcessorListener); } /** - * Call the registered listeners in reverse order, respecting and - * prioritising those that implement {@link Ordered}. + * Call the registered listeners in reverse order, respecting and prioritising those + * that implement {@link Ordered}. * @see org.springframework.batch.core.ItemProcessListener#afterProcess(java.lang.Object, * java.lang.Object) */ @@ -64,8 +64,8 @@ public class CompositeItemProcessListener implements ItemProcessListener implements ItemProcessListener implements ItemReadListener { /** * Public setter for the listeners. - * - * @param itemReadListeners list of {@link ItemReadListener}s to be called when read events occur. + * @param itemReadListeners list of {@link ItemReadListener}s to be called when read + * events occur. */ public void setListeners(List> itemReadListeners) { this.listeners.setItems(itemReadListeners); @@ -41,7 +41,6 @@ public class CompositeItemReadListener implements ItemReadListener { /** * Register additional listener. - * * @param itemReaderListener instance of {@link ItemReadListener} to be registered. */ public void register(ItemReadListener itemReaderListener) { @@ -49,8 +48,8 @@ public class CompositeItemReadListener implements ItemReadListener { } /** - * Call the registered listeners in reverse order, respecting and - * prioritising those that implement {@link Ordered}. + * Call the registered listeners in reverse order, respecting and prioritising those + * that implement {@link Ordered}. * @see org.springframework.batch.core.ItemReadListener#afterRead(java.lang.Object) */ @Override @@ -62,8 +61,8 @@ public class CompositeItemReadListener implements ItemReadListener { } /** - * Call the registered listeners in order, respecting and prioritising those - * that implement {@link Ordered}. + * Call the registered listeners in order, respecting and prioritising those that + * implement {@link Ordered}. * @see org.springframework.batch.core.ItemReadListener#beforeRead() */ @Override @@ -75,8 +74,8 @@ public class CompositeItemReadListener implements ItemReadListener { } /** - * Call the registered listeners in reverse order, respecting and - * prioritising those that implement {@link Ordered}. + * Call the registered listeners in reverse order, respecting and prioritising those + * that implement {@link Ordered}. * @see org.springframework.batch.core.ItemReadListener#onReadError(java.lang.Exception) */ @Override @@ -86,4 +85,5 @@ public class CompositeItemReadListener implements ItemReadListener { listener.onReadError(ex); } } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/CompositeItemWriteListener.java b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/CompositeItemWriteListener.java index 67dd84fea..de28c07e6 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/CompositeItemWriteListener.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/CompositeItemWriteListener.java @@ -32,8 +32,8 @@ public class CompositeItemWriteListener implements ItemWriteListener { /** * Public setter for the listeners. - * - * @param itemWriteListeners list of {@link ItemWriteListener}s to be called when write events occur. + * @param itemWriteListeners list of {@link ItemWriteListener}s to be called when + * write events occur. */ public void setListeners(List> itemWriteListeners) { this.listeners.setItems(itemWriteListeners); @@ -41,7 +41,6 @@ public class CompositeItemWriteListener implements ItemWriteListener { /** * Register additional listener. - * * @param itemWriteListener list of {@link ItemWriteListener}s to be registered. */ public void register(ItemWriteListener itemWriteListener) { @@ -49,8 +48,8 @@ public class CompositeItemWriteListener implements ItemWriteListener { } /** - * Call the registered listeners in reverse order, respecting and - * prioritising those that implement {@link Ordered}. + * Call the registered listeners in reverse order, respecting and prioritising those + * that implement {@link Ordered}. * @see ItemWriteListener#afterWrite(java.util.List) */ @Override @@ -62,8 +61,8 @@ public class CompositeItemWriteListener implements ItemWriteListener { } /** - * Call the registered listeners in order, respecting and prioritising those - * that implement {@link Ordered}. + * Call the registered listeners in order, respecting and prioritising those that + * implement {@link Ordered}. * @see ItemWriteListener#beforeWrite(List) */ @Override @@ -75,8 +74,8 @@ public class CompositeItemWriteListener implements ItemWriteListener { } /** - * Call the registered listeners in reverse order, respecting and - * prioritising those that implement {@link Ordered}. + * Call the registered listeners in reverse order, respecting and prioritising those + * that implement {@link Ordered}. * @see ItemWriteListener#onWriteError(Exception, List) */ @Override @@ -86,4 +85,5 @@ public class CompositeItemWriteListener implements ItemWriteListener { listener.onWriteError(ex, items); } } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/CompositeJobExecutionListener.java b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/CompositeJobExecutionListener.java index 0495fd0c0..b65c3c290 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/CompositeJobExecutionListener.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/CompositeJobExecutionListener.java @@ -32,8 +32,8 @@ public class CompositeJobExecutionListener implements JobExecutionListener { /** * Public setter for the listeners. - * - * @param listeners list of {@link JobExecutionListener}s to be called when job execution events occur. + * @param listeners list of {@link JobExecutionListener}s to be called when job + * execution events occur. */ public void setListeners(List listeners) { this.listeners.setItems(listeners); @@ -41,7 +41,6 @@ public class CompositeJobExecutionListener implements JobExecutionListener { /** * Register additional listener. - * * @param jobExecutionListener instance {@link JobExecutionListener} to be registered. */ public void register(JobExecutionListener jobExecutionListener) { @@ -49,8 +48,8 @@ public class CompositeJobExecutionListener implements JobExecutionListener { } /** - * Call the registered listeners in reverse order, respecting and - * prioritising those that implement {@link Ordered}. + * Call the registered listeners in reverse order, respecting and prioritising those + * that implement {@link Ordered}. * @see org.springframework.batch.core.JobExecutionListener#afterJob(org.springframework.batch.core.JobExecution) */ @Override @@ -62,8 +61,8 @@ public class CompositeJobExecutionListener implements JobExecutionListener { } /** - * Call the registered listeners in order, respecting and prioritising those - * that implement {@link Ordered}. + * Call the registered listeners in order, respecting and prioritising those that + * implement {@link Ordered}. * @see org.springframework.batch.core.JobExecutionListener#beforeJob(org.springframework.batch.core.JobExecution) */ @Override diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/CompositeSkipListener.java b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/CompositeSkipListener.java index 488d057da..7edc8c032 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/CompositeSkipListener.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/CompositeSkipListener.java @@ -25,65 +25,63 @@ import org.springframework.core.Ordered; * @author Dave Syer * */ -public class CompositeSkipListener implements SkipListener { +public class CompositeSkipListener implements SkipListener { - private OrderedComposite> listeners = new OrderedComposite<>(); + private OrderedComposite> listeners = new OrderedComposite<>(); /** * Public setter for the listeners. - * * @param listeners list of {@link SkipListener}s to be called when skip events occur. */ - public void setListeners(List> listeners) { + public void setListeners(List> listeners) { this.listeners.setItems(listeners); } /** * Register additional listener. - * * @param listener instance of {@link SkipListener} to be registered. */ - public void register(SkipListener listener) { + public void register(SkipListener listener) { listeners.add(listener); } /** - * Call the registered listeners in order, respecting and prioritising those - * that implement {@link Ordered}. + * Call the registered listeners in order, respecting and prioritising those that + * implement {@link Ordered}. * @see org.springframework.batch.core.SkipListener#onSkipInRead(java.lang.Throwable) */ @Override public void onSkipInRead(Throwable t) { - for (Iterator> iterator = listeners.iterator(); iterator.hasNext();) { - SkipListener listener = iterator.next(); + for (Iterator> iterator = listeners.iterator(); iterator.hasNext();) { + SkipListener listener = iterator.next(); listener.onSkipInRead(t); } } /** - * Call the registered listeners in order, respecting and prioritising those - * that implement {@link Ordered}. + * Call the registered listeners in order, respecting and prioritising those that + * implement {@link Ordered}. * @see org.springframework.batch.core.SkipListener#onSkipInWrite(java.lang.Object, * java.lang.Throwable) */ @Override public void onSkipInWrite(S item, Throwable t) { - for (Iterator> iterator = listeners.iterator(); iterator.hasNext();) { - SkipListener listener = iterator.next(); + for (Iterator> iterator = listeners.iterator(); iterator.hasNext();) { + SkipListener listener = iterator.next(); listener.onSkipInWrite(item, t); } } /** - * Call the registered listeners in order, respecting and prioritising those - * that implement {@link Ordered}. + * Call the registered listeners in order, respecting and prioritising those that + * implement {@link Ordered}. * @see org.springframework.batch.core.SkipListener#onSkipInWrite(java.lang.Object, * java.lang.Throwable) */ @Override public void onSkipInProcess(T item, Throwable t) { - for (Iterator> iterator = listeners.iterator(); iterator.hasNext();) { - SkipListener listener = iterator.next(); + for (Iterator> iterator = listeners.iterator(); iterator.hasNext();) { + SkipListener listener = iterator.next(); listener.onSkipInProcess(item, t); } } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/CompositeStepExecutionListener.java b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/CompositeStepExecutionListener.java index 64fc10717..e0d8c40f6 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/CompositeStepExecutionListener.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/CompositeStepExecutionListener.java @@ -35,8 +35,8 @@ public class CompositeStepExecutionListener implements StepExecutionListener { /** * Public setter for the listeners. - * - * @param listeners list of {@link StepExecutionListener}s to be called when step execution events occur. + * @param listeners list of {@link StepExecutionListener}s to be called when step + * execution events occur. */ public void setListeners(StepExecutionListener[] listeners) { list.setItems(Arrays.asList(listeners)); @@ -44,16 +44,16 @@ public class CompositeStepExecutionListener implements StepExecutionListener { /** * Register additional listener. - * - * @param stepExecutionListener instance of {@link StepExecutionListener} to be registered. + * @param stepExecutionListener instance of {@link StepExecutionListener} to be + * registered. */ public void register(StepExecutionListener stepExecutionListener) { list.add(stepExecutionListener); } /** - * Call the registered listeners in reverse order, respecting and - * prioritizing those that implement {@link Ordered}. + * Call the registered listeners in reverse order, respecting and prioritizing those + * that implement {@link Ordered}. * @see org.springframework.batch.core.StepExecutionListener#afterStep(StepExecution) */ @Nullable @@ -68,8 +68,8 @@ public class CompositeStepExecutionListener implements StepExecutionListener { } /** - * Call the registered listeners in order, respecting and prioritizing those - * that implement {@link Ordered}. + * Call the registered listeners in order, respecting and prioritizing those that + * implement {@link Ordered}. * @see org.springframework.batch.core.StepExecutionListener#beforeStep(StepExecution) */ @Override diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/ExecutionContextPromotionListener.java b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/ExecutionContextPromotionListener.java index d0950adab..3d70205cb 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/ExecutionContextPromotionListener.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/ExecutionContextPromotionListener.java @@ -1,112 +1,111 @@ -/* - * Copyright 2006-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.listener; - -import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.Step; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.StepExecutionListener; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.support.PatternMatcher; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.lang.Nullable; -import org.springframework.util.Assert; - -/** - * This class can be used to automatically promote items from the {@link Step} - * {@link ExecutionContext} to the {@link Job} {@link ExecutionContext} at the - * end of a step. A list of keys should be provided that correspond to the items - * in the {@link Step} {@link ExecutionContext} that should be promoted. - * - * Additionally, an optional list of statuses can be set to indicate for which - * exit status codes the promotion should occur. These statuses will be checked - * using the {@link PatternMatcher}, so wildcards are allowed. By default, - * promotion will only occur for steps with an exit code of "COMPLETED". - * - * @author Dan Garrette - * @author Mahmoud Ben Hassine - * @since 2.0 - */ -public class ExecutionContextPromotionListener implements StepExecutionListener, InitializingBean { - - private String[] keys = null; - - private String[] statuses = new String[] { ExitStatus.COMPLETED.getExitCode() }; - - private boolean strict = false; - - @Nullable - @Override - public ExitStatus afterStep(StepExecution stepExecution) { - ExecutionContext stepContext = stepExecution.getExecutionContext(); - ExecutionContext jobContext = stepExecution.getJobExecution().getExecutionContext(); - String exitCode = stepExecution.getExitStatus().getExitCode(); - for (String statusPattern : statuses) { - if (PatternMatcher.match(statusPattern, exitCode)) { - for (String key : keys) { - if (stepContext.containsKey(key)) { - jobContext.put(key, stepContext.get(key)); - } else { - if (strict) { - throw new IllegalArgumentException("The key [" + key - + "] was not found in the Step's ExecutionContext."); - } - } - } - break; - } - } - - return null; - } - - @Override - public void afterPropertiesSet() throws Exception { - Assert.notNull(this.keys, "The 'keys' property must be provided"); - Assert.notEmpty(this.keys, "The 'keys' property must not be empty"); - Assert.notNull(this.statuses, "The 'statuses' property must be provided"); - Assert.notEmpty(this.statuses, "The 'statuses' property must not be empty"); - } - - /** - * @param keys A list of keys corresponding to items in the {@link Step} - * {@link ExecutionContext} that must be promoted. - */ - public void setKeys(String[] keys) { - this.keys = keys; - } - - /** - * @param statuses A list of statuses for which the promotion should occur. - * Statuses can may contain wildcards recognizable by a - * {@link PatternMatcher}. - */ - public void setStatuses(String[] statuses) { - this.statuses = statuses; - } - - /** - * If set to TRUE, the listener will throw an exception if any 'key' is not - * found in the Step {@link ExecutionContext}. FALSE by default. - * - * @param strict boolean the value of the flag. - */ - public void setStrict(boolean strict) { - this.strict = strict; - } - -} +/* + * Copyright 2006-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.listener; + +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.Job; +import org.springframework.batch.core.Step; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.StepExecutionListener; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.support.PatternMatcher; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; + +/** + * This class can be used to automatically promote items from the {@link Step} + * {@link ExecutionContext} to the {@link Job} {@link ExecutionContext} at the end of a + * step. A list of keys should be provided that correspond to the items in the + * {@link Step} {@link ExecutionContext} that should be promoted. + * + * Additionally, an optional list of statuses can be set to indicate for which exit status + * codes the promotion should occur. These statuses will be checked using the + * {@link PatternMatcher}, so wildcards are allowed. By default, promotion will only occur + * for steps with an exit code of "COMPLETED". + * + * @author Dan Garrette + * @author Mahmoud Ben Hassine + * @since 2.0 + */ +public class ExecutionContextPromotionListener implements StepExecutionListener, InitializingBean { + + private String[] keys = null; + + private String[] statuses = new String[] { ExitStatus.COMPLETED.getExitCode() }; + + private boolean strict = false; + + @Nullable + @Override + public ExitStatus afterStep(StepExecution stepExecution) { + ExecutionContext stepContext = stepExecution.getExecutionContext(); + ExecutionContext jobContext = stepExecution.getJobExecution().getExecutionContext(); + String exitCode = stepExecution.getExitStatus().getExitCode(); + for (String statusPattern : statuses) { + if (PatternMatcher.match(statusPattern, exitCode)) { + for (String key : keys) { + if (stepContext.containsKey(key)) { + jobContext.put(key, stepContext.get(key)); + } + else { + if (strict) { + throw new IllegalArgumentException( + "The key [" + key + "] was not found in the Step's ExecutionContext."); + } + } + } + break; + } + } + + return null; + } + + @Override + public void afterPropertiesSet() throws Exception { + Assert.notNull(this.keys, "The 'keys' property must be provided"); + Assert.notEmpty(this.keys, "The 'keys' property must not be empty"); + Assert.notNull(this.statuses, "The 'statuses' property must be provided"); + Assert.notEmpty(this.statuses, "The 'statuses' property must not be empty"); + } + + /** + * @param keys A list of keys corresponding to items in the {@link Step} + * {@link ExecutionContext} that must be promoted. + */ + public void setKeys(String[] keys) { + this.keys = keys; + } + + /** + * @param statuses A list of statuses for which the promotion should occur. Statuses + * can may contain wildcards recognizable by a {@link PatternMatcher}. + */ + public void setStatuses(String[] statuses) { + this.statuses = statuses; + } + + /** + * If set to TRUE, the listener will throw an exception if any 'key' is not found in + * the Step {@link ExecutionContext}. FALSE by default. + * @param strict boolean the value of the flag. + */ + public void setStrict(boolean strict) { + this.strict = strict; + } + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/ItemListenerSupport.java b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/ItemListenerSupport.java index dda662e11..f2023a929 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/ItemListenerSupport.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/ItemListenerSupport.java @@ -21,9 +21,8 @@ import org.springframework.batch.core.ItemWriteListener; /** * Basic no-op implementation of the {@link ItemReadListener}, - * {@link ItemProcessListener}, and {@link ItemWriteListener} interfaces. All - * are implemented, since it is very common that all may need to be implemented - * at once. + * {@link ItemProcessListener}, and {@link ItemWriteListener} interfaces. All are + * implemented, since it is very common that all may need to be implemented at once. * * @author Lucas Ward * @author Mahmoud Ben Hassine diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/JobExecutionListenerSupport.java b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/JobExecutionListenerSupport.java index 623673c4f..b28dbeed4 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/JobExecutionListenerSupport.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/JobExecutionListenerSupport.java @@ -20,21 +20,27 @@ import org.springframework.batch.core.JobExecutionListener; /** * @author Dave Syer - * - * @deprecated as of 5.0, in favor of the default methods on the {@link JobExecutionListener} + * @deprecated as of 5.0, in favor of the default methods on the + * {@link JobExecutionListener} */ @Deprecated public class JobExecutionListenerSupport implements JobExecutionListener { - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.springframework.batch.core.domain.JobListener#afterJob() */ @Override public void afterJob(JobExecution jobExecution) { } - /* (non-Javadoc) - * @see org.springframework.batch.core.domain.JobListener#beforeJob(org.springframework.batch.core.domain.JobExecution) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.core.domain.JobListener#beforeJob(org.springframework. + * batch.core.domain.JobExecution) */ @Override public void beforeJob(JobExecution jobExecution) { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/JobListenerFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/JobListenerFactoryBean.java index bea210d1a..76ae37e5f 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/JobListenerFactoryBean.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/JobListenerFactoryBean.java @@ -52,7 +52,6 @@ public class JobListenerFactoryBean extends AbstractListenerFactoryBean annotation; + private static final Map propertyMap; JobListenerMetaData(String methodName, String propertyName, Class annotation) { @@ -51,9 +53,9 @@ public enum JobListenerMetaData implements ListenerMetaData { this.annotation = annotation; } - static{ + static { propertyMap = new HashMap<>(); - for(JobListenerMetaData metaData : values()){ + for (JobListenerMetaData metaData : values()) { propertyMap.put(metaData.getPropertyName(), metaData); } } @@ -80,17 +82,17 @@ public enum JobListenerMetaData implements ListenerMetaData { @Override public Class[] getParamTypes() { - return new Class[]{ JobExecution.class }; + return new Class[] { JobExecution.class }; } /** * Return the relevant meta data for the provided property name. - * * @param propertyName name of the property to retrieve. * @return meta data with supplied property name, {@code null} if none exists. */ @Nullable - public static JobListenerMetaData fromPropertyName(String propertyName){ + public static JobListenerMetaData fromPropertyName(String propertyName) { return propertyMap.get(propertyName); } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/JobParameterExecutionContextCopyListener.java b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/JobParameterExecutionContextCopyListener.java index 640d15ee3..c26d473ad 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/JobParameterExecutionContextCopyListener.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/JobParameterExecutionContextCopyListener.java @@ -1,70 +1,70 @@ -/* - * Copyright 2006-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.listener; - -import java.util.Arrays; -import java.util.Collection; - -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.Step; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.StepExecutionListener; -import org.springframework.batch.item.ExecutionContext; - -/** - * This class can be used to automatically copy items from the - * {@link JobParameters} to the {@link Step} {@link ExecutionContext}. A list of - * keys should be provided that correspond to the items in the {@link Step} - * {@link ExecutionContext} that should be copied. - * - * @author Dave Syer - * @author Mahmoud Ben Hassine - * @since 2.0 - */ -public class JobParameterExecutionContextCopyListener implements StepExecutionListener { - - private Collection keys = null; - - /** - * @param keys A list of keys corresponding to items in the - * {@link JobParameters} that should be copied. - */ - public void setKeys(String[] keys) { - this.keys = Arrays.asList(keys); - } - - /** - * Copy attributes from the {@link JobParameters} to the {@link Step} - * {@link ExecutionContext}, if not already present. The key is already - * present we assume that a restart is in operation and the previous value - * is needed. If the provided keys are empty defaults to copy all keys in - * the {@link JobParameters}. - */ - @Override - public void beforeStep(StepExecution stepExecution) { - ExecutionContext stepContext = stepExecution.getExecutionContext(); - JobParameters jobParameters = stepExecution.getJobParameters(); - Collection keys = this.keys; - if (keys == null) { - keys = jobParameters.getParameters().keySet(); - } - for (String key : keys) { - if (!stepContext.containsKey(key)) { - stepContext.put(key, jobParameters.getParameters().get(key).getValue()); - } - } - } -} +/* + * Copyright 2006-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.listener; + +import java.util.Arrays; +import java.util.Collection; + +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.Step; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.StepExecutionListener; +import org.springframework.batch.item.ExecutionContext; + +/** + * This class can be used to automatically copy items from the {@link JobParameters} to + * the {@link Step} {@link ExecutionContext}. A list of keys should be provided that + * correspond to the items in the {@link Step} {@link ExecutionContext} that should be + * copied. + * + * @author Dave Syer + * @author Mahmoud Ben Hassine + * @since 2.0 + */ +public class JobParameterExecutionContextCopyListener implements StepExecutionListener { + + private Collection keys = null; + + /** + * @param keys A list of keys corresponding to items in the {@link JobParameters} that + * should be copied. + */ + public void setKeys(String[] keys) { + this.keys = Arrays.asList(keys); + } + + /** + * Copy attributes from the {@link JobParameters} to the {@link Step} + * {@link ExecutionContext}, if not already present. The key is already present we + * assume that a restart is in operation and the previous value is needed. If the + * provided keys are empty defaults to copy all keys in the {@link JobParameters}. + */ + @Override + public void beforeStep(StepExecution stepExecution) { + ExecutionContext stepContext = stepExecution.getExecutionContext(); + JobParameters jobParameters = stepExecution.getJobParameters(); + Collection keys = this.keys; + if (keys == null) { + keys = jobParameters.getParameters().keySet(); + } + for (String key : keys) { + if (!stepContext.containsKey(key)) { + stepContext.put(key, jobParameters.getParameters().get(key).getValue()); + } + } + } + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/MethodInvokerMethodInterceptor.java b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/MethodInvokerMethodInterceptor.java index 4f4918974..180f8dae9 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/MethodInvokerMethodInterceptor.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/MethodInvokerMethodInterceptor.java @@ -25,13 +25,12 @@ import org.springframework.batch.core.StepExecutionListener; import org.springframework.batch.support.MethodInvoker; /** - * {@link MethodInterceptor} that, given a map of method names and - * {@link MethodInvoker}s, will execute all methods tied to a particular method - * name, with the provided arguments. The only possible return value that is - * handled is of type ExitStatus, since the only StepListener implementation - * that isn't void is - * {@link StepExecutionListener#afterStep(org.springframework.batch.core.StepExecution)} - * , which returns ExitStatus. + * {@link MethodInterceptor} that, given a map of method names and {@link MethodInvoker}s, + * will execute all methods tied to a particular method name, with the provided arguments. + * The only possible return value that is handled is of type ExitStatus, since the only + * StepListener implementation that isn't void is + * {@link StepExecutionListener#afterStep(org.springframework.batch.core.StepExecution)} , + * which returns ExitStatus. * * @author Lucas Ward * @since 2.0 @@ -40,6 +39,7 @@ import org.springframework.batch.support.MethodInvoker; public class MethodInvokerMethodInterceptor implements MethodInterceptor { private final Map> invokerMap; + private final boolean ordered; public MethodInvokerMethodInterceptor(Map> invokerMap) { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/MulticasterBatchListener.java b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/MulticasterBatchListener.java index cc9144069..90170a4a7 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/MulticasterBatchListener.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/MulticasterBatchListener.java @@ -38,7 +38,7 @@ import org.springframework.lang.Nullable; * @author Mahmoud Ben Hassine */ public class MulticasterBatchListener implements StepExecutionListener, ChunkListener, ItemReadListener, -ItemProcessListener, ItemWriteListener, SkipListener { + ItemProcessListener, ItemWriteListener, SkipListener { private CompositeStepExecutionListener stepListener = new CompositeStepExecutionListener(); @@ -62,7 +62,6 @@ ItemProcessListener, ItemWriteListener, SkipListener { /** * Register each of the objects as listeners. Once registered, calls to the * {@link MulticasterBatchListener} broadcast to the individual listeners. - * * @param listeners listener objects of types known to the multicaster. */ public void setListeners(List listeners) { @@ -72,10 +71,9 @@ ItemProcessListener, ItemWriteListener, SkipListener { } /** - * Register the listener for callbacks on the appropriate interfaces - * implemented. Any {@link StepListener} can be provided, or an - * {@link ItemStream}. Other types will be ignored. - * + * Register the listener for callbacks on the appropriate interfaces implemented. Any + * {@link StepListener} can be provided, or an {@link ItemStream}. Other types will be + * ignored. * @param listener the {@link StepListener} instance to be registered. */ public void register(StepListener listener) { @@ -176,7 +174,8 @@ ItemProcessListener, ItemWriteListener, SkipListener { } /** - * @see org.springframework.batch.core.listener.CompositeChunkListener#afterChunk(ChunkContext context) + * @see org.springframework.batch.core.listener.CompositeChunkListener#afterChunk(ChunkContext + * context) */ @Override public void afterChunk(ChunkContext context) { @@ -189,7 +188,8 @@ ItemProcessListener, ItemWriteListener, SkipListener { } /** - * @see org.springframework.batch.core.listener.CompositeChunkListener#beforeChunk(ChunkContext context) + * @see org.springframework.batch.core.listener.CompositeChunkListener#beforeChunk(ChunkContext + * context) */ @Override public void beforeChunk(ChunkContext context) { @@ -327,4 +327,5 @@ ItemProcessListener, ItemWriteListener, SkipListener { } return e; } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/OrderedComposite.java b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/OrderedComposite.java index f8cf88e5d..5307ae387 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/OrderedComposite.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/OrderedComposite.java @@ -28,21 +28,20 @@ import org.springframework.core.annotation.Order; /** * @author Dave Syer - * + * */ class OrderedComposite { private List unordered = new ArrayList<>(); private List ordered = new ArrayList<>(); - + private Comparator comparator = new AnnotationAwareOrderComparator(); private List list = new ArrayList<>(); /** * Public setter for the listeners. - * * @param items */ public void setItems(List items) { @@ -55,7 +54,6 @@ class OrderedComposite { /** * Register additional item. - * * @param item */ public void add(S item) { @@ -79,8 +77,8 @@ class OrderedComposite { } /** - * Public getter for the list of items. The {@link Ordered} items come - * first, followed by any unordered ones. + * Public getter for the list of items. The {@link Ordered} items come first, followed + * by any unordered ones. * @return an iterator over the list of items */ public Iterator iterator() { @@ -88,8 +86,8 @@ class OrderedComposite { } /** - * Public getter for the list of items in reverse. The {@link Ordered} items - * come last, after any unordered ones. + * Public getter for the list of items in reverse. The {@link Ordered} items come + * last, after any unordered ones. * @return an iterator over the list of items */ public Iterator reverse() { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/SkipListenerSupport.java b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/SkipListenerSupport.java index 437206747..b61eb4f2f 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/SkipListenerSupport.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/SkipListenerSupport.java @@ -22,29 +22,36 @@ import org.springframework.batch.core.SkipListener; * * @author Dave Syer * @author Mahmoud Ben Hassine - * * @deprecated as of v5.0 in favor of the default methods in {@link SkipListener}. * */ @Deprecated -public class SkipListenerSupport implements SkipListener { +public class SkipListenerSupport implements SkipListener { - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.springframework.batch.core.SkipListener#onSkipInRead(java.lang.Throwable) */ @Override public void onSkipInRead(Throwable t) { } - /* (non-Javadoc) - * @see org.springframework.batch.core.SkipListener#onSkipInWrite(java.lang.Object, java.lang.Throwable) + /* + * (non-Javadoc) + * + * @see org.springframework.batch.core.SkipListener#onSkipInWrite(java.lang.Object, + * java.lang.Throwable) */ @Override public void onSkipInWrite(S item, Throwable t) { } - /* (non-Javadoc) - * @see org.springframework.batch.core.SkipListener#onSkipInProcess(java.lang.Object, java.lang.Throwable) + /* + * (non-Javadoc) + * + * @see org.springframework.batch.core.SkipListener#onSkipInProcess(java.lang.Object, + * java.lang.Throwable) */ @Override public void onSkipInProcess(T item, Throwable t) { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/StepExecutionListenerSupport.java b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/StepExecutionListenerSupport.java index b07a2c51f..6853e454e 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/StepExecutionListenerSupport.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/StepExecutionListenerSupport.java @@ -22,14 +22,17 @@ import org.springframework.lang.Nullable; /** * @author Dave Syer - * - * @deprecated as of 5.0, in favor of the default methods on the {@link StepExecutionListener} + * @deprecated as of 5.0, in favor of the default methods on the + * {@link StepExecutionListener} */ @Deprecated public class StepExecutionListenerSupport implements StepExecutionListener { - /* (non-Javadoc) - * @see org.springframework.batch.core.domain.StepListener#afterStep(StepExecution stepExecution) + /* + * (non-Javadoc) + * + * @see org.springframework.batch.core.domain.StepListener#afterStep(StepExecution + * stepExecution) */ @Nullable @Override @@ -37,8 +40,12 @@ public class StepExecutionListenerSupport implements StepExecutionListener { return null; } - /* (non-Javadoc) - * @see org.springframework.batch.core.domain.StepListener#open(org.springframework.batch.item.ExecutionContext) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.core.domain.StepListener#open(org.springframework.batch. + * item.ExecutionContext) */ @Override public void beforeStep(StepExecution stepExecution) { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/StepListenerFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/StepListenerFactoryBean.java index bd9685946..ace030474 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/StepListenerFactoryBean.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/StepListenerFactoryBean.java @@ -52,7 +52,6 @@ public class StepListenerFactoryBean extends AbstractListenerFactoryBean annotation; + private final Class listenerInterface; + private final Class[] paramTypes; + private static final Map propertyMap; - StepListenerMetaData(String methodName, String propertyName, Class annotation, Class listenerInterface, Class... paramTypes) { + StepListenerMetaData(String methodName, String propertyName, Class annotation, + Class listenerInterface, Class... paramTypes) { this.methodName = methodName; this.propertyName = propertyName; this.annotation = annotation; @@ -90,9 +103,9 @@ public enum StepListenerMetaData implements ListenerMetaData { this.paramTypes = paramTypes; } - static{ + static { propertyMap = new HashMap<>(); - for(StepListenerMetaData metaData : values()){ + for (StepListenerMetaData metaData : values()) { propertyMap.put(metaData.getPropertyName(), metaData); } } @@ -124,24 +137,25 @@ public enum StepListenerMetaData implements ListenerMetaData { /** * Return the relevant meta data for the provided property name. - * * @param propertyName property name to retrieve data for. * @return meta data with supplied property name, null if none exists. */ - public static StepListenerMetaData fromPropertyName(String propertyName){ + public static StepListenerMetaData fromPropertyName(String propertyName) { return propertyMap.get(propertyName); } public static ListenerMetaData[] itemListenerMetaData() { - return new ListenerMetaData[] {BEFORE_WRITE, AFTER_WRITE, ON_WRITE_ERROR, BEFORE_PROCESS, AFTER_PROCESS, ON_PROCESS_ERROR, BEFORE_READ, AFTER_READ, ON_READ_ERROR, ON_SKIP_IN_WRITE, ON_SKIP_IN_PROCESS, ON_SKIP_IN_READ}; + return new ListenerMetaData[] { BEFORE_WRITE, AFTER_WRITE, ON_WRITE_ERROR, BEFORE_PROCESS, AFTER_PROCESS, + ON_PROCESS_ERROR, BEFORE_READ, AFTER_READ, ON_READ_ERROR, ON_SKIP_IN_WRITE, ON_SKIP_IN_PROCESS, + ON_SKIP_IN_READ }; } public static ListenerMetaData[] stepExecutionListenerMetaData() { - return new ListenerMetaData[] {BEFORE_STEP, AFTER_STEP}; + return new ListenerMetaData[] { BEFORE_STEP, AFTER_STEP }; } public static ListenerMetaData[] taskletListenerMetaData() { - return new ListenerMetaData[] {BEFORE_CHUNK, AFTER_CHUNK, AFTER_CHUNK_ERROR}; + return new ListenerMetaData[] { BEFORE_CHUNK, AFTER_CHUNK, AFTER_CHUNK_ERROR }; } } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/StepListenerSupport.java b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/StepListenerSupport.java index eee538132..bc10b1d2b 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/StepListenerSupport.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/StepListenerSupport.java @@ -27,7 +27,7 @@ import org.springframework.batch.core.StepListener; * @author Robert Kasanicky * @author Mahmoud Ben Hassine */ -public class StepListenerSupport extends ItemListenerSupport - implements StepExecutionListener, ChunkListener, SkipListener { +public class StepListenerSupport extends ItemListenerSupport + implements StepExecutionListener, ChunkListener, SkipListener { } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/observability/BatchJobKeyValuesProvider.java b/spring-batch-core/src/main/java/org/springframework/batch/core/observability/BatchJobKeyValuesProvider.java index 2ef1f6429..ba6af7505 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/observability/BatchJobKeyValuesProvider.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/observability/BatchJobKeyValuesProvider.java @@ -20,7 +20,7 @@ import io.micrometer.observation.Observation; /** * {@link Observation.KeyValuesProvider} for {@link BatchJobContext}. - * + * * @author Marcin Grzejszczak * @since 5.0 */ @@ -30,4 +30,5 @@ public interface BatchJobKeyValuesProvider extends Observation.KeyValuesProvider default boolean supportsContext(Observation.Context context) { return context instanceof BatchJobContext; } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/observability/BatchJobObservation.java b/spring-batch-core/src/main/java/org/springframework/batch/core/observability/BatchJobObservation.java index 81f1170e3..4114d33f4 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/observability/BatchJobObservation.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/observability/BatchJobObservation.java @@ -102,4 +102,5 @@ public enum BatchJobObservation implements DocumentedObservation { } } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/observability/BatchMetrics.java b/spring-batch-core/src/main/java/org/springframework/batch/core/observability/BatchMetrics.java index 1bf4b4c75..ce218572f 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/observability/BatchMetrics.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/observability/BatchMetrics.java @@ -34,10 +34,10 @@ import org.springframework.lang.Nullable; * Central class for batch metrics. It provides: * *
      - *
    • the main entry point to interact with Micrometer's {@link Metrics#globalRegistry} - * with common metrics such as {@link Timer} and {@link LongTaskTimer}.
    • - *
    • Some utility methods like calculating durations and formatting them in - * a human readable format.
    • + *
    • the main entry point to interact with Micrometer's {@link Metrics#globalRegistry} + * with common metrics such as {@link Timer} and {@link LongTaskTimer}.
    • + *
    • Some utility methods like calculating durations and formatting them in a human + * readable format.
    • *
    * * Only intended for internal use. @@ -69,25 +69,24 @@ public final class BatchMetrics { /** * Create a {@link Timer}. - * @param name of the timer. Will be prefixed with {@link BatchMetrics#METRICS_PREFIX}. + * @param name of the timer. Will be prefixed with + * {@link BatchMetrics#METRICS_PREFIX}. * @param description of the timer * @param tags of the timer * @return a new timer instance */ public static Timer createTimer(String name, String description, Tag... tags) { - return Timer.builder(METRICS_PREFIX + name) - .description(description) - .tags(Arrays.asList(tags)) + return Timer.builder(METRICS_PREFIX + name).description(description).tags(Arrays.asList(tags)) .register(Metrics.globalRegistry); } /** - * Create a new {@link Observation}. It's not started, you must - * explicitly call {@link Observation#start()} to start it. + * Create a new {@link Observation}. It's not started, you must explicitly call + * {@link Observation#start()} to start it. * - * Remember to register the {@link TimerObservationHandler} - * via the {@code Metrics.globalRegistry.withTimerObservationHandler()} - * in the user code. Otherwise you won't observe any metrics. + * Remember to register the {@link TimerObservationHandler} via the + * {@code Metrics.globalRegistry.withTimerObservationHandler()} in the user code. + * Otherwise you won't observe any metrics. * @param name of the observation * @param context of the observation * @return a new observation instance @@ -107,15 +106,14 @@ public final class BatchMetrics { /** * Create a new {@link LongTaskTimer}. - * @param name of the long task timer. Will be prefixed with {@link BatchMetrics#METRICS_PREFIX}. + * @param name of the long task timer. Will be prefixed with + * {@link BatchMetrics#METRICS_PREFIX}. * @param description of the long task timer. * @param tags of the timer * @return a new long task timer instance */ public static LongTaskTimer createLongTaskTimer(String name, String description, Tag... tags) { - return LongTaskTimer.builder(METRICS_PREFIX + name) - .description(description) - .tags(Arrays.asList(tags)) + return LongTaskTimer.builder(METRICS_PREFIX + name).description(description).tags(Arrays.asList(tags)) .register(Metrics.globalRegistry); } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/observability/BatchStepTagsProvider.java b/spring-batch-core/src/main/java/org/springframework/batch/core/observability/BatchStepTagsProvider.java index 9ec704545..25b7e7355 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/observability/BatchStepTagsProvider.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/observability/BatchStepTagsProvider.java @@ -30,4 +30,5 @@ public interface BatchStepTagsProvider extends Observation.KeyValuesProvider handle(StepExecutionSplitter stepSplitter, StepExecution stepExecution) throws Exception; diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/partition/StepExecutionSplitter.java b/spring-batch-core/src/main/java/org/springframework/batch/core/partition/StepExecutionSplitter.java index f39db7175..0b5e83f95 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/partition/StepExecutionSplitter.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/partition/StepExecutionSplitter.java @@ -23,39 +23,35 @@ import org.springframework.batch.core.StepExecution; import java.util.Set; /** - * Strategy interface for generating input contexts for a partitioned step - * execution independent from the fabric they are going to run on. - * + * Strategy interface for generating input contexts for a partitioned step execution + * independent from the fabric they are going to run on. + * * @author Dave Syer * @since 2.0 */ public interface StepExecutionSplitter { /** - * The name of the step configuration that will be executed remotely. Remote - * workers are going to execute a the same step for each execution context - * in the partition. + * The name of the step configuration that will be executed remotely. Remote workers + * are going to execute a the same step for each execution context in the partition. * @return the name of the step that will execute the business logic */ String getStepName(); /** - * Partition the provided {@link StepExecution} into a set of parallel - * executable instances with the same parent {@link JobExecution}. The grid - * size will be treated as a hint for the size of the collection to be - * returned. It may or may not correspond to the physical size of an - * execution grid.
    + * Partition the provided {@link StepExecution} into a set of parallel executable + * instances with the same parent {@link JobExecution}. The grid size will be treated + * as a hint for the size of the collection to be returned. It may or may not + * correspond to the physical size of an execution grid.
    *
    - * - * On a restart clients of the {@link StepExecutionSplitter} should expect - * it to reconstitute the state of the last failed execution and only return - * those executions that need to be restarted. Thus the grid size hint will - * be ignored on a restart. - * + * + * On a restart clients of the {@link StepExecutionSplitter} should expect it to + * reconstitute the state of the last failed execution and only return those + * executions that need to be restarted. Thus the grid size hint will be ignored on a + * restart. * @param stepExecution the {@link StepExecution} to be partitioned. * @param gridSize a hint for the splitter if the size of the grid is known * @return a set of {@link StepExecution} instances for remote processing - * * @throws JobExecutionException if the split cannot be made */ Set split(StepExecution stepExecution, int gridSize) throws JobExecutionException; diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/AbstractPartitionHandler.java b/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/AbstractPartitionHandler.java index 819e53906..bf507a510 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/AbstractPartitionHandler.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/AbstractPartitionHandler.java @@ -23,11 +23,11 @@ import org.springframework.batch.core.partition.PartitionHandler; import org.springframework.batch.core.partition.StepExecutionSplitter; /** - * Base {@link PartitionHandler} implementation providing common base - * features. Subclasses are expected to implement only the - * {@link #doHandle(org.springframework.batch.core.StepExecution, java.util.Set)} - * method which returns with the result of the execution(s) or an exception if - * the step failed to process. + * Base {@link PartitionHandler} implementation providing common base features. Subclasses + * are expected to implement only the + * {@link #doHandle(org.springframework.batch.core.StepExecution, java.util.Set)} method + * which returns with the result of the execution(s) or an exception if the step failed to + * process. * * @author Sebastien Gerard * @author Dave Syer @@ -38,15 +38,13 @@ public abstract class AbstractPartitionHandler implements PartitionHandler { private int gridSize = 1; /** - * Executes the specified {@link StepExecution} instances and returns an updated - * view of them. Throws an {@link Exception} if anything goes wrong. - * + * Executes the specified {@link StepExecution} instances and returns an updated view + * of them. Throws an {@link Exception} if anything goes wrong. * @param managerStepExecution the whole partition execution * @param partitionStepExecutions the {@link StepExecution} instances to execute * @return an updated view of these completed {@link StepExecution} instances - * @throws Exception if anything goes wrong. This allows implementations to - * be liberal and rely on the caller to translate an exception into a step - * failure as necessary. + * @throws Exception if anything goes wrong. This allows implementations to be liberal + * and rely on the caller to translate an exception into a step failure as necessary. */ protected abstract Set doHandle(StepExecution managerStepExecution, Set partitionStepExecutions) throws Exception; @@ -64,7 +62,6 @@ public abstract class AbstractPartitionHandler implements PartitionHandler { /** * Returns the number of step executions. - * * @return the number of step executions */ public int getGridSize() { @@ -73,11 +70,10 @@ public abstract class AbstractPartitionHandler implements PartitionHandler { /** * Passed to the {@link StepExecutionSplitter} in the - * {@link #handle(StepExecutionSplitter, StepExecution)} method, instructing - * it how many {@link StepExecution} instances are required, ideally. The - * {@link StepExecutionSplitter} is allowed to ignore the grid size in the - * case of a restart, since the input data partitions must be preserved. - * + * {@link #handle(StepExecutionSplitter, StepExecution)} method, instructing it how + * many {@link StepExecution} instances are required, ideally. The + * {@link StepExecutionSplitter} is allowed to ignore the grid size in the case of a + * restart, since the input data partitions must be preserved. * @param gridSize the number of step executions that will be created */ public void setGridSize(int gridSize) { @@ -85,4 +81,3 @@ public abstract class AbstractPartitionHandler implements PartitionHandler { } } - diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/DefaultStepExecutionAggregator.java b/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/DefaultStepExecutionAggregator.java index 2f9eb3d48..27ba91b01 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/DefaultStepExecutionAggregator.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/DefaultStepExecutionAggregator.java @@ -24,8 +24,8 @@ import org.springframework.util.Assert; import java.util.Collection; /** - * Convenience class for aggregating a set of {@link StepExecution} instances - * into a single result. + * Convenience class for aggregating a set of {@link StepExecution} instances into a + * single result. * * @author Dave Syer * @since 2.1 @@ -33,8 +33,8 @@ import java.util.Collection; public class DefaultStepExecutionAggregator implements StepExecutionAggregator { /** - * Aggregates the input executions into the result {@link StepExecution}. - * The aggregated fields are + * Aggregates the input executions into the result {@link StepExecution}. The + * aggregated fields are *
      *
    • status - choosing the highest value using * {@link BatchStatus#max(BatchStatus, BatchStatus)}
    • diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/MultiResourcePartitioner.java b/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/MultiResourcePartitioner.java index 28086b994..32cfe6f06 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/MultiResourcePartitioner.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/MultiResourcePartitioner.java @@ -25,11 +25,10 @@ import org.springframework.core.io.Resource; import org.springframework.util.Assert; /** - * Implementation of {@link Partitioner} that locates multiple resources and - * associates their file names with execution context keys. Creates an - * {@link ExecutionContext} per resource, and labels them as - * {partition0, partition1, ..., partitionN}. The grid size is - * ignored. + * Implementation of {@link Partitioner} that locates multiple resources and associates + * their file names with execution context keys. Creates an {@link ExecutionContext} per + * resource, and labels them as {partition0, partition1, ..., partitionN}. + * The grid size is ignored. * * @author Dave Syer * @since 2.0 @@ -45,8 +44,8 @@ public class MultiResourcePartitioner implements Partitioner { private String keyName = DEFAULT_KEY_NAME; /** - * The resources to assign to each partition. In Spring configuration you - * can use a pattern to select multiple resources. + * The resources to assign to each partition. In Spring configuration you can use a + * pattern to select multiple resources. * @param resources the resources to use */ public void setResources(Resource[] resources) { @@ -54,8 +53,8 @@ public class MultiResourcePartitioner implements Partitioner { } /** - * The name of the key for the file name in each {@link ExecutionContext}. - * Defaults to "fileName". + * The name of the key for the file name in each {@link ExecutionContext}. Defaults to + * "fileName". * @param keyName the value of the key */ public void setKeyName(String keyName) { @@ -74,12 +73,12 @@ public class MultiResourcePartitioner implements Partitioner { int i = 0; for (Resource resource : resources) { ExecutionContext context = new ExecutionContext(); - Assert.state(resource.exists(), "Resource does not exist: "+resource); + Assert.state(resource.exists(), "Resource does not exist: " + resource); try { context.putString(keyName, resource.getURL().toExternalForm()); } catch (IOException e) { - throw new IllegalArgumentException("File could not be located for: "+resource, e); + throw new IllegalArgumentException("File could not be located for: " + resource, e); } map.put(PARTITION_KEY + i, context); i++; diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/PartitionNameProvider.java b/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/PartitionNameProvider.java index 88d05fb31..6198b3a1d 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/PartitionNameProvider.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/PartitionNameProvider.java @@ -1,46 +1,43 @@ -/* - * Copyright 2006-2009 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.core.partition.support; - -import java.util.Collection; - -/** - *

      - * Optional interface for {@link Partitioner} implementations that need to use a - * custom naming scheme for partitions. It is not necessary to implement this - * interface if a partitioner extends {@link SimplePartitioner} and re-uses the - * default partition names. - *

      - *

      - * If a partitioner does implement this interface, however, on a restart the - * {@link Partitioner#partition(int)} method will not be called again, instead - * the partitions will be re-used from the last execution, and matched by name - * with the results of {@link PartitionNameProvider#getPartitionNames(int)}. - * This can be a useful performance optimisation if the partitioning process is - * expensive. - *

      - * - * @author Dave Syer - * - * @since 2.1.3 - * - */ -public interface PartitionNameProvider { - - Collection getPartitionNames(int gridSize); - -} +/* + * Copyright 2006-2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.core.partition.support; + +import java.util.Collection; + +/** + *

      + * Optional interface for {@link Partitioner} implementations that need to use a custom + * naming scheme for partitions. It is not necessary to implement this interface if a + * partitioner extends {@link SimplePartitioner} and re-uses the default partition names. + *

      + *

      + * If a partitioner does implement this interface, however, on a restart the + * {@link Partitioner#partition(int)} method will not be called again, instead the + * partitions will be re-used from the last execution, and matched by name with the + * results of {@link PartitionNameProvider#getPartitionNames(int)}. This can be a useful + * performance optimisation if the partitioning process is expensive. + *

      + * + * @author Dave Syer + * @since 2.1.3 + * + */ +public interface PartitionNameProvider { + + Collection getPartitionNames(int gridSize); + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/PartitionStep.java b/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/PartitionStep.java index d86fe2783..f5d926ed5 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/PartitionStep.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/PartitionStep.java @@ -29,8 +29,8 @@ import org.springframework.util.Assert; import java.util.Collection; /** - * Implementation of {@link Step} which partitions the execution and spreads the - * load using a {@link PartitionHandler}. + * Implementation of {@link Step} which partitions the execution and spreads the load + * using a {@link PartitionHandler}. * * @author Dave Syer * @author Mahmoud Ben Hassine @@ -45,9 +45,8 @@ public class PartitionStep extends AbstractStep { private StepExecutionAggregator stepExecutionAggregator = new DefaultStepExecutionAggregator(); /** - * A {@link PartitionHandler} which can send out step executions for remote - * processing and bring back the results. - * + * A {@link PartitionHandler} which can send out step executions for remote processing + * and bring back the results. * @param partitionHandler the {@link PartitionHandler} to set */ public void setPartitionHandler(PartitionHandler partitionHandler) { @@ -55,10 +54,8 @@ public class PartitionStep extends AbstractStep { } /** - * A {@link StepExecutionAggregator} that can aggregate step executions when - * they come back from the handler. Defaults to a - * {@link DefaultStepExecutionAggregator}. - * + * A {@link StepExecutionAggregator} that can aggregate step executions when they come + * back from the handler. Defaults to a {@link DefaultStepExecutionAggregator}. * @param stepExecutionAggregator the {@link StepExecutionAggregator} to set */ public void setStepExecutionAggregator(StepExecutionAggregator stepExecutionAggregator) { @@ -74,8 +71,8 @@ public class PartitionStep extends AbstractStep { } /** - * Assert that mandatory properties are set (stepExecutionSplitter, - * partitionHandler) and delegate top superclass. + * Assert that mandatory properties are set (stepExecutionSplitter, partitionHandler) + * and delegate top superclass. * * @see AbstractStep#afterPropertiesSet() */ @@ -88,13 +85,11 @@ public class PartitionStep extends AbstractStep { /** * Delegate execution to the {@link PartitionHandler} provided. The - * {@link StepExecution} passed in here becomes the parent or manager - * execution for the partition, summarising the status on exit of the - * logical grouping of work carried out by the {@link PartitionHandler}. The - * individual step executions and their input parameters (through - * {@link ExecutionContext}) for the partition elements are provided by the - * {@link StepExecutionSplitter}. - * + * {@link StepExecution} passed in here becomes the parent or manager execution for + * the partition, summarising the status on exit of the logical grouping of work + * carried out by the {@link PartitionHandler}. The individual step executions and + * their input parameters (through {@link ExecutionContext}) for the partition + * elements are provided by the {@link StepExecutionSplitter}. * @param stepExecution the manager step execution for the partition * * @see Step#execute(StepExecution) @@ -121,4 +116,5 @@ public class PartitionStep extends AbstractStep { protected PartitionHandler getPartitionHandler() { return partitionHandler; } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/Partitioner.java b/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/Partitioner.java index 2e711d780..ee90086f1 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/Partitioner.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/Partitioner.java @@ -21,22 +21,20 @@ import java.util.Map; import org.springframework.batch.item.ExecutionContext; /** - * Central strategy interface for creating input parameters for a partitioned - * step in the form of {@link ExecutionContext} instances. The usual aim is to - * create a set of distinct input values, e.g. a set of non-overlapping primary - * key ranges, or a set of unique filenames. - * + * Central strategy interface for creating input parameters for a partitioned step in the + * form of {@link ExecutionContext} instances. The usual aim is to create a set of + * distinct input values, e.g. a set of non-overlapping primary key ranges, or a set of + * unique filenames. + * * @author Dave Syer * @since 2.0 */ public interface Partitioner { /** - * Create a set of distinct {@link ExecutionContext} instances together with - * a unique identifier for each one. The identifiers should be short, - * mnemonic values, and only have to be unique within the return value (e.g. - * use an incrementer). - * + * Create a set of distinct {@link ExecutionContext} instances together with a unique + * identifier for each one. The identifiers should be short, mnemonic values, and only + * have to be unique within the return value (e.g. use an incrementer). * @param gridSize the size of the map to return * @return a map from identifier to input parameters */ diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/RemoteStepExecutionAggregator.java b/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/RemoteStepExecutionAggregator.java index dd8b60d73..88e0afd42 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/RemoteStepExecutionAggregator.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/RemoteStepExecutionAggregator.java @@ -25,9 +25,8 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; /** - * Convenience class for aggregating a set of {@link StepExecution} instances - * when the input comes from remote steps, so the data need to be refreshed from - * the repository. + * Convenience class for aggregating a set of {@link StepExecution} instances when the + * input comes from remote steps, so the data need to be refreshed from the repository. * * @author Dave Syer * @since 2.1 @@ -45,9 +44,8 @@ public class RemoteStepExecutionAggregator implements StepExecutionAggregator, I } /** - * Create a new instance with a job explorer that can be used to refresh the - * data when aggregating. - * + * Create a new instance with a job explorer that can be used to refresh the data when + * aggregating. * @param jobExplorer the {@link JobExplorer} to use */ public RemoteStepExecutionAggregator(JobExplorer jobExplorer) { @@ -78,9 +76,9 @@ public class RemoteStepExecutionAggregator implements StepExecutionAggregator, I } /** - * Aggregates the input executions into the result {@link StepExecution} - * delegating to the delegate aggregator once the input has been refreshed - * from the {@link JobExplorer}. + * Aggregates the input executions into the result {@link StepExecution} delegating to + * the delegate aggregator once the input has been refreshed from the + * {@link JobExplorer}. * * @see StepExecutionAggregator #aggregate(StepExecution, Collection) */ diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/SimplePartitioner.java b/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/SimplePartitioner.java index c1de4f868..9e3ebbaa1 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/SimplePartitioner.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/SimplePartitioner.java @@ -22,10 +22,10 @@ import java.util.Map; import org.springframework.batch.item.ExecutionContext; /** - * Simplest possible implementation of {@link Partitioner}. Just creates a set - * of empty {@link ExecutionContext} instances, and labels them as - * {partition0, partition1, ..., partitionN}, where N is the grid - * size. + * Simplest possible implementation of {@link Partitioner}. Just creates a set of empty + * {@link ExecutionContext} instances, and labels them as + * {partition0, partition1, ..., partitionN}, where N is the + * grid size. * * @author Dave Syer * @since 2.0 diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/SimpleStepExecutionSplitter.java b/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/SimpleStepExecutionSplitter.java index 3bc5a53fa..699e95fc1 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/SimpleStepExecutionSplitter.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/SimpleStepExecutionSplitter.java @@ -37,12 +37,11 @@ import org.springframework.util.Assert; /** * Generic implementation of {@link StepExecutionSplitter} that delegates to a - * {@link Partitioner} to generate {@link ExecutionContext} instances. Takes - * care of restartability and identifying the step executions from previous runs - * of the same job. The generated {@link StepExecution} instances have names - * that identify them uniquely in the partition. The name is constructed from a - * base (name of the target step) plus a suffix taken from the - * {@link Partitioner} identifiers, separated by a colon, e.g. + * {@link Partitioner} to generate {@link ExecutionContext} instances. Takes care of + * restartability and identifying the step executions from previous runs of the same job. + * The generated {@link StepExecution} instances have names that identify them uniquely in + * the partition. The name is constructed from a base (name of the target step) plus a + * suffix taken from the {@link Partitioner} identifiers, separated by a colon, e.g. * {step1:partition0, step1:partition1, ...}. * * @author Dave Syer @@ -68,16 +67,14 @@ public class SimpleStepExecutionSplitter implements StepExecutionSplitter, Initi } /** - * Construct a {@link SimpleStepExecutionSplitter} from its mandatory - * properties. - * + * Construct a {@link SimpleStepExecutionSplitter} from its mandatory properties. * @param jobRepository the {@link JobRepository} * @param allowStartIfComplete flag specifying preferences on restart * @param stepName the target step name - * @param partitioner a {@link Partitioner} to use for generating input - * parameters + * @param partitioner a {@link Partitioner} to use for generating input parameters */ - public SimpleStepExecutionSplitter(JobRepository jobRepository, boolean allowStartIfComplete, String stepName, Partitioner partitioner) { + public SimpleStepExecutionSplitter(JobRepository jobRepository, boolean allowStartIfComplete, String stepName, + Partitioner partitioner) { this.jobRepository = jobRepository; this.allowStartIfComplete = allowStartIfComplete; this.partitioner = partitioner; @@ -97,12 +94,11 @@ public class SimpleStepExecutionSplitter implements StepExecutionSplitter, Initi } /** - * Flag to indicate that the partition target step is allowed to start if an - * execution is complete. Defaults to the same value as the underlying step. - * Set this manually to override the underlying step properties. + * Flag to indicate that the partition target step is allowed to start if an execution + * is complete. Defaults to the same value as the underlying step. Set this manually + * to override the underlying step properties. * * @see Step#isAllowStartIfComplete() - * * @param allowStartIfComplete the value to set */ public void setAllowStartIfComplete(boolean allowStartIfComplete) { @@ -110,9 +106,8 @@ public class SimpleStepExecutionSplitter implements StepExecutionSplitter, Initi } /** - * The job repository that will be used to manage the persistence of the - * delegate step executions. - * + * The job repository that will be used to manage the persistence of the delegate step + * executions. * @param jobRepository the JobRepository to set */ public void setJobRepository(JobRepository jobRepository) { @@ -120,9 +115,8 @@ public class SimpleStepExecutionSplitter implements StepExecutionSplitter, Initi } /** - * The {@link Partitioner} that will be used to generate step execution meta - * data for the target step. - * + * The {@link Partitioner} that will be used to generate step execution meta data for + * the target step. * @param partitioner the partitioner to set */ public void setPartitioner(Partitioner partitioner) { @@ -130,9 +124,8 @@ public class SimpleStepExecutionSplitter implements StepExecutionSplitter, Initi } /** - * The name of the target step that will be executed across the partitions. - * Mandatory with no default. - * + * The name of the target step that will be executed across the partitions. Mandatory + * with no default. * @param stepName the step name to set */ public void setStepName(String stepName) { @@ -203,9 +196,8 @@ public class SimpleStepExecutionSplitter implements StepExecutionSplitter, Initi Collection names = ((PartitionNameProvider) partitioner).getPartitionNames(splitSize); for (String name : names) { /* - * We need to return the same keys as the original (failed) - * execution, but the execution contexts will be discarded - * so they can be empty. + * We need to return the same keys as the original (failed) execution, + * but the execution contexts will be discarded so they can be empty. */ result.put(name, new ExecutionContext()); } @@ -244,8 +236,8 @@ public class SimpleStepExecutionSplitter implements StepExecutionSplitter, Initi } - private boolean shouldStart(boolean allowStartIfComplete, StepExecution stepExecution, StepExecution lastStepExecution) - throws JobExecutionException { + private boolean shouldStart(boolean allowStartIfComplete, StepExecution stepExecution, + StepExecution lastStepExecution) throws JobExecutionException { if (lastStepExecution == null) { return true; @@ -280,11 +272,8 @@ public class SimpleStepExecutionSplitter implements StepExecutionSplitter, Initi if (stepStatus == BatchStatus.STARTED || stepStatus == BatchStatus.STARTING || stepStatus == BatchStatus.STOPPING) { - throw new JobExecutionException( - "Cannot restart step from " - + stepStatus - + " status. " - + "The old execution may still be executing, so you may need to verify manually that this is the case."); + throw new JobExecutionException("Cannot restart step from " + stepStatus + " status. " + + "The old execution may still be executing, so you may need to verify manually that this is the case."); } throw new JobExecutionException("Cannot restart step from " + stepStatus + " status. " @@ -293,8 +282,8 @@ public class SimpleStepExecutionSplitter implements StepExecutionSplitter, Initi } private boolean isSameJobExecution(StepExecution stepExecution, StepExecution lastStepExecution) { - if (stepExecution.getJobExecutionId()==null) { - return lastStepExecution.getJobExecutionId()==null; + if (stepExecution.getJobExecutionId() == null) { + return lastStepExecution.getJobExecutionId() == null; } return stepExecution.getJobExecutionId().equals(lastStepExecution.getJobExecutionId()); } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/StepExecutionAggregator.java b/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/StepExecutionAggregator.java index bcd5e1ab0..1cb7f3c16 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/StepExecutionAggregator.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/StepExecutionAggregator.java @@ -20,19 +20,17 @@ import java.util.Collection; import org.springframework.batch.core.StepExecution; /** - * Strategy for a aggregating step executions, usually when they are the result - * of partitioned or remote execution. - * + * Strategy for a aggregating step executions, usually when they are the result of + * partitioned or remote execution. + * * @author Dave Syer - * * @since 2.1 - * + * */ public interface StepExecutionAggregator { /** * Take the inputs and aggregate, putting the aggregates into the result. - * * @param result the result to overwrite * @param executions the inputs */ diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/TaskExecutorPartitionHandler.java b/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/TaskExecutorPartitionHandler.java index 16400e1e0..6606f25c9 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/TaskExecutorPartitionHandler.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/partition/support/TaskExecutorPartitionHandler.java @@ -35,10 +35,9 @@ import org.springframework.core.task.TaskRejectedException; import org.springframework.util.Assert; /** - * A {@link PartitionHandler} that uses a {@link TaskExecutor} to execute the - * partitioned {@link Step} locally in multiple threads. This can be an - * effective approach for scaling batch steps that are IO intensive, like - * directory and filesystem scanning and copying. + * A {@link PartitionHandler} that uses a {@link TaskExecutor} to execute the partitioned + * {@link Step} locally in multiple threads. This can be an effective approach for scaling + * batch steps that are IO intensive, like directory and filesystem scanning and copying. *
      * By default, the thread pool is synchronous. * @@ -52,14 +51,14 @@ public class TaskExecutorPartitionHandler extends AbstractPartitionHandler imple private Step step; - @Override + @Override public void afterPropertiesSet() throws Exception { Assert.state(step != null, "A Step must be provided."); } /** - * Setter for the {@link TaskExecutor} that is used to farm out step - * executions to multiple threads. + * Setter for the {@link TaskExecutor} that is used to farm out step executions to + * multiple threads. * @param taskExecutor a {@link TaskExecutor} */ public void setTaskExecutor(TaskExecutor taskExecutor) { @@ -68,10 +67,9 @@ public class TaskExecutorPartitionHandler extends AbstractPartitionHandler imple /** * Setter for the {@link Step} that will be used to execute the partitioned - * {@link StepExecution}. This is a regular Spring Batch step, with all the - * business logic required to complete an execution based on the input - * parameters in its {@link StepExecution} context. - * + * {@link StepExecution}. This is a regular Spring Batch step, with all the business + * logic required to complete an execution based on the input parameters in its + * {@link StepExecution} context. * @param step the {@link Step} instance to use to execute business logic */ public void setStep(Step step) { @@ -80,65 +78,63 @@ public class TaskExecutorPartitionHandler extends AbstractPartitionHandler imple /** * The step instance that will be executed in parallel by this handler. - * * @return the step instance that will be used * @see StepHolder#getStep() */ - @Override + @Override public Step getStep() { return this.step; } - @Override - protected Set doHandle(StepExecution managerStepExecution, - Set partitionStepExecutions) throws Exception { - Assert.notNull(step, "A Step must be provided."); - final Set> tasks = new HashSet<>(getGridSize()); - final Set result = new HashSet<>(); + @Override + protected Set doHandle(StepExecution managerStepExecution, + Set partitionStepExecutions) throws Exception { + Assert.notNull(step, "A Step must be provided."); + final Set> tasks = new HashSet<>(getGridSize()); + final Set result = new HashSet<>(); - for (final StepExecution stepExecution : partitionStepExecutions) { - final FutureTask task = createTask(step, stepExecution); + for (final StepExecution stepExecution : partitionStepExecutions) { + final FutureTask task = createTask(step, stepExecution); - try { - taskExecutor.execute(task); - tasks.add(task); - } catch (TaskRejectedException e) { - // couldn't execute one of the tasks - ExitStatus exitStatus = ExitStatus.FAILED - .addExitDescription("TaskExecutor rejected the task for this step."); - /* - * Set the status in case the caller is tracking it through the - * JobExecution. - */ - stepExecution.setStatus(BatchStatus.FAILED); - stepExecution.setExitStatus(exitStatus); - result.add(stepExecution); - } - } + try { + taskExecutor.execute(task); + tasks.add(task); + } + catch (TaskRejectedException e) { + // couldn't execute one of the tasks + ExitStatus exitStatus = ExitStatus.FAILED + .addExitDescription("TaskExecutor rejected the task for this step."); + /* + * Set the status in case the caller is tracking it through the + * JobExecution. + */ + stepExecution.setStatus(BatchStatus.FAILED); + stepExecution.setExitStatus(exitStatus); + result.add(stepExecution); + } + } - for (Future task : tasks) { - result.add(task.get()); - } + for (Future task : tasks) { + result.add(task.get()); + } - return result; + return result; } - /** - * Creates the task executing the given step in the context of the given execution. - * - * @param step the step to execute - * @param stepExecution the given execution - * @return the task executing the given step - */ - protected FutureTask createTask(final Step step, - final StepExecution stepExecution) { - return new FutureTask<>(new Callable() { - @Override - public StepExecution call() throws Exception { - step.execute(stepExecution); - return stepExecution; - } - }); - } + /** + * Creates the task executing the given step in the context of the given execution. + * @param step the step to execute + * @param stepExecution the given execution + * @return the task executing the given step + */ + protected FutureTask createTask(final Step step, final StepExecution stepExecution) { + return new FutureTask<>(new Callable() { + @Override + public StepExecution call() throws Exception { + step.execute(stepExecution); + return stepExecution; + } + }); + } } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/ExecutionContextSerializer.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/ExecutionContextSerializer.java index cce7d69d9..26970b1fd 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/ExecutionContextSerializer.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/ExecutionContextSerializer.java @@ -21,10 +21,9 @@ import org.springframework.core.serializer.Deserializer; import org.springframework.core.serializer.Serializer; /** - * A composite interface that combines both serialization and deserialization - * of an execution context into a single implementation. Implementations of this - * interface are used to serialize the execution context for persistence during - * the execution of a job. + * A composite interface that combines both serialization and deserialization of an + * execution context into a single implementation. Implementations of this interface are + * used to serialize the execution context for persistence during the execution of a job. * * @author Michael Minella * @since 2.2 diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/JobInstanceAlreadyCompleteException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/JobInstanceAlreadyCompleteException.java index b60a15a19..a735eec3c 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/JobInstanceAlreadyCompleteException.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/JobInstanceAlreadyCompleteException.java @@ -18,11 +18,11 @@ package org.springframework.batch.core.repository; import org.springframework.batch.core.JobExecutionException; /** - * An exception indicating an illegal attempt to restart a job that was already - * completed successfully. - * + * An exception indicating an illegal attempt to restart a job that was already completed + * successfully. + * * @author Dave Syer - * + * */ @SuppressWarnings("serial") public class JobInstanceAlreadyCompleteException extends JobExecutionException { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/JobRepository.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/JobRepository.java index 15471953b..8174ced46 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/JobRepository.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/JobRepository.java @@ -38,7 +38,6 @@ import java.util.Collection; * @see JobInstance * @see JobExecution * @see StepExecution - * * @author Lucas Ward * @author Dave Syer * @author Robert Kasanicky @@ -49,19 +48,16 @@ import java.util.Collection; public interface JobRepository { /** - * Check if an instance of this job already exists with the parameters - * provided. - * + * Check if an instance of this job already exists with the parameters provided. * @param jobName the name of the job * @param jobParameters the parameters to match - * @return true if a {@link JobInstance} already exists for this job name - * and job parameters + * @return true if a {@link JobInstance} already exists for this job name and job + * parameters */ boolean isJobInstanceExists(String jobName, JobParameters jobParameters); /** * Create a new {@link JobInstance} with the name and job parameters provided. - * * @param jobName logical name of the job * @param jobParameters parameters used to execute the job * @return the new {@link JobInstance} @@ -70,40 +66,32 @@ public interface JobRepository { /** *

      - * Create a {@link JobExecution} for a given {@link Job} and - * {@link JobParameters}. If matching {@link JobInstance} already exists, - * the job must be restartable and it's last JobExecution must *not* be - * completed. If matching {@link JobInstance} does not exist yet it will be - * created. + * Create a {@link JobExecution} for a given {@link Job} and {@link JobParameters}. If + * matching {@link JobInstance} already exists, the job must be restartable and it's + * last JobExecution must *not* be completed. If matching {@link JobInstance} does not + * exist yet it will be created. *

      * *

      - * If this method is run in a transaction (as it normally would be) with - * isolation level at {@link Isolation#REPEATABLE_READ} or better, then this - * method should block if another transaction is already executing it (for - * the same {@link JobParameters} and job name). The first transaction to - * complete in this scenario obtains a valid {@link JobExecution}, and - * others throw {@link JobExecutionAlreadyRunningException} (or timeout). - * There are no such guarantees if the {@link JobInstanceDao} and - * {@link JobExecutionDao} do not respect the transaction isolation levels - * (e.g. if using a non-relational data-store, or if the platform does not - * support the higher isolation levels). + * If this method is run in a transaction (as it normally would be) with isolation + * level at {@link Isolation#REPEATABLE_READ} or better, then this method should block + * if another transaction is already executing it (for the same {@link JobParameters} + * and job name). The first transaction to complete in this scenario obtains a valid + * {@link JobExecution}, and others throw {@link JobExecutionAlreadyRunningException} + * (or timeout). There are no such guarantees if the {@link JobInstanceDao} and + * {@link JobExecutionDao} do not respect the transaction isolation levels (e.g. if + * using a non-relational data-store, or if the platform does not support the higher + * isolation levels). *

      - * * @param jobName the name of the job that is to be executed - * * @param jobParameters the runtime parameters for the job - * * @return a valid {@link JobExecution} for the arguments provided - * - * @throws JobExecutionAlreadyRunningException if there is a - * {@link JobExecution} already running for the job instance with the - * provided job and parameters. - * @throws JobRestartException if one or more existing {@link JobInstance}s - * is found with the same parameters and {@link Job#isRestartable()} is - * false. - * @throws JobInstanceAlreadyCompleteException if a {@link JobInstance} is - * found and was already completed successfully. + * @throws JobExecutionAlreadyRunningException if there is a {@link JobExecution} + * already running for the job instance with the provided job and parameters. + * @throws JobRestartException if one or more existing {@link JobInstance}s is found + * with the same parameters and {@link Job#isRestartable()} is false. + * @throws JobInstanceAlreadyCompleteException if a {@link JobInstance} is found and + * was already completed successfully. * */ JobExecution createJobExecution(String jobName, JobParameters jobParameters) @@ -112,33 +100,31 @@ public interface JobRepository { /** * Update the {@link JobExecution} (but not its {@link ExecutionContext}). * - * Preconditions: {@link JobExecution} must contain a valid - * {@link JobInstance} and be saved (have an id assigned). - * + * Preconditions: {@link JobExecution} must contain a valid {@link JobInstance} and be + * saved (have an id assigned). * @param jobExecution {@link JobExecution} instance to be updated in the repo. */ void update(JobExecution jobExecution); /** - * Save the {@link StepExecution} and its {@link ExecutionContext}. ID will - * be assigned - it is not permitted that an ID be assigned before calling - * this method. Instead, it should be left blank, to be assigned by a - * {@link JobRepository}. + * Save the {@link StepExecution} and its {@link ExecutionContext}. ID will be + * assigned - it is not permitted that an ID be assigned before calling this method. + * Instead, it should be left blank, to be assigned by a {@link JobRepository}. * * Preconditions: {@link StepExecution} must have a valid {@link Step}. - * * @param stepExecution {@link StepExecution} instance to be added to the repo. */ void add(StepExecution stepExecution); /** * Save a collection of {@link StepExecution}s and each {@link ExecutionContext}. The - * StepExecution ID will be assigned - it is not permitted that an ID be assigned before calling - * this method. Instead, it should be left blank, to be assigned by {@link JobRepository}. + * StepExecution ID will be assigned - it is not permitted that an ID be assigned + * before calling this method. Instead, it should be left blank, to be assigned by + * {@link JobRepository}. * * Preconditions: {@link StepExecution} must have a valid {@link Step}. - * - * @param stepExecutions collection of {@link StepExecution} instances to be added to the repo. + * @param stepExecutions collection of {@link StepExecution} instances to be added to + * the repo. */ void addAll(Collection stepExecutions); @@ -146,22 +132,19 @@ public interface JobRepository { * Update the {@link StepExecution} (but not its {@link ExecutionContext}). * * Preconditions: {@link StepExecution} must be saved (have an id assigned). - * * @param stepExecution {@link StepExecution} instance to be updated in the repo. */ void update(StepExecution stepExecution); /** - * Persist the updated {@link ExecutionContext}s of the given - * {@link StepExecution}. - * - * @param stepExecution {@link StepExecution} instance to be used to update the context. + * Persist the updated {@link ExecutionContext}s of the given {@link StepExecution}. + * @param stepExecution {@link StepExecution} instance to be used to update the + * context. */ void updateExecutionContext(StepExecution stepExecution); /** - * Persist the updated {@link ExecutionContext} of the given - * {@link JobExecution}. + * Persist the updated {@link ExecutionContext} of the given {@link JobExecution}. * @param jobExecution {@link JobExecution} instance to be used to update the context. */ void updateExecutionContext(JobExecution jobExecution); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/AbstractJdbcBatchMetadataDao.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/AbstractJdbcBatchMetadataDao.java index be76f7e19..57c48811c 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/AbstractJdbcBatchMetadataDao.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/AbstractJdbcBatchMetadataDao.java @@ -24,8 +24,8 @@ import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** - * Encapsulates common functionality needed by JDBC batch metadata DAOs - - * provides jdbcTemplate for subclasses and handles table prefixes. + * Encapsulates common functionality needed by JDBC batch metadata DAOs - provides + * jdbcTemplate for subclasses and handles table prefixes. * * @author Robert Kasanicky */ @@ -53,10 +53,8 @@ public abstract class AbstractJdbcBatchMetadataDao implements InitializingBean { } /** - * Public setter for the table prefix property. This will be prefixed to all - * the table names before queries are executed. Defaults to - * {@link #DEFAULT_TABLE_PREFIX}. - * + * Public setter for the table prefix property. This will be prefixed to all the table + * names before queries are executed. Defaults to {@link #DEFAULT_TABLE_PREFIX}. * @param tablePrefix the tablePrefix to set */ public void setTablePrefix(String tablePrefix) { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/DefaultExecutionContextSerializer.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/DefaultExecutionContextSerializer.java index ca3aeb74a..cd537bb40 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/DefaultExecutionContextSerializer.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/DefaultExecutionContextSerializer.java @@ -40,15 +40,15 @@ import org.springframework.util.Assert; public class DefaultExecutionContextSerializer implements ExecutionContextSerializer { private Serializer serializer = new DefaultSerializer(); + private Deserializer deserializer = new DefaultDeserializer(); /** - * Serializes an execution context to the provided {@link OutputStream}. The - * stream is not closed prior to it's return. - * + * Serializes an execution context to the provided {@link OutputStream}. The stream is + * not closed prior to it's return. * @param context {@link Map} contents of the {@code ExecutionContext}. - * @param out {@link OutputStream} where the serialized context information - * will be written. + * @param out {@link OutputStream} where the serialized context information will be + * written. */ @Override @SuppressWarnings("unchecked") @@ -56,13 +56,12 @@ public class DefaultExecutionContextSerializer implements ExecutionContextSerial Assert.notNull(context, "context is required"); Assert.notNull(out, "OutputStream is required"); - for(Object value : context.values()) { + for (Object value : context.values()) { Assert.notNull(value, "A null value was found"); if (!(value instanceof Serializable)) { throw new IllegalArgumentException( - "Value: [" + value + "] must be serializable. " - + "Object of class: [" + value.getClass().getName() - + "] must be an instance of " + Serializable.class); + "Value: [" + value + "] must be serializable. " + "Object of class: [" + + value.getClass().getName() + "] must be an instance of " + Serializable.class); } } serializer.serialize(context, out); @@ -70,8 +69,8 @@ public class DefaultExecutionContextSerializer implements ExecutionContextSerial /** * Deserializes an execution context from the provided {@link InputStream}. - * - * @param inputStream {@link InputStream} containing the information to be deserialized. + * @param inputStream {@link InputStream} containing the information to be + * deserialized. * @return the object serialized in the provided {@link InputStream} */ @SuppressWarnings("unchecked") diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/ExecutionContextDao.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/ExecutionContextDao.java index a6e236bc8..9a086cbc2 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/ExecutionContextDao.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/ExecutionContextDao.java @@ -24,7 +24,7 @@ import org.springframework.batch.item.ExecutionContext; /** * DAO interface for persisting and retrieving {@link ExecutionContext}s. - * + * * @author Robert Kasanicky * @author David Turanski */ @@ -43,43 +43,39 @@ public interface ExecutionContextDao { ExecutionContext getExecutionContext(StepExecution stepExecution); /** - * Persist the execution context associated with the given jobExecution, - * persistent entry for the context should not exist yet. - * + * Persist the execution context associated with the given jobExecution, persistent + * entry for the context should not exist yet. * @param jobExecution {@link JobExecution} instance that contains the context. */ void saveExecutionContext(final JobExecution jobExecution); /** - * Persist the execution context associated with the given stepExecution, - * persistent entry for the context should not exist yet. - * + * Persist the execution context associated with the given stepExecution, persistent + * entry for the context should not exist yet. * @param stepExecution {@link StepExecution} instance that contains the context. */ void saveExecutionContext(final StepExecution stepExecution); /** - * Persist the execution context associated with each stepExecution in a given collection, - * persistent entry for the context should not exist yet. - * - * @param stepExecutions a collection of {@link StepExecution}s that contain - * the contexts. + * Persist the execution context associated with each stepExecution in a given + * collection, persistent entry for the context should not exist yet. + * @param stepExecutions a collection of {@link StepExecution}s that contain the + * contexts. */ void saveExecutionContexts(final Collection stepExecutions); /** - * Persist the updates of execution context associated with the given - * jobExecution. Persistent entry should already exist for this context. - * + * Persist the updates of execution context associated with the given jobExecution. + * Persistent entry should already exist for this context. * @param jobExecution {@link JobExecution} instance that contains the context. */ void updateExecutionContext(final JobExecution jobExecution); /** - * Persist the updates of execution context associated with the given - * stepExecution. Persistent entry should already exist for this context. - * + * Persist the updates of execution context associated with the given stepExecution. + * Persistent entry should already exist for this context. * @param stepExecution {@link StepExecution} instance that contains the context. */ void updateExecutionContext(final StepExecution stepExecution); + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/Jackson2ExecutionContextStringSerializer.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/Jackson2ExecutionContextStringSerializer.java index 42bc56161..532db6afa 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/Jackson2ExecutionContextStringSerializer.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/Jackson2ExecutionContextStringSerializer.java @@ -59,23 +59,23 @@ import org.springframework.core.annotation.AnnotationUtils; import org.springframework.util.Assert; /** - * Implementation that uses Jackson2 to provide (de)serialization. - * - * By default, this implementation trusts a limited set of classes to be - * deserialized from the execution context. If a class is not trusted by default - * and is safe to deserialize, you can add it to the base set of trusted classes - * at {@link Jackson2ExecutionContextStringSerializer construction time} or provide - * an explicit mapping using Jackson annotations, as shown in the following example: - * + * Implementation that uses Jackson2 to provide (de)serialization. + * + * By default, this implementation trusts a limited set of classes to be deserialized from + * the execution context. If a class is not trusted by default and is safe to deserialize, + * you can add it to the base set of trusted classes at + * {@link Jackson2ExecutionContextStringSerializer construction time} or provide an + * explicit mapping using Jackson annotations, as shown in the following example: + * *
        *     @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
        *     public class MyTrustedType implements Serializable {
      - *        
      + *
        *     }
        * 
      - * - * It is also possible to provide a custom {@link ObjectMapper} with a mixin for - * the trusted type: + * + * It is also possible to provide a custom {@link ObjectMapper} with a mixin for the + * trusted type: * *
        *     ObjectMapper objectMapper = new ObjectMapper();
      @@ -84,14 +84,14 @@ import org.springframework.util.Assert;
        *     serializer.setObjectMapper(objectMapper);
        *     // register serializer in JobRepositoryFactoryBean
        * 
      - * - * If the (de)serialization is only done by a trusted source, you can also enable - * default typing: + * + * If the (de)serialization is only done by a trusted source, you can also enable default + * typing: * *
        *     PolymorphicTypeValidator polymorphicTypeValidator = .. // configure your trusted PolymorphicTypeValidator
        *     ObjectMapper objectMapper = new ObjectMapper();
      - *     objectMapper.activateDefaultTyping(polymorphicTypeValidator); 
      + *     objectMapper.activateDefaultTyping(polymorphicTypeValidator);
        *     Jackson2ExecutionContextStringSerializer serializer = new Jackson2ExecutionContextStringSerializer();
        *     serializer.setObjectMapper(objectMapper);
        *     // register serializer in JobRepositoryFactoryBean
      @@ -100,278 +100,250 @@ import org.springframework.util.Assert;
        * @author Marten Deinum
        * @author Mahmoud Ben Hassine
        * @since 3.0.7
      - *
        * @see ExecutionContextSerializer
        */
       public class Jackson2ExecutionContextStringSerializer implements ExecutionContextSerializer {
       
      -    private ObjectMapper objectMapper;
      +	private ObjectMapper objectMapper;
       
      -    /**
      -     * Create a new {@link Jackson2ExecutionContextStringSerializer}.
      -     * 
      -     * @param trustedClassNames fully qualified names of classes that are safe
      -     * to deserialize from the execution context and which should be added to the
      -     * default set of trusted classes.
      -     */
      -    public Jackson2ExecutionContextStringSerializer(String... trustedClassNames) {
      -        this.objectMapper = JsonMapper.builder()
      -                .configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false)
      -                .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true)
      -                .configure(MapperFeature.BLOCK_UNSAFE_POLYMORPHIC_BASE_TYPES, true)
      -                .setDefaultTyping(createTrustedDefaultTyping(trustedClassNames))
      -                .addModule(new JobParametersModule())
      -                .build();
      -    }
      +	/**
      +	 * Create a new {@link Jackson2ExecutionContextStringSerializer}.
      +	 * @param trustedClassNames fully qualified names of classes that are safe to
      +	 * deserialize from the execution context and which should be added to the default set
      +	 * of trusted classes.
      +	 */
      +	public Jackson2ExecutionContextStringSerializer(String... trustedClassNames) {
      +		this.objectMapper = JsonMapper.builder().configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false)
      +				.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true)
      +				.configure(MapperFeature.BLOCK_UNSAFE_POLYMORPHIC_BASE_TYPES, true)
      +				.setDefaultTyping(createTrustedDefaultTyping(trustedClassNames)).addModule(new JobParametersModule())
      +				.build();
      +	}
       
      -    public void setObjectMapper(ObjectMapper objectMapper) {
      -        Assert.notNull(objectMapper, "ObjectMapper must not be null");
      -        this.objectMapper = objectMapper.copy();
      -        this.objectMapper.registerModule(new JobParametersModule());
      -    }
      +	public void setObjectMapper(ObjectMapper objectMapper) {
      +		Assert.notNull(objectMapper, "ObjectMapper must not be null");
      +		this.objectMapper = objectMapper.copy();
      +		this.objectMapper.registerModule(new JobParametersModule());
      +	}
       
      -    public Map deserialize(InputStream in) throws IOException {
      +	public Map deserialize(InputStream in) throws IOException {
       
      -        TypeReference> typeRef = new TypeReference>() {};
      -        return objectMapper.readValue(in, typeRef);
      -    }
      +		TypeReference> typeRef = new TypeReference>() {
      +		};
      +		return objectMapper.readValue(in, typeRef);
      +	}
       
      -    public void serialize(Map context, OutputStream out) throws IOException {
      +	public void serialize(Map context, OutputStream out) throws IOException {
       
      -        Assert.notNull(context, "A context is required");
      -        Assert.notNull(out, "An OutputStream is required");
      +		Assert.notNull(context, "A context is required");
      +		Assert.notNull(out, "An OutputStream is required");
       
      -        objectMapper.writeValue(out, context);
      -    }
      +		objectMapper.writeValue(out, context);
      +	}
       
      -    // BATCH-2680
      -    /**
      -     * Custom Jackson module to support {@link JobParameter} and {@link JobParameters}
      -     * deserialization.
      -     */
      -    private class JobParametersModule extends SimpleModule {
      +	// BATCH-2680
      +	/**
      +	 * Custom Jackson module to support {@link JobParameter} and {@link JobParameters}
      +	 * deserialization.
      +	 */
      +	private class JobParametersModule extends SimpleModule {
       
      -        private static final long serialVersionUID = 1L;
      +		private static final long serialVersionUID = 1L;
       
      -        private JobParametersModule() {
      -            super("Job parameters module");
      -            setMixInAnnotation(JobParameters.class, JobParametersMixIn.class);
      -            addDeserializer(JobParameter.class, new JobParameterDeserializer());
      -        }
      +		private JobParametersModule() {
      +			super("Job parameters module");
      +			setMixInAnnotation(JobParameters.class, JobParametersMixIn.class);
      +			addDeserializer(JobParameter.class, new JobParameterDeserializer());
      +		}
       
      -        private abstract class JobParametersMixIn {
      -            @JsonIgnore
      -            abstract boolean isEmpty();
      -        }
      +		private abstract class JobParametersMixIn {
       
      -        private class JobParameterDeserializer extends StdDeserializer {
      +			@JsonIgnore
      +			abstract boolean isEmpty();
       
      -            private static final long serialVersionUID = 1L;
      -            private static final String IDENTIFYING_KEY_NAME = "identifying";
      -            private static final String TYPE_KEY_NAME = "type";
      -            private static final String VALUE_KEY_NAME = "value";
      +		}
       
      -            JobParameterDeserializer() {
      -                super(JobParameter.class);
      -            }
      +		private class JobParameterDeserializer extends StdDeserializer {
       
      -            @Override
      -            public JobParameter deserialize(JsonParser parser, DeserializationContext context) throws IOException {
      -                JsonNode node = parser.readValueAsTree();
      -                boolean identifying = node.get(IDENTIFYING_KEY_NAME).asBoolean();
      -                String type = node.get(TYPE_KEY_NAME).asText();
      -                JsonNode value = node.get(VALUE_KEY_NAME);
      -                Object parameterValue;
      -                switch (JobParameter.ParameterType.valueOf(type)) {
      -                    case STRING: {
      -                        parameterValue = value.asText();
      -                        return new JobParameter((String) parameterValue, identifying);
      -                    }
      -                    case DATE: {
      -                        parameterValue = new Date(value.get(1).asLong());
      -                        return new JobParameter((Date) parameterValue, identifying);
      -                    }
      -                    case LONG: {
      -                        parameterValue = value.get(1).asLong();
      -                        return new JobParameter((Long) parameterValue, identifying);
      -                    }
      -                    case DOUBLE: {
      -                        parameterValue = value.asDouble();
      -                        return new JobParameter((Double) parameterValue, identifying);
      -                    }
      -                }
      -                return null;
      -            }
      -        }
      +			private static final long serialVersionUID = 1L;
       
      -    }
      +			private static final String IDENTIFYING_KEY_NAME = "identifying";
       
      -    /**
      -     * Creates a TypeResolverBuilder that checks if a type is trusted.
      -     * @return a TypeResolverBuilder that checks if a type is trusted.
      -     * @param trustedClassNames array of fully qualified trusted class names
      -     */
      -    private static TypeResolverBuilder createTrustedDefaultTyping(String[] trustedClassNames) {
      -        TypeResolverBuilder  result = new TrustedTypeResolverBuilder(ObjectMapper.DefaultTyping.NON_FINAL, trustedClassNames);
      -        result = result.init(JsonTypeInfo.Id.CLASS, null);
      -        result = result.inclusion(JsonTypeInfo.As.PROPERTY);
      -        return result;
      -    }
      +			private static final String TYPE_KEY_NAME = "type";
       
      -    /**
      -     * An implementation of {@link ObjectMapper.DefaultTypeResolverBuilder}
      -     * that inserts an {@code allow all} {@link PolymorphicTypeValidator}
      -     * and overrides the {@code TypeIdResolver}
      -     * @author Rob Winch
      -     */
      -    static class TrustedTypeResolverBuilder extends ObjectMapper.DefaultTypeResolverBuilder {
      +			private static final String VALUE_KEY_NAME = "value";
       
      -        private final String[] trustedClassNames;
      +			JobParameterDeserializer() {
      +				super(JobParameter.class);
      +			}
       
      -        TrustedTypeResolverBuilder(ObjectMapper.DefaultTyping defaultTyping, String[] trustedClassNames) {
      -            super(
      -                    defaultTyping,
      -                    //we do explicit validation in the TypeIdResolver
      -                    BasicPolymorphicTypeValidator.builder()
      -                            .allowIfSubType(Object.class)
      -                            .build()
      -            );
      -            this.trustedClassNames =
      -                    trustedClassNames != null ? Arrays.copyOf(trustedClassNames, trustedClassNames.length) : null;
      -        }
      +			@Override
      +			public JobParameter deserialize(JsonParser parser, DeserializationContext context) throws IOException {
      +				JsonNode node = parser.readValueAsTree();
      +				boolean identifying = node.get(IDENTIFYING_KEY_NAME).asBoolean();
      +				String type = node.get(TYPE_KEY_NAME).asText();
      +				JsonNode value = node.get(VALUE_KEY_NAME);
      +				Object parameterValue;
      +				switch (JobParameter.ParameterType.valueOf(type)) {
      +				case STRING: {
      +					parameterValue = value.asText();
      +					return new JobParameter((String) parameterValue, identifying);
      +				}
      +				case DATE: {
      +					parameterValue = new Date(value.get(1).asLong());
      +					return new JobParameter((Date) parameterValue, identifying);
      +				}
      +				case LONG: {
      +					parameterValue = value.get(1).asLong();
      +					return new JobParameter((Long) parameterValue, identifying);
      +				}
      +				case DOUBLE: {
      +					parameterValue = value.asDouble();
      +					return new JobParameter((Double) parameterValue, identifying);
      +				}
      +				}
      +				return null;
      +			}
       
      -        @Override
      -        protected TypeIdResolver idResolver(MapperConfig config,
      -                                            JavaType baseType,
      -                                            PolymorphicTypeValidator subtypeValidator,
      -                                            Collection subtypes, boolean forSer, boolean forDeser) {
      -            TypeIdResolver result = super.idResolver(config, baseType, subtypeValidator, subtypes, forSer, forDeser);
      -            return new TrustedTypeIdResolver(result, this.trustedClassNames);
      -        }
      -    }
      +		}
       
      -    /**
      -     * A {@link TypeIdResolver} that delegates to an existing implementation and throws an IllegalStateException if the
      -     * class being looked up is not trusted, does not provide an explicit mixin, and is not annotated with Jackson
      -     * mappings.
      -     */
      -    static class TrustedTypeIdResolver implements TypeIdResolver {
      -        private static final Set TRUSTED_CLASS_NAMES = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
      -                "javax.xml.namespace.QName",
      -                "java.util.UUID",
      -                "java.util.ArrayList",
      -                "java.util.Arrays$ArrayList",
      -                "java.util.LinkedList",
      -                "java.util.Collections$EmptyList",
      -                "java.util.Collections$EmptyMap",
      -                "java.util.Collections$EmptySet",
      -                "java.util.Collections$UnmodifiableRandomAccessList",
      -                "java.util.Collections$UnmodifiableList",
      -                "java.util.Collections$UnmodifiableMap",
      -                "java.util.Collections$UnmodifiableSet",
      -                "java.util.Collections$SingletonList",
      -                "java.util.Collections$SingletonMap",
      -                "java.util.Collections$SingletonSet",
      -                "java.util.Date",
      -                "java.time.Instant",
      -                "java.time.Duration",
      -                "java.time.LocalDate",
      -                "java.time.LocalTime",
      -                "java.time.LocalDateTime",
      -                "java.sql.Timestamp",
      -                "java.net.URL",
      -                "java.util.TreeMap",
      -                "java.util.HashMap",
      -                "java.util.LinkedHashMap",
      -                "java.util.TreeSet",
      -                "java.util.HashSet",
      -                "java.util.LinkedHashSet",
      -                "java.lang.Boolean",
      -                "java.lang.Byte",
      -                "java.lang.Short",
      -                "java.lang.Integer",
      -                "java.lang.Long",
      -                "java.lang.Double",
      -                "java.lang.Float",
      -                "java.math.BigDecimal",
      -                "java.math.BigInteger",
      -                "java.lang.String",
      -                "java.lang.Character",
      -                "java.lang.CharSequence",
      -                "java.util.Properties",
      -                "[Ljava.util.Properties;",
      -                "org.springframework.batch.core.JobParameter",
      -                "org.springframework.batch.core.JobParameters"
      -        )));
      +	}
       
      -        private final Set trustedClassNames = new LinkedHashSet<>(TRUSTED_CLASS_NAMES);
      +	/**
      +	 * Creates a TypeResolverBuilder that checks if a type is trusted.
      +	 * @return a TypeResolverBuilder that checks if a type is trusted.
      +	 * @param trustedClassNames array of fully qualified trusted class names
      +	 */
      +	private static TypeResolverBuilder createTrustedDefaultTyping(
      +			String[] trustedClassNames) {
      +		TypeResolverBuilder result = new TrustedTypeResolverBuilder(
      +				ObjectMapper.DefaultTyping.NON_FINAL, trustedClassNames);
      +		result = result.init(JsonTypeInfo.Id.CLASS, null);
      +		result = result.inclusion(JsonTypeInfo.As.PROPERTY);
      +		return result;
      +	}
       
      -        private final TypeIdResolver delegate;
      +	/**
      +	 * An implementation of {@link ObjectMapper.DefaultTypeResolverBuilder} that inserts
      +	 * an {@code allow all} {@link PolymorphicTypeValidator} and overrides the
      +	 * {@code TypeIdResolver}
      +	 *
      +	 * @author Rob Winch
      +	 */
      +	static class TrustedTypeResolverBuilder extends ObjectMapper.DefaultTypeResolverBuilder {
       
      -        TrustedTypeIdResolver(TypeIdResolver delegate, String[] trustedClassNames) {
      -            this.delegate = delegate;
      -            if (trustedClassNames != null) {
      -                this.trustedClassNames.addAll(Arrays.asList(trustedClassNames));
      -            }
      -        }
      +		private final String[] trustedClassNames;
       
      -        @Override
      -        public void init(JavaType baseType) {
      -            delegate.init(baseType);
      -        }
      +		TrustedTypeResolverBuilder(ObjectMapper.DefaultTyping defaultTyping, String[] trustedClassNames) {
      +			super(defaultTyping,
      +					// we do explicit validation in the TypeIdResolver
      +					BasicPolymorphicTypeValidator.builder().allowIfSubType(Object.class).build());
      +			this.trustedClassNames = trustedClassNames != null
      +					? Arrays.copyOf(trustedClassNames, trustedClassNames.length) : null;
      +		}
       
      -        @Override
      -        public String idFromValue(Object value) {
      -            return delegate.idFromValue(value);
      -        }
      +		@Override
      +		protected TypeIdResolver idResolver(MapperConfig config, JavaType baseType,
      +				PolymorphicTypeValidator subtypeValidator, Collection subtypes, boolean forSer,
      +				boolean forDeser) {
      +			TypeIdResolver result = super.idResolver(config, baseType, subtypeValidator, subtypes, forSer, forDeser);
      +			return new TrustedTypeIdResolver(result, this.trustedClassNames);
      +		}
       
      -        @Override
      -        public String idFromValueAndType(Object value, Class suggestedType) {
      -            return delegate.idFromValueAndType(value, suggestedType);
      -        }
      +	}
       
      -        @Override
      -        public String idFromBaseType() {
      -            return delegate.idFromBaseType();
      -        }
      +	/**
      +	 * A {@link TypeIdResolver} that delegates to an existing implementation and throws an
      +	 * IllegalStateException if the class being looked up is not trusted, does not provide
      +	 * an explicit mixin, and is not annotated with Jackson mappings.
      +	 */
      +	static class TrustedTypeIdResolver implements TypeIdResolver {
       
      -        @Override
      -        public JavaType typeFromId(DatabindContext context, String id) throws IOException {
      -            DeserializationConfig config = (DeserializationConfig) context.getConfig();
      -            JavaType result = delegate.typeFromId(context, id);
      -            String className = result.getRawClass().getName();
      -            if (isTrusted(className)) {
      -                return result;
      -            }
      -            boolean isExplicitMixin = config.findMixInClassFor(result.getRawClass()) != null;
      -            if (isExplicitMixin) {
      -                return result;
      -            }
      -            Class rawClass = result.getRawClass();
      -            JacksonAnnotation jacksonAnnotation = AnnotationUtils.findAnnotation(rawClass, JacksonAnnotation.class);
      -            if (jacksonAnnotation != null) {
      -                return result;
      -            }
      -            throw new IllegalArgumentException("The class with " + id + " and name of " + className + " is not trusted. " +
      -                    "If you believe this class is safe to deserialize, you can add it to the base set of trusted classes " +
      -                    "at construction time or provide an explicit mapping using Jackson annotations or a custom ObjectMapper. " +
      -                    "If the serialization is only done by a trusted source, you can also enable default typing.");
      -        }
      +		private static final Set TRUSTED_CLASS_NAMES = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
      +				"javax.xml.namespace.QName", "java.util.UUID", "java.util.ArrayList", "java.util.Arrays$ArrayList",
      +				"java.util.LinkedList", "java.util.Collections$EmptyList", "java.util.Collections$EmptyMap",
      +				"java.util.Collections$EmptySet", "java.util.Collections$UnmodifiableRandomAccessList",
      +				"java.util.Collections$UnmodifiableList", "java.util.Collections$UnmodifiableMap",
      +				"java.util.Collections$UnmodifiableSet", "java.util.Collections$SingletonList",
      +				"java.util.Collections$SingletonMap", "java.util.Collections$SingletonSet", "java.util.Date",
      +				"java.time.Instant", "java.time.Duration", "java.time.LocalDate", "java.time.LocalTime",
      +				"java.time.LocalDateTime", "java.sql.Timestamp", "java.net.URL", "java.util.TreeMap",
      +				"java.util.HashMap", "java.util.LinkedHashMap", "java.util.TreeSet", "java.util.HashSet",
      +				"java.util.LinkedHashSet", "java.lang.Boolean", "java.lang.Byte", "java.lang.Short",
      +				"java.lang.Integer", "java.lang.Long", "java.lang.Double", "java.lang.Float", "java.math.BigDecimal",
      +				"java.math.BigInteger", "java.lang.String", "java.lang.Character", "java.lang.CharSequence",
      +				"java.util.Properties", "[Ljava.util.Properties;", "org.springframework.batch.core.JobParameter",
      +				"org.springframework.batch.core.JobParameters")));
       
      -        private boolean isTrusted(String id) {
      -            return this.trustedClassNames.contains(id);
      -        }
      +		private final Set trustedClassNames = new LinkedHashSet<>(TRUSTED_CLASS_NAMES);
       
      -        @Override
      -        public String getDescForKnownTypeIds() {
      -            return delegate.getDescForKnownTypeIds();
      -        }
      +		private final TypeIdResolver delegate;
       
      -        @Override
      -        public JsonTypeInfo.Id getMechanism() {
      -            return delegate.getMechanism();
      -        }
      +		TrustedTypeIdResolver(TypeIdResolver delegate, String[] trustedClassNames) {
      +			this.delegate = delegate;
      +			if (trustedClassNames != null) {
      +				this.trustedClassNames.addAll(Arrays.asList(trustedClassNames));
      +			}
      +		}
       
      -    }
      +		@Override
      +		public void init(JavaType baseType) {
      +			delegate.init(baseType);
      +		}
      +
      +		@Override
      +		public String idFromValue(Object value) {
      +			return delegate.idFromValue(value);
      +		}
      +
      +		@Override
      +		public String idFromValueAndType(Object value, Class suggestedType) {
      +			return delegate.idFromValueAndType(value, suggestedType);
      +		}
      +
      +		@Override
      +		public String idFromBaseType() {
      +			return delegate.idFromBaseType();
      +		}
      +
      +		@Override
      +		public JavaType typeFromId(DatabindContext context, String id) throws IOException {
      +			DeserializationConfig config = (DeserializationConfig) context.getConfig();
      +			JavaType result = delegate.typeFromId(context, id);
      +			String className = result.getRawClass().getName();
      +			if (isTrusted(className)) {
      +				return result;
      +			}
      +			boolean isExplicitMixin = config.findMixInClassFor(result.getRawClass()) != null;
      +			if (isExplicitMixin) {
      +				return result;
      +			}
      +			Class rawClass = result.getRawClass();
      +			JacksonAnnotation jacksonAnnotation = AnnotationUtils.findAnnotation(rawClass, JacksonAnnotation.class);
      +			if (jacksonAnnotation != null) {
      +				return result;
      +			}
      +			throw new IllegalArgumentException("The class with " + id + " and name of " + className
      +					+ " is not trusted. "
      +					+ "If you believe this class is safe to deserialize, you can add it to the base set of trusted classes "
      +					+ "at construction time or provide an explicit mapping using Jackson annotations or a custom ObjectMapper. "
      +					+ "If the serialization is only done by a trusted source, you can also enable default typing.");
      +		}
      +
      +		private boolean isTrusted(String id) {
      +			return this.trustedClassNames.contains(id);
      +		}
      +
      +		@Override
      +		public String getDescForKnownTypeIds() {
      +			return delegate.getDescForKnownTypeIds();
      +		}
      +
      +		@Override
      +		public JsonTypeInfo.Id getMechanism() {
      +			return delegate.getMechanism();
      +		}
      +
      +	}
       
       }
      diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcExecutionContextDao.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcExecutionContextDao.java
      index 1cca50720..f9c05997a 100644
      --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcExecutionContextDao.java
      +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcExecutionContextDao.java
      @@ -47,8 +47,8 @@ import org.springframework.util.Assert;
       /**
        * JDBC DAO for {@link ExecutionContext}.
        *
      - * Stores execution context data related to both Step and Job using
      - * a different table for each.
      + * Stores execution context data related to both Step and Job using a different table for
      + * each.
        *
        * @author Lucas Ward
        * @author Robert Kasanicky
      @@ -89,7 +89,6 @@ public class JdbcExecutionContextDao extends AbstractJdbcBatchMetadataDao implem
       
       	/**
       	 * Setter for {@link Serializer} implementation
      -	 *
       	 * @param serializer {@link ExecutionContextSerializer} instance to use.
       	 */
       	public void setSerializer(ExecutionContextSerializer serializer) {
      @@ -98,13 +97,12 @@ public class JdbcExecutionContextDao extends AbstractJdbcBatchMetadataDao implem
       	}
       
       	/**
      -	 * The maximum size that an execution context can have and still be stored
      -	 * completely in short form in the column SHORT_CONTEXT.
      -	 * Anything longer than this will overflow into large-object storage, and
      -	 * the first part only will be retained in the short form for readability.
      -	 * Default value is 2500. Clients using multi-bytes charsets on the database
      -	 * server may need to reduce this value to as little as half the value of
      -	 * the column size.
      +	 * The maximum size that an execution context can have and still be stored completely
      +	 * in short form in the column SHORT_CONTEXT. Anything longer than this
      +	 * will overflow into large-object storage, and the first part only will be retained
      +	 * in the short form for readability. Default value is 2500. Clients using multi-bytes
      +	 * charsets on the database server may need to reduce this value to as little as half
      +	 * the value of the column size.
       	 * @param shortContextLength int max length of the short context.
       	 */
       	public void setShortContextLength(int shortContextLength) {
      @@ -112,8 +110,8 @@ public class JdbcExecutionContextDao extends AbstractJdbcBatchMetadataDao implem
       	}
       
       	/**
      -	 * Set the {@link Charset} to use when serializing/deserializing the execution context.
      -	 * Must not be {@code null}. Defaults to "UTF-8".
      +	 * Set the {@link Charset} to use when serializing/deserializing the execution
      +	 * context. Must not be {@code null}. Defaults to "UTF-8".
       	 * @param charset to use when serializing/deserializing the execution context.
       	 * @since 5.0
       	 */
      @@ -269,41 +267,43 @@ public class JdbcExecutionContextDao extends AbstractJdbcBatchMetadataDao implem
       	 * @param sql with parameters (shortContext, longContext, executionId)
       	 */
       	private void persistSerializedContexts(final Map serializedContexts, String sql) {
      -        if (!serializedContexts.isEmpty()) {
      -            final Iterator executionIdIterator = serializedContexts.keySet().iterator();
      +		if (!serializedContexts.isEmpty()) {
      +			final Iterator executionIdIterator = serializedContexts.keySet().iterator();
       
      -            getJdbcTemplate().batchUpdate(getQuery(sql), new BatchPreparedStatementSetter() {
      -                @Override
      -                public void setValues(PreparedStatement ps, int i) throws SQLException {
      -                    Long executionId = executionIdIterator.next();
      -                    String serializedContext = serializedContexts.get(executionId);
      -                    String shortContext;
      -                    String longContext;
      -                    if (serializedContext.length() > shortContextLength) {
      -                        // Overestimate length of ellipsis to be on the safe side with
      -                        // 2-byte chars
      -                        shortContext = serializedContext.substring(0, shortContextLength - 8) + " ...";
      -                        longContext = serializedContext;
      -                    } else {
      -                        shortContext = serializedContext;
      -                        longContext = null;
      -                    }
      -                    ps.setString(1, shortContext);
      -                    if (longContext != null) {
      -                        lobHandler.getLobCreator().setClobAsString(ps, 2, longContext);
      -                    } else {
      -                        ps.setNull(2, getClobTypeToUse());
      -                    }
      -                    ps.setLong(3, executionId);
      -                }
      +			getJdbcTemplate().batchUpdate(getQuery(sql), new BatchPreparedStatementSetter() {
      +				@Override
      +				public void setValues(PreparedStatement ps, int i) throws SQLException {
      +					Long executionId = executionIdIterator.next();
      +					String serializedContext = serializedContexts.get(executionId);
      +					String shortContext;
      +					String longContext;
      +					if (serializedContext.length() > shortContextLength) {
      +						// Overestimate length of ellipsis to be on the safe side with
      +						// 2-byte chars
      +						shortContext = serializedContext.substring(0, shortContextLength - 8) + " ...";
      +						longContext = serializedContext;
      +					}
      +					else {
      +						shortContext = serializedContext;
      +						longContext = null;
      +					}
      +					ps.setString(1, shortContext);
      +					if (longContext != null) {
      +						lobHandler.getLobCreator().setClobAsString(ps, 2, longContext);
      +					}
      +					else {
      +						ps.setNull(2, getClobTypeToUse());
      +					}
      +					ps.setLong(3, executionId);
      +				}
       
      -                @Override
      -                public int getBatchSize() {
      -                    return serializedContexts.size();
      -                }
      -            });
      -        }
      -    }
      +				@Override
      +				public int getBatchSize() {
      +					return serializedContexts.size();
      +				}
      +			});
      +		}
      +	}
       
       	private String serializeContext(ExecutionContext ctx) {
       		Map m = new HashMap<>();
      @@ -348,6 +348,7 @@ public class JdbcExecutionContextDao extends AbstractJdbcBatchMetadataDao implem
       			}
       			return executionContext;
       		}
      +
       	}
       
       }
      diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcJobExecutionDao.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcJobExecutionDao.java
      index 5cbb17b0d..3e04fbaea 100644
      --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcJobExecutionDao.java
      +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcJobExecutionDao.java
      @@ -47,12 +47,11 @@ import org.springframework.util.Assert;
       
       /**
        * JDBC implementation of {@link JobExecutionDao}. Uses sequences (via Spring's
      - * {@link DataFieldMaxValueIncrementer} abstraction) to create all primary keys
      - * before inserting a new row. Objects are checked to ensure all mandatory
      - * fields to be stored are not null. If any are found to be null, an
      - * IllegalArgumentException will be thrown. This could be left to JdbcTemplate,
      - * however, the exception will be fairly vague, and fails to highlight which
      - * field caused the exception.
      + * {@link DataFieldMaxValueIncrementer} abstraction) to create all primary keys before
      + * inserting a new row. Objects are checked to ensure all mandatory fields to be stored
      + * are not null. If any are found to be null, an IllegalArgumentException will be thrown.
      + * This could be left to JdbcTemplate, however, the exception will be fairly vague, and
      + * fails to highlight which field caused the exception.
        *
        * @author Lucas Ward
        * @author Dave Syer
      @@ -100,8 +99,8 @@ public class JdbcJobExecutionDao extends AbstractJdbcBatchMetadataDao implements
       	private DataFieldMaxValueIncrementer jobExecutionIncrementer;
       
       	/**
      -	 * Public setter for the exit message length in database. Do not set this if
      -	 * you haven't modified the schema.
      +	 * Public setter for the exit message length in database. Do not set this if you
      +	 * haven't modified the schema.
       	 * @param exitMessageLength the exitMessageLength to set
       	 */
       	public void setExitMessageLength(int exitMessageLength) {
      @@ -109,9 +108,8 @@ public class JdbcJobExecutionDao extends AbstractJdbcBatchMetadataDao implements
       	}
       
       	/**
      -	 * Setter for {@link DataFieldMaxValueIncrementer} to be used when
      -	 * generating primary keys for {@link JobExecution} instances.
      -	 *
      +	 * Setter for {@link DataFieldMaxValueIncrementer} to be used when generating primary
      +	 * keys for {@link JobExecution} instances.
       	 * @param jobExecutionIncrementer the {@link DataFieldMaxValueIncrementer}
       	 */
       	public void setJobExecutionIncrementer(DataFieldMaxValueIncrementer jobExecutionIncrementer) {
      @@ -135,13 +133,12 @@ public class JdbcJobExecutionDao extends AbstractJdbcBatchMetadataDao implements
       
       	/**
       	 *
      -	 * SQL implementation using Sequences via the Spring incrementer
      -	 * abstraction. Once a new id has been obtained, the JobExecution is saved
      -	 * via a SQL INSERT statement.
      +	 * SQL implementation using Sequences via the Spring incrementer abstraction. Once a
      +	 * new id has been obtained, the JobExecution is saved via a SQL INSERT statement.
       	 *
       	 * @see JobExecutionDao#saveJobExecution(JobExecution)
      -	 * @throws IllegalArgumentException if jobExecution is null, as well as any
      -	 * of it's fields to be persisted.
      +	 * @throws IllegalArgumentException if jobExecution is null, as well as any of it's
      +	 * fields to be persisted.
       	 */
       	@Override
       	public void saveJobExecution(JobExecution jobExecution) {
      @@ -151,22 +148,19 @@ public class JdbcJobExecutionDao extends AbstractJdbcBatchMetadataDao implements
       		jobExecution.incrementVersion();
       
       		jobExecution.setId(jobExecutionIncrementer.nextLongValue());
      -		Object[] parameters = new Object[] { jobExecution.getId(), jobExecution.getJobId(),
      -				jobExecution.getStartTime(), jobExecution.getEndTime(), jobExecution.getStatus().toString(),
      +		Object[] parameters = new Object[] { jobExecution.getId(), jobExecution.getJobId(), jobExecution.getStartTime(),
      +				jobExecution.getEndTime(), jobExecution.getStatus().toString(),
       				jobExecution.getExitStatus().getExitCode(), jobExecution.getExitStatus().getExitDescription(),
       				jobExecution.getVersion(), jobExecution.getCreateTime(), jobExecution.getLastUpdated() };
      -		getJdbcTemplate().update(
      -				getQuery(SAVE_JOB_EXECUTION),
      -				parameters,
      -				new int[] { Types.BIGINT, Types.BIGINT, Types.TIMESTAMP, Types.TIMESTAMP, Types.VARCHAR,
      -					Types.VARCHAR, Types.VARCHAR, Types.INTEGER, Types.TIMESTAMP, Types.TIMESTAMP });
      +		getJdbcTemplate().update(getQuery(SAVE_JOB_EXECUTION), parameters,
      +				new int[] { Types.BIGINT, Types.BIGINT, Types.TIMESTAMP, Types.TIMESTAMP, Types.VARCHAR, Types.VARCHAR,
      +						Types.VARCHAR, Types.INTEGER, Types.TIMESTAMP, Types.TIMESTAMP });
       
       		insertJobParameters(jobExecution.getId(), jobExecution.getJobParameters());
       	}
       
       	/**
       	 * Validate JobExecution. At a minimum, JobId, Status, CreateTime cannot be null.
      -	 *
       	 * @param jobExecution
       	 * @throws IllegalArgumentException
       	 */
      @@ -179,10 +173,9 @@ public class JdbcJobExecutionDao extends AbstractJdbcBatchMetadataDao implements
       	}
       
       	/**
      -	 * Update given JobExecution using a SQL UPDATE statement. The JobExecution
      -	 * is first checked to ensure all fields are not null, and that it has an
      -	 * ID. The database is then queried to ensure that the ID exists, which
      -	 * ensures that it is valid.
      +	 * Update given JobExecution using a SQL UPDATE statement. The JobExecution is first
      +	 * checked to ensure all fields are not null, and that it has an ID. The database is
      +	 * then queried to ensure that the ID exists, which ensures that it is valid.
       	 *
       	 * @see JobExecutionDao#updateJobExecution(JobExecution)
       	 */
      @@ -221,19 +214,17 @@ public class JdbcJobExecutionDao extends AbstractJdbcBatchMetadataDao implements
       				throw new NoSuchObjectException("Invalid JobExecution, ID " + jobExecution.getId() + " not found.");
       			}
       
      -			int count = getJdbcTemplate().update(
      -					getQuery(UPDATE_JOB_EXECUTION),
      -					parameters,
      +			int count = getJdbcTemplate().update(getQuery(UPDATE_JOB_EXECUTION), parameters,
       					new int[] { Types.TIMESTAMP, Types.TIMESTAMP, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
      -						Types.INTEGER, Types.TIMESTAMP, Types.TIMESTAMP, Types.BIGINT, Types.INTEGER });
      +							Types.INTEGER, Types.TIMESTAMP, Types.TIMESTAMP, Types.BIGINT, Types.INTEGER });
       
       			// Avoid concurrent modifications...
       			if (count == 0) {
      -				int currentVersion = getJdbcTemplate().queryForObject(getQuery(CURRENT_VERSION_JOB_EXECUTION), Integer.class,
      -						new Object[] { jobExecution.getId() });
      -				throw new OptimisticLockingFailureException("Attempt to update job execution id="
      -						+ jobExecution.getId() + " with wrong version (" + jobExecution.getVersion()
      -						+ "), where current version is " + currentVersion);
      +				int currentVersion = getJdbcTemplate().queryForObject(getQuery(CURRENT_VERSION_JOB_EXECUTION),
      +						Integer.class, new Object[] { jobExecution.getId() });
      +				throw new OptimisticLockingFailureException(
      +						"Attempt to update job execution id=" + jobExecution.getId() + " with wrong version ("
      +								+ jobExecution.getVersion() + "), where current version is " + currentVersion);
       			}
       
       			jobExecution.incrementVersion();
      @@ -313,45 +304,40 @@ public class JdbcJobExecutionDao extends AbstractJdbcBatchMetadataDao implements
       	}
       
       	/**
      -	 * Convenience method that inserts all parameters from the provided
      -	 * JobParameters.
      +	 * Convenience method that inserts all parameters from the provided JobParameters.
       	 *
       	 */
       	private void insertJobParameters(Long executionId, JobParameters jobParameters) {
       
      -		for (Entry entry : jobParameters.getParameters()
      -				.entrySet()) {
      +		for (Entry entry : jobParameters.getParameters().entrySet()) {
       			JobParameter jobParameter = entry.getValue();
      -			insertParameter(executionId, jobParameter.getType(), entry.getKey(),
      -					jobParameter.getValue(), jobParameter.isIdentifying());
      +			insertParameter(executionId, jobParameter.getType(), entry.getKey(), jobParameter.getValue(),
      +					jobParameter.isIdentifying());
       		}
       	}
       
       	/**
      -	 * Convenience method that inserts an individual records into the
      -	 * JobParameters table.
      +	 * Convenience method that inserts an individual records into the JobParameters table.
       	 */
      -	private void insertParameter(Long executionId, ParameterType type, String key,
      -			Object value, boolean identifying) {
      +	private void insertParameter(Long executionId, ParameterType type, String key, Object value, boolean identifying) {
       
       		Object[] args = new Object[0];
      -		int[] argTypes = new int[] { Types.BIGINT, Types.VARCHAR,
      -				Types.VARCHAR, Types.VARCHAR, Types.TIMESTAMP, Types.BIGINT,
      -				Types.DOUBLE, Types.CHAR };
      +		int[] argTypes = new int[] { Types.BIGINT, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.TIMESTAMP,
      +				Types.BIGINT, Types.DOUBLE, Types.CHAR };
       
      -		String identifyingFlag = identifying? "Y":"N";
      +		String identifyingFlag = identifying ? "Y" : "N";
       
       		if (type == ParameterType.STRING) {
      -			args = new Object[] { executionId, key, type, value, null,
      -					0L, 0D, identifyingFlag};
      -		} else if (type == ParameterType.LONG) {
      -			args = new Object[] { executionId, key, type, "", null,
      -					value, 0.0d, identifyingFlag};
      -		} else if (type == ParameterType.DOUBLE) {
      -			args = new Object[] { executionId, key, type, "", null, 0L,
      -					value, identifyingFlag};
      -		} else if (type == ParameterType.DATE) {
      -			args = new Object[] { executionId, key, type, "", value, 0L, 0D, identifyingFlag};
      +			args = new Object[] { executionId, key, type, value, null, 0L, 0D, identifyingFlag };
      +		}
      +		else if (type == ParameterType.LONG) {
      +			args = new Object[] { executionId, key, type, "", null, value, 0.0d, identifyingFlag };
      +		}
      +		else if (type == ParameterType.DOUBLE) {
      +			args = new Object[] { executionId, key, type, "", null, 0L, value, identifyingFlag };
      +		}
      +		else if (type == ParameterType.DATE) {
      +			args = new Object[] { executionId, key, type, "", value, 0L, 0D, identifyingFlag };
       		}
       
       		getJdbcTemplate().update(getQuery(CREATE_JOB_PARAMETERS), args, argTypes);
      @@ -371,11 +357,14 @@ public class JdbcJobExecutionDao extends AbstractJdbcBatchMetadataDao implements
       
       				if (type == ParameterType.STRING) {
       					value = new JobParameter(rs.getString(4), rs.getString(8).equalsIgnoreCase("Y"));
      -				} else if (type == ParameterType.LONG) {
      +				}
      +				else if (type == ParameterType.LONG) {
       					value = new JobParameter(rs.getLong(6), rs.getString(8).equalsIgnoreCase("Y"));
      -				} else if (type == ParameterType.DOUBLE) {
      +				}
      +				else if (type == ParameterType.DOUBLE) {
       					value = new JobParameter(rs.getDouble(7), rs.getString(8).equalsIgnoreCase("Y"));
      -				} else if (type == ParameterType.DATE) {
      +				}
      +				else if (type == ParameterType.DATE) {
       					value = new JobParameter(rs.getTimestamp(5), rs.getString(8).equalsIgnoreCase("Y"));
       				}
       
      @@ -434,4 +423,5 @@ public class JdbcJobExecutionDao extends AbstractJdbcBatchMetadataDao implements
       		}
       
       	}
      +
       }
      diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcJobInstanceDao.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcJobInstanceDao.java
      index 426119743..f0307c7a8 100644
      --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcJobInstanceDao.java
      +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcJobInstanceDao.java
      @@ -40,12 +40,11 @@ import org.springframework.util.StringUtils;
       
       /**
        * JDBC implementation of {@link JobInstanceDao}. Uses sequences (via Spring's
      - * {@link DataFieldMaxValueIncrementer} abstraction) to create all primary keys
      - * before inserting a new row. Objects are checked to ensure all mandatory
      - * fields to be stored are not null. If any are found to be null, an
      - * IllegalArgumentException will be thrown. This could be left to JdbcTemplate,
      - * however, the exception will be fairly vague, and fails to highlight which
      - * field caused the exception.
      + * {@link DataFieldMaxValueIncrementer} abstraction) to create all primary keys before
      + * inserting a new row. Objects are checked to ensure all mandatory fields to be stored
      + * are not null. If any are found to be null, an IllegalArgumentException will be thrown.
      + * This could be left to JdbcTemplate, however, the exception will be fairly vague, and
      + * fails to highlight which field caused the exception.
        *
        * @author Lucas Ward
        * @author Dave Syer
      @@ -55,20 +54,18 @@ import org.springframework.util.StringUtils;
        * @author Mahmoud Ben Hassine
        * @author Parikshit Dutta
        */
      -public class JdbcJobInstanceDao extends AbstractJdbcBatchMetadataDao implements
      -JobInstanceDao, InitializingBean {
      +public class JdbcJobInstanceDao extends AbstractJdbcBatchMetadataDao implements JobInstanceDao, InitializingBean {
       
       	private static final String STAR_WILDCARD = "*";
      -	
      +
       	private static final String SQL_WILDCARD = "%";
      -	
      +
       	private static final String CREATE_JOB_INSTANCE = "INSERT into %PREFIX%JOB_INSTANCE(JOB_INSTANCE_ID, JOB_NAME, JOB_KEY, VERSION)"
       			+ " values (?, ?, ?, ?)";
       
       	private static final String FIND_JOBS_WITH_NAME = "SELECT JOB_INSTANCE_ID, JOB_NAME from %PREFIX%JOB_INSTANCE where JOB_NAME = ?";
       
      -	private static final String FIND_JOBS_WITH_KEY = FIND_JOBS_WITH_NAME
      -			+ " and JOB_KEY = ?";
      +	private static final String FIND_JOBS_WITH_KEY = FIND_JOBS_WITH_NAME + " and JOB_KEY = ?";
       
       	private static final String COUNT_JOBS_WITH_NAME = "SELECT COUNT(*) from %PREFIX%JOB_INSTANCE where JOB_NAME = ?";
       
      @@ -83,8 +80,8 @@ JobInstanceDao, InitializingBean {
       
       	private static final String FIND_LAST_JOBS_BY_NAME = "SELECT JOB_INSTANCE_ID, JOB_NAME from %PREFIX%JOB_INSTANCE where JOB_NAME = ? order by JOB_INSTANCE_ID desc";
       
      -	private static final String FIND_LAST_JOB_INSTANCE_BY_JOB_NAME = "SELECT JOB_INSTANCE_ID, JOB_NAME from %PREFIX%JOB_INSTANCE I1 where" +
      -			" I1.JOB_NAME = ? and I1.JOB_INSTANCE_ID in (SELECT max(I2.JOB_INSTANCE_ID) from %PREFIX%JOB_INSTANCE I2 where I2.JOB_NAME = ?)";
      +	private static final String FIND_LAST_JOB_INSTANCE_BY_JOB_NAME = "SELECT JOB_INSTANCE_ID, JOB_NAME from %PREFIX%JOB_INSTANCE I1 where"
      +			+ " I1.JOB_NAME = ? and I1.JOB_INSTANCE_ID in (SELECT max(I2.JOB_INSTANCE_ID) from %PREFIX%JOB_INSTANCE I2 where I2.JOB_NAME = ?)";
       
       	private static final String FIND_LAST_JOBS_LIKE_NAME = "SELECT JOB_INSTANCE_ID, JOB_NAME from %PREFIX%JOB_INSTANCE where JOB_NAME like ? order by JOB_INSTANCE_ID desc";
       
      @@ -98,47 +95,39 @@ JobInstanceDao, InitializingBean {
       	 * then passing the Id and parameter values into an INSERT statement.
       	 *
       	 * @see JobInstanceDao#createJobInstance(String, JobParameters)
      -	 * @throws IllegalArgumentException
      -	 *             if any {@link JobParameters} fields are null.
      +	 * @throws IllegalArgumentException if any {@link JobParameters} fields are null.
       	 */
       	@Override
      -	public JobInstance createJobInstance(String jobName,
      -			JobParameters jobParameters) {
      +	public JobInstance createJobInstance(String jobName, JobParameters jobParameters) {
       
       		Assert.notNull(jobName, "Job name must not be null.");
       		Assert.notNull(jobParameters, "JobParameters must not be null.");
       
      -		Assert.state(getJobInstance(jobName, jobParameters) == null,
      -				"JobInstance must not already exist");
      +		Assert.state(getJobInstance(jobName, jobParameters) == null, "JobInstance must not already exist");
       
       		Long jobInstanceId = jobInstanceIncrementer.nextLongValue();
       
       		JobInstance jobInstance = new JobInstance(jobInstanceId, jobName);
       		jobInstance.incrementVersion();
       
      -		Object[] parameters = new Object[] { jobInstanceId, jobName,
      -				jobKeyGenerator.generateKey(jobParameters), jobInstance.getVersion() };
      -		getJdbcTemplate().update(
      -				getQuery(CREATE_JOB_INSTANCE),
      -				parameters,
      -				new int[] { Types.BIGINT, Types.VARCHAR, Types.VARCHAR,
      -					Types.INTEGER });
      +		Object[] parameters = new Object[] { jobInstanceId, jobName, jobKeyGenerator.generateKey(jobParameters),
      +				jobInstance.getVersion() };
      +		getJdbcTemplate().update(getQuery(CREATE_JOB_INSTANCE), parameters,
      +				new int[] { Types.BIGINT, Types.VARCHAR, Types.VARCHAR, Types.INTEGER });
       
       		return jobInstance;
       	}
       
       	/**
      -	 * The job table is queried for any jobs that match the
      -	 * given identifier, adding them to a list via the RowMapper callback.
      +	 * The job table is queried for any jobs that match the given
      +	 * identifier, adding them to a list via the RowMapper callback.
       	 *
       	 * @see JobInstanceDao#getJobInstance(String, JobParameters)
      -	 * @throws IllegalArgumentException
      -	 *             if any {@link JobParameters} fields are null.
      +	 * @throws IllegalArgumentException if any {@link JobParameters} fields are null.
       	 */
       	@Override
       	@Nullable
      -	public JobInstance getJobInstance(final String jobName,
      -			final JobParameters jobParameters) {
      +	public JobInstance getJobInstance(final String jobName, final JobParameters jobParameters) {
       
       		Assert.notNull(jobName, "Job name must not be null.");
       		Assert.notNull(jobParameters, "JobParameters must not be null.");
      @@ -149,17 +138,16 @@ JobInstanceDao, InitializingBean {
       
       		List instances;
       		if (StringUtils.hasLength(jobKey)) {
      -			instances = getJdbcTemplate().query(getQuery(FIND_JOBS_WITH_KEY),
      -					rowMapper, jobName, jobKey);
      -		} else {
      -			instances = getJdbcTemplate().query(
      -					getQuery(FIND_JOBS_WITH_EMPTY_KEY), rowMapper, jobName,
      -					jobKey);
      +			instances = getJdbcTemplate().query(getQuery(FIND_JOBS_WITH_KEY), rowMapper, jobName, jobKey);
      +		}
      +		else {
      +			instances = getJdbcTemplate().query(getQuery(FIND_JOBS_WITH_EMPTY_KEY), rowMapper, jobName, jobKey);
       		}
       
       		if (instances.isEmpty()) {
       			return null;
      -		} else {
      +		}
      +		else {
       			Assert.state(instances.size() == 1, "instance count must be 1 but was " + instances.size());
       			return instances.get(0);
       		}
      @@ -168,8 +156,7 @@ JobInstanceDao, InitializingBean {
       	/*
       	 * (non-Javadoc)
       	 *
      -	 * @see
      -	 * org.springframework.batch.core.repository.dao.JobInstanceDao#getJobInstance
      +	 * @see org.springframework.batch.core.repository.dao.JobInstanceDao#getJobInstance
       	 * (java.lang.Long)
       	 */
       	@Override
      @@ -177,9 +164,9 @@ JobInstanceDao, InitializingBean {
       	public JobInstance getJobInstance(@Nullable Long instanceId) {
       
       		try {
      -			return getJdbcTemplate().queryForObject(getQuery(GET_JOB_FROM_ID),
      -					new JobInstanceRowMapper(), instanceId);
      -		} catch (EmptyResultDataAccessException e) {
      +			return getJdbcTemplate().queryForObject(getQuery(GET_JOB_FROM_ID), new JobInstanceRowMapper(), instanceId);
      +		}
      +		catch (EmptyResultDataAccessException e) {
       			return null;
       		}
       
      @@ -188,17 +175,13 @@ JobInstanceDao, InitializingBean {
       	/*
       	 * (non-Javadoc)
       	 *
      -	 * @see
      -	 * org.springframework.batch.core.repository.dao.JobInstanceDao#getJobNames
      -	 * ()
      +	 * @see org.springframework.batch.core.repository.dao.JobInstanceDao#getJobNames ()
       	 */
       	@Override
       	public List getJobNames() {
      -		return getJdbcTemplate().query(getQuery(FIND_JOB_NAMES),
      -				new RowMapper() {
      +		return getJdbcTemplate().query(getQuery(FIND_JOB_NAMES), new RowMapper() {
       			@Override
      -			public String mapRow(ResultSet rs, int rowNum)
      -					throws SQLException {
      +			public String mapRow(ResultSet rs, int rowNum) throws SQLException {
       				return rs.getString(1);
       			}
       		});
      @@ -211,16 +194,14 @@ JobInstanceDao, InitializingBean {
       	 * getLastJobInstances(java.lang.String, int)
       	 */
       	@Override
      -	public List getJobInstances(String jobName, final int start,
      -			final int count) {
      +	public List getJobInstances(String jobName, final int start, final int count) {
       
       		ResultSetExtractor> extractor = new ResultSetExtractor>() {
       
       			private List list = new ArrayList<>();
       
       			@Override
      -			public List extractData(ResultSet rs) throws SQLException,
      -			DataAccessException {
      +			public List extractData(ResultSet rs) throws SQLException, DataAccessException {
       				int rowNum = 0;
       				while (rowNum < start && rs.next()) {
       					rowNum++;
      @@ -235,8 +216,7 @@ JobInstanceDao, InitializingBean {
       
       		};
       
      -		List result = getJdbcTemplate().query(getQuery(FIND_LAST_JOBS_BY_NAME),
      -				extractor, jobName);
      +		List result = getJdbcTemplate().query(getQuery(FIND_LAST_JOBS_BY_NAME), extractor, jobName);
       
       		return result;
       	}
      @@ -251,11 +231,29 @@ JobInstanceDao, InitializingBean {
       	@Nullable
       	public JobInstance getLastJobInstance(String jobName) {
       		try {
      -			return getJdbcTemplate().queryForObject(
      -					getQuery(FIND_LAST_JOB_INSTANCE_BY_JOB_NAME),
      -					new JobInstanceRowMapper(),
      -					jobName, jobName);
      -		} catch (EmptyResultDataAccessException e) {
      +			return getJdbcTemplate().queryForObject(getQuery(FIND_LAST_JOB_INSTANCE_BY_JOB_NAME),
      +					new JobInstanceRowMapper(), jobName, jobName);
      +		}
      +		catch (EmptyResultDataAccessException e) {
      +			return null;
      +		}
      +	}
      +
      +	/*
      +	 * (non-Javadoc)
      +	 *
      +	 * @see org.springframework.batch.core.repository.dao.JobInstanceDao#getJobInstance
      +	 * (org.springframework.batch.core.JobExecution)
      +	 */
      +	@Override
      +	@Nullable
      +	public JobInstance getJobInstance(JobExecution jobExecution) {
      +
      +		try {
      +			return getJdbcTemplate().queryForObject(getQuery(GET_JOB_FROM_EXECUTION_ID), new JobInstanceRowMapper(),
      +					jobExecution.getId());
      +		}
      +		catch (EmptyResultDataAccessException e) {
       			return null;
       		}
       	}
      @@ -264,45 +262,24 @@ JobInstanceDao, InitializingBean {
       	 * (non-Javadoc)
       	 *
       	 * @see
      -	 * org.springframework.batch.core.repository.dao.JobInstanceDao#getJobInstance
      -	 * (org.springframework.batch.core.JobExecution)
      -	 */
      -	@Override
      -	@Nullable
      -	public JobInstance getJobInstance(JobExecution jobExecution) {
      -
      -		try {
      -			return getJdbcTemplate().queryForObject(
      -					getQuery(GET_JOB_FROM_EXECUTION_ID),
      -					new JobInstanceRowMapper(), jobExecution.getId());
      -		} catch (EmptyResultDataAccessException e) {
      -			return null;
      -		}
      -	}
      -
      -	/* (non-Javadoc)
      -	 * @see org.springframework.batch.core.repository.dao.JobInstanceDao#getJobInstanceCount(java.lang.String)
      +	 * org.springframework.batch.core.repository.dao.JobInstanceDao#getJobInstanceCount(
      +	 * java.lang.String)
       	 */
       	@Override
       	public int getJobInstanceCount(@Nullable String jobName) throws NoSuchJobException {
       
       		try {
      -			return getJdbcTemplate().queryForObject(
      -					getQuery(COUNT_JOBS_WITH_NAME),
      -					Integer.class,
      -					jobName);
      -		} catch (EmptyResultDataAccessException e) {
      +			return getJdbcTemplate().queryForObject(getQuery(COUNT_JOBS_WITH_NAME), Integer.class, jobName);
      +		}
      +		catch (EmptyResultDataAccessException e) {
       			throw new NoSuchJobException("No job instances were found for job name " + jobName);
       		}
       	}
       
       	/**
      -	 * Setter for {@link DataFieldMaxValueIncrementer} to be used when
      -	 * generating primary keys for {@link JobInstance} instances.
      -	 *
      -	 * @param jobIncrementer
      -	 *            the {@link DataFieldMaxValueIncrementer}
      -	 *
      +	 * Setter for {@link DataFieldMaxValueIncrementer} to be used when generating primary
      +	 * keys for {@link JobInstance} instances.
      +	 * @param jobIncrementer the {@link DataFieldMaxValueIncrementer}
       	 * @deprecated as of v5.0 in favor of using the {@link setJobInstanceIncrementer}
       	 */
       	@Deprecated
      @@ -311,9 +288,8 @@ JobInstanceDao, InitializingBean {
       	}
       
       	/**
      -	 * Setter for {@link DataFieldMaxValueIncrementer} to be used when
      -	 * generating primary keys for {@link JobInstance} instances.
      -	 *
      +	 * Setter for {@link DataFieldMaxValueIncrementer} to be used when generating primary
      +	 * keys for {@link JobInstance} instances.
       	 * @param jobInstanceIncrementer the {@link DataFieldMaxValueIncrementer}
       	 *
       	 * @since 5.0
      @@ -344,6 +320,7 @@ JobInstanceDao, InitializingBean {
       			jobInstance.incrementVersion();
       			return jobInstance;
       		}
      +
       	}
       
       	@Override
      @@ -353,8 +330,7 @@ JobInstanceDao, InitializingBean {
       			private List list = new ArrayList<>();
       
       			@Override
      -			public Object extractData(ResultSet rs) throws SQLException,
      -			DataAccessException {
      +			public Object extractData(ResultSet rs) throws SQLException, DataAccessException {
       				int rowNum = 0;
       				while (rowNum < start && rs.next()) {
       					rowNum++;
      @@ -371,11 +347,12 @@ JobInstanceDao, InitializingBean {
       		if (jobName.contains(STAR_WILDCARD)) {
       			jobName = jobName.replaceAll("\\" + STAR_WILDCARD, SQL_WILDCARD);
       		}
      -		
      +
       		@SuppressWarnings("unchecked")
       		List result = (List) getJdbcTemplate().query(getQuery(FIND_LAST_JOBS_LIKE_NAME),
       				extractor, jobName);
       
       		return result;
       	}
      +
       }
      diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcStepExecutionDao.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcStepExecutionDao.java
      index a4aee020c..edf8d3b57 100644
      --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcStepExecutionDao.java
      +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcStepExecutionDao.java
      @@ -46,15 +46,15 @@ import org.springframework.util.Assert;
       /**
        * JDBC implementation of {@link StepExecutionDao}.
      * - * Allows customization of the tables names used by Spring Batch for step meta - * data via a prefix property.
      + * Allows customization of the tables names used by Spring Batch for step meta data via a + * prefix property.
      * * Uses sequences or tables (via Spring's {@link DataFieldMaxValueIncrementer} - * abstraction) to create all primary keys before inserting a new row. All - * objects are checked to ensure all fields to be stored are not null. If any - * are found to be null, an IllegalArgumentException will be thrown. This could - * be left to JdbcTemplate, however, the exception will be fairly vague, and - * fails to highlight which field caused the exception.
      + * abstraction) to create all primary keys before inserting a new row. All objects are + * checked to ensure all fields to be stored are not null. If any are found to be null, an + * IllegalArgumentException will be thrown. This could be left to JdbcTemplate, however, + * the exception will be fairly vague, and fails to highlight which field caused the + * exception.
      * * @author Lucas Ward * @author Dave Syer @@ -62,61 +62,56 @@ import org.springframework.util.Assert; * @author David Turanski * @author Mahmoud Ben Hassine * @author Baris Cubukcuoglu - * * @see StepExecutionDao */ public class JdbcStepExecutionDao extends AbstractJdbcBatchMetadataDao implements StepExecutionDao, InitializingBean { private static final Log logger = LogFactory.getLog(JdbcStepExecutionDao.class); - private static final String SAVE_STEP_EXECUTION = "INSERT into %PREFIX%STEP_EXECUTION(STEP_EXECUTION_ID, VERSION, " + - "STEP_NAME, JOB_EXECUTION_ID, START_TIME, END_TIME, STATUS, COMMIT_COUNT, READ_COUNT, FILTER_COUNT, " + - "WRITE_COUNT, EXIT_CODE, EXIT_MESSAGE, READ_SKIP_COUNT, WRITE_SKIP_COUNT, PROCESS_SKIP_COUNT, " + - "ROLLBACK_COUNT, LAST_UPDATED, CREATE_TIME) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + private static final String SAVE_STEP_EXECUTION = "INSERT into %PREFIX%STEP_EXECUTION(STEP_EXECUTION_ID, VERSION, " + + "STEP_NAME, JOB_EXECUTION_ID, START_TIME, END_TIME, STATUS, COMMIT_COUNT, READ_COUNT, FILTER_COUNT, " + + "WRITE_COUNT, EXIT_CODE, EXIT_MESSAGE, READ_SKIP_COUNT, WRITE_SKIP_COUNT, PROCESS_SKIP_COUNT, " + + "ROLLBACK_COUNT, LAST_UPDATED, CREATE_TIME) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; private static final String UPDATE_STEP_EXECUTION = "UPDATE %PREFIX%STEP_EXECUTION set START_TIME = ?, END_TIME = ?, " + "STATUS = ?, COMMIT_COUNT = ?, READ_COUNT = ?, FILTER_COUNT = ?, WRITE_COUNT = ?, EXIT_CODE = ?, " + "EXIT_MESSAGE = ?, VERSION = ?, READ_SKIP_COUNT = ?, PROCESS_SKIP_COUNT = ?, WRITE_SKIP_COUNT = ?, " - + "ROLLBACK_COUNT = ?, LAST_UPDATED = ?" - + " where STEP_EXECUTION_ID = ? and VERSION = ?"; + + "ROLLBACK_COUNT = ?, LAST_UPDATED = ?" + " where STEP_EXECUTION_ID = ? and VERSION = ?"; - private static final String GET_RAW_STEP_EXECUTIONS = "SELECT STEP_EXECUTION_ID, STEP_NAME, START_TIME, END_TIME, " + - "STATUS, COMMIT_COUNT, READ_COUNT, FILTER_COUNT, WRITE_COUNT, EXIT_CODE, EXIT_MESSAGE, READ_SKIP_COUNT, " + - "WRITE_SKIP_COUNT, PROCESS_SKIP_COUNT, ROLLBACK_COUNT, LAST_UPDATED, VERSION, CREATE_TIME from " + - "%PREFIX%STEP_EXECUTION where JOB_EXECUTION_ID = ?"; + private static final String GET_RAW_STEP_EXECUTIONS = "SELECT STEP_EXECUTION_ID, STEP_NAME, START_TIME, END_TIME, " + + "STATUS, COMMIT_COUNT, READ_COUNT, FILTER_COUNT, WRITE_COUNT, EXIT_CODE, EXIT_MESSAGE, READ_SKIP_COUNT, " + + "WRITE_SKIP_COUNT, PROCESS_SKIP_COUNT, ROLLBACK_COUNT, LAST_UPDATED, VERSION, CREATE_TIME from " + + "%PREFIX%STEP_EXECUTION where JOB_EXECUTION_ID = ?"; private static final String GET_STEP_EXECUTIONS = GET_RAW_STEP_EXECUTIONS + " order by STEP_EXECUTION_ID"; private static final String GET_STEP_EXECUTION = GET_RAW_STEP_EXECUTIONS + " and STEP_EXECUTION_ID = ?"; - private static final String GET_LAST_STEP_EXECUTION = "SELECT " + - " SE.STEP_EXECUTION_ID, SE.STEP_NAME, SE.START_TIME, SE.END_TIME, SE.STATUS, SE.COMMIT_COUNT, " + - "SE.READ_COUNT, SE.FILTER_COUNT, SE.WRITE_COUNT, SE.EXIT_CODE, SE.EXIT_MESSAGE, SE.READ_SKIP_COUNT, " + - "SE.WRITE_SKIP_COUNT, SE.PROCESS_SKIP_COUNT, SE.ROLLBACK_COUNT, SE.LAST_UPDATED, SE.VERSION, SE.CREATE_TIME," + - " JE.JOB_EXECUTION_ID, JE.START_TIME, JE.END_TIME, JE.STATUS, JE.EXIT_CODE, JE.EXIT_MESSAGE, " + - "JE.CREATE_TIME, JE.LAST_UPDATED, JE.VERSION" + - " from %PREFIX%JOB_EXECUTION JE join %PREFIX%STEP_EXECUTION SE" + - " on SE.JOB_EXECUTION_ID = JE.JOB_EXECUTION_ID " + - "where JE.JOB_INSTANCE_ID = ?" + - " and SE.STEP_NAME = ?" + - " order by SE.CREATE_TIME desc, SE.STEP_EXECUTION_ID desc"; + private static final String GET_LAST_STEP_EXECUTION = "SELECT " + + " SE.STEP_EXECUTION_ID, SE.STEP_NAME, SE.START_TIME, SE.END_TIME, SE.STATUS, SE.COMMIT_COUNT, " + + "SE.READ_COUNT, SE.FILTER_COUNT, SE.WRITE_COUNT, SE.EXIT_CODE, SE.EXIT_MESSAGE, SE.READ_SKIP_COUNT, " + + "SE.WRITE_SKIP_COUNT, SE.PROCESS_SKIP_COUNT, SE.ROLLBACK_COUNT, SE.LAST_UPDATED, SE.VERSION, SE.CREATE_TIME," + + " JE.JOB_EXECUTION_ID, JE.START_TIME, JE.END_TIME, JE.STATUS, JE.EXIT_CODE, JE.EXIT_MESSAGE, " + + "JE.CREATE_TIME, JE.LAST_UPDATED, JE.VERSION" + + " from %PREFIX%JOB_EXECUTION JE join %PREFIX%STEP_EXECUTION SE" + + " on SE.JOB_EXECUTION_ID = JE.JOB_EXECUTION_ID " + "where JE.JOB_INSTANCE_ID = ?" + + " and SE.STEP_NAME = ?" + " order by SE.CREATE_TIME desc, SE.STEP_EXECUTION_ID desc"; - private static final String CURRENT_VERSION_STEP_EXECUTION = "SELECT VERSION FROM %PREFIX%STEP_EXECUTION WHERE " + - "STEP_EXECUTION_ID=?"; + private static final String CURRENT_VERSION_STEP_EXECUTION = "SELECT VERSION FROM %PREFIX%STEP_EXECUTION WHERE " + + "STEP_EXECUTION_ID=?"; - private static final String COUNT_STEP_EXECUTIONS = "SELECT COUNT(*) " + - " from %PREFIX%JOB_EXECUTION JE JOIN %PREFIX%STEP_EXECUTION SE " + - " on SE.JOB_EXECUTION_ID = JE.JOB_EXECUTION_ID " + - "where JE.JOB_INSTANCE_ID = ?" + - " and SE.STEP_NAME = ?"; + private static final String COUNT_STEP_EXECUTIONS = "SELECT COUNT(*) " + + " from %PREFIX%JOB_EXECUTION JE JOIN %PREFIX%STEP_EXECUTION SE " + + " on SE.JOB_EXECUTION_ID = JE.JOB_EXECUTION_ID " + "where JE.JOB_INSTANCE_ID = ?" + + " and SE.STEP_NAME = ?"; private int exitMessageLength = DEFAULT_EXIT_MESSAGE_LENGTH; private DataFieldMaxValueIncrementer stepExecutionIncrementer; /** - * Public setter for the exit message length in database. Do not set this if - * you haven't modified the schema. + * Public setter for the exit message length in database. Do not set this if you + * haven't modified the schema. * @param exitMessageLength the exitMessageLength to set */ public void setExitMessageLength(int exitMessageLength) { @@ -135,8 +130,8 @@ public class JdbcStepExecutionDao extends AbstractJdbcBatchMetadataDao implement /** * Save a StepExecution. A unique id will be generated by the - * stepExecutionIncrementer, and then set in the StepExecution. All values - * will then be stored via an INSERT statement. + * stepExecutionIncrementer, and then set in the StepExecution. All values will then + * be stored via an INSERT statement. * * @see StepExecutionDao#saveStepExecution(StepExecution) */ @@ -145,10 +140,10 @@ public class JdbcStepExecutionDao extends AbstractJdbcBatchMetadataDao implement List parameters = buildStepExecutionParameters(stepExecution); Object[] parameterValues = parameters.get(0); - //Template expects an int array fails with Integer + // Template expects an int array fails with Integer int[] parameterTypes = new int[parameters.get(1).length]; for (int i = 0; i < parameterTypes.length; i++) { - parameterTypes[i] = (Integer)parameters.get(1)[i]; + parameterTypes[i] = (Integer) parameters.get(1)[i]; } getJdbcTemplate().update(getQuery(SAVE_STEP_EXECUTION), parameterValues, parameterTypes); @@ -162,48 +157,50 @@ public class JdbcStepExecutionDao extends AbstractJdbcBatchMetadataDao implement public void saveStepExecutions(final Collection stepExecutions) { Assert.notNull(stepExecutions, "Attempt to save a null collection of step executions"); - if (!stepExecutions.isEmpty()) { - final Iterator iterator = stepExecutions.iterator(); - getJdbcTemplate().batchUpdate(getQuery(SAVE_STEP_EXECUTION), new BatchPreparedStatementSetter() { + if (!stepExecutions.isEmpty()) { + final Iterator iterator = stepExecutions.iterator(); + getJdbcTemplate().batchUpdate(getQuery(SAVE_STEP_EXECUTION), new BatchPreparedStatementSetter() { - @Override - public int getBatchSize() { - return stepExecutions.size(); - } + @Override + public int getBatchSize() { + return stepExecutions.size(); + } - @Override - public void setValues(PreparedStatement ps, int i) throws SQLException { - StepExecution stepExecution = iterator.next(); - List parameters = buildStepExecutionParameters(stepExecution); - Object[] parameterValues = parameters.get(0); - Integer[] parameterTypes = (Integer[]) parameters.get(1); - for (int indx = 0; indx < parameterValues.length; indx++) { - switch (parameterTypes[indx]) { - case Types.INTEGER: - ps.setInt(indx + 1, (Integer) parameterValues[indx]); - break; - case Types.VARCHAR: - ps.setString(indx + 1, (String) parameterValues[indx]); - break; - case Types.TIMESTAMP: - if (parameterValues[indx] != null) { - ps.setTimestamp(indx + 1, new Timestamp(((java.util.Date) parameterValues[indx]).getTime())); - } else { - ps.setNull(indx + 1, Types.TIMESTAMP); - } - break; - case Types.BIGINT: - ps.setLong(indx + 1, (Long) parameterValues[indx]); - break; - default: - throw new IllegalArgumentException( - "unsupported SQL parameter type for step execution field index " + i); - } - } - } - }); - } - } + @Override + public void setValues(PreparedStatement ps, int i) throws SQLException { + StepExecution stepExecution = iterator.next(); + List parameters = buildStepExecutionParameters(stepExecution); + Object[] parameterValues = parameters.get(0); + Integer[] parameterTypes = (Integer[]) parameters.get(1); + for (int indx = 0; indx < parameterValues.length; indx++) { + switch (parameterTypes[indx]) { + case Types.INTEGER: + ps.setInt(indx + 1, (Integer) parameterValues[indx]); + break; + case Types.VARCHAR: + ps.setString(indx + 1, (String) parameterValues[indx]); + break; + case Types.TIMESTAMP: + if (parameterValues[indx] != null) { + ps.setTimestamp(indx + 1, + new Timestamp(((java.util.Date) parameterValues[indx]).getTime())); + } + else { + ps.setNull(indx + 1, Types.TIMESTAMP); + } + break; + case Types.BIGINT: + ps.setLong(indx + 1, (Long) parameterValues[indx]); + break; + default: + throw new IllegalArgumentException( + "unsupported SQL parameter type for step execution field index " + i); + } + } + } + }); + } + } private List buildStepExecutionParameters(StepExecution stepExecution) { Assert.isNull(stepExecution.getId(), @@ -212,7 +209,7 @@ public class JdbcStepExecutionDao extends AbstractJdbcBatchMetadataDao implement "to-be-saved (not updated) StepExecution can't already have a version assigned"); validateStepExecution(stepExecution); stepExecution.setId(stepExecutionIncrementer.nextLongValue()); - stepExecution.incrementVersion(); //Should be 0 + stepExecution.incrementVersion(); // Should be 0 List parameters = new ArrayList<>(); String exitDescription = truncateExitDescription(stepExecution.getExitStatus().getExitDescription()); Object[] parameterValues = new Object[] { stepExecution.getId(), stepExecution.getVersion(), @@ -223,18 +220,17 @@ public class JdbcStepExecutionDao extends AbstractJdbcBatchMetadataDao implement stepExecution.getWriteSkipCount(), stepExecution.getProcessSkipCount(), stepExecution.getRollbackCount(), stepExecution.getLastUpdated(), stepExecution.getCreateTime() }; Integer[] parameterTypes = new Integer[] { Types.BIGINT, Types.INTEGER, Types.VARCHAR, Types.BIGINT, - Types.TIMESTAMP, Types.TIMESTAMP, Types.VARCHAR, Types.BIGINT, Types.BIGINT, Types.BIGINT, - Types.BIGINT, Types.VARCHAR, Types.VARCHAR, Types.BIGINT, Types.BIGINT, Types.BIGINT, - Types.BIGINT, Types.TIMESTAMP, Types.TIMESTAMP }; - parameters.add(0, Arrays.copyOf(parameterValues,parameterValues.length)); - parameters.add(1, Arrays.copyOf(parameterTypes,parameterTypes.length)); + Types.TIMESTAMP, Types.TIMESTAMP, Types.VARCHAR, Types.BIGINT, Types.BIGINT, Types.BIGINT, Types.BIGINT, + Types.VARCHAR, Types.VARCHAR, Types.BIGINT, Types.BIGINT, Types.BIGINT, Types.BIGINT, Types.TIMESTAMP, + Types.TIMESTAMP }; + parameters.add(0, Arrays.copyOf(parameterValues, parameterValues.length)); + parameters.add(1, Arrays.copyOf(parameterTypes, parameterTypes.length)); return parameters; } /** - * Validate StepExecution. At a minimum, JobId, CreateTime, and Status cannot - * be null. EndTime can be null for an unfinished job. - * + * Validate StepExecution. At a minimum, JobId, CreateTime, and Status cannot be null. + * EndTime can be null for an unfinished job. * @throws IllegalArgumentException */ private void validateStepExecution(StepExecution stepExecution) { @@ -248,8 +244,8 @@ public class JdbcStepExecutionDao extends AbstractJdbcBatchMetadataDao implement public void updateStepExecution(StepExecution stepExecution) { validateStepExecution(stepExecution); - Assert.notNull(stepExecution.getId(), "StepExecution Id cannot be null. StepExecution must saved" - + " before it can be updated."); + Assert.notNull(stepExecution.getId(), + "StepExecution Id cannot be null. StepExecution must saved" + " before it can be updated."); // Do not check for existence of step execution considering // it is saved at every commit point. @@ -266,23 +262,21 @@ public class JdbcStepExecutionDao extends AbstractJdbcBatchMetadataDao implement stepExecution.getFilterCount(), stepExecution.getWriteCount(), stepExecution.getExitStatus().getExitCode(), exitDescription, version, stepExecution.getReadSkipCount(), stepExecution.getProcessSkipCount(), - stepExecution.getWriteSkipCount(), stepExecution.getRollbackCount(), - stepExecution.getLastUpdated(), stepExecution.getId(), stepExecution.getVersion() }; - int count = getJdbcTemplate() - .update(getQuery(UPDATE_STEP_EXECUTION), - parameters, - new int[] { Types.TIMESTAMP, Types.TIMESTAMP, Types.VARCHAR, Types.INTEGER, Types.INTEGER, - Types.INTEGER, Types.INTEGER, Types.VARCHAR, Types.VARCHAR, Types.INTEGER, - Types.INTEGER, Types.INTEGER, Types.INTEGER, Types.INTEGER, Types.TIMESTAMP, - Types.BIGINT, Types.INTEGER }); + stepExecution.getWriteSkipCount(), stepExecution.getRollbackCount(), stepExecution.getLastUpdated(), + stepExecution.getId(), stepExecution.getVersion() }; + int count = getJdbcTemplate().update(getQuery(UPDATE_STEP_EXECUTION), parameters, + new int[] { Types.TIMESTAMP, Types.TIMESTAMP, Types.VARCHAR, Types.INTEGER, Types.INTEGER, + Types.INTEGER, Types.INTEGER, Types.VARCHAR, Types.VARCHAR, Types.INTEGER, Types.INTEGER, + Types.INTEGER, Types.INTEGER, Types.INTEGER, Types.TIMESTAMP, Types.BIGINT, + Types.INTEGER }); // Avoid concurrent modifications... if (count == 0) { int currentVersion = getJdbcTemplate().queryForObject(getQuery(CURRENT_VERSION_STEP_EXECUTION), Integer.class, stepExecution.getId()); - throw new OptimisticLockingFailureException("Attempt to update step execution id=" - + stepExecution.getId() + " with wrong version (" + stepExecution.getVersion() - + "), where current version is " + currentVersion); + throw new OptimisticLockingFailureException( + "Attempt to update step execution id=" + stepExecution.getId() + " with wrong version (" + + stepExecution.getVersion() + "), where current version is " + currentVersion); } stepExecution.incrementVersion(); @@ -299,10 +293,12 @@ public class JdbcStepExecutionDao extends AbstractJdbcBatchMetadataDao implement private String truncateExitDescription(String description) { if (description != null && description.length() > exitMessageLength) { if (logger.isDebugEnabled()) { - logger.debug("Truncating long message before update of StepExecution, original message is: " + description); + logger.debug( + "Truncating long message before update of StepExecution, original message is: " + description); } return description.substring(0, exitMessageLength); - } else { + } + else { return description; } } @@ -317,31 +313,30 @@ public class JdbcStepExecutionDao extends AbstractJdbcBatchMetadataDao implement "There can be at most one step execution with given name for single job execution"); if (executions.isEmpty()) { return null; - } else { + } + else { return executions.get(0); } } @Override public StepExecution getLastStepExecution(JobInstance jobInstance, String stepName) { - List executions = getJdbcTemplate().query( - getQuery(GET_LAST_STEP_EXECUTION), - (rs, rowNum) -> { - Long jobExecutionId = rs.getLong(19); - JobExecution jobExecution = new JobExecution(jobExecutionId); - jobExecution.setStartTime(rs.getTimestamp(20)); - jobExecution.setEndTime(rs.getTimestamp(21)); - jobExecution.setStatus(BatchStatus.valueOf(rs.getString(22))); - jobExecution.setExitStatus(new ExitStatus(rs.getString(23), rs.getString(24))); - jobExecution.setCreateTime(rs.getTimestamp(25)); - jobExecution.setLastUpdated(rs.getTimestamp(26)); - jobExecution.setVersion(rs.getInt(27)); - return new StepExecutionRowMapper(jobExecution).mapRow(rs, rowNum); - }, - jobInstance.getInstanceId(), stepName); + List executions = getJdbcTemplate().query(getQuery(GET_LAST_STEP_EXECUTION), (rs, rowNum) -> { + Long jobExecutionId = rs.getLong(19); + JobExecution jobExecution = new JobExecution(jobExecutionId); + jobExecution.setStartTime(rs.getTimestamp(20)); + jobExecution.setEndTime(rs.getTimestamp(21)); + jobExecution.setStatus(BatchStatus.valueOf(rs.getString(22))); + jobExecution.setExitStatus(new ExitStatus(rs.getString(23), rs.getString(24))); + jobExecution.setCreateTime(rs.getTimestamp(25)); + jobExecution.setLastUpdated(rs.getTimestamp(26)); + jobExecution.setVersion(rs.getInt(27)); + return new StepExecutionRowMapper(jobExecution).mapRow(rs, rowNum); + }, jobInstance.getInstanceId(), stepName); if (executions.isEmpty()) { return null; - } else { + } + else { return executions.get(0); } } @@ -354,7 +349,8 @@ public class JdbcStepExecutionDao extends AbstractJdbcBatchMetadataDao implement @Override public int countStepExecutions(JobInstance jobInstance, String stepName) { - return getJdbcTemplate().queryForObject(getQuery(COUNT_STEP_EXECUTIONS), Integer.class, jobInstance.getInstanceId(), stepName); + return getJdbcTemplate().queryForObject(getQuery(COUNT_STEP_EXECUTIONS), Integer.class, + jobInstance.getInstanceId(), stepName); } private static class StepExecutionRowMapper implements RowMapper { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JobExecutionDao.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JobExecutionDao.java index 3b86d47af..5ca024b0b 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JobExecutionDao.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JobExecutionDao.java @@ -25,7 +25,7 @@ import org.springframework.lang.Nullable; /** * Data Access Object for job executions. - * + * * @author Lucas Ward * @author Robert Kasanicky * @author Mahmoud Ben Hassine @@ -34,28 +34,24 @@ public interface JobExecutionDao { /** * Save a new JobExecution. - * - * Preconditions: jobInstance the jobExecution belongs to must have a - * jobInstanceId. - * + * + * Preconditions: jobInstance the jobExecution belongs to must have a jobInstanceId. * @param jobExecution {@link JobExecution} instance to be saved. */ void saveJobExecution(JobExecution jobExecution); /** * Update and existing JobExecution. - * - * Preconditions: jobExecution must have an Id (which can be obtained by the - * save method) and a jobInstanceId. - * + * + * Preconditions: jobExecution must have an Id (which can be obtained by the save + * method) and a jobInstanceId. * @param jobExecution {@link JobExecution} instance to be updated. */ void updateJobExecution(JobExecution jobExecution); /** - * Return all {@link JobExecution}s for given {@link JobInstance}, sorted - * backwards by creation order (so the first element is the most recent). - * + * Return all {@link JobExecution}s for given {@link JobInstance}, sorted backwards by + * creation order (so the first element is the most recent). * @param jobInstance parent {@link JobInstance} of the {@link JobExecution}s to find. * @return {@link List} containing JobExecutions for the jobInstance. */ @@ -65,16 +61,16 @@ public interface JobExecutionDao { * Find the last {@link JobExecution} to have been created for a given * {@link JobInstance}. * @param jobInstance the {@link JobInstance} - * @return the last {@link JobExecution} to execute for this instance or - * {@code null} if no job execution is found for the given job instance. + * @return the last {@link JobExecution} to execute for this instance or {@code null} + * if no job execution is found for the given job instance. */ @Nullable JobExecution getLastJobExecution(JobInstance jobInstance); /** * @param jobName {@link String} containing the name of the job. - * @return all {@link JobExecution} that are still running (or indeterminate - * state), i.e. having null end date, for the specified job name. + * @return all {@link JobExecution} that are still running (or indeterminate state), + * i.e. having null end date, for the specified job name. */ Set findRunningJobExecutions(String jobName); @@ -86,10 +82,8 @@ public interface JobExecutionDao { JobExecution getJobExecution(Long executionId); /** - * Because it may be possible that the status of a JobExecution is updated - * while running, the following method will synchronize only the status and - * version fields. - * + * Because it may be possible that the status of a JobExecution is updated while + * running, the following method will synchronize only the status and version fields. * @param jobExecution to be updated. */ void synchronizeStatus(JobExecution jobExecution); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JobInstanceDao.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JobInstanceDao.java index 92af7964e..441b54401 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JobInstanceDao.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JobInstanceDao.java @@ -38,34 +38,30 @@ public interface JobInstanceDao { /** * Create a JobInstance with given name and parameters. * - * PreConditions: JobInstance for given name and parameters must not already - * exist - * - * PostConditions: A valid job instance will be returned which has been - * persisted and contains an unique Id. + * PreConditions: JobInstance for given name and parameters must not already exist * + * PostConditions: A valid job instance will be returned which has been persisted and + * contains an unique Id. * @param jobName {@link String} containing the name of the job. - * @param jobParameters {@link JobParameters} containing the parameters for - * the JobInstance. + * @param jobParameters {@link JobParameters} containing the parameters for the + * JobInstance. * @return JobInstance {@link JobInstance} instance that was created. */ JobInstance createJobInstance(String jobName, JobParameters jobParameters); /** - * Find the job instance that matches the given name and parameters. If no - * matching job instances are found, then returns null. - * + * Find the job instance that matches the given name and parameters. If no matching + * job instances are found, then returns null. * @param jobName the name of the job * @param jobParameters the parameters with which the job was executed - * @return {@link JobInstance} object matching the job name and - * {@link JobParameters} or {@code null} + * @return {@link JobInstance} object matching the job name and {@link JobParameters} + * or {@code null} */ @Nullable JobInstance getJobInstance(String jobName, JobParameters jobParameters); /** * Fetch the job instance with the provided identifier. - * * @param instanceId the job identifier * @return the job instance with this identifier or {@code null} if it doesn't exist */ @@ -74,21 +70,19 @@ public interface JobInstanceDao { /** * Fetch the JobInstance for the provided JobExecution. - * * @param jobExecution the JobExecution - * @return the JobInstance for the provided execution or {@code null} if it doesn't exist. + * @return the JobInstance for the provided execution or {@code null} if it doesn't + * exist. */ @Nullable JobInstance getJobInstance(JobExecution jobExecution); /** - * Fetch the last job instances with the provided name, sorted backwards by - * primary key. - * - * if using the JdbcJobInstance, you can provide the jobName with a wildcard - * (e.g. *Job) to return 'like' job names. (e.g. *Job will return 'someJob' - * and 'otherJob') + * Fetch the last job instances with the provided name, sorted backwards by primary + * key. * + * if using the JdbcJobInstance, you can provide the jobName with a wildcard (e.g. + * *Job) to return 'like' job names. (e.g. *Job will return 'someJob' and 'otherJob') * @param jobName the job name * @param start the start index of the instances to return * @param count the maximum number of objects to return @@ -109,34 +103,29 @@ public interface JobInstanceDao { } /** - * Retrieve the names of all job instances sorted alphabetically - i.e. jobs - * that have ever been executed. - * + * Retrieve the names of all job instances sorted alphabetically - i.e. jobs that have + * ever been executed. * @return the names of all job instances */ List getJobNames(); - + /** - * Fetch the last job instances with the provided name, sorted backwards by - * primary key, using a 'like' criteria - * + * Fetch the last job instances with the provided name, sorted backwards by primary + * key, using a 'like' criteria * @param jobName {@link String} containing the name of the job. - * @param start int containing the offset of where list of job instances - * results should begin. + * @param start int containing the offset of where list of job instances results + * should begin. * @param count int containing the number of job instances to return. * @return a list of {@link JobInstance} for the job name requested. */ List findJobInstancesByName(String jobName, int start, int count); - /** - * Query the repository for the number of unique {@link JobInstance}s - * associated with the supplied job name. - * + * Query the repository for the number of unique {@link JobInstance}s associated with + * the supplied job name. * @param jobName the name of the job to query for - * @return the number of {@link JobInstance}s that exist within the - * associated job repository - * + * @return the number of {@link JobInstance}s that exist within the associated job + * repository * @throws NoSuchJobException thrown if no Job has the jobName specified. */ int getJobInstanceCount(@Nullable String jobName) throws NoSuchJobException; diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/NoSuchObjectException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/NoSuchObjectException.java index 80fad9ce6..4c84d89c9 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/NoSuchObjectException.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/NoSuchObjectException.java @@ -17,9 +17,9 @@ package org.springframework.batch.core.repository.dao; /** - * This exception identifies that a batch domain object is invalid, which - * is generally caused by an invalid ID. (An ID which doesn't exist in the database). - * + * This exception identifies that a batch domain object is invalid, which is generally + * caused by an invalid ID. (An ID which doesn't exist in the database). + * * @author Lucas Ward * @author Dave Syer * @@ -28,7 +28,8 @@ public class NoSuchObjectException extends RuntimeException { private static final long serialVersionUID = 4399621765157283111L; - public NoSuchObjectException(String message){ + public NoSuchObjectException(String message) { super(message); } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/StepExecutionDao.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/StepExecutionDao.java index 8e7b4f476..4e3039824 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/StepExecutionDao.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/StepExecutionDao.java @@ -27,38 +27,34 @@ public interface StepExecutionDao { /** * Save the given StepExecution. - * + * * Preconditions: Id must be null. - * + * * Postconditions: Id will be set to a unique Long. - * * @param stepExecution {@link StepExecution} instance to be saved. */ void saveStepExecution(StepExecution stepExecution); /** * Save the given collection of StepExecution as a batch. - * + * * Preconditions: StepExecution Id must be null. - * + * * Postconditions: StepExecution Id will be set to a unique Long. - * * @param stepExecutions a collection of {@link JobExecution} instances to be saved. */ void saveStepExecutions(Collection stepExecutions); /** * Update the given StepExecution - * + * * Preconditions: Id must not be null. - * * @param stepExecution {@link StepExecution} instance to be updated. */ void updateStepExecution(StepExecution stepExecution); /** * Retrieve a {@link StepExecution} from its id. - * * @param jobExecution the parent {@link JobExecution} * @param stepExecutionId the step execution id * @return a {@link StepExecution} @@ -67,9 +63,8 @@ public interface StepExecutionDao { StepExecution getStepExecution(JobExecution jobExecution, Long stepExecutionId); /** - * Retrieve the last {@link StepExecution} for a given {@link JobInstance} - * ordered by creation time and then id. - * + * Retrieve the last {@link StepExecution} for a given {@link JobInstance} ordered by + * creation time and then id. * @param jobInstance the parent {@link JobInstance} * @param stepName the name of the step * @return a {@link StepExecution} @@ -81,14 +76,12 @@ public interface StepExecutionDao { /** * Retrieve all the {@link StepExecution} for the parent {@link JobExecution}. - * * @param jobExecution the parent job execution */ void addStepExecutions(JobExecution jobExecution); /** * Counts all the {@link StepExecution} for a given step name. - * * @param jobInstance the parent {@link JobInstance} * @param stepName the name of the step * @since 4.3 @@ -97,4 +90,5 @@ public interface StepExecutionDao { default int countStepExecutions(JobInstance jobInstance, String stepName) { throw new UnsupportedOperationException(); } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/AbstractJobRepositoryFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/AbstractJobRepositoryFactoryBean.java index a87506560..0a0f761c2 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/AbstractJobRepositoryFactoryBean.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/AbstractJobRepositoryFactoryBean.java @@ -39,12 +39,10 @@ import org.springframework.transaction.support.TransactionSynchronizationManager import org.springframework.util.Assert; /** - * A {@link FactoryBean} that automates the creation of a - * {@link SimpleJobRepository}. Declares abstract methods for providing DAO - * object implementations. + * A {@link FactoryBean} that automates the creation of a {@link SimpleJobRepository}. + * Declares abstract methods for providing DAO object implementations. * * @see JobRepositoryFactoryBean - * * @author Ben Hale * @author Lucas Ward * @author Robert Kasanicky @@ -69,35 +67,30 @@ public abstract class AbstractJobRepositoryFactoryBean implements FactoryBean "'" + databaseType - + "' is an unsupported database type. The supported database types are " - + StringUtils.arrayToCommaDelimitedString(incrementerFactory.getSupportedIncrementerTypes())); + Assert.isTrue(incrementerFactory.isSupportedIncrementerType(databaseType), + () -> "'" + databaseType + "' is an unsupported database type. The supported database types are " + + StringUtils.arrayToCommaDelimitedString(incrementerFactory.getSupportedIncrementerTypes())); - if(lobType != null) { + if (lobType != null) { Assert.isTrue(isValidTypes(lobType), "lobType must be a value from the java.sql.Types class"); } @@ -239,8 +236,8 @@ public class JobRepositoryFactoryBean extends AbstractJobRepositoryFactoryBean i protected JobExecutionDao createJobExecutionDao() throws Exception { JdbcJobExecutionDao dao = new JdbcJobExecutionDao(); dao.setJdbcTemplate(jdbcOperations); - dao.setJobExecutionIncrementer(incrementerFactory.getIncrementer(databaseType, tablePrefix - + "JOB_EXECUTION_SEQ")); + dao.setJobExecutionIncrementer( + incrementerFactory.getIncrementer(databaseType, tablePrefix + "JOB_EXECUTION_SEQ")); dao.setTablePrefix(tablePrefix); dao.setClobTypeToUse(determineClobTypeToUse(this.databaseType)); dao.setExitMessageLength(maxVarCharLength); @@ -252,8 +249,8 @@ public class JobRepositoryFactoryBean extends AbstractJobRepositoryFactoryBean i protected StepExecutionDao createStepExecutionDao() throws Exception { JdbcStepExecutionDao dao = new JdbcStepExecutionDao(); dao.setJdbcTemplate(jdbcOperations); - dao.setStepExecutionIncrementer(incrementerFactory.getIncrementer(databaseType, tablePrefix - + "STEP_EXECUTION_SEQ")); + dao.setStepExecutionIncrementer( + incrementerFactory.getIncrementer(databaseType, tablePrefix + "STEP_EXECUTION_SEQ")); dao.setTablePrefix(tablePrefix); dao.setClobTypeToUse(determineClobTypeToUse(this.databaseType)); dao.setExitMessageLength(maxVarCharLength); @@ -281,9 +278,10 @@ public class JobRepositoryFactoryBean extends AbstractJobRepositoryFactoryBean i } private int determineClobTypeToUse(String databaseType) throws Exception { - if(lobType != null) { + if (lobType != null) { return lobType; - } else { + } + else { if (SYBASE == DatabaseType.valueOf(databaseType.toUpperCase())) { return Types.LONGVARCHAR; } @@ -298,7 +296,7 @@ public class JobRepositoryFactoryBean extends AbstractJobRepositoryFactoryBean i for (Field field : Types.class.getFields()) { int curValue = field.getInt(null); - if(curValue == value) { + if (curValue == value) { result = true; break; } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/SimpleJobRepository.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/SimpleJobRepository.java index 6b8ebf037..ff8007c02 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/SimpleJobRepository.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/SimpleJobRepository.java @@ -43,8 +43,8 @@ import java.util.List; /** * *

      - * Implementation of {@link JobRepository} that stores job instances, - * job executions, and step executions using the injected DAOs. + * Implementation of {@link JobRepository} that stores job instances, job executions, and + * step executions using the injected DAOs. *

      * * @author Lucas Ward @@ -53,7 +53,6 @@ import java.util.List; * @author David Turanski * @author Mahmoud Ben Hassine * @author Baris Cubukcuoglu - * * @see JobRepository * @see JobInstanceDao * @see JobExecutionDao @@ -73,8 +72,8 @@ public class SimpleJobRepository implements JobRepository { private ExecutionContextDao ecDao; /** - * Provide default constructor with low visibility in case user wants to use - * use aop:proxy-target-class="true" for AOP interceptor. + * Provide default constructor with low visibility in case user wants to use use + * aop:proxy-target-class="true" for AOP interceptor. */ SimpleJobRepository() { } @@ -103,10 +102,9 @@ public class SimpleJobRepository implements JobRepository { /* * Find all jobs matching the runtime information. * - * If this method is transactional, and the isolation level is - * REPEATABLE_READ or better, another launcher trying to start the same - * job in another thread or process will block until this transaction - * has finished. + * If this method is transactional, and the isolation level is REPEATABLE_READ or + * better, another launcher trying to start the same job in another thread or + * process will block until this transaction has finished. */ JobInstance jobInstance = jobInstanceDao.getJobInstance(jobName, jobParameters); @@ -124,8 +122,8 @@ public class SimpleJobRepository implements JobRepository { // check for running executions and find the last started for (JobExecution execution : executions) { if (execution.isRunning() || execution.isStopping()) { - throw new JobExecutionAlreadyRunningException("A job execution for this job is already running: " - + jobInstance); + throw new JobExecutionAlreadyRunningException( + "A job execution for this job is already running: " + jobInstance); } BatchStatus status = execution.getStatus(); if (status == BatchStatus.UNKNOWN) { @@ -134,11 +132,13 @@ public class SimpleJobRepository implements JobRepository { + "so it may be dangerous to proceed. Manual intervention is probably necessary."); } Collection allJobParameters = execution.getJobParameters().getParameters().values(); - long identifyingJobParametersCount = allJobParameters.stream().filter(JobParameter::isIdentifying).count(); - if (identifyingJobParametersCount > 0 && (status == BatchStatus.COMPLETED || status == BatchStatus.ABANDONED)) { + long identifyingJobParametersCount = allJobParameters.stream().filter(JobParameter::isIdentifying) + .count(); + if (identifyingJobParametersCount > 0 + && (status == BatchStatus.COMPLETED || status == BatchStatus.ABANDONED)) { throw new JobInstanceAlreadyCompleteException( "A job instance already exists and is complete for parameters=" + jobParameters - + ". If you want to run this job again, change the parameters."); + + ". If you want to run this job again, change the parameters."); } } executionContext = ecDao.getExecutionContext(jobExecutionDao.getLastJobExecution(jobInstance)); @@ -247,11 +247,10 @@ public class SimpleJobRepository implements JobRepository { } /** - * Check to determine whether or not the JobExecution that is the parent of - * the provided StepExecution has been interrupted. If, after synchronizing - * the status with the database, the status has been updated to STOPPING, - * then the job has been interrupted. - * + * Check to determine whether or not the JobExecution that is the parent of the + * provided StepExecution has been interrupted. If, after synchronizing the status + * with the database, the status has been updated to STOPPING, then the job has been + * interrupted. * @param stepExecution */ private void checkForInterruption(StepExecution stepExecution) { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/resource/StepExecutionSimpleCompletionPolicy.java b/spring-batch-core/src/main/java/org/springframework/batch/core/resource/StepExecutionSimpleCompletionPolicy.java index fc8968220..3bc7bc0ae 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/resource/StepExecutionSimpleCompletionPolicy.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/resource/StepExecutionSimpleCompletionPolicy.java @@ -27,24 +27,22 @@ import org.springframework.util.Assert; /** *

      - * A {@link CompletionPolicy} that picks up a commit interval from - * {@link JobParameters} by listening to the start of a step. Use anywhere that - * a {@link CompletionPolicy} can be used (usually at the chunk level in a - * step), and inject as a {@link StepExecutionListener} into the surrounding - * step. N.B. only after the step has started will the completion policy be - * usable. + * A {@link CompletionPolicy} that picks up a commit interval from {@link JobParameters} + * by listening to the start of a step. Use anywhere that a {@link CompletionPolicy} can + * be used (usually at the chunk level in a step), and inject as a + * {@link StepExecutionListener} into the surrounding step. N.B. only after the step has + * started will the completion policy be usable. *

      * *

      - * It is easier and probably preferable to simply declare the chunk with a - * commit-interval that is a late-binding expression (e.g. - * #{jobParameters['commit.interval']}). That feature is available - * from of Spring Batch 2.1.7. + * It is easier and probably preferable to simply declare the chunk with a commit-interval + * that is a late-binding expression (e.g. + * #{jobParameters['commit.interval']}). That feature is available from of + * Spring Batch 2.1.7. *

      * * @author Dave Syer * @author Mahmoud Ben Hassine - * * @see CompletionPolicy */ public class StepExecutionSimpleCompletionPolicy implements StepExecutionListener, CompletionPolicy { @@ -54,9 +52,8 @@ public class StepExecutionSimpleCompletionPolicy implements StepExecutionListene private String keyName = "commit.interval"; /** - * Public setter for the key name of a Long value in the - * {@link JobParameters} that will contain a commit interval. Defaults to - * "commit.interval". + * Public setter for the key name of a Long value in the {@link JobParameters} that + * will contain a commit interval. Defaults to "commit.interval". * @param keyName the keyName to set */ public void setKeyName(String keyName) { @@ -64,10 +61,9 @@ public class StepExecutionSimpleCompletionPolicy implements StepExecutionListene } /** - * Set up a {@link SimpleCompletionPolicy} with a commit interval taken from - * the {@link JobParameters}. If there is a Long parameter with the given - * key name, the intValue of this parameter is used. If not an exception - * will be thrown. + * Set up a {@link SimpleCompletionPolicy} with a commit interval taken from the + * {@link JobParameters}. If there is a Long parameter with the given key name, the + * intValue of this parameter is used. If not an exception will be thrown. * * @see org.springframework.batch.core.StepExecutionListener#beforeStep(org.springframework.batch.core.StepExecution) */ @@ -80,8 +76,8 @@ public class StepExecutionSimpleCompletionPolicy implements StepExecutionListene } /** - * @return true if the commit interval has been reached or the result - * indicates completion + * @return true if the commit interval has been reached or the result indicates + * completion * @see CompletionPolicy#isComplete(RepeatContext, RepeatStatus) */ @Override @@ -124,8 +120,8 @@ public class StepExecutionSimpleCompletionPolicy implements StepExecutionListene } /** - * Delegates to the wrapped {@link CompletionPolicy} if set, otherwise - * returns the value of {@link #setKeyName(String)}. + * Delegates to the wrapped {@link CompletionPolicy} if set, otherwise returns the + * value of {@link #setKeyName(String)}. */ @Override public String toString() { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/scope/BatchScopeSupport.java b/spring-batch-core/src/main/java/org/springframework/batch/core/scope/BatchScopeSupport.java index e08f310ea..9c7223a2b 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/scope/BatchScopeSupport.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/scope/BatchScopeSupport.java @@ -1,226 +1,221 @@ -/* - * Copyright 2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope; - -import org.springframework.aop.scope.ScopedProxyUtils; -import org.springframework.batch.core.scope.context.StepContext; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.config.BeanDefinitionHolder; -import org.springframework.beans.factory.config.BeanDefinitionVisitor; -import org.springframework.beans.factory.config.BeanFactoryPostProcessor; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.beans.factory.config.Scope; -import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.core.Ordered; -import org.springframework.util.Assert; -import org.springframework.util.StringValueResolver; - -/** - * ScopeSupport. - * - * @author Michael Minella - * @since 3.0 - */ -public abstract class BatchScopeSupport implements Scope, BeanFactoryPostProcessor, Ordered { - - private boolean autoProxy = true; - - private boolean proxyTargetClass = false; - - private String name; - - private int order = Ordered.LOWEST_PRECEDENCE; - - /** - * @param order the order value to set priority of callback execution for - * the {@link BeanFactoryPostProcessor} part of this scope bean. - */ - public void setOrder(int order) { - this.order = order; - } - - @Override - public int getOrder() { - return order; - } - - public String getName() { - return this.name; - } - - /** - * Public setter for the name property. This can then be used as a bean - * definition attribute, e.g. scope="job". - * - * @param name the name to set for this scope. - */ - public void setName(String name) { - this.name = name; - } - - /** - * Flag to indicate that proxies should use dynamic subclassing. This allows - * classes with no interface to be proxied. Defaults to false. - * - * @param proxyTargetClass set to true to have proxies created using dynamic - * subclasses - */ - public void setProxyTargetClass(boolean proxyTargetClass) { - this.proxyTargetClass = proxyTargetClass; - } - - /** - * Flag to indicate that bean definitions need not be auto proxied. This gives control back to the declarer of the - * bean definition (e.g. in an @Configuration class). - * - * @param autoProxy the flag value to set (default true) - */ - public void setAutoProxy(boolean autoProxy) { - this.autoProxy = autoProxy; - } - - public abstract String getTargetNamePrefix(); - - /** - * Register this scope with the enclosing BeanFactory. - * - * @see BeanFactoryPostProcessor#postProcessBeanFactory(ConfigurableListableBeanFactory) - * - * @param beanFactory the BeanFactory to register with - * @throws BeansException if there is a problem. - */ - @Override - public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { - - beanFactory.registerScope(name, this); - - if(!autoProxy) { - return; - } - - Assert.state(beanFactory instanceof BeanDefinitionRegistry, - "BeanFactory was not a BeanDefinitionRegistry, so JobScope cannot be used."); - BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; - - for (String beanName : beanFactory.getBeanDefinitionNames()) { - if (!beanName.startsWith(getTargetNamePrefix())) { - BeanDefinition definition = beanFactory.getBeanDefinition(beanName); - // Replace this or any of its inner beans with scoped proxy if it - // has this scope - boolean scoped = name.equals(definition.getScope()); - Scopifier scopifier = new Scopifier(registry, name, proxyTargetClass, scoped); - scopifier.visitBeanDefinition(definition); - - if (scoped && !definition.isAbstract()) { - createScopedProxy(beanName, definition, registry, proxyTargetClass); - } - } - } - - } - - /** - * Wrap a target bean definition in a proxy that defers initialization until - * after the {@link StepContext} is available. Amounts to adding - * <aop-auto-proxy/> to a step scoped bean. - * - * @param beanName the bean name to replace - * @param definition the bean definition to replace - * @param registry the enclosing {@link BeanDefinitionRegistry} - * @param proxyTargetClass true if we need to force use of dynamic - * subclasses - * @return a {@link BeanDefinitionHolder} for the new representation of the - * target. Caller should register it if needed to be visible at top level in - * bean factory. - */ - protected static BeanDefinitionHolder createScopedProxy(String beanName, BeanDefinition definition, - BeanDefinitionRegistry registry, boolean proxyTargetClass) { - - BeanDefinitionHolder proxyHolder; - - proxyHolder = ScopedProxyUtils.createScopedProxy(new BeanDefinitionHolder(definition, beanName), registry, - proxyTargetClass); - - registry.registerBeanDefinition(beanName, proxyHolder.getBeanDefinition()); - - return proxyHolder; - - } - - /** - * Helper class to scan a bean definition hierarchy and force the use of - * auto-proxy for step scoped beans. - * - * @author Dave Syer - * - */ - protected static class Scopifier extends BeanDefinitionVisitor { - - private final boolean proxyTargetClass; - - private final BeanDefinitionRegistry registry; - - private final String scope; - - private final boolean scoped; - - public Scopifier(BeanDefinitionRegistry registry, String scope, boolean proxyTargetClass, boolean scoped) { - super(new StringValueResolver() { - @Override - public String resolveStringValue(String value) { - return value; - } - }); - this.registry = registry; - this.proxyTargetClass = proxyTargetClass; - this.scope = scope; - this.scoped = scoped; - } - - @Override - protected Object resolveValue(Object value) { - - BeanDefinition definition = null; - String beanName = null; - if (value instanceof BeanDefinition) { - definition = (BeanDefinition) value; - beanName = BeanDefinitionReaderUtils.generateBeanName(definition, registry); - } - else if (value instanceof BeanDefinitionHolder) { - BeanDefinitionHolder holder = (BeanDefinitionHolder) value; - definition = holder.getBeanDefinition(); - beanName = holder.getBeanName(); - } - - if (definition != null) { - boolean nestedScoped = scope.equals(definition.getScope()); - boolean scopeChangeRequiresProxy = !scoped && nestedScoped; - if (scopeChangeRequiresProxy) { - // Exit here so that nested inner bean definitions are not - // analysed - return createScopedProxy(beanName, definition, registry, proxyTargetClass); - } - } - - // Nested inner bean definitions are recursively analysed here - value = super.resolveValue(value); - return value; - - } - } -} +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope; + +import org.springframework.aop.scope.ScopedProxyUtils; +import org.springframework.batch.core.scope.context.StepContext; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.BeanDefinitionHolder; +import org.springframework.beans.factory.config.BeanDefinitionVisitor; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.config.Scope; +import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.core.Ordered; +import org.springframework.util.Assert; +import org.springframework.util.StringValueResolver; + +/** + * ScopeSupport. + * + * @author Michael Minella + * @since 3.0 + */ +public abstract class BatchScopeSupport implements Scope, BeanFactoryPostProcessor, Ordered { + + private boolean autoProxy = true; + + private boolean proxyTargetClass = false; + + private String name; + + private int order = Ordered.LOWEST_PRECEDENCE; + + /** + * @param order the order value to set priority of callback execution for the + * {@link BeanFactoryPostProcessor} part of this scope bean. + */ + public void setOrder(int order) { + this.order = order; + } + + @Override + public int getOrder() { + return order; + } + + public String getName() { + return this.name; + } + + /** + * Public setter for the name property. This can then be used as a bean definition + * attribute, e.g. scope="job". + * @param name the name to set for this scope. + */ + public void setName(String name) { + this.name = name; + } + + /** + * Flag to indicate that proxies should use dynamic subclassing. This allows classes + * with no interface to be proxied. Defaults to false. + * @param proxyTargetClass set to true to have proxies created using dynamic + * subclasses + */ + public void setProxyTargetClass(boolean proxyTargetClass) { + this.proxyTargetClass = proxyTargetClass; + } + + /** + * Flag to indicate that bean definitions need not be auto proxied. This gives control + * back to the declarer of the bean definition (e.g. in an @Configuration class). + * @param autoProxy the flag value to set (default true) + */ + public void setAutoProxy(boolean autoProxy) { + this.autoProxy = autoProxy; + } + + public abstract String getTargetNamePrefix(); + + /** + * Register this scope with the enclosing BeanFactory. + * + * @see BeanFactoryPostProcessor#postProcessBeanFactory(ConfigurableListableBeanFactory) + * @param beanFactory the BeanFactory to register with + * @throws BeansException if there is a problem. + */ + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { + + beanFactory.registerScope(name, this); + + if (!autoProxy) { + return; + } + + Assert.state(beanFactory instanceof BeanDefinitionRegistry, + "BeanFactory was not a BeanDefinitionRegistry, so JobScope cannot be used."); + BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; + + for (String beanName : beanFactory.getBeanDefinitionNames()) { + if (!beanName.startsWith(getTargetNamePrefix())) { + BeanDefinition definition = beanFactory.getBeanDefinition(beanName); + // Replace this or any of its inner beans with scoped proxy if it + // has this scope + boolean scoped = name.equals(definition.getScope()); + Scopifier scopifier = new Scopifier(registry, name, proxyTargetClass, scoped); + scopifier.visitBeanDefinition(definition); + + if (scoped && !definition.isAbstract()) { + createScopedProxy(beanName, definition, registry, proxyTargetClass); + } + } + } + + } + + /** + * Wrap a target bean definition in a proxy that defers initialization until after the + * {@link StepContext} is available. Amounts to adding <aop-auto-proxy/> to a + * step scoped bean. + * @param beanName the bean name to replace + * @param definition the bean definition to replace + * @param registry the enclosing {@link BeanDefinitionRegistry} + * @param proxyTargetClass true if we need to force use of dynamic subclasses + * @return a {@link BeanDefinitionHolder} for the new representation of the target. + * Caller should register it if needed to be visible at top level in bean factory. + */ + protected static BeanDefinitionHolder createScopedProxy(String beanName, BeanDefinition definition, + BeanDefinitionRegistry registry, boolean proxyTargetClass) { + + BeanDefinitionHolder proxyHolder; + + proxyHolder = ScopedProxyUtils.createScopedProxy(new BeanDefinitionHolder(definition, beanName), registry, + proxyTargetClass); + + registry.registerBeanDefinition(beanName, proxyHolder.getBeanDefinition()); + + return proxyHolder; + + } + + /** + * Helper class to scan a bean definition hierarchy and force the use of auto-proxy + * for step scoped beans. + * + * @author Dave Syer + * + */ + protected static class Scopifier extends BeanDefinitionVisitor { + + private final boolean proxyTargetClass; + + private final BeanDefinitionRegistry registry; + + private final String scope; + + private final boolean scoped; + + public Scopifier(BeanDefinitionRegistry registry, String scope, boolean proxyTargetClass, boolean scoped) { + super(new StringValueResolver() { + @Override + public String resolveStringValue(String value) { + return value; + } + }); + this.registry = registry; + this.proxyTargetClass = proxyTargetClass; + this.scope = scope; + this.scoped = scoped; + } + + @Override + protected Object resolveValue(Object value) { + + BeanDefinition definition = null; + String beanName = null; + if (value instanceof BeanDefinition) { + definition = (BeanDefinition) value; + beanName = BeanDefinitionReaderUtils.generateBeanName(definition, registry); + } + else if (value instanceof BeanDefinitionHolder) { + BeanDefinitionHolder holder = (BeanDefinitionHolder) value; + definition = holder.getBeanDefinition(); + beanName = holder.getBeanName(); + } + + if (definition != null) { + boolean nestedScoped = scope.equals(definition.getScope()); + boolean scopeChangeRequiresProxy = !scoped && nestedScoped; + if (scopeChangeRequiresProxy) { + // Exit here so that nested inner bean definitions are not + // analysed + return createScopedProxy(beanName, definition, registry, proxyTargetClass); + } + } + + // Nested inner bean definitions are recursively analysed here + value = super.resolveValue(value); + return value; + + } + + } + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/scope/JobScope.java b/spring-batch-core/src/main/java/org/springframework/batch/core/scope/JobScope.java index 6a591ef56..6bb8583cc 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/scope/JobScope.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/scope/JobScope.java @@ -1,168 +1,166 @@ -/* - * Copyright 2006-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.batch.core.scope.context.JobContext; -import org.springframework.batch.core.scope.context.JobSynchronizationManager; -import org.springframework.beans.BeanWrapper; -import org.springframework.beans.BeanWrapperImpl; -import org.springframework.beans.factory.ObjectFactory; -import org.springframework.beans.factory.config.Scope; - -/** - * Scope for job context. Objects in this scope use the Spring container as an - * object factory, so there is only one instance of such a bean per executing - * job. All objects in this scope are <aop:scoped-proxy/> (no need to - * decorate the bean definitions).
      - *
      - * - * In addition, support is provided for late binding of references accessible - * from the {@link JobContext} using #{..} placeholders. Using this feature, - * bean properties can be pulled from the job or job execution context and the - * job parameters. E.g. - * - *
      - * <bean id="..." class="..." scope="job">
      - * 	<property name="name" value="#{jobParameters[input]}" />
      - * </bean>
      - *
      - * <bean id="..." class="..." scope="job">
      - * 	<property name="name" value="#{jobExecutionContext['input.stem']}.txt" />
      - * </bean>
      - * 
      - * - * The {@link JobContext} is referenced using standard bean property paths (as - * per {@link BeanWrapper}). The examples above all show the use of the Map - * accessors provided as a convenience for job attributes. - * - * @author Dave Syer - * @author Jimmy Praet (create JobScope based on {@link StepScope}) - * @author Michael Minella - * @since 3.0 - */ -public class JobScope extends BatchScopeSupport { - - private static final String TARGET_NAME_PREFIX = "jobScopedTarget."; - - private Log logger = LogFactory.getLog(getClass()); - - private final Object mutex = new Object(); - - /** - * Context key for clients to use for conversation identifier. - */ - public static final String ID_KEY = "JOB_IDENTIFIER"; - - public JobScope() { - super(); - setName("job"); - } - - /** - * This will be used to resolve expressions in job-scoped beans. - */ - @Override - public Object resolveContextualObject(String key) { - JobContext context = getContext(); - // TODO: support for attributes as well maybe (setters not exposed yet - // so not urgent). - return new BeanWrapperImpl(context).getPropertyValue(key); - } - - /** - * @see Scope#get(String, ObjectFactory) - */ - @Override - public Object get(String name, ObjectFactory objectFactory) { - JobContext context = getContext(); - Object scopedObject = context.getAttribute(name); - - if (scopedObject == null) { - - synchronized (mutex) { - scopedObject = context.getAttribute(name); - if (scopedObject == null) { - - if (logger.isDebugEnabled()) { - logger.debug(String.format("Creating object in scope=%s, name=%s", this.getName(), name)); - } - - scopedObject = objectFactory.getObject(); - context.setAttribute(name, scopedObject); - - } - - } - - } - return scopedObject; - } - - /** - * @see Scope#getConversationId() - */ - @Override - public String getConversationId() { - JobContext context = getContext(); - return context.getId(); - } - - /** - * @see Scope#registerDestructionCallback(String, Runnable) - */ - @Override - public void registerDestructionCallback(String name, Runnable callback) { - JobContext context = getContext(); - if (logger.isDebugEnabled()) { - logger.debug(String.format("Registered destruction callback in scope=%s, name=%s", this.getName(), name)); - } - context.registerDestructionCallback(name, callback); - } - - /** - * @see Scope#remove(String) - */ - @Override - public Object remove(String name) { - JobContext context = getContext(); - if (logger.isDebugEnabled()) { - logger.debug(String.format("Removing from scope=%s, name=%s", this.getName(), name)); - } - return context.removeAttribute(name); - } - - /** - * Get an attribute accessor in the form of a {@link JobContext} that can - * be used to store scoped bean instances. - * - * @return the current job context which we can use as a scope storage - * medium - */ - private JobContext getContext() { - JobContext context = JobSynchronizationManager.getContext(); - if (context == null) { - throw new IllegalStateException("No context holder available for job scope"); - } - return context; - } - - @Override - public String getTargetNamePrefix() { - return TARGET_NAME_PREFIX; - } -} +/* + * Copyright 2006-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.batch.core.scope.context.JobContext; +import org.springframework.batch.core.scope.context.JobSynchronizationManager; +import org.springframework.beans.BeanWrapper; +import org.springframework.beans.BeanWrapperImpl; +import org.springframework.beans.factory.ObjectFactory; +import org.springframework.beans.factory.config.Scope; + +/** + * Scope for job context. Objects in this scope use the Spring container as an object + * factory, so there is only one instance of such a bean per executing job. All objects in + * this scope are <aop:scoped-proxy/> (no need to decorate the bean + * definitions).
      + *
      + * + * In addition, support is provided for late binding of references accessible from the + * {@link JobContext} using #{..} placeholders. Using this feature, bean properties can be + * pulled from the job or job execution context and the job parameters. E.g. + * + *
      + * <bean id="..." class="..." scope="job">
      + * 	<property name="name" value="#{jobParameters[input]}" />
      + * </bean>
      + *
      + * <bean id="..." class="..." scope="job">
      + * 	<property name="name" value="#{jobExecutionContext['input.stem']}.txt" />
      + * </bean>
      + * 
      + * + * The {@link JobContext} is referenced using standard bean property paths (as per + * {@link BeanWrapper}). The examples above all show the use of the Map accessors provided + * as a convenience for job attributes. + * + * @author Dave Syer + * @author Jimmy Praet (create JobScope based on {@link StepScope}) + * @author Michael Minella + * @since 3.0 + */ +public class JobScope extends BatchScopeSupport { + + private static final String TARGET_NAME_PREFIX = "jobScopedTarget."; + + private Log logger = LogFactory.getLog(getClass()); + + private final Object mutex = new Object(); + + /** + * Context key for clients to use for conversation identifier. + */ + public static final String ID_KEY = "JOB_IDENTIFIER"; + + public JobScope() { + super(); + setName("job"); + } + + /** + * This will be used to resolve expressions in job-scoped beans. + */ + @Override + public Object resolveContextualObject(String key) { + JobContext context = getContext(); + // TODO: support for attributes as well maybe (setters not exposed yet + // so not urgent). + return new BeanWrapperImpl(context).getPropertyValue(key); + } + + /** + * @see Scope#get(String, ObjectFactory) + */ + @Override + public Object get(String name, ObjectFactory objectFactory) { + JobContext context = getContext(); + Object scopedObject = context.getAttribute(name); + + if (scopedObject == null) { + + synchronized (mutex) { + scopedObject = context.getAttribute(name); + if (scopedObject == null) { + + if (logger.isDebugEnabled()) { + logger.debug(String.format("Creating object in scope=%s, name=%s", this.getName(), name)); + } + + scopedObject = objectFactory.getObject(); + context.setAttribute(name, scopedObject); + + } + + } + + } + return scopedObject; + } + + /** + * @see Scope#getConversationId() + */ + @Override + public String getConversationId() { + JobContext context = getContext(); + return context.getId(); + } + + /** + * @see Scope#registerDestructionCallback(String, Runnable) + */ + @Override + public void registerDestructionCallback(String name, Runnable callback) { + JobContext context = getContext(); + if (logger.isDebugEnabled()) { + logger.debug(String.format("Registered destruction callback in scope=%s, name=%s", this.getName(), name)); + } + context.registerDestructionCallback(name, callback); + } + + /** + * @see Scope#remove(String) + */ + @Override + public Object remove(String name) { + JobContext context = getContext(); + if (logger.isDebugEnabled()) { + logger.debug(String.format("Removing from scope=%s, name=%s", this.getName(), name)); + } + return context.removeAttribute(name); + } + + /** + * Get an attribute accessor in the form of a {@link JobContext} that can be used to + * store scoped bean instances. + * @return the current job context which we can use as a scope storage medium + */ + private JobContext getContext() { + JobContext context = JobSynchronizationManager.getContext(); + if (context == null) { + throw new IllegalStateException("No context holder available for job scope"); + } + return context; + } + + @Override + public String getTargetNamePrefix() { + return TARGET_NAME_PREFIX; + } + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/scope/StepScope.java b/spring-batch-core/src/main/java/org/springframework/batch/core/scope/StepScope.java index f014bf10e..fe81095ec 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/scope/StepScope.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/scope/StepScope.java @@ -1,176 +1,173 @@ -/* - * Copyright 2006-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.batch.core.scope.context.StepContext; -import org.springframework.batch.core.scope.context.StepSynchronizationManager; -import org.springframework.beans.BeanWrapper; -import org.springframework.beans.BeanWrapperImpl; -import org.springframework.beans.factory.ObjectFactory; -import org.springframework.beans.factory.config.Scope; - -/** - * Scope for step context. Objects in this scope use the Spring container as an - * object factory, so there is only one instance of such a bean per executing - * step. All objects in this scope are <aop:scoped-proxy/> (no need to - * decorate the bean definitions).
      - *
      - * - * In addition, support is provided for late binding of references accessible - * from the {@link StepContext} using #{..} placeholders. Using this feature, - * bean properties can be pulled from the step or job execution context and the - * job parameters. E.g. - * - *
      - * <bean id="..." class="..." scope="step">
      - * 	<property name="parent" ref="#{stepExecutionContext[helper]}" />
      - * </bean>
      - *
      - * <bean id="..." class="..." scope="step">
      - * 	<property name="name" value="#{stepExecutionContext['input.name']}" />
      - * </bean>
      - *
      - * <bean id="..." class="..." scope="step">
      - * 	<property name="name" value="#{jobParameters[input]}" />
      - * </bean>
      - *
      - * <bean id="..." class="..." scope="step">
      - * 	<property name="name" value="#{jobExecutionContext['input.stem']}.txt" />
      - * </bean>
      - * 
      - * - * The {@link StepContext} is referenced using standard bean property paths (as - * per {@link BeanWrapper}). The examples above all show the use of the Map - * accessors provided as a convenience for step and job attributes. - * - * @author Dave Syer - * @author Michael Minella - * @since 2.0 - */ -public class StepScope extends BatchScopeSupport { - - private static final String TARGET_NAME_PREFIX = "stepScopedTarget."; - - private Log logger = LogFactory.getLog(getClass()); - - private final Object mutex = new Object(); - - /** - * Context key for clients to use for conversation identifier. - */ - public static final String ID_KEY = "STEP_IDENTIFIER"; - - public StepScope() { - super(); - setName("step"); - } - - /** - * This will be used to resolve expressions in step-scoped beans. - */ - @Override - public Object resolveContextualObject(String key) { - StepContext context = getContext(); - // TODO: support for attributes as well maybe (setters not exposed yet - // so not urgent). - return new BeanWrapperImpl(context).getPropertyValue(key); - } - - /** - * @see Scope#get(String, ObjectFactory) - */ - @Override - public Object get(String name, ObjectFactory objectFactory) { - StepContext context = getContext(); - Object scopedObject = context.getAttribute(name); - - if (scopedObject == null) { - - synchronized (mutex) { - scopedObject = context.getAttribute(name); - if (scopedObject == null) { - - if (logger.isDebugEnabled()) { - logger.debug(String.format("Creating object in scope=%s, name=%s", this.getName(), name)); - } - - - scopedObject = objectFactory.getObject(); - context.setAttribute(name, scopedObject); - - } - - } - - } - return scopedObject; - } - - /** - * @see Scope#getConversationId() - */ - @Override - public String getConversationId() { - StepContext context = getContext(); - return context.getId(); - } - - /** - * @see Scope#registerDestructionCallback(String, Runnable) - */ - @Override - public void registerDestructionCallback(String name, Runnable callback) { - StepContext context = getContext(); - if (logger.isDebugEnabled()) { - logger.debug(String.format("Registered destruction callback in scope=%s, name=%s", this.getName(), name)); - } - context.registerDestructionCallback(name, callback); - } - - /** - * @see Scope#remove(String) - */ - @Override - public Object remove(String name) { - StepContext context = getContext(); - if (logger.isDebugEnabled()) { - logger.debug(String.format("Removing from scope=%s, name=%s", this.getName(), name)); - } - return context.removeAttribute(name); - } - - /** - * Get an attribute accessor in the form of a {@link StepContext} that can - * be used to store scoped bean instances. - * - * @return the current step context which we can use as a scope storage - * medium - */ - private StepContext getContext() { - StepContext context = StepSynchronizationManager.getContext(); - if (context == null) { - throw new IllegalStateException("No context holder available for step scope"); - } - return context; - } - - @Override - public String getTargetNamePrefix() { - return TARGET_NAME_PREFIX; - } -} +/* + * Copyright 2006-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.batch.core.scope.context.StepContext; +import org.springframework.batch.core.scope.context.StepSynchronizationManager; +import org.springframework.beans.BeanWrapper; +import org.springframework.beans.BeanWrapperImpl; +import org.springframework.beans.factory.ObjectFactory; +import org.springframework.beans.factory.config.Scope; + +/** + * Scope for step context. Objects in this scope use the Spring container as an object + * factory, so there is only one instance of such a bean per executing step. All objects + * in this scope are <aop:scoped-proxy/> (no need to decorate the bean + * definitions).
      + *
      + * + * In addition, support is provided for late binding of references accessible from the + * {@link StepContext} using #{..} placeholders. Using this feature, bean properties can + * be pulled from the step or job execution context and the job parameters. E.g. + * + *
      + * <bean id="..." class="..." scope="step">
      + * 	<property name="parent" ref="#{stepExecutionContext[helper]}" />
      + * </bean>
      + *
      + * <bean id="..." class="..." scope="step">
      + * 	<property name="name" value="#{stepExecutionContext['input.name']}" />
      + * </bean>
      + *
      + * <bean id="..." class="..." scope="step">
      + * 	<property name="name" value="#{jobParameters[input]}" />
      + * </bean>
      + *
      + * <bean id="..." class="..." scope="step">
      + * 	<property name="name" value="#{jobExecutionContext['input.stem']}.txt" />
      + * </bean>
      + * 
      + * + * The {@link StepContext} is referenced using standard bean property paths (as per + * {@link BeanWrapper}). The examples above all show the use of the Map accessors provided + * as a convenience for step and job attributes. + * + * @author Dave Syer + * @author Michael Minella + * @since 2.0 + */ +public class StepScope extends BatchScopeSupport { + + private static final String TARGET_NAME_PREFIX = "stepScopedTarget."; + + private Log logger = LogFactory.getLog(getClass()); + + private final Object mutex = new Object(); + + /** + * Context key for clients to use for conversation identifier. + */ + public static final String ID_KEY = "STEP_IDENTIFIER"; + + public StepScope() { + super(); + setName("step"); + } + + /** + * This will be used to resolve expressions in step-scoped beans. + */ + @Override + public Object resolveContextualObject(String key) { + StepContext context = getContext(); + // TODO: support for attributes as well maybe (setters not exposed yet + // so not urgent). + return new BeanWrapperImpl(context).getPropertyValue(key); + } + + /** + * @see Scope#get(String, ObjectFactory) + */ + @Override + public Object get(String name, ObjectFactory objectFactory) { + StepContext context = getContext(); + Object scopedObject = context.getAttribute(name); + + if (scopedObject == null) { + + synchronized (mutex) { + scopedObject = context.getAttribute(name); + if (scopedObject == null) { + + if (logger.isDebugEnabled()) { + logger.debug(String.format("Creating object in scope=%s, name=%s", this.getName(), name)); + } + + scopedObject = objectFactory.getObject(); + context.setAttribute(name, scopedObject); + + } + + } + + } + return scopedObject; + } + + /** + * @see Scope#getConversationId() + */ + @Override + public String getConversationId() { + StepContext context = getContext(); + return context.getId(); + } + + /** + * @see Scope#registerDestructionCallback(String, Runnable) + */ + @Override + public void registerDestructionCallback(String name, Runnable callback) { + StepContext context = getContext(); + if (logger.isDebugEnabled()) { + logger.debug(String.format("Registered destruction callback in scope=%s, name=%s", this.getName(), name)); + } + context.registerDestructionCallback(name, callback); + } + + /** + * @see Scope#remove(String) + */ + @Override + public Object remove(String name) { + StepContext context = getContext(); + if (logger.isDebugEnabled()) { + logger.debug(String.format("Removing from scope=%s, name=%s", this.getName(), name)); + } + return context.removeAttribute(name); + } + + /** + * Get an attribute accessor in the form of a {@link StepContext} that can be used to + * store scoped bean instances. + * @return the current step context which we can use as a scope storage medium + */ + private StepContext getContext() { + StepContext context = StepSynchronizationManager.getContext(); + if (context == null) { + throw new IllegalStateException("No context holder available for step scope"); + } + return context; + } + + @Override + public String getTargetNamePrefix() { + return TARGET_NAME_PREFIX; + } + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/ChunkContext.java b/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/ChunkContext.java index 0aac72ec6..23ca8f5e2 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/ChunkContext.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/ChunkContext.java @@ -21,13 +21,12 @@ import java.util.Arrays; import org.springframework.core.AttributeAccessorSupport; /** - * Context object for weakly typed data stored for the duration of a chunk - * (usually a group of items processed together in a transaction). If there is a - * rollback and the chunk is retried the same context will be associated with - * it. - * + * Context object for weakly typed data stored for the duration of a chunk (usually a + * group of items processed together in a transaction). If there is a rollback and the + * chunk is retried the same context will be associated with it. + * * @author Dave Syer - * + * */ @SuppressWarnings("serial") public class ChunkContext extends AttributeAccessorSupport { @@ -66,13 +65,13 @@ public class ChunkContext extends AttributeAccessorSupport { /* * (non-Javadoc) - * + * * @see java.lang.Object#toString() */ @Override public String toString() { - return String.format("ChunkContext: attributes=%s, complete=%b, stepContext=%s", Arrays - .asList(attributeNames()), complete, stepContext); + return String.format("ChunkContext: attributes=%s, complete=%b, stepContext=%s", + Arrays.asList(attributeNames()), complete, stepContext); } } \ No newline at end of file diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/JobContext.java b/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/JobContext.java index 038432702..4121b25f2 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/JobContext.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/JobContext.java @@ -1,239 +1,232 @@ -/* - * Copyright 2006-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope.context; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Properties; -import java.util.Set; - -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobInstance; -import org.springframework.batch.core.JobParameter; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.UnexpectedJobExecutionException; -import org.springframework.batch.core.scope.StepScope; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.repeat.context.SynchronizedAttributeAccessor; -import org.springframework.lang.Nullable; -import org.springframework.util.Assert; - -/** - * A context object that can be used to interrogate the current {@link JobExecution} and some of its associated - * properties using expressions - * based on bean paths. Has public getters for the job execution and - * convenience methods for accessing commonly used properties like the {@link ExecutionContext} associated with the job - * execution. - * - * @author Dave Syer - * @author Jimmy Praet (create JobContext based on {@link StepContext}) - * @author Mahmoud Ben Hassine - * @since 3.0 - */ -public class JobContext extends SynchronizedAttributeAccessor { - - private JobExecution jobExecution; - - private Map> callbacks = new HashMap<>(); - - public JobContext(JobExecution jobExecution) { - super(); - Assert.notNull(jobExecution, "A JobContext must have a non-null JobExecution"); - this.jobExecution = jobExecution; - } - - /** - * Convenient accessor for current job name identifier. - * - * @return the job name identifier of the enclosing {@link JobInstance} associated with the current - * {@link JobExecution} - */ - public String getJobName() { - Assert.state(jobExecution.getJobInstance() != null, "JobExecution does not have a JobInstance"); - return jobExecution.getJobInstance().getJobName(); - } - - /** - * Convenient accessor for System properties to make it easy to access them - * from placeholder expressions. - * - * @return the current System properties - */ - public Properties getSystemProperties() { - return System.getProperties(); - } - - /** - * @return a map containing the items from the job {@link ExecutionContext} - */ - public Map getJobExecutionContext() { - Map result = new HashMap<>(); - for (Entry entry : jobExecution.getExecutionContext().entrySet()) { - result.put(entry.getKey(), entry.getValue()); - } - return Collections.unmodifiableMap(result); - } - - /** - * @return a map containing the items from the {@link JobParameters} - */ - public Map getJobParameters() { - Map result = new HashMap<>(); - for (Entry entry : jobExecution.getJobParameters().getParameters() - .entrySet()) { - result.put(entry.getKey(), entry.getValue().getValue()); - } - return Collections.unmodifiableMap(result); - } - - /** - * Allow clients to register callbacks for clean up on close. - * - * @param name - * the callback id (unique attribute key in this context) - * @param callback - * a callback to execute on close - */ - public void registerDestructionCallback(String name, Runnable callback) { - synchronized (callbacks) { - Set set = callbacks.get(name); - if (set == null) { - set = new HashSet<>(); - callbacks.put(name, set); - } - set.add(callback); - } - } - - private void unregisterDestructionCallbacks(String name) { - synchronized (callbacks) { - callbacks.remove(name); - } - } - - /** - * Override base class behaviour to ensure destruction callbacks are - * unregistered as well as the default behaviour. - * - * @see SynchronizedAttributeAccessor#removeAttribute(String) - */ - @Override - @Nullable - public Object removeAttribute(String name) { - unregisterDestructionCallbacks(name); - return super.removeAttribute(name); - } - - /** - * Clean up the context at the end of a step execution. Must be called once - * at the end of a step execution to honour the destruction callback - * contract from the {@link StepScope}. - */ - public void close() { - - List errors = new ArrayList<>(); - - Map> copy = Collections.unmodifiableMap(callbacks); - - for (Entry> entry : copy.entrySet()) { - Set set = entry.getValue(); - for (Runnable callback : set) { - if (callback != null) { - /* - * The documentation of the interface says that these - * callbacks must not throw exceptions, but we don't trust - * them necessarily... - */ - try { - callback.run(); - } catch (RuntimeException t) { - errors.add(t); - } - } - } - } - - if (errors.isEmpty()) { - return; - } - - Exception error = errors.get(0); - if (error instanceof RuntimeException) { - throw (RuntimeException) error; - } else { - throw new UnexpectedJobExecutionException("Could not close step context, rethrowing first of " - + errors.size() + " exceptions.", error); - } - } - - /** - * The current {@link JobExecution} that is active in this context. - * - * @return the current {@link JobExecution} - */ - public JobExecution getJobExecution() { - return jobExecution; - } - - /** - * @return unique identifier for this context based on the step execution - */ - public String getId() { - Assert.state(jobExecution.getId() != null, "JobExecution has no id. " - + "It must be saved before it can be used in job scope."); - return "jobExecution#" + jobExecution.getId(); - } - - /** - * Extend the base class method to include the job execution itself as a key - * (i.e. two contexts are only equal if their job executions are the same). - */ - @Override - public boolean equals(Object other) { - if (!(other instanceof JobContext)) { - return false; - } - if (other == this) { - return true; - } - JobContext context = (JobContext) other; - if (context.jobExecution == jobExecution) { - return true; - } - return jobExecution.equals(context.jobExecution); - } - - /** - * Overrides the default behaviour to provide a hash code based only on the - * job execution. - */ - @Override - public int hashCode() { - return jobExecution.hashCode(); - } - - @Override - public String toString() { - return super.toString() + ", jobExecutionContext=" + getJobExecutionContext() + ", jobParameters=" - + getJobParameters(); - } - -} +/* + * Copyright 2006-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope.context; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Properties; +import java.util.Set; + +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobInstance; +import org.springframework.batch.core.JobParameter; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.UnexpectedJobExecutionException; +import org.springframework.batch.core.scope.StepScope; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.repeat.context.SynchronizedAttributeAccessor; +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; + +/** + * A context object that can be used to interrogate the current {@link JobExecution} and + * some of its associated properties using expressions based on bean paths. Has public + * getters for the job execution and convenience methods for accessing commonly used + * properties like the {@link ExecutionContext} associated with the job execution. + * + * @author Dave Syer + * @author Jimmy Praet (create JobContext based on {@link StepContext}) + * @author Mahmoud Ben Hassine + * @since 3.0 + */ +public class JobContext extends SynchronizedAttributeAccessor { + + private JobExecution jobExecution; + + private Map> callbacks = new HashMap<>(); + + public JobContext(JobExecution jobExecution) { + super(); + Assert.notNull(jobExecution, "A JobContext must have a non-null JobExecution"); + this.jobExecution = jobExecution; + } + + /** + * Convenient accessor for current job name identifier. + * @return the job name identifier of the enclosing {@link JobInstance} associated + * with the current {@link JobExecution} + */ + public String getJobName() { + Assert.state(jobExecution.getJobInstance() != null, "JobExecution does not have a JobInstance"); + return jobExecution.getJobInstance().getJobName(); + } + + /** + * Convenient accessor for System properties to make it easy to access them from + * placeholder expressions. + * @return the current System properties + */ + public Properties getSystemProperties() { + return System.getProperties(); + } + + /** + * @return a map containing the items from the job {@link ExecutionContext} + */ + public Map getJobExecutionContext() { + Map result = new HashMap<>(); + for (Entry entry : jobExecution.getExecutionContext().entrySet()) { + result.put(entry.getKey(), entry.getValue()); + } + return Collections.unmodifiableMap(result); + } + + /** + * @return a map containing the items from the {@link JobParameters} + */ + public Map getJobParameters() { + Map result = new HashMap<>(); + for (Entry entry : jobExecution.getJobParameters().getParameters().entrySet()) { + result.put(entry.getKey(), entry.getValue().getValue()); + } + return Collections.unmodifiableMap(result); + } + + /** + * Allow clients to register callbacks for clean up on close. + * @param name the callback id (unique attribute key in this context) + * @param callback a callback to execute on close + */ + public void registerDestructionCallback(String name, Runnable callback) { + synchronized (callbacks) { + Set set = callbacks.get(name); + if (set == null) { + set = new HashSet<>(); + callbacks.put(name, set); + } + set.add(callback); + } + } + + private void unregisterDestructionCallbacks(String name) { + synchronized (callbacks) { + callbacks.remove(name); + } + } + + /** + * Override base class behaviour to ensure destruction callbacks are unregistered as + * well as the default behaviour. + * + * @see SynchronizedAttributeAccessor#removeAttribute(String) + */ + @Override + @Nullable + public Object removeAttribute(String name) { + unregisterDestructionCallbacks(name); + return super.removeAttribute(name); + } + + /** + * Clean up the context at the end of a step execution. Must be called once at the end + * of a step execution to honour the destruction callback contract from the + * {@link StepScope}. + */ + public void close() { + + List errors = new ArrayList<>(); + + Map> copy = Collections.unmodifiableMap(callbacks); + + for (Entry> entry : copy.entrySet()) { + Set set = entry.getValue(); + for (Runnable callback : set) { + if (callback != null) { + /* + * The documentation of the interface says that these callbacks must + * not throw exceptions, but we don't trust them necessarily... + */ + try { + callback.run(); + } + catch (RuntimeException t) { + errors.add(t); + } + } + } + } + + if (errors.isEmpty()) { + return; + } + + Exception error = errors.get(0); + if (error instanceof RuntimeException) { + throw (RuntimeException) error; + } + else { + throw new UnexpectedJobExecutionException( + "Could not close step context, rethrowing first of " + errors.size() + " exceptions.", error); + } + } + + /** + * The current {@link JobExecution} that is active in this context. + * @return the current {@link JobExecution} + */ + public JobExecution getJobExecution() { + return jobExecution; + } + + /** + * @return unique identifier for this context based on the step execution + */ + public String getId() { + Assert.state(jobExecution.getId() != null, + "JobExecution has no id. " + "It must be saved before it can be used in job scope."); + return "jobExecution#" + jobExecution.getId(); + } + + /** + * Extend the base class method to include the job execution itself as a key (i.e. two + * contexts are only equal if their job executions are the same). + */ + @Override + public boolean equals(Object other) { + if (!(other instanceof JobContext)) { + return false; + } + if (other == this) { + return true; + } + JobContext context = (JobContext) other; + if (context.jobExecution == jobExecution) { + return true; + } + return jobExecution.equals(context.jobExecution); + } + + /** + * Overrides the default behaviour to provide a hash code based only on the job + * execution. + */ + @Override + public int hashCode() { + return jobExecution.hashCode(); + } + + @Override + public String toString() { + return super.toString() + ", jobExecutionContext=" + getJobExecutionContext() + ", jobParameters=" + + getJobParameters(); + } + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/JobScopeManager.java b/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/JobScopeManager.java index 467ebafad..668f53c8f 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/JobScopeManager.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/JobScopeManager.java @@ -22,9 +22,8 @@ import org.springframework.batch.core.Job; import org.springframework.batch.core.JobExecution; /** - * Convenient aspect to wrap a single threaded job execution, where the - * implementation of the {@link Job} is not job scope aware (i.e. not the ones - * provided by the framework). + * Convenient aspect to wrap a single threaded job execution, where the implementation of + * the {@link Job} is not job scope aware (i.e. not the ones provided by the framework). * * @author Dave Syer * @author Jimmy Praet diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/JobSynchronizationManager.java b/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/JobSynchronizationManager.java index ba0892c23..8e234046a 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/JobSynchronizationManager.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/JobSynchronizationManager.java @@ -1,94 +1,93 @@ -/* - * Copyright 2013-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope.context; - -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.lang.Nullable; - -/** - * Central convenience class for framework use in managing the job scope - * context. Generally only to be used by implementations of {@link Job}. N.B. - * it is the responsibility of every {@link Job} implementation to ensure that - * a {@link JobContext} is available on every thread that might be involved in - * a job execution, including worker threads from a pool. - * - * @author Dave Syer - * @author Jimmy Praet - * @author Mahmoud Ben Hassine - * @since 3.0 - */ -public class JobSynchronizationManager { - - private static final SynchronizationManagerSupport manager = new SynchronizationManagerSupport() { - - @Override - protected JobContext createNewContext(JobExecution execution) { - return new JobContext(execution); - } - - @Override - protected void close(JobContext context) { - context.close(); - } - }; - - /** - * Getter for the current context if there is one, otherwise returns {@code null}. - * - * @return the current {@link JobContext} or {@code null} if there is none (if one - * has not been registered for this thread). - */ - @Nullable - public static JobContext getContext() { - return manager.getContext(); - } - - /** - * Register a context with the current thread - always put a matching - * {@link #close()} call in a finally block to ensure that the correct - * context is available in the enclosing block. - * - * @param JobExecution the step context to register - * @return a new {@link JobContext} or the current one if it has the same - * {@link JobExecution} - */ - public static JobContext register(JobExecution JobExecution) { - return manager.register(JobExecution); - } - - /** - * Method for unregistering the current context - should always and only be - * used by in conjunction with a matching {@link #register(JobExecution)} - * to ensure that {@link #getContext()} always returns the correct value. - * Does not call {@link JobContext#close()} - that is left up to the caller - * because he has a reference to the context (having registered it) and only - * he has knowledge of when the step actually ended. - */ - public static void close() { - manager.close(); - } - - /** - * A convenient "deep" close operation. Call this instead of - * {@link #close()} if the step execution for the current context is ending. - * Delegates to {@link JobContext#close()} and then ensures that - * {@link #close()} is also called in a finally block. - */ - public static void release() { - manager.release(); - } -} +/* + * Copyright 2013-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope.context; + +import org.springframework.batch.core.Job; +import org.springframework.batch.core.JobExecution; +import org.springframework.lang.Nullable; + +/** + * Central convenience class for framework use in managing the job scope context. + * Generally only to be used by implementations of {@link Job}. N.B. it is the + * responsibility of every {@link Job} implementation to ensure that a {@link JobContext} + * is available on every thread that might be involved in a job execution, including + * worker threads from a pool. + * + * @author Dave Syer + * @author Jimmy Praet + * @author Mahmoud Ben Hassine + * @since 3.0 + */ +public class JobSynchronizationManager { + + private static final SynchronizationManagerSupport manager = new SynchronizationManagerSupport() { + + @Override + protected JobContext createNewContext(JobExecution execution) { + return new JobContext(execution); + } + + @Override + protected void close(JobContext context) { + context.close(); + } + }; + + /** + * Getter for the current context if there is one, otherwise returns {@code null}. + * @return the current {@link JobContext} or {@code null} if there is none (if one has + * not been registered for this thread). + */ + @Nullable + public static JobContext getContext() { + return manager.getContext(); + } + + /** + * Register a context with the current thread - always put a matching {@link #close()} + * call in a finally block to ensure that the correct context is available in the + * enclosing block. + * @param JobExecution the step context to register + * @return a new {@link JobContext} or the current one if it has the same + * {@link JobExecution} + */ + public static JobContext register(JobExecution JobExecution) { + return manager.register(JobExecution); + } + + /** + * Method for unregistering the current context - should always and only be used by in + * conjunction with a matching {@link #register(JobExecution)} to ensure that + * {@link #getContext()} always returns the correct value. Does not call + * {@link JobContext#close()} - that is left up to the caller because he has a + * reference to the context (having registered it) and only he has knowledge of when + * the step actually ended. + */ + public static void close() { + manager.close(); + } + + /** + * A convenient "deep" close operation. Call this instead of {@link #close()} if the + * step execution for the current context is ending. Delegates to + * {@link JobContext#close()} and then ensures that {@link #close()} is also called in + * a finally block. + */ + public static void release() { + manager.release(); + } + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/StepContext.java b/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/StepContext.java index 20ff9fe4d..fb6faf25a 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/StepContext.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/StepContext.java @@ -37,12 +37,11 @@ import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** - * A context object that can be used to interrogate the current - * {@link StepExecution} and some of its associated properties using expressions - * based on bean paths. Has public getters for the step execution and - * convenience methods for accessing commonly used properties like the - * {@link ExecutionContext} associated with the step or its enclosing job - * execution. + * A context object that can be used to interrogate the current {@link StepExecution} and + * some of its associated properties using expressions based on bean paths. Has public + * getters for the step execution and convenience methods for accessing commonly used + * properties like the {@link ExecutionContext} associated with the step or its enclosing + * job execution. * * @author Dave Syer * @author Michael Minella @@ -57,9 +56,7 @@ public class StepContext extends SynchronizedAttributeAccessor { private Map> callbacks = new HashMap<>(); /** - * Create a new instance of {@link StepContext} for this - * {@link StepExecution}. - * + * Create a new instance of {@link StepContext} for this {@link StepExecution}. * @param stepExecution a step execution */ public StepContext(StepExecution stepExecution) { @@ -69,10 +66,8 @@ public class StepContext extends SynchronizedAttributeAccessor { } /** - * Convenient accessor for current step name identifier. Usually this is the - * same as the bean name of the step that is executing (but might not be - * e.g. in a partition). - * + * Convenient accessor for current step name identifier. Usually this is the same as + * the bean name of the step that is executing (but might not be e.g. in a partition). * @return the step name identifier of the current {@link StepExecution} */ public String getStepName() { @@ -81,9 +76,8 @@ public class StepContext extends SynchronizedAttributeAccessor { /** * Convenient accessor for current job name identifier. - * - * @return the job name identifier of the enclosing {@link JobInstance} - * associated with the current {@link StepExecution} + * @return the job name identifier of the enclosing {@link JobInstance} associated + * with the current {@link StepExecution} */ public String getJobName() { Assert.state(stepExecution.getJobExecution() != null, "StepExecution does not have a JobExecution"); @@ -94,9 +88,8 @@ public class StepContext extends SynchronizedAttributeAccessor { /** * Convenient accessor for current {@link JobInstance} identifier. - * - * @return the identifier of the enclosing {@link JobInstance} - * associated with the current {@link StepExecution} + * @return the identifier of the enclosing {@link JobInstance} associated with the + * current {@link StepExecution} */ public Long getJobInstanceId() { Assert.state(stepExecution.getJobExecution() != null, "StepExecution does not have a JobExecution"); @@ -106,9 +99,8 @@ public class StepContext extends SynchronizedAttributeAccessor { } /** - * Convenient accessor for System properties to make it easy to access them - * from placeholder expressions. - * + * Convenient accessor for System properties to make it easy to access them from + * placeholder expressions. * @return the current System properties */ public Properties getSystemProperties() { @@ -150,7 +142,6 @@ public class StepContext extends SynchronizedAttributeAccessor { /** * Allow clients to register callbacks for clean up on close. - * * @param name the callback id (unique attribute key in this context) * @param callback a callback to execute on close */ @@ -172,8 +163,8 @@ public class StepContext extends SynchronizedAttributeAccessor { } /** - * Override base class behaviour to ensure destruction callbacks are - * unregistered as well as the default behaviour. + * Override base class behaviour to ensure destruction callbacks are unregistered as + * well as the default behaviour. * * @see SynchronizedAttributeAccessor#removeAttribute(String) */ @@ -185,9 +176,9 @@ public class StepContext extends SynchronizedAttributeAccessor { } /** - * Clean up the context at the end of a step execution. Must be called once - * at the end of a step execution to honour the destruction callback - * contract from the {@link StepScope}. + * Clean up the context at the end of a step execution. Must be called once at the end + * of a step execution to honour the destruction callback contract from the + * {@link StepScope}. */ public void close() { @@ -200,9 +191,8 @@ public class StepContext extends SynchronizedAttributeAccessor { for (Runnable callback : set) { if (callback != null) { /* - * The documentation of the interface says that these - * callbacks must not throw exceptions, but we don't trust - * them necessarily... + * The documentation of the interface says that these callbacks must + * not throw exceptions, but we don't trust them necessarily... */ try { callback.run(); @@ -223,14 +213,13 @@ public class StepContext extends SynchronizedAttributeAccessor { throw (RuntimeException) error; } else { - throw new UnexpectedJobExecutionException("Could not close step context, rethrowing first of " - + errors.size() + " exceptions.", error); + throw new UnexpectedJobExecutionException( + "Could not close step context, rethrowing first of " + errors.size() + " exceptions.", error); } } /** * The current {@link StepExecution} that is active in this context. - * * @return the current {@link StepExecution} */ public StepExecution getStepExecution() { @@ -241,15 +230,14 @@ public class StepContext extends SynchronizedAttributeAccessor { * @return unique identifier for this context based on the step execution */ public String getId() { - Assert.state(stepExecution.getId() != null, "StepExecution has no id. " - + "It must be saved before it can be used in step scope."); + Assert.state(stepExecution.getId() != null, + "StepExecution has no id. " + "It must be saved before it can be used in step scope."); return "execution#" + stepExecution.getId(); } /** - * Extend the base class method to include the step execution itself as a - * key (i.e. two contexts are only equal if their step executions are the - * same). + * Extend the base class method to include the step execution itself as a key (i.e. + * two contexts are only equal if their step executions are the same). * * @see SynchronizedAttributeAccessor#equals(Object) */ @@ -269,8 +257,8 @@ public class StepContext extends SynchronizedAttributeAccessor { } /** - * Overrides the default behaviour to provide a hash code based only on the - * step execution. + * Overrides the default behaviour to provide a hash code based only on the step + * execution. * * @see SynchronizedAttributeAccessor#hashCode() */ diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/StepContextRepeatCallback.java b/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/StepContextRepeatCallback.java index 7ca7fae71..a30466c37 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/StepContextRepeatCallback.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/StepContextRepeatCallback.java @@ -28,8 +28,8 @@ import org.springframework.batch.repeat.RepeatStatus; import org.springframework.util.ObjectUtils; /** - * Convenient base class for clients who need to do something in a repeat - * callback inside a {@link Step}. + * Convenient base class for clients who need to do something in a repeat callback inside + * a {@link Step}. * * @author Dave Syer * @author Mahmoud Ben Hassine @@ -44,19 +44,19 @@ public abstract class StepContextRepeatCallback implements RepeatCallback { private final Log logger = LogFactory.getLog(StepContextRepeatCallback.class); /** - * @param stepExecution instance of {@link StepExecution} to be used by StepContextRepeatCallback. + * @param stepExecution instance of {@link StepExecution} to be used by + * StepContextRepeatCallback. */ public StepContextRepeatCallback(StepExecution stepExecution) { this.stepExecution = stepExecution; } /** - * Manage the {@link StepContext} lifecycle. Business processing should be - * delegated to {@link #doInChunkContext(RepeatContext, ChunkContext)}. This - * is to ensure that the current thread has a reference to the context, even - * if the callback is executed in a pooled thread. Handles the registration - * and unregistration of the step context, so clients should not duplicate - * those calls. + * Manage the {@link StepContext} lifecycle. Business processing should be delegated + * to {@link #doInChunkContext(RepeatContext, ChunkContext)}. This is to ensure that + * the current thread has a reference to the context, even if the callback is executed + * in a pooled thread. Handles the registration and unregistration of the step + * context, so clients should not duplicate those calls. * * @see RepeatCallback#doInIteration(RepeatContext) */ @@ -67,7 +67,7 @@ public abstract class StepContextRepeatCallback implements RepeatCallback { // otherwise step-scoped beans will be re-initialised for each chunk. StepContext stepContext = StepSynchronizationManager.register(stepExecution); if (logger.isDebugEnabled()) { - logger.debug("Preparing chunk execution for StepContext: "+ObjectUtils.identityToString(stepContext)); + logger.debug("Preparing chunk execution for StepContext: " + ObjectUtils.identityToString(stepContext)); } ChunkContext chunkContext = attributeQueue.poll(); @@ -77,7 +77,7 @@ public abstract class StepContextRepeatCallback implements RepeatCallback { try { if (logger.isDebugEnabled()) { - logger.debug("Chunk execution starting: queue size="+attributeQueue.size()); + logger.debug("Chunk execution starting: queue size=" + attributeQueue.size()); } return doInChunkContext(context, chunkContext); } @@ -92,20 +92,17 @@ public abstract class StepContextRepeatCallback implements RepeatCallback { } /** - * Do the work required for this chunk of the step. The {@link ChunkContext} - * provided is managed by the base class, so that if there is still work to - * do for the task in hand state can be stored here. In a multi-threaded - * client, the base class ensures that only one thread at a time can be - * working on each instance of {@link ChunkContext}. Workers should signal - * that they are finished with a context by removing all the attributes they - * have added. If a worker does not remove them another thread might see - * stale state. - * + * Do the work required for this chunk of the step. The {@link ChunkContext} provided + * is managed by the base class, so that if there is still work to do for the task in + * hand state can be stored here. In a multi-threaded client, the base class ensures + * that only one thread at a time can be working on each instance of + * {@link ChunkContext}. Workers should signal that they are finished with a context + * by removing all the attributes they have added. If a worker does not remove them + * another thread might see stale state. * @param context the current {@link RepeatContext} * @param chunkContext the chunk context in which to carry out the work * @return the repeat status from the execution - * @throws Exception implementations can throw an exception if anything goes - * wrong + * @throws Exception implementations can throw an exception if anything goes wrong */ public abstract RepeatStatus doInChunkContext(RepeatContext context, ChunkContext chunkContext) throws Exception; diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/StepScopeManager.java b/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/StepScopeManager.java index f9f35a1f1..7780dc950 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/StepScopeManager.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/StepScopeManager.java @@ -23,12 +23,11 @@ import org.springframework.batch.core.Step; import org.springframework.batch.core.StepExecution; /** - * Convenient aspect to wrap a single threaded step execution, where the - * implementation of the {@link Step} is not step scope aware (i.e. not the ones - * provided by the framework). - * + * Convenient aspect to wrap a single threaded step execution, where the implementation of + * the {@link Step} is not step scope aware (i.e. not the ones provided by the framework). + * * @author Dave Syer - * + * */ @Aspect public class StepScopeManager { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/StepSynchronizationManager.java b/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/StepSynchronizationManager.java index 88ac3ab47..9565d9cd2 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/StepSynchronizationManager.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/StepSynchronizationManager.java @@ -1,95 +1,93 @@ -/* - * Copyright 2006-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope.context; - -import org.springframework.batch.core.Step; -import org.springframework.batch.core.StepExecution; -import org.springframework.lang.Nullable; - -/** - * Central convenience class for framework use in managing the step scope - * context. Generally only to be used by implementations of {@link Step}. N.B. - * it is the responsibility of every {@link Step} implementation to ensure that - * a {@link StepContext} is available on every thread that might be involved in - * a step execution, including worker threads from a pool. - * - * @author Dave Syer - * @author Michael Minella - * @author Mahmoud Ben Hassine - * - */ -public class StepSynchronizationManager { - - private static final SynchronizationManagerSupport manager = - new SynchronizationManagerSupport() { - - @Override - protected StepContext createNewContext(StepExecution execution) { - return new StepContext(execution); - } - - @Override - protected void close(StepContext context) { - context.close(); - } - }; - - /** - * Getter for the current context if there is one, otherwise returns {@code null}. - * - * @return the current {@link StepContext} or {@code null} if there is none (if one - * has not been registered for this thread). - */ - @Nullable - public static StepContext getContext() { - return manager.getContext(); - } - - /** - * Register a context with the current thread - always put a matching - * {@link #close()} call in a finally block to ensure that the correct - * context is available in the enclosing block. - * - * @param stepExecution the step context to register - * @return a new {@link StepContext} or the current one if it has the same - * {@link StepExecution} - */ - public static StepContext register(StepExecution stepExecution) { - return manager.register(stepExecution); - } - - /** - * Method for unregistering the current context - should always and only be - * used by in conjunction with a matching {@link #register(StepExecution)} - * to ensure that {@link #getContext()} always returns the correct value. - * Does not call {@link StepContext#close()} - that is left up to the caller - * because he has a reference to the context (having registered it) and only - * he has knowledge of when the step actually ended. - */ - public static void close() { - manager.close(); - } - - /** - * A convenient "deep" close operation. Call this instead of - * {@link #close()} if the step execution for the current context is ending. - * Delegates to {@link StepContext#close()} and then ensures that - * {@link #close()} is also called in a finally block. - */ - public static void release() { - manager.release(); - } -} +/* + * Copyright 2006-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope.context; + +import org.springframework.batch.core.Step; +import org.springframework.batch.core.StepExecution; +import org.springframework.lang.Nullable; + +/** + * Central convenience class for framework use in managing the step scope context. + * Generally only to be used by implementations of {@link Step}. N.B. it is the + * responsibility of every {@link Step} implementation to ensure that a + * {@link StepContext} is available on every thread that might be involved in a step + * execution, including worker threads from a pool. + * + * @author Dave Syer + * @author Michael Minella + * @author Mahmoud Ben Hassine + * + */ +public class StepSynchronizationManager { + + private static final SynchronizationManagerSupport manager = new SynchronizationManagerSupport() { + + @Override + protected StepContext createNewContext(StepExecution execution) { + return new StepContext(execution); + } + + @Override + protected void close(StepContext context) { + context.close(); + } + }; + + /** + * Getter for the current context if there is one, otherwise returns {@code null}. + * @return the current {@link StepContext} or {@code null} if there is none (if one + * has not been registered for this thread). + */ + @Nullable + public static StepContext getContext() { + return manager.getContext(); + } + + /** + * Register a context with the current thread - always put a matching {@link #close()} + * call in a finally block to ensure that the correct context is available in the + * enclosing block. + * @param stepExecution the step context to register + * @return a new {@link StepContext} or the current one if it has the same + * {@link StepExecution} + */ + public static StepContext register(StepExecution stepExecution) { + return manager.register(stepExecution); + } + + /** + * Method for unregistering the current context - should always and only be used by in + * conjunction with a matching {@link #register(StepExecution)} to ensure that + * {@link #getContext()} always returns the correct value. Does not call + * {@link StepContext#close()} - that is left up to the caller because he has a + * reference to the context (having registered it) and only he has knowledge of when + * the step actually ended. + */ + public static void close() { + manager.close(); + } + + /** + * A convenient "deep" close operation. Call this instead of {@link #close()} if the + * step execution for the current context is ending. Delegates to + * {@link StepContext#close()} and then ensures that {@link #close()} is also called + * in a finally block. + */ + public static void release() { + manager.release(); + } + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/SynchronizationManagerSupport.java b/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/SynchronizationManagerSupport.java index 72c4e7d5a..1891f5588 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/SynchronizationManagerSupport.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/SynchronizationManagerSupport.java @@ -1,178 +1,172 @@ -/* - * Copyright 2013-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope.context; - -import java.util.Map; -import java.util.Stack; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicInteger; - -import org.springframework.lang.Nullable; - - -/** - * Central convenience class for framework use in managing the scope - * context. - * - * @author Dave Syer - * @author Jimmy Praet - * @author Mahmoud Ben Hassine - * @since 3.0 - */ -public abstract class SynchronizationManagerSupport { - - /* - * We have to deal with single and multi-threaded execution, with a single - * and with multiple step execution instances. That's 2x2 = 4 scenarios. - */ - - /** - * Storage for the current execution; has to be ThreadLocal because it - * is needed to locate a context in components that are not part of a - * step/job (like when re-hydrating a scoped proxy). Doesn't use - * InheritableThreadLocal because there are side effects if a step is trying - * to run multiple child steps (e.g. with partitioning). The Stack is used - * to cover the single threaded case, so that the API is the same as - * multi-threaded. - */ - private final ThreadLocal> executionHolder = new ThreadLocal<>(); - - /** - * Reference counter for each execution: how many threads are using the - * same one? - */ - private final Map counts = new ConcurrentHashMap<>(); - - /** - * Simple map from a running execution to the associated context. - */ - private final Map contexts = new ConcurrentHashMap<>(); - - /** - * Getter for the current context if there is one, otherwise returns {@code null}. - * - * @return the current context or {@code null} if there is none (if one - * has not been registered for this thread). - */ - @Nullable - public C getContext() { - if (getCurrent().isEmpty()) { - return null; - } - synchronized (contexts) { - return contexts.get(getCurrent().peek()); - } - } - - /** - * Register a context with the current thread - always put a matching {@link #close()} call in a finally block to - * ensure that the correct - * context is available in the enclosing block. - * - * @param execution the execution to register - * @return a new context or the current one if it has the same - * execution - */ - @Nullable - public C register(@Nullable E execution) { - if (execution == null) { - return null; - } - getCurrent().push(execution); - C context; - synchronized (contexts) { - context = contexts.get(execution); - if (context == null) { - context = createNewContext(execution); - contexts.put(execution, context); - } - } - increment(); - return context; - } - - /** - * Method for unregistering the current context - should always and only be - * used by in conjunction with a matching {@link #register(Object)} to ensure that {@link #getContext()} always returns - * the correct value. - * Does not call close on the context - that is left up to the caller - * because he has a reference to the context (having registered it) and only - * he has knowledge of when the execution actually ended. - */ - public void close() { - C oldSession = getContext(); - if (oldSession == null) { - return; - } - decrement(); - } - - private void decrement() { - E current = getCurrent().pop(); - if (current != null) { - int remaining = counts.get(current).decrementAndGet(); - if (remaining <= 0) { - synchronized (contexts) { - contexts.remove(current); - counts.remove(current); - } - } - } - } - - public void increment() { - E current = getCurrent().peek(); - if (current != null) { - AtomicInteger count; - synchronized (counts) { - count = counts.get(current); - if (count == null) { - count = new AtomicInteger(); - counts.put(current, count); - } - } - count.incrementAndGet(); - } - } - - public Stack getCurrent() { - if (executionHolder.get() == null) { - executionHolder.set(new Stack<>()); - } - return executionHolder.get(); - } - - /** - * A convenient "deep" close operation. Call this instead of {@link #close()} if the execution for the current - * context is ending. - * Delegates to {@link #close(Object)} and then ensures that {@link #close()} is also called in a finally block. - */ - public void release() { - C context = getContext(); - try { - if (context != null) { - close(context); - } - } finally { - close(); - } - } - - protected abstract void close(C context); - - protected abstract C createNewContext(E execution); - -} +/* + * Copyright 2013-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope.context; + +import java.util.Map; +import java.util.Stack; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; + +import org.springframework.lang.Nullable; + +/** + * Central convenience class for framework use in managing the scope context. + * + * @author Dave Syer + * @author Jimmy Praet + * @author Mahmoud Ben Hassine + * @since 3.0 + */ +public abstract class SynchronizationManagerSupport { + + /* + * We have to deal with single and multi-threaded execution, with a single and with + * multiple step execution instances. That's 2x2 = 4 scenarios. + */ + + /** + * Storage for the current execution; has to be ThreadLocal because it is needed to + * locate a context in components that are not part of a step/job (like when + * re-hydrating a scoped proxy). Doesn't use InheritableThreadLocal because there are + * side effects if a step is trying to run multiple child steps (e.g. with + * partitioning). The Stack is used to cover the single threaded case, so that the API + * is the same as multi-threaded. + */ + private final ThreadLocal> executionHolder = new ThreadLocal<>(); + + /** + * Reference counter for each execution: how many threads are using the same one? + */ + private final Map counts = new ConcurrentHashMap<>(); + + /** + * Simple map from a running execution to the associated context. + */ + private final Map contexts = new ConcurrentHashMap<>(); + + /** + * Getter for the current context if there is one, otherwise returns {@code null}. + * @return the current context or {@code null} if there is none (if one has not been + * registered for this thread). + */ + @Nullable + public C getContext() { + if (getCurrent().isEmpty()) { + return null; + } + synchronized (contexts) { + return contexts.get(getCurrent().peek()); + } + } + + /** + * Register a context with the current thread - always put a matching {@link #close()} + * call in a finally block to ensure that the correct context is available in the + * enclosing block. + * @param execution the execution to register + * @return a new context or the current one if it has the same execution + */ + @Nullable + public C register(@Nullable E execution) { + if (execution == null) { + return null; + } + getCurrent().push(execution); + C context; + synchronized (contexts) { + context = contexts.get(execution); + if (context == null) { + context = createNewContext(execution); + contexts.put(execution, context); + } + } + increment(); + return context; + } + + /** + * Method for unregistering the current context - should always and only be used by in + * conjunction with a matching {@link #register(Object)} to ensure that + * {@link #getContext()} always returns the correct value. Does not call close on the + * context - that is left up to the caller because he has a reference to the context + * (having registered it) and only he has knowledge of when the execution actually + * ended. + */ + public void close() { + C oldSession = getContext(); + if (oldSession == null) { + return; + } + decrement(); + } + + private void decrement() { + E current = getCurrent().pop(); + if (current != null) { + int remaining = counts.get(current).decrementAndGet(); + if (remaining <= 0) { + synchronized (contexts) { + contexts.remove(current); + counts.remove(current); + } + } + } + } + + public void increment() { + E current = getCurrent().peek(); + if (current != null) { + AtomicInteger count; + synchronized (counts) { + count = counts.get(current); + if (count == null) { + count = new AtomicInteger(); + counts.put(current, count); + } + } + count.incrementAndGet(); + } + } + + public Stack getCurrent() { + if (executionHolder.get() == null) { + executionHolder.set(new Stack<>()); + } + return executionHolder.get(); + } + + /** + * A convenient "deep" close operation. Call this instead of {@link #close()} if the + * execution for the current context is ending. Delegates to {@link #close(Object)} + * and then ensures that {@link #close()} is also called in a finally block. + */ + public void release() { + C context = getContext(); + try { + if (context != null) { + close(context); + } + } + finally { + close(); + } + } + + protected abstract void close(C context); + + protected abstract C createNewContext(E execution); + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/package-info.java b/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/package-info.java index a12e79cc4..48d5db343 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/package-info.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/scope/context/package-info.java @@ -1,5 +1,6 @@ /** - * Implementation of the contexts for each of the custom bean scopes in Spring Batch (Job and Step). + * Implementation of the contexts for each of the custom bean scopes in Spring Batch (Job + * and Step). * * @author Michael Minella * @author Mahmoud Ben Hassine diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/AbstractStep.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/AbstractStep.java index b4bdd031f..785a6f008 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/AbstractStep.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/AbstractStep.java @@ -50,8 +50,8 @@ import org.springframework.util.Assert; import org.springframework.util.ClassUtils; /** - * A {@link Step} implementation that provides common behavior to subclasses, including registering and calling - * listeners. + * A {@link Step} implementation that provides common behavior to subclasses, including + * registering and calling listeners. * * @author Dave Syer * @author Ben Hale @@ -60,7 +60,8 @@ import org.springframework.util.ClassUtils; * @author Chris Schaefer * @author Mahmoud Ben Hassine */ -public abstract class AbstractStep implements Step, InitializingBean, BeanNameAware, Observation.KeyValuesProviderAware { +public abstract class AbstractStep + implements Step, InitializingBean, BeanNameAware, Observation.KeyValuesProviderAware { private static final Log logger = LogFactory.getLog(AbstractStep.class); @@ -95,7 +96,8 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw } /** - * Set the name property. Always overrides the default value if this object is a Spring bean. + * Set the name property. Always overrides the default value if this object is a + * Spring bean. * @param name the name of the {@link Step}. * @see #setBeanName(java.lang.String) */ @@ -104,9 +106,11 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw } /** - * Set the name property if it is not already set. Because of the order of the callbacks in a Spring container the - * name property will be set first if it is present. Care is needed with bean definition inheritance - if a parent - * bean has a name, then its children need an explicit name as well, otherwise they will not be unique. + * Set the name property if it is not already set. Because of the order of the + * callbacks in a Spring container the name property will be set first if it is + * present. Care is needed with bean definition inheritance - if a parent bean has a + * name, then its children need an explicit name as well, otherwise they will not be + * unique. * * @see org.springframework.beans.factory.BeanNameAware#setBeanName(java.lang.String) */ @@ -124,7 +128,6 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw /** * Public setter for the startLimit. - * * @param startLimit the startLimit to set */ public void setStartLimit(int startLimit) { @@ -137,9 +140,8 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw } /** - * Public setter for flag that determines whether the step should start again if it is already complete. Defaults to - * false. - * + * Public setter for flag that determines whether the step should start again if it is + * already complete. Defaults to false. * @param allowStartIfComplete the value of the flag to set */ public void setAllowStartIfComplete(boolean allowStartIfComplete) { @@ -148,7 +150,6 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw /** * Convenient constructor for setting only the name property. - * * @param name Name of the step */ public AbstractStep(String name) { @@ -156,18 +157,16 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw } /** - * Extension point for subclasses to execute business logic. Subclasses should set the {@link ExitStatus} on the - * {@link StepExecution} before returning. - * + * Extension point for subclasses to execute business logic. Subclasses should set the + * {@link ExitStatus} on the {@link StepExecution} before returning. * @param stepExecution the current step context * @throws Exception checked exception thrown by implementation */ protected abstract void doExecute(StepExecution stepExecution) throws Exception; /** - * Extension point for subclasses to provide callbacks to their collaborators at the beginning of a step, to open or - * acquire resources. Does nothing by default. - * + * Extension point for subclasses to provide callbacks to their collaborators at the + * beginning of a step, to open or acquire resources. Does nothing by default. * @param ctx the {@link ExecutionContext} to use * @throws Exception checked exception thrown by implementation */ @@ -175,9 +174,9 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw } /** - * Extension point for subclasses to provide callbacks to their collaborators at the end of a step (right at the end - * of the finally block), to close or release resources. Does nothing by default. - * + * Extension point for subclasses to provide callbacks to their collaborators at the + * end of a step (right at the end of the finally block), to close or release + * resources. Does nothing by default. * @param ctx the {@link ExecutionContext} to use * @throws Exception checked exception thrown by implementation */ @@ -185,13 +184,14 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw } /** - * Template method for step execution logic - calls abstract methods for resource initialization ( - * {@link #open(ExecutionContext)}), execution logic ({@link #doExecute(StepExecution)}) and resource closing ( + * Template method for step execution logic - calls abstract methods for resource + * initialization ( {@link #open(ExecutionContext)}), execution logic + * ({@link #doExecute(StepExecution)}) and resource closing ( * {@link #close(ExecutionContext)}). */ @Override - public final void execute(StepExecution stepExecution) throws JobInterruptedException, - UnexpectedJobExecutionException { + public final void execute(StepExecution stepExecution) + throws JobInterruptedException, UnexpectedJobExecutionException { Assert.notNull(stepExecution, "stepExecution must not be null"); @@ -200,10 +200,10 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw } stepExecution.setStartTime(new Date()); stepExecution.setStatus(BatchStatus.STARTED); - Observation observation = BatchMetrics.createObservation(BatchStepObservation.BATCH_STEP_OBSERVATION.getName(), new BatchStepContext(stepExecution)) - .contextualName(stepExecution.getStepName()) - .keyValuesProvider(this.keyValuesProvider) - .start(); + Observation observation = BatchMetrics + .createObservation(BatchStepObservation.BATCH_STEP_OBSERVATION.getName(), + new BatchStepContext(stepExecution)) + .contextualName(stepExecution.getStepName()).keyValuesProvider(this.keyValuesProvider).start(); getJobRepository().update(stepExecution); // Start with a default value that will be trumped by anything @@ -239,13 +239,15 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw exitStatus = exitStatus.and(getDefaultExitStatusForFailure(e)); stepExecution.addFailureException(e); if (stepExecution.getStatus() == BatchStatus.STOPPED) { - logger.info(String.format("Encountered interruption executing step %s in job %s : %s", name, stepExecution.getJobExecution().getJobInstance().getJobName(), e.getMessage())); + logger.info(String.format("Encountered interruption executing step %s in job %s : %s", name, + stepExecution.getJobExecution().getJobInstance().getJobName(), e.getMessage())); if (logger.isDebugEnabled()) { logger.debug("Full exception", e); } } else { - logger.error(String.format("Encountered an error executing step %s in job %s", name, stepExecution.getJobExecution().getJobInstance().getJobName()), e); + logger.error(String.format("Encountered an error executing step %s in job %s", name, + stepExecution.getJobExecution().getJobInstance().getJobName()), e); } } finally { @@ -258,7 +260,8 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw exitStatus = exitStatus.and(getCompositeListener().afterStep(stepExecution)); } catch (Exception e) { - logger.error(String.format("Exception in afterStep callback in step %s in job %s", name, stepExecution.getJobExecution().getJobInstance().getJobName()), e); + logger.error(String.format("Exception in afterStep callback in step %s in job %s", name, + stepExecution.getJobExecution().getJobInstance().getJobName()), e); } try { @@ -268,15 +271,19 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw stepExecution.setStatus(BatchStatus.UNKNOWN); exitStatus = exitStatus.and(ExitStatus.UNKNOWN); stepExecution.addFailureException(e); - logger.error(String.format("Encountered an error saving batch meta data for step %s in job %s. " - + "This job is now in an unknown state and should not be restarted.", name, stepExecution.getJobExecution().getJobInstance().getJobName()), e); + logger.error(String.format( + "Encountered an error saving batch meta data for step %s in job %s. " + + "This job is now in an unknown state and should not be restarted.", + name, stepExecution.getJobExecution().getJobInstance().getJobName()), e); } stopObservation(stepExecution, observation); stepExecution.setEndTime(new Date()); stepExecution.setExitStatus(exitStatus); - Duration stepExecutionDuration = BatchMetrics.calculateDuration(stepExecution.getStartTime(), stepExecution.getEndTime()); + Duration stepExecutionDuration = BatchMetrics.calculateDuration(stepExecution.getStartTime(), + stepExecution.getEndTime()); if (logger.isInfoEnabled()) { - logger.info("Step: [" + stepExecution.getStepName() + "] executed in " + BatchMetrics.formatDuration(stepExecutionDuration)); + logger.info("Step: [" + stepExecution.getStepName() + "] executed in " + + BatchMetrics.formatDuration(stepExecutionDuration)); } try { getJobRepository().update(stepExecution); @@ -285,15 +292,18 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw stepExecution.setStatus(BatchStatus.UNKNOWN); stepExecution.setExitStatus(exitStatus.and(ExitStatus.UNKNOWN)); stepExecution.addFailureException(e); - logger.error(String.format("Encountered an error saving batch meta data for step %s in job %s. " - + "This job is now in an unknown state and should not be restarted.", name, stepExecution.getJobExecution().getJobInstance().getJobName()), e); + logger.error(String.format( + "Encountered an error saving batch meta data for step %s in job %s. " + + "This job is now in an unknown state and should not be restarted.", + name, stepExecution.getJobExecution().getJobInstance().getJobName()), e); } try { close(stepExecution.getExecutionContext()); } catch (Exception e) { - logger.error(String.format("Exception while closing step execution resources in step %s in job %s", name, stepExecution.getJobExecution().getJobInstance().getJobName()), e); + logger.error(String.format("Exception while closing step execution resources in step %s in job %s", + name, stepExecution.getJobExecution().getJobInstance().getJobName()), e); stepExecution.addFailureException(e); } @@ -327,7 +337,6 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw /** * Registers the {@link StepExecution} for property resolution via {@link StepScope} - * * @param stepExecution StepExecution to use when hydrating the StepScoped beans */ protected void doExecutionRegistration(StepExecution stepExecution) { @@ -347,8 +356,8 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw } /** - * Register a step listener for callbacks at the appropriate stages in a step execution. - * + * Register a step listener for callbacks at the appropriate stages in a step + * execution. * @param listener a {@link StepExecutionListener} */ public void registerStepExecutionListener(StepExecutionListener listener) { @@ -357,7 +366,6 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw /** * Register each of the objects as listeners. - * * @param listeners an array of listener objects of known types. */ public void setStepExecutionListeners(StepExecutionListener[] listeners) { @@ -375,7 +383,6 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw /** * Public setter for {@link JobRepository}. - * * @param jobRepository is a mandatory dependence (no default). */ public void setJobRepository(JobRepository jobRepository) { @@ -392,9 +399,8 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw } /** - * Default mapping from throwable to {@link ExitStatus}. Clients can modify the exit code using a - * {@link StepExecutionListener}. - * + * Default mapping from throwable to {@link ExitStatus}. Clients can modify the exit + * code using a {@link StepExecutionListener}. * @param ex the cause of the failure * @return an {@link ExitStatus} */ @@ -417,4 +423,5 @@ public abstract class AbstractStep implements Step, InitializingBean, BeanNameAw public void setKeyValuesProvider(BatchStepTagsProvider keyValuesProvider) { this.keyValuesProvider = keyValuesProvider; } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/NoSuchStepException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/NoSuchStepException.java index 3d6de212f..ae972d1d3 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/NoSuchStepException.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/NoSuchStepException.java @@ -16,11 +16,10 @@ package org.springframework.batch.core.step; /** - * Exception to signal that a step was requested that is unknown or does not - * exist. - * + * Exception to signal that a step was requested that is unknown or does not exist. + * * @author Dave Syer - * + * */ @SuppressWarnings("serial") public class NoSuchStepException extends RuntimeException { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/StepHolder.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/StepHolder.java index 2b9410481..1f4a51c91 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/StepHolder.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/StepHolder.java @@ -18,9 +18,9 @@ package org.springframework.batch.core.step; import org.springframework.batch.core.Step; /** - * Interface for holders of a {@link Step} as a convenience for callers who need - * access to the underlying instance. - * + * Interface for holders of a {@link Step} as a convenience for callers who need access to + * the underlying instance. + * * @author Dave Syer * @since 2.0 */ diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/StepInterruptionPolicy.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/StepInterruptionPolicy.java index c9ab46fe3..20a90fa6d 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/StepInterruptionPolicy.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/StepInterruptionPolicy.java @@ -21,20 +21,19 @@ import org.springframework.batch.core.Step; import org.springframework.batch.core.StepExecution; /** - * Strategy interface for an interruption policy. This policy allows - * {@link Step} implementations to check if a job has been interrupted. - * + * Strategy interface for an interruption policy. This policy allows {@link Step} + * implementations to check if a job has been interrupted. + * * @author Lucas Ward - * + * */ public interface StepInterruptionPolicy { /** - * Has the job been interrupted? If so then throw a - * {@link JobInterruptedException}. + * Has the job been interrupted? If so then throw a {@link JobInterruptedException}. * @param stepExecution the current context of the running step. - * * @throws JobInterruptedException when the job has been interrupted. */ void checkInterrupted(StepExecution stepExecution) throws JobInterruptedException; + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/StepLocator.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/StepLocator.java index 1c5aba4f2..c275d2062 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/StepLocator.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/StepLocator.java @@ -21,14 +21,14 @@ import org.springframework.batch.core.Step; /** * Interface for locating a {@link Step} instance by name. - * + * * @author Dave Syer * */ public interface StepLocator { - + Collection getStepNames(); - + Step getStep(String stepName) throws NoSuchStepException; } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/StepLocatorStepFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/StepLocatorStepFactoryBean.java index 25a10e38d..98faf4b48 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/StepLocatorStepFactoryBean.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/StepLocatorStepFactoryBean.java @@ -1,79 +1,79 @@ -/* - * Copyright 2012-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.step; - -import org.springframework.batch.core.Job; -import org.springframework.batch.core.Step; -import org.springframework.beans.factory.FactoryBean; - -/** - * Convenience factory for {@link Step} instances given a {@link StepLocator}. - * Most implementations of {@link Job} implement StepLocator, so that can be a - * good starting point. - * - * @author Dave Syer - * - */ -public class StepLocatorStepFactoryBean implements FactoryBean { - - public StepLocator stepLocator; - - public String stepName; - - /** - * @param stepLocator instance of {@link StepLocator} to be used by the factory bean. - */ - public void setStepLocator(StepLocator stepLocator) { - this.stepLocator = stepLocator; - } - - /** - * @param stepName the name to be associated with the step. - */ - public void setStepName(String stepName) { - this.stepName = stepName; - } - - /** - * - * @see FactoryBean#getObject() - */ - @Override - public Step getObject() throws Exception { - return stepLocator.getStep(stepName); - } - - /** - * Tell clients that we are a factory for {@link Step} instances. - * - * @see FactoryBean#getObjectType() - */ - @Override - public Class getObjectType() { - return Step.class; - } - - /** - * Always return true as optimization for bean factory. - * - * @see FactoryBean#isSingleton() - */ - @Override - public boolean isSingleton() { - return true; - } - -} +/* + * Copyright 2012-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.step; + +import org.springframework.batch.core.Job; +import org.springframework.batch.core.Step; +import org.springframework.beans.factory.FactoryBean; + +/** + * Convenience factory for {@link Step} instances given a {@link StepLocator}. Most + * implementations of {@link Job} implement StepLocator, so that can be a good starting + * point. + * + * @author Dave Syer + * + */ +public class StepLocatorStepFactoryBean implements FactoryBean { + + public StepLocator stepLocator; + + public String stepName; + + /** + * @param stepLocator instance of {@link StepLocator} to be used by the factory bean. + */ + public void setStepLocator(StepLocator stepLocator) { + this.stepLocator = stepLocator; + } + + /** + * @param stepName the name to be associated with the step. + */ + public void setStepName(String stepName) { + this.stepName = stepName; + } + + /** + * + * @see FactoryBean#getObject() + */ + @Override + public Step getObject() throws Exception { + return stepLocator.getStep(stepName); + } + + /** + * Tell clients that we are a factory for {@link Step} instances. + * + * @see FactoryBean#getObjectType() + */ + @Override + public Class getObjectType() { + return Step.class; + } + + /** + * Always return true as optimization for bean factory. + * + * @see FactoryBean#isSingleton() + */ + @Override + public boolean isSingleton() { + return true; + } + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/ThreadStepInterruptionPolicy.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/ThreadStepInterruptionPolicy.java index c6a8ec710..f1ee332fb 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/ThreadStepInterruptionPolicy.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/ThreadStepInterruptionPolicy.java @@ -33,8 +33,8 @@ public class ThreadStepInterruptionPolicy implements StepInterruptionPolicy { protected static final Log logger = LogFactory.getLog(ThreadStepInterruptionPolicy.class); /** - * Returns if the current job lifecycle has been interrupted by checking if - * the current thread is interrupted. + * Returns if the current job lifecycle has been interrupted by checking if the + * current thread is interrupted. */ @Override public void checkInterrupted(StepExecution stepExecution) throws JobInterruptedException { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/AbstractTaskletStepBuilder.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/AbstractTaskletStepBuilder.java index d3288e8a8..1481d9ca6 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/AbstractTaskletStepBuilder.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/AbstractTaskletStepBuilder.java @@ -41,19 +41,18 @@ import org.springframework.core.task.TaskExecutor; import org.springframework.transaction.interceptor.TransactionAttribute; /** - * Base class for step builders that want to build a {@link TaskletStep}. Handles common concerns across all tasklet - * step variants, which are mostly to do with the type of tasklet they carry. + * Base class for step builders that want to build a {@link TaskletStep}. Handles common + * concerns across all tasklet step variants, which are mostly to do with the type of + * tasklet they carry. * * @author Dave Syer * @author Michael Minella * @author Mahmoud Ben Hassine - * * @since 2.2 - * * @param the type of builder represented */ -public abstract class AbstractTaskletStepBuilder> extends -StepBuilderHelper> { +public abstract class AbstractTaskletStepBuilder> + extends StepBuilderHelper> { protected Set chunkListeners = new LinkedHashSet<>(); @@ -76,9 +75,9 @@ StepBuilderHelper> { protected abstract Tasklet createTasklet(); /** - * Build the step from the components collected by the fluent setters. Delegates first to {@link #enhance(Step)} and - * then to {@link #createTasklet()} in subclasses to create the actual tasklet. - * + * Build the step from the components collected by the fluent setters. Delegates first + * to {@link #enhance(Step)} and then to {@link #createTasklet()} in subclasses to + * create the actual tasklet. * @return a tasklet step fully configured and ready to execute */ public TaskletStep build() { @@ -126,16 +125,15 @@ StepBuilderHelper> { } protected void registerStepListenerAsChunkListener() { - for (StepExecutionListener stepExecutionListener: properties.getStepExecutionListeners()){ - if (stepExecutionListener instanceof ChunkListener){ - listener((ChunkListener)stepExecutionListener); + for (StepExecutionListener stepExecutionListener : properties.getStepExecutionListeners()) { + if (stepExecutionListener instanceof ChunkListener) { + listener((ChunkListener) stepExecutionListener); } } } /** * Register a chunk listener. - * * @param listener the listener to register * @return this for fluent chaining */ @@ -146,7 +144,6 @@ StepBuilderHelper> { /** * Registers objects using the annotation based listener configuration. - * * @param listener the object that has a method configured with listener annotation * @return this for fluent chaining */ @@ -159,7 +156,7 @@ StepBuilderHelper> { chunkListenerMethods.addAll(ReflectionUtils.findMethod(listener.getClass(), AfterChunk.class)); chunkListenerMethods.addAll(ReflectionUtils.findMethod(listener.getClass(), AfterChunkError.class)); - if(chunkListenerMethods.size() > 0) { + if (chunkListenerMethods.size() > 0) { StepListenerFactoryBean factory = new StepListenerFactoryBean(); factory.setDelegate(listener); this.listener((ChunkListener) factory.getObject()); @@ -172,7 +169,6 @@ StepBuilderHelper> { /** * Register a stream for callbacks that manage restart data. - * * @param stream the stream to register * @return this for fluent chaining */ @@ -182,9 +178,8 @@ StepBuilderHelper> { } /** - * Provide a task executor to use when executing the tasklet. Default is to use a single-threaded (synchronous) - * executor. - * + * Provide a task executor to use when executing the tasklet. Default is to use a + * single-threaded (synchronous) executor. * @param taskExecutor the task executor to register * @return this for fluent chaining */ @@ -194,10 +189,10 @@ StepBuilderHelper> { } /** - * In the case of an asynchronous {@link #taskExecutor(TaskExecutor)} the number of concurrent tasklet executions - * can be throttled (beyond any throttling provided by a thread pool). The throttle limit should be less than the - * data source pool size used in the job repository for this step. - * + * In the case of an asynchronous {@link #taskExecutor(TaskExecutor)} the number of + * concurrent tasklet executions can be throttled (beyond any throttling provided by a + * thread pool). The throttle limit should be less than the data source pool size used + * in the job repository for this step. * @param throttleLimit maximum number of concurrent tasklet executions allowed * @return this for fluent chaining */ @@ -207,8 +202,8 @@ StepBuilderHelper> { } /** - * Sets the exception handler to use in the case of tasklet failures. Default is to rethrow everything. - * + * Sets the exception handler to use in the case of tasklet failures. Default is to + * rethrow everything. * @param exceptionHandler the exception handler * @return this for fluent chaining */ @@ -218,9 +213,8 @@ StepBuilderHelper> { } /** - * Sets the repeat template used for iterating the tasklet execution. By default it will terminate only when the - * tasklet returns FINISHED (or null). - * + * Sets the repeat template used for iterating the tasklet execution. By default it + * will terminate only when the tasklet returns FINISHED (or null). * @param repeatTemplate a repeat template with rules for iterating * @return this for fluent chaining */ @@ -230,9 +224,9 @@ StepBuilderHelper> { } /** - * Sets the transaction attributes for the tasklet execution. Defaults to the default values for the transaction - * manager, but can be manipulated to provide longer timeouts for instance. - * + * Sets the transaction attributes for the tasklet execution. Defaults to the default + * values for the transaction manager, but can be manipulated to provide longer + * timeouts for instance. * @param transactionAttribute a transaction attribute set * @return this for fluent chaining */ @@ -242,8 +236,8 @@ StepBuilderHelper> { } /** - * Convenience method for subclasses to access the step operations that were injected by user. - * + * Convenience method for subclasses to access the step operations that were injected + * by user. * @return the repeat operations used to iterate the tasklet executions */ protected RepeatOperations getStepOperations() { @@ -251,8 +245,8 @@ StepBuilderHelper> { } /** - * Convenience method for subclasses to access the exception handler that was injected by user. - * + * Convenience method for subclasses to access the exception handler that was injected + * by user. * @return the exception handler */ protected ExceptionHandler getExceptionHandler() { @@ -261,7 +255,6 @@ StepBuilderHelper> { /** * Convenience method for subclasses to determine if the step is concurrent. - * * @return true if the tasklet is going to be run in multiple threads */ protected boolean concurrent() { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/FaultTolerantStepBuilder.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/FaultTolerantStepBuilder.java index 53c2f4660..376fe816e 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/FaultTolerantStepBuilder.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/FaultTolerantStepBuilder.java @@ -82,14 +82,14 @@ import org.springframework.transaction.interceptor.TransactionAttribute; import org.springframework.util.Assert; /** - * A step builder for fully fault tolerant chunk-oriented item processing steps. Extends {@link SimpleStepBuilder} with - * additional properties for retry and skip of failed items. + * A step builder for fully fault tolerant chunk-oriented item processing steps. Extends + * {@link SimpleStepBuilder} with additional properties for retry and skip of failed + * items. * * @author Dave Syer * @author Chris Schaefer * @author Michael Minella * @author Mahmoud Ben Hassine - * * @since 2.2 */ public class FaultTolerantStepBuilder extends SimpleStepBuilder { @@ -129,8 +129,8 @@ public class FaultTolerantStepBuilder extends SimpleStepBuilder { private boolean processorTransactional = true; /** - * Create a new builder initialized with any properties in the parent. The parent is copied, so it can be re-used. - * + * Create a new builder initialized with any properties in the parent. The parent is + * copied, so it can be re-used. * @param parent a parent helper containing common step properties */ public FaultTolerantStepBuilder(StepBuilderHelper parent) { @@ -138,8 +138,8 @@ public class FaultTolerantStepBuilder extends SimpleStepBuilder { } /** - * Create a new builder initialized with any properties in the parent. The parent is copied, so it can be re-used. - * + * Create a new builder initialized with any properties in the parent. The parent is + * copied, so it can be re-used. * @param parent a parent helper containing common step properties */ protected FaultTolerantStepBuilder(SimpleStepBuilder parent) { @@ -154,14 +154,14 @@ public class FaultTolerantStepBuilder extends SimpleStepBuilder { @SuppressWarnings("unchecked") protected void registerStepListenerAsSkipListener() { - for (StepExecutionListener stepExecutionListener: properties.getStepExecutionListeners()){ - if (stepExecutionListener instanceof SkipListener){ - listener((SkipListener)stepExecutionListener); + for (StepExecutionListener stepExecutionListener : properties.getStepExecutionListeners()) { + if (stepExecutionListener instanceof SkipListener) { + listener((SkipListener) stepExecutionListener); } } - for (ChunkListener chunkListener: this.chunkListeners){ - if (chunkListener instanceof SkipListener){ - listener((SkipListener)chunkListener); + for (ChunkListener chunkListener : this.chunkListeners) { + if (chunkListener instanceof SkipListener) { + listener((SkipListener) chunkListener); } } } @@ -186,7 +186,6 @@ public class FaultTolerantStepBuilder extends SimpleStepBuilder { /** * Registers objects using the annotation based listener configuration. - * * @param listener the object that has a method configured with listener annotation * @return this for fluent chaining */ @@ -200,7 +199,7 @@ public class FaultTolerantStepBuilder extends SimpleStepBuilder { skipListenerMethods.addAll(ReflectionUtils.findMethod(listener.getClass(), OnSkipInProcess.class)); skipListenerMethods.addAll(ReflectionUtils.findMethod(listener.getClass(), OnSkipInWrite.class)); - if(skipListenerMethods.size() > 0) { + if (skipListenerMethods.size() > 0) { StepListenerFactoryBean factory = new StepListenerFactoryBean(); factory.setDelegate(listener); skipListeners.add((SkipListener) factory.getObject()); @@ -211,10 +210,8 @@ public class FaultTolerantStepBuilder extends SimpleStepBuilder { return result; } - /** * Register a skip listener. - * * @param listener the listener to register * @return this for fluent chaining */ @@ -237,7 +234,6 @@ public class FaultTolerantStepBuilder extends SimpleStepBuilder { /** * Register a retry listener. - * * @param listener the listener to register * @return this for fluent chaining */ @@ -247,12 +243,13 @@ public class FaultTolerantStepBuilder extends SimpleStepBuilder { } /** - * Sets the key generator for identifying retried items. Retry across transaction boundaries requires items to be - * identified when they are encountered again. The default strategy is to use the items themselves, relying on their - * own implementation to ensure that they can be identified. Often a key generator is not necessary as long as the - * items have reliable hash code and equals implementations, or the reader is not transactional (the default) and - * the item processor either is itself not transactional (not the default) or does not create new items. - * + * Sets the key generator for identifying retried items. Retry across transaction + * boundaries requires items to be identified when they are encountered again. The + * default strategy is to use the items themselves, relying on their own + * implementation to ensure that they can be identified. Often a key generator is not + * necessary as long as the items have reliable hash code and equals implementations, + * or the reader is not transactional (the default) and the item processor either is + * itself not transactional (not the default) or does not create new items. * @param keyGenerator a key generator for the stateful retry * @return this for fluent chaining */ @@ -262,9 +259,8 @@ public class FaultTolerantStepBuilder extends SimpleStepBuilder { } /** - * The maximum number of times to try a failed item. Zero and one both translate to try only once and do not retry. - * Ignored if an explicit {@link #retryPolicy} is set. - * + * The maximum number of times to try a failed item. Zero and one both translate to + * try only once and do not retry. Ignored if an explicit {@link #retryPolicy} is set. * @param retryLimit the retry limit (default 0) * @return this for fluent chaining */ @@ -274,9 +270,9 @@ public class FaultTolerantStepBuilder extends SimpleStepBuilder { } /** - * Provide an explicit retry policy instead of using the {@link #retryLimit(int)} and retryable exceptions provided - * elsewhere. Can be used to retry different exceptions a different number of times, for instance. - * + * Provide an explicit retry policy instead of using the {@link #retryLimit(int)} and + * retryable exceptions provided elsewhere. Can be used to retry different exceptions + * a different number of times, for instance. * @param retryPolicy a retry policy * @return this for fluent chaining */ @@ -286,10 +282,9 @@ public class FaultTolerantStepBuilder extends SimpleStepBuilder { } /** - * Provide a backoff policy to prevent items being retried immediately (e.g. in case the failure was caused by a - * remote resource failure that might take some time to be resolved). Ignored if an explicit {@link #retryPolicy} is - * set. - * + * Provide a backoff policy to prevent items being retried immediately (e.g. in case + * the failure was caused by a remote resource failure that might take some time to be + * resolved). Ignored if an explicit {@link #retryPolicy} is set. * @param backOffPolicy the back off policy to use (default no backoff) * @return this for fluent chaining */ @@ -299,11 +294,11 @@ public class FaultTolerantStepBuilder extends SimpleStepBuilder { } /** - * Provide an explicit retry context cache. Retry is stateful across transactions in the case of failures in item - * processing or writing, so some information about the context for subsequent retries has to be stored. - * - * @param retryContextCache cache for retry contexts in between transactions (default to standard in-memory - * implementation) + * Provide an explicit retry context cache. Retry is stateful across transactions in + * the case of failures in item processing or writing, so some information about the + * context for subsequent retries has to be stored. + * @param retryContextCache cache for retry contexts in between transactions (default + * to standard in-memory implementation) * @return this for fluent chaining */ public FaultTolerantStepBuilder retryContextCache(RetryContextCache retryContextCache) { @@ -312,9 +307,8 @@ public class FaultTolerantStepBuilder extends SimpleStepBuilder { } /** - * Sets the maximum number of failed items to skip before the step fails. Ignored if an explicit - * {@link #skipPolicy(SkipPolicy)} is provided. - * + * Sets the maximum number of failed items to skip before the step fails. Ignored if + * an explicit {@link #skipPolicy(SkipPolicy)} is provided. * @param skipLimit the skip limit to set * @return this for fluent chaining */ @@ -325,7 +319,6 @@ public class FaultTolerantStepBuilder extends SimpleStepBuilder { /** * Explicitly prevent certain exceptions (and subclasses) from being skipped. - * * @param type the non-skippable exception * @return this for fluent chaining */ @@ -337,9 +330,8 @@ public class FaultTolerantStepBuilder extends SimpleStepBuilder { /** * Explicitly request certain exceptions (and subclasses) to be skipped. These * exceptions (and their subclasses) might be thrown during any phase of the chunk - * processing (read, process, write) but separate counts are made of skips on - * read, process and write inside the step execution. - * + * processing (read, process, write) but separate counts are made of skips on read, + * process and write inside the step execution. * @param type the exception type. * @return this for fluent chaining */ @@ -349,9 +341,8 @@ public class FaultTolerantStepBuilder extends SimpleStepBuilder { } /** - * Provide an explicit policy for managing skips. A skip policy determines which exceptions are skippable and how - * many times. - * + * Provide an explicit policy for managing skips. A skip policy determines which + * exceptions are skippable and how many times. * @param skipPolicy the skip policy * @return this for fluent chaining */ @@ -361,10 +352,10 @@ public class FaultTolerantStepBuilder extends SimpleStepBuilder { } /** - * Mark this exception as ignorable during item read or processing operations. Processing continues with no - * additional callbacks (use skips instead if you need to be notified). Ignored during write because there is no - * guarantee of skip and retry without rollback. - * + * Mark this exception as ignorable during item read or processing operations. + * Processing continues with no additional callbacks (use skips instead if you need to + * be notified). Ignored during write because there is no guarantee of skip and retry + * without rollback. * @param type the exception to mark as no rollback * @return this for fluent chaining */ @@ -375,7 +366,6 @@ public class FaultTolerantStepBuilder extends SimpleStepBuilder { /** * Explicitly ask for an exception (and subclasses) to be excluded from retry. - * * @param type the exception to exclude from retry * @return this for fluent chaining */ @@ -386,7 +376,6 @@ public class FaultTolerantStepBuilder extends SimpleStepBuilder { /** * Explicitly ask for an exception (and subclasses) to be retried. - * * @param type the exception to retry * @return this for fluent chaining */ @@ -396,10 +385,10 @@ public class FaultTolerantStepBuilder extends SimpleStepBuilder { } /** - * Mark the item processor as non-transactional (default is the opposite). If this flag is set the results of item - * processing are cached across transactions in between retries and during skip processing, otherwise the processor - * will be called in every transaction. - * + * Mark the item processor as non-transactional (default is the opposite). If this + * flag is set the results of item processing are cached across transactions in + * between retries and during skip processing, otherwise the processor will be called + * in every transaction. * @return this for fluent chaining */ public FaultTolerantStepBuilder processorNonTransactional() { @@ -423,7 +412,7 @@ public class FaultTolerantStepBuilder extends SimpleStepBuilder { } return this; } - + /** * Override parent method to prevent creation of a new FaultTolerantStepBuilder */ @@ -499,7 +488,8 @@ public class FaultTolerantStepBuilder extends SimpleStepBuilder { } /** - * Register explicitly set item listeners and auto-register reader, processor and writer if applicable + * Register explicitly set item listeners and auto-register reader, processor and + * writer if applicable */ private void registerSkipListeners() { // auto-register reader, processor and writer @@ -517,8 +507,8 @@ public class FaultTolerantStepBuilder extends SimpleStepBuilder { } /** - * Convenience method to get an exception classifier based on the provided transaction attributes. - * + * Convenience method to get an exception classifier based on the provided transaction + * attributes. * @return an exception classifier: maps to true if an exception should cause rollback */ protected Classifier getRollbackClassifier() { @@ -564,8 +554,7 @@ public class FaultTolerantStepBuilder extends SimpleStepBuilder { protected SkipPolicy createSkipPolicy() { SkipPolicy skipPolicy = this.skipPolicy; - Map, Boolean> map = new HashMap<>( - skippableExceptionClasses); + Map, Boolean> map = new HashMap<>(skippableExceptionClasses); map.put(ForceRollbackForWriteSkipException.class, true); LimitCheckingItemSkipPolicy limitCheckingItemSkipPolicy = new LimitCheckingItemSkipPolicy(skipLimit, map); if (skipPolicy == null) { @@ -587,8 +576,7 @@ public class FaultTolerantStepBuilder extends SimpleStepBuilder { RetryPolicy retryPolicy = this.retryPolicy; SimpleRetryPolicy simpleRetryPolicy = null; - Map, Boolean> map = new HashMap<>( - retryableExceptionClasses); + Map, Boolean> map = new HashMap<>(retryableExceptionClasses); map.put(ForceRollbackForWriteSkipException.class, true); simpleRetryPolicy = new SimpleRetryPolicy(retryLimit, map); @@ -639,8 +627,8 @@ public class FaultTolerantStepBuilder extends SimpleStepBuilder { } /** - * Wrap the provided {@link org.springframework.retry.RetryPolicy} so that it never retries explicitly non-retryable - * exceptions. + * Wrap the provided {@link org.springframework.retry.RetryPolicy} so that it never + * retries explicitly non-retryable exceptions. */ private RetryPolicy getFatalExceptionAwareProxy(RetryPolicy retryPolicy) { @@ -650,8 +638,7 @@ public class FaultTolerantStepBuilder extends SimpleStepBuilder { map.put(fatal, neverRetryPolicy); } - SubclassClassifier classifier = new SubclassClassifier<>( - retryPolicy); + SubclassClassifier classifier = new SubclassClassifier<>(retryPolicy); classifier.setTypeMap(map); ExceptionClassifierRetryPolicy retryPolicyWrapper = new ExceptionClassifierRetryPolicy(); @@ -662,7 +649,6 @@ public class FaultTolerantStepBuilder extends SimpleStepBuilder { /** * Wrap a {@link SkipPolicy} and make it consistent with known fatal exceptions. - * * @param skipPolicy an existing skip policy * @return a skip policy that will not skip fatal exceptions */ @@ -711,11 +697,11 @@ public class FaultTolerantStepBuilder extends SimpleStepBuilder { } /** - * ChunkListener that wraps exceptions thrown from the ChunkListener in {@link FatalStepExecutionException} to force - * termination of StepExecution + * ChunkListener that wraps exceptions thrown from the ChunkListener in + * {@link FatalStepExecutionException} to force termination of StepExecution * - * ChunkListeners shoulnd't throw exceptions and expect continued processing, they must be handled in the - * implementation or the step will terminate + * ChunkListeners shoulnd't throw exceptions and expect continued processing, they + * must be handled in the implementation or the step will terminate * */ private class TerminateOnExceptionChunkListenerDelegate implements ChunkListener { @@ -764,12 +750,13 @@ public class FaultTolerantStepBuilder extends SimpleStepBuilder { @SuppressWarnings("unchecked") @Override public boolean equals(Object obj) { - if (obj instanceof FaultTolerantStepBuilder.TerminateOnExceptionChunkListenerDelegate){ + if (obj instanceof FaultTolerantStepBuilder.TerminateOnExceptionChunkListenerDelegate) { // unwrap the ChunkListener - obj = ((TerminateOnExceptionChunkListenerDelegate)obj).chunkListener; + obj = ((TerminateOnExceptionChunkListenerDelegate) obj).chunkListener; } return chunkListener.equals(obj); } } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/FlowStepBuilder.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/FlowStepBuilder.java index 2e9851669..7b7f4a552 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/FlowStepBuilder.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/FlowStepBuilder.java @@ -20,11 +20,10 @@ import org.springframework.batch.core.job.flow.Flow; import org.springframework.batch.core.job.flow.FlowStep; /** - * A step builder for {@link FlowStep} instances. A flow step delegates processing to a nested flow composed of other - * steps. - * + * A step builder for {@link FlowStep} instances. A flow step delegates processing to a + * nested flow composed of other steps. + * * @author Dave Syer - * * @since 2.2 */ public class FlowStepBuilder extends StepBuilderHelper { @@ -32,8 +31,8 @@ public class FlowStepBuilder extends StepBuilderHelper { private Flow flow; /** - * Create a new builder initialized with any properties in the parent. The parent is copied, so it can be re-used. - * + * Create a new builder initialized with any properties in the parent. The parent is + * copied, so it can be re-used. * @param parent a parent helper containing common step properties */ public FlowStepBuilder(StepBuilderHelper parent) { @@ -42,7 +41,6 @@ public class FlowStepBuilder extends StepBuilderHelper { /** * Provide a flow to execute during the step. - * * @param flow the flow to execute * @return this for fluent chaining */ @@ -52,9 +50,9 @@ public class FlowStepBuilder extends StepBuilderHelper { } /** - * Build a step that executes the flow provided, normally composed of other steps. The flow is not executed in a - * transaction because the individual steps are supposed to manage their own transaction state. - * + * Build a step that executes the flow provided, normally composed of other steps. The + * flow is not executed in a transaction because the individual steps are supposed to + * manage their own transaction state. * @return a flow step */ public Step build() { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/JobStepBuilder.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/JobStepBuilder.java index 256850836..13a132561 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/JobStepBuilder.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/JobStepBuilder.java @@ -23,11 +23,10 @@ import org.springframework.batch.core.step.job.JobParametersExtractor; import org.springframework.batch.core.step.job.JobStep; /** - * A step builder for {@link JobStep} instances. A job step executes a nested {@link Job} with parameters taken from the - * parent job or from the step execution. - * + * A step builder for {@link JobStep} instances. A job step executes a nested {@link Job} + * with parameters taken from the parent job or from the step execution. + * * @author Dave Syer - * * @since 2.2 */ public class JobStepBuilder extends StepBuilderHelper { @@ -39,8 +38,8 @@ public class JobStepBuilder extends StepBuilderHelper { private JobParametersExtractor jobParametersExtractor; /** - * Create a new builder initialized with any properties in the parent. The parent is copied, so it can be re-used. - * + * Create a new builder initialized with any properties in the parent. The parent is + * copied, so it can be re-used. * @param parent a parent helper containing common step properties */ public JobStepBuilder(StepBuilderHelper parent) { @@ -49,7 +48,6 @@ public class JobStepBuilder extends StepBuilderHelper { /** * Provide a job to execute during the step. - * * @param job the job to execute * @return this for fluent chaining */ @@ -60,7 +58,6 @@ public class JobStepBuilder extends StepBuilderHelper { /** * Add a job launcher. Defaults to a simple job launcher. - * * @param jobLauncher the job launcher to use * @return this for fluent chaining */ @@ -70,9 +67,8 @@ public class JobStepBuilder extends StepBuilderHelper { } /** - * Provide a job parameters extractor. Useful for extracting job parameters from the parent step execution context - * or job parameters. - * + * Provide a job parameters extractor. Useful for extracting job parameters from the + * parent step execution context or job parameters. * @param jobParametersExtractor the job parameters extractor to use * @return this for fluent chaining */ @@ -83,7 +79,6 @@ public class JobStepBuilder extends StepBuilderHelper { /** * Build a step from the job provided. - * * @return a new job step */ public Step build() { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/PartitionStepBuilder.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/PartitionStepBuilder.java index 733f2f66c..92668b31f 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/PartitionStepBuilder.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/PartitionStepBuilder.java @@ -27,13 +27,13 @@ import org.springframework.core.task.SyncTaskExecutor; import org.springframework.core.task.TaskExecutor; /** - * Step builder for {@link PartitionStep} instances. A partition step executes the same step (possibly remotely) - * multiple times with different input parameters (in the form of execution context). Useful for parallelization. + * Step builder for {@link PartitionStep} instances. A partition step executes the same + * step (possibly remotely) multiple times with different input parameters (in the form of + * execution context). Useful for parallelization. * * @author Dave Syer * @author Mahmoud Ben Hassine * @author Dimitrios Liapis - * * @since 2.2 */ public class PartitionStepBuilder extends StepBuilderHelper { @@ -57,8 +57,8 @@ public class PartitionStepBuilder extends StepBuilderHelper parent) { @@ -66,10 +66,10 @@ public class PartitionStepBuilder extends StepBuilderHelper extends AbstractTaskletStepBuilder> { @@ -87,8 +85,8 @@ public class SimpleStepBuilder extends AbstractTaskletStepBuilder parent) { @@ -96,8 +94,8 @@ public class SimpleStepBuilder extends AbstractTaskletStepBuilder parent) { @@ -130,24 +128,24 @@ public class SimpleStepBuilder extends AbstractTaskletStepBuilder)stepListener); + if (stepListener instanceof ItemReadListener) { + listener((ItemReadListener) stepListener); } - if (stepListener instanceof ItemProcessListener){ - listener((ItemProcessListener)stepListener); + if (stepListener instanceof ItemProcessListener) { + listener((ItemProcessListener) stepListener); } - if (stepListener instanceof ItemWriteListener){ - listener((ItemWriteListener)stepListener); + if (stepListener instanceof ItemWriteListener) { + listener((ItemWriteListener) stepListener); } } @@ -166,10 +164,9 @@ public class SimpleStepBuilder extends AbstractTaskletStepBuilder extends AbstractTaskletStepBuilder extends AbstractTaskletStepBuilder extends AbstractTaskletStepBuilder extends AbstractTaskletStepBuilder extends AbstractTaskletStepBuilder readerIsTransactionalQueue() { @@ -245,7 +243,6 @@ public class SimpleStepBuilder extends AbstractTaskletStepBuilder extends AbstractTaskletStepBuilder 0) { + if (itemListenerMethods.size() > 0) { StepListenerFactoryBean factory = new StepListenerFactoryBean(); factory.setDelegate(listener); itemListeners.add((StepListener) factory.getObject()); @@ -276,10 +273,8 @@ public class SimpleStepBuilder extends AbstractTaskletStepBuilder extends AbstractTaskletStepBuilder extends AbstractTaskletStepBuilder extends AbstractTaskletStepBuilder extends AbstractTaskletStepBuilder 0), @@ -391,7 +385,7 @@ public class SimpleStepBuilder extends AbstractTaskletStepBuilder || listener instanceof ItemProcessListener - || listener instanceof ItemWriteListener) { + || listener instanceof ItemWriteListener) { itemListeners.add(listener); } } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/StepBuilder.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/StepBuilder.java index efc837945..e20bd2d6d 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/StepBuilder.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/StepBuilder.java @@ -23,17 +23,16 @@ import org.springframework.batch.core.step.tasklet.Tasklet; import org.springframework.batch.repeat.CompletionPolicy; /** - * Convenient entry point for building all kinds of steps. Use this as a factory for fluent builders of any step. + * Convenient entry point for building all kinds of steps. Use this as a factory for + * fluent builders of any step. * * @author Dave Syer - * * @since 2.2 */ public class StepBuilder extends StepBuilderHelper { /** * Initialize a step builder for a step with the given name. - * * @param name the name of the step */ public StepBuilder(String name) { @@ -42,7 +41,6 @@ public class StepBuilder extends StepBuilderHelper { /** * Build a step with a custom tasklet, not necessarily item processing. - * * @param tasklet a tasklet * @return a {@link TaskletStepBuilder} */ @@ -51,15 +49,15 @@ public class StepBuilder extends StepBuilderHelper { } /** - * Build a step that processes items in chunks with the size provided. To extend the step to being fault tolerant, - * call the {@link SimpleStepBuilder#faultTolerant()} method on the builder. In most cases you will want to - * parameterize your call to this method, to preserve the type safety of your readers and writers, e.g. + * Build a step that processes items in chunks with the size provided. To extend the + * step to being fault tolerant, call the {@link SimpleStepBuilder#faultTolerant()} + * method on the builder. In most cases you will want to parameterize your call to + * this method, to preserve the type safety of your readers and writers, e.g. * *
       	 * new StepBuilder("step1").<Order, Ledger> chunk(100).reader(new OrderReader()).writer(new LedgerWriter())
       	 * // ... etc.
       	 * 
      - * * @param chunkSize the chunk size (commit interval) * @return a {@link SimpleStepBuilder} * @param the type of item to be processed as input @@ -70,15 +68,16 @@ public class StepBuilder extends StepBuilderHelper { } /** - * Build a step that processes items in chunks with the completion policy provided. To extend the step to being - * fault tolerant, call the {@link SimpleStepBuilder#faultTolerant()} method on the builder. In most cases you will - * want to parameterize your call to this method, to preserve the type safety of your readers and writers, e.g. + * Build a step that processes items in chunks with the completion policy provided. To + * extend the step to being fault tolerant, call the + * {@link SimpleStepBuilder#faultTolerant()} method on the builder. In most cases you + * will want to parameterize your call to this method, to preserve the type safety of + * your readers and writers, e.g. * *
       	 * new StepBuilder("step1").<Order, Ledger> chunk(100).reader(new OrderReader()).writer(new LedgerWriter())
       	 * // ... etc.
       	 * 
      - * * @param completionPolicy the completion policy to use to control chunk processing * @return a {@link SimpleStepBuilder} * @param the type of item to be processed as input @@ -90,7 +89,6 @@ public class StepBuilder extends StepBuilderHelper { /** * Create a partition step builder for a remote (or local) step. - * * @param stepName the name of the remote or delegate step * @param partitioner a partitioner to be used to construct new step executions * @return a {@link PartitionStepBuilder} @@ -101,7 +99,6 @@ public class StepBuilder extends StepBuilderHelper { /** * Create a partition step builder for a remote (or local) step. - * * @param step the step to execute in parallel * @return a PartitionStepBuilder */ @@ -111,7 +108,6 @@ public class StepBuilder extends StepBuilderHelper { /** * Create a new step builder that will execute a job. - * * @param job a job to execute * @return a {@link JobStepBuilder} */ @@ -121,7 +117,6 @@ public class StepBuilder extends StepBuilderHelper { /** * Create a new step builder that will execute a flow. - * * @param flow a flow to execute * @return a {@link FlowStepBuilder} */ diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/StepBuilderException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/StepBuilderException.java index f6de1fe26..34896178c 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/StepBuilderException.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/StepBuilderException.java @@ -17,9 +17,8 @@ package org.springframework.batch.core.step.builder; /** * Utility exception thrown by builders when they encounter unexpected checked exceptions. - * + * * @author Dave Syer - * * @since 2.2 */ @SuppressWarnings("serial") diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/StepBuilderHelper.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/StepBuilderHelper.java index 5b6fb190e..135f673f7 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/StepBuilderHelper.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/StepBuilderHelper.java @@ -35,12 +35,11 @@ import java.util.List; import java.util.Set; /** - * A base class and utility for other step builders providing access to common properties like job repository and - * transaction manager. - * + * A base class and utility for other step builders providing access to common properties + * like job repository and transaction manager. + * * @author Dave Syer * @author Michael Minella - * * @since 2.2 */ public abstract class StepBuilderHelper> { @@ -55,8 +54,8 @@ public abstract class StepBuilderHelper> { } /** - * Create a new builder initialized with any properties in the parent. The parent is copied, so it can be re-used. - * + * Create a new builder initialized with any properties in the parent. The parent is + * copied, so it can be re-used. * @param parent a parent helper containing common step properties */ protected StepBuilderHelper(StepBuilderHelper parent) { @@ -86,7 +85,6 @@ public abstract class StepBuilderHelper> { /** * Registers objects using the annotation based listener configuration. - * * @param listener the object that has a method configured with listener annotation * @return this for fluent chaining */ @@ -95,7 +93,7 @@ public abstract class StepBuilderHelper> { stepExecutionListenerMethods.addAll(ReflectionUtils.findMethod(listener.getClass(), BeforeStep.class)); stepExecutionListenerMethods.addAll(ReflectionUtils.findMethod(listener.getClass(), AfterStep.class)); - if(stepExecutionListenerMethods.size() > 0) { + if (stepExecutionListenerMethods.size() > 0) { StepListenerFactoryBean factory = new StepListenerFactoryBean(); factory.setDelegate(listener); properties.addStepExecutionListener((StepExecutionListener) factory.getObject()); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/TaskletStepBuilder.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/TaskletStepBuilder.java index 68fb9d94f..b4e5aa68c 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/TaskletStepBuilder.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/TaskletStepBuilder.java @@ -19,9 +19,8 @@ import org.springframework.batch.core.step.tasklet.Tasklet; /** * Builder for tasklet step based on a custom tasklet (not item oriented). - * + * * @author Dave Syer - * * @since 2.2 */ public class TaskletStepBuilder extends AbstractTaskletStepBuilder { @@ -29,8 +28,8 @@ public class TaskletStepBuilder extends AbstractTaskletStepBuilder parent) { @@ -45,7 +44,7 @@ public class TaskletStepBuilder extends AbstractTaskletStepBuilder extends SimpleStepFactoryBean extends SimpleStepFactoryBean extends SimpleStepFactoryBeanretryLimit == 1
      by default. - * + * Public setter for the retry limit. Each item can be retried up to this limit. Note + * this limit includes the initial attempt to process the item, therefore + * retryLimit == 1 by default. * @param retryLimit the retry limit to set, must be greater or equal to 1. */ public void setRetryLimit(int retryLimit) { @@ -107,16 +107,17 @@ public class FaultTolerantStepFactoryBean extends SimpleStepFactoryBean + * Public setter for the capacity of the cache in the retry policy. If more items than + * this fail without being skipped or recovered an exception will be thrown. This is + * to guard against inadvertent infinite loops generated by item identity + * problems.
      * - * The default value should be high enough and more for most purposes. To breach the limit in a single-threaded step - * typically you have to have this many failures in a single transaction. Defaults to the value in the - * {@link MapRetryContextCache}.
      - * - * This property is ignored if the {@link #setRetryContextCache(RetryContextCache)} is set directly. + * The default value should be high enough and more for most purposes. To breach the + * limit in a single-threaded step typically you have to have this many failures in a + * single transaction. Defaults to the value in the {@link MapRetryContextCache}.
      * + * This property is ignored if the {@link #setRetryContextCache(RetryContextCache)} is + * set directly. * @param cacheCapacity the cache capacity to set (greater than 0 else ignored) */ public void setCacheCapacity(int cacheCapacity) { @@ -124,9 +125,8 @@ public class FaultTolerantStepFactoryBean extends SimpleStepFactoryBean extends SimpleStepFactoryBean, Boolean> retryableExceptionClasses) { @@ -144,7 +144,6 @@ public class FaultTolerantStepFactoryBean extends SimpleStepFactoryBean extends SimpleStepFactoryBean extends SimpleStepFactoryBean extends SimpleStepFactoryBean extends SimpleStepFactoryBean + * Exception classes that when raised won't crash the job but will result in the item + * which handling caused the exception being skipped. Any exception which is marked + * for "no rollback" is also skippable, but not vice versa. Remember to set the + * {@link #setSkipLimit(int) skip limit} as well.
      * Defaults to all no exception. - * * @param exceptionClasses defaults to Exception */ public void setSkippableExceptionClasses(Map, Boolean> exceptionClasses) { @@ -196,12 +193,11 @@ public class FaultTolerantStepFactoryBean extends SimpleStepFactoryBean + * Exception classes that are candidates for no rollback. The {@link Step} can not + * honour the no rollback hint in all circumstances, but any exception on this list is + * counted as skippable, so even if there has to be a rollback, then the step will not + * fail as long as the skip limit is not breached.
      * Defaults is empty. - * * @param noRollbackExceptionClasses the exception classes to set */ public void setNoRollbackExceptionClasses(Collection> noRollbackExceptionClasses) { @@ -209,7 +205,8 @@ public class FaultTolerantStepFactoryBean extends SimpleStepFactoryBean extends SimpleStepFactoryBean listener : BatchListenerFactoryHelper.> getListeners(getListeners(), + for (SkipListener listener : BatchListenerFactoryHelper.>getListeners(getListeners(), SkipListener.class)) { faultTolerantBuilder.listener(listener); } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/factory/SimpleStepFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/factory/SimpleStepFactoryBean.java index f149337a4..8c3b875b6 100755 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/factory/SimpleStepFactoryBean.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/factory/SimpleStepFactoryBean.java @@ -48,14 +48,13 @@ import org.springframework.transaction.interceptor.DefaultTransactionAttribute; import org.springframework.transaction.interceptor.TransactionAttribute; /** - * Most common configuration options for simple steps should be found here. Use this factory bean instead of creating a - * {@link Step} implementation manually. + * Most common configuration options for simple steps should be found here. Use this + * factory bean instead of creating a {@link Step} implementation manually. * - * This factory does not support configuration of fault-tolerant behavior, use appropriate subclass of this factory bean - * to configure skip or retry. + * This factory does not support configuration of fault-tolerant behavior, use appropriate + * subclass of this factory bean to configure skip or retry. * * @see FaultTolerantStepFactoryBean - * * @author Dave Syer * @author Robert Kasanicky * @@ -116,9 +115,9 @@ public class SimpleStepFactoryBean implements FactoryBean, BeanNameA } /** - * Flag to signal that the reader is transactional (usually a JMS consumer) so that items are re-presented after a - * rollback. The default is false and readers are assumed to be forward-only. - * + * Flag to signal that the reader is transactional (usually a JMS consumer) so that + * items are re-presented after a rollback. The default is false and readers are + * assumed to be forward-only. * @param isReaderTransactionalQueue the value of the flag */ public void setIsReaderTransactionalQueue(boolean isReaderTransactionalQueue) { @@ -134,7 +133,8 @@ public class SimpleStepFactoryBean implements FactoryBean, BeanNameA } /** - * Set the bean name property, which will become the name of the {@link Step} when it is created. + * Set the bean name property, which will become the name of the {@link Step} when it + * is created. * * @see org.springframework.beans.factory.BeanNameAware#setBeanName(java.lang.String) */ @@ -153,7 +153,6 @@ public class SimpleStepFactoryBean implements FactoryBean, BeanNameA /** * The timeout for an individual transaction in the step. - * * @param transactionTimeout the transaction timeout to set, defaults to infinite */ public void setTransactionTimeout(int transactionTimeout) { @@ -176,7 +175,6 @@ public class SimpleStepFactoryBean implements FactoryBean, BeanNameA /** * Public setter for the start limit for the step. - * * @param startLimit the startLimit to set */ public void setStartLimit(int startLimit) { @@ -184,9 +182,8 @@ public class SimpleStepFactoryBean implements FactoryBean, BeanNameA } /** - * Public setter for the flag to indicate that the step should be replayed on a restart, even if successful the - * first time. - * + * Public setter for the flag to indicate that the step should be replayed on a + * restart, even if successful the first time. * @param allowStartIfComplete the shouldAllowStartIfComplete to set */ public void setAllowStartIfComplete(boolean allowStartIfComplete) { @@ -215,9 +212,8 @@ public class SimpleStepFactoryBean implements FactoryBean, BeanNameA } /** - * The streams to inject into the {@link Step}. Any instance of {@link ItemStream} can be used, and will then - * receive callbacks at the appropriate stage in the step. - * + * The streams to inject into the {@link Step}. Any instance of {@link ItemStream} can + * be used, and will then receive callbacks at the appropriate stage in the step. * @param streams an array of listeners */ public void setStreams(ItemStream[] streams) { @@ -225,9 +221,8 @@ public class SimpleStepFactoryBean implements FactoryBean, BeanNameA } /** - * The listeners to inject into the {@link Step}. Any instance of {@link StepListener} can be used, and will then - * receive callbacks at the appropriate stage in the step. - * + * The listeners to inject into the {@link Step}. Any instance of {@link StepListener} + * can be used, and will then receive callbacks at the appropriate stage in the step. * @param listeners an array of listeners */ public void setListeners(StepListener[] listeners) { @@ -268,7 +263,6 @@ public class SimpleStepFactoryBean implements FactoryBean, BeanNameA /** * Public setter for {@link JobRepository}. - * * @param jobRepository is a mandatory dependence (no default). */ public void setJobRepository(JobRepository jobRepository) { @@ -277,7 +271,6 @@ public class SimpleStepFactoryBean implements FactoryBean, BeanNameA /** * Public setter for the {@link PlatformTransactionManager}. - * * @param transactionManager the transaction manager to set */ public void setTransactionManager(PlatformTransactionManager transactionManager) { @@ -298,8 +291,9 @@ public class SimpleStepFactoryBean implements FactoryBean, BeanNameA return new DefaultTransactionAttribute(attribute) { /** - * Ignore the default behaviour and rollback on all exceptions that bubble up to the tasklet level. The - * tasklet has to deal with the rollback rules internally. + * Ignore the default behaviour and rollback on all exceptions that bubble up + * to the tasklet level. The tasklet has to deal with the rollback rules + * internally. */ @Override public boolean rollbackOn(Throwable ex) { @@ -333,8 +327,9 @@ public class SimpleStepFactoryBean implements FactoryBean, BeanNameA } /** - * Returns true by default, but in most cases a {@link Step} should not be treated as thread-safe. Clients are - * recommended to create a new step for each job execution. + * Returns true by default, but in most cases a {@link Step} should not be + * treated as thread-safe. Clients are recommended to create a new step for each job + * execution. * * @see org.springframework.beans.factory.FactoryBean#isSingleton() */ @@ -353,7 +348,6 @@ public class SimpleStepFactoryBean implements FactoryBean, BeanNameA /** * Set the commit interval. Either set this or the chunkCompletionPolicy but not both. - * * @param commitInterval 1 by default */ public void setCommitInterval(int commitInterval) { @@ -361,10 +355,10 @@ public class SimpleStepFactoryBean implements FactoryBean, BeanNameA } /** - * Public setter for the {@link CompletionPolicy} applying to the chunk level. A transaction will be committed when - * this policy decides to complete. Defaults to a {@link SimpleCompletionPolicy} with chunk size equal to the - * commitInterval property. - * + * Public setter for the {@link CompletionPolicy} applying to the chunk level. A + * transaction will be committed when this policy decides to complete. Defaults to a + * {@link SimpleCompletionPolicy} with chunk size equal to the commitInterval + * property. * @param chunkCompletionPolicy the chunkCompletionPolicy to set */ public void setChunkCompletionPolicy(CompletionPolicy chunkCompletionPolicy) { @@ -420,9 +414,8 @@ public class SimpleStepFactoryBean implements FactoryBean, BeanNameA } /** - * Public setter for the {@link TaskExecutor}. If this is set, then it will be used to execute the chunk processing - * inside the {@link Step}. - * + * Public setter for the {@link TaskExecutor}. If this is set, then it will be used to + * execute the chunk processing inside the {@link Step}. * @param taskExecutor the taskExecutor to set */ public void setTaskExecutor(TaskExecutor taskExecutor) { @@ -438,8 +431,9 @@ public class SimpleStepFactoryBean implements FactoryBean, BeanNameA } /** - * Public setter for the throttle limit. This limits the number of tasks queued for concurrent processing to prevent - * thread pools from being overwhelmed. Defaults to {@link TaskExecutorRepeatTemplate#DEFAULT_THROTTLE_LIMIT}. + * Public setter for the throttle limit. This limits the number of tasks queued for + * concurrent processing to prevent thread pools from being overwhelmed. Defaults to + * {@link TaskExecutorRepeatTemplate#DEFAULT_THROTTLE_LIMIT}. * @param throttleLimit the throttle limit to set. */ public void setThrottleLimit(int throttleLimit) { @@ -451,24 +445,24 @@ public class SimpleStepFactoryBean implements FactoryBean, BeanNameA builder.reader(itemReader); builder.processor(itemProcessor); builder.writer(itemWriter); - for (StepExecutionListener listener : BatchListenerFactoryHelper. getListeners( - listeners, StepExecutionListener.class)) { + for (StepExecutionListener listener : BatchListenerFactoryHelper.getListeners(listeners, + StepExecutionListener.class)) { builder.listener(listener); } - for (ChunkListener listener : BatchListenerFactoryHelper. getListeners(listeners, + for (ChunkListener listener : BatchListenerFactoryHelper.getListeners(listeners, ChunkListener.class)) { builder.listener(listener); } - for (ItemReadListener listener : BatchListenerFactoryHelper.> getListeners(listeners, + for (ItemReadListener listener : BatchListenerFactoryHelper.>getListeners(listeners, ItemReadListener.class)) { builder.listener(listener); } - for (ItemWriteListener listener : BatchListenerFactoryHelper.> getListeners(listeners, + for (ItemWriteListener listener : BatchListenerFactoryHelper.>getListeners(listeners, ItemWriteListener.class)) { builder.listener(listener); } - for (ItemProcessListener listener : BatchListenerFactoryHelper.> getListeners( - listeners, ItemProcessListener.class)) { + for (ItemProcessListener listener : BatchListenerFactoryHelper + .>getListeners(listeners, ItemProcessListener.class)) { builder.listener(listener); } builder.transactionManager(transactionManager); @@ -491,4 +485,5 @@ public class SimpleStepFactoryBean implements FactoryBean, BeanNameA } } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/BatchRetryTemplate.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/BatchRetryTemplate.java index 1dd93e515..01f78cd1b 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/BatchRetryTemplate.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/BatchRetryTemplate.java @@ -38,19 +38,18 @@ import java.util.Iterator; import java.util.List; /** - * A special purpose retry template that deals specifically with multi-valued - * stateful retry. This is useful in the case where the operation to be retried - * operates on multiple items, and when it fails there is no way to decide which - * (if any) of the items was responsible. The {@link RetryState} used in the - * execute methods is composite, and when a failure occurs, all of the keys in - * the composite are "tarred with the same brush". Subsequent attempts to - * execute with any of the keys that have failed previously results in a new - * attempt and the previous state is used to check the {@link RetryPolicy}. If - * one of the failed items eventually succeeds then the others in the current - * composite for that attempt will be cleared from the context cache (as - * normal), but there may still be entries in the cache for the original failed - * items. This might mean that an item that did not cause a failure is never - * retried because other items in the same batch fail fatally first. + * A special purpose retry template that deals specifically with multi-valued stateful + * retry. This is useful in the case where the operation to be retried operates on + * multiple items, and when it fails there is no way to decide which (if any) of the items + * was responsible. The {@link RetryState} used in the execute methods is composite, and + * when a failure occurs, all of the keys in the composite are "tarred with the same + * brush". Subsequent attempts to execute with any of the keys that have failed previously + * results in a new attempt and the previous state is used to check the + * {@link RetryPolicy}. If one of the failed items eventually succeeds then the others in + * the current composite for that attempt will be cleared from the context cache (as + * normal), but there may still be entries in the cache for the original failed items. + * This might mean that an item that did not cause a failure is never retried because + * other items in the same batch fail fatally first. * * @author Dave Syer * @@ -199,8 +198,8 @@ public class BatchRetryTemplate implements RetryOperations { private RetryPolicy retryPolicy; - public T execute(RetryCallback retryCallback, Collection states) throws E, - Exception { + public T execute(RetryCallback retryCallback, Collection states) + throws E, Exception { RetryState batchState = new BatchRetryState(states); return delegate.execute(retryCallback, batchState); } @@ -212,19 +211,20 @@ public class BatchRetryTemplate implements RetryOperations { } @Override - public final T execute(RetryCallback retryCallback, RecoveryCallback recoveryCallback, - RetryState retryState) throws E { + public final T execute(RetryCallback retryCallback, + RecoveryCallback recoveryCallback, RetryState retryState) throws E { return regular.execute(retryCallback, recoveryCallback, retryState); } @Override - public final T execute(RetryCallback retryCallback, RecoveryCallback recoveryCallback) throws E { + public final T execute(RetryCallback retryCallback, + RecoveryCallback recoveryCallback) throws E { return regular.execute(retryCallback, recoveryCallback); } @Override - public final T execute(RetryCallback retryCallback, RetryState retryState) throws E, - ExhaustedRetryException { + public final T execute(RetryCallback retryCallback, RetryState retryState) + throws E, ExhaustedRetryException { return regular.execute(retryCallback, retryState); } @@ -276,7 +276,7 @@ public class BatchRetryTemplate implements RetryOperations { } public boolean canRetry(RetryContext context) { - return context==null ? true : retryPolicy.canRetry(context); + return context == null ? true : retryPolicy.canRetry(context); } } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/Chunk.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/Chunk.java index ae4e38639..9fa7f4682 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/Chunk.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/Chunk.java @@ -23,11 +23,11 @@ import java.util.Iterator; import java.util.List; /** - * Encapsulation of a list of items to be processed and possibly a list of - * failed items to be skipped. To mark an item as skipped clients should iterate - * over the chunk using the {@link #iterator()} method, and if there is a - * failure call {@link org.springframework.batch.core.step.item.Chunk.ChunkIterator#remove()} on the iterator. - * The skipped items are then available through the chunk. + * Encapsulation of a list of items to be processed and possibly a list of failed items to + * be skipped. To mark an item as skipped clients should iterate over the chunk using the + * {@link #iterator()} method, and if there is a failure call + * {@link org.springframework.batch.core.step.item.Chunk.ChunkIterator#remove()} on the + * iterator. The skipped items are then available through the chunk. * * @author Dave Syer * @since 2.0 @@ -105,7 +105,6 @@ public class Chunk implements Iterable { /** * Register an anonymous skip. To skip an individual item, use * {@link ChunkIterator#remove()}. - * * @param e the exception that caused the skip */ public void skip(Exception e) { @@ -137,7 +136,6 @@ public class Chunk implements Iterable { /** * Flag to indicate if the source data is exhausted. - * * @return true if there is no more data to process */ public boolean isEnd() { @@ -145,17 +143,16 @@ public class Chunk implements Iterable { } /** - * Set the flag to say that this chunk represents an end of stream (there is - * no more data to process). + * Set the flag to say that this chunk represents an end of stream (there is no more + * data to process). */ public void setEnd() { this.end = true; } /** - * Query the chunk to see if anyone has registered an interest in keeping a - * reference to it. - * + * Query the chunk to see if anyone has registered an interest in keeping a reference + * to it. * @return the busy flag */ public boolean isBusy() { @@ -163,9 +160,8 @@ public class Chunk implements Iterable { } /** - * Register an interest in the chunk to prevent it from being cleaned up - * before the flag is reset to false. - * + * Register an interest in the chunk to prevent it from being cleaned up before the + * flag is reset to false. * @param busy the flag to set */ public void setBusy(boolean busy) { @@ -198,8 +194,8 @@ public class Chunk implements Iterable { } /** - * Special iterator for a chunk providing the {@link #remove(Throwable)} - * method for dynamically removing an item and adding it to the skips. + * Special iterator for a chunk providing the {@link #remove(Throwable)} method for + * dynamically removing an item and adding it to the skips. * * @author Dave Syer * diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/ChunkMonitor.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/ChunkMonitor.java index c452c2a06..1f4a74e81 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/ChunkMonitor.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/ChunkMonitor.java @@ -1,163 +1,165 @@ -/* - * Copyright 2006-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.step.item; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.ItemStream; -import org.springframework.batch.item.ItemStreamException; -import org.springframework.batch.item.ItemStreamSupport; -import org.springframework.batch.item.support.CompositeItemStream; - -/** - * Manage the offset data between the last successful commit and updates made to - * an input chunk. Only works with single threaded steps because it has to use a - * {@link ThreadLocal} to manage the state and coordinate between the caller - * and the wrapped {@link ItemStream}. - * - * @author Dave Syer - * @since 2.0 - */ -public class ChunkMonitor extends ItemStreamSupport { - - private Log logger = LogFactory.getLog(getClass()); - - private boolean streamsRegistered = false; - - public static class ChunkMonitorData { - public int offset; - - public int chunkSize; - - public ChunkMonitorData(int offset, int chunkSize) { - this.offset = offset; - this.chunkSize = chunkSize; - } - } - - private static final String OFFSET = "OFFSET"; - - private CompositeItemStream stream = new CompositeItemStream(); - - private ThreadLocal holder = new ThreadLocal<>(); - - private ItemReader reader; - - public ChunkMonitor() { - this.setExecutionContextName(ChunkMonitor.class.getName()); - } - - /** - * @param stream the stream to set - */ - public void registerItemStream(ItemStream stream) { - streamsRegistered = true; - this.stream.register(stream); - } - - /** - * @param reader the reader to set - */ - public void setItemReader(ItemReader reader) { - this.reader = reader; - } - - public void incrementOffset() { - ChunkMonitorData data = getData(); - data.offset ++; - if (data.offset >= data.chunkSize) { - resetOffset(); - } - } - - public int getOffset() { - return getData().offset; - } - - public void resetOffset() { - getData().offset = 0; - } - - public void setChunkSize(int chunkSize) { - getData().chunkSize = chunkSize; - resetOffset(); - } - - @Override - public void close() throws ItemStreamException { - super.close(); - holder.set(null); - if (streamsRegistered) { - stream.close(); - } - } - - @Override - public void open(ExecutionContext executionContext) throws ItemStreamException { - super.open(executionContext); - if (streamsRegistered) { - stream.open(executionContext); - ChunkMonitorData data = new ChunkMonitorData(executionContext.getInt(getExecutionContextKey(OFFSET), 0), 0); - holder.set(data); - if (reader == null) { - logger.warn("No ItemReader set (must be concurrent step), so ignoring offset data."); - return; - } - for (int i = 0; i < data.offset; i++) { - try { - reader.read(); - } - catch (Exception e) { - throw new ItemStreamException("Could not position reader with offset: " + data.offset, e); - } - } - - resetOffset(); - } - } - - @Override - public void update(ExecutionContext executionContext) throws ItemStreamException { - super.update(executionContext); - if (streamsRegistered) { - ChunkMonitorData data = getData(); - if (data.offset == 0) { - // Only call the underlying update method if we are on a chunk - // boundary - stream.update(executionContext); - executionContext.remove(getExecutionContextKey(OFFSET)); - } - else { - executionContext.putInt(getExecutionContextKey(OFFSET), data.offset); - } - } - } - - private ChunkMonitorData getData() { - ChunkMonitorData data = holder.get(); - if (data==null) { - if (streamsRegistered) { - logger.warn("ItemStream was opened in a different thread. Restart data could be compromised."); - } - data = new ChunkMonitorData(0,0); - holder.set(data); - } - return data; - } - -} +/* + * Copyright 2006-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.step.item; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemStream; +import org.springframework.batch.item.ItemStreamException; +import org.springframework.batch.item.ItemStreamSupport; +import org.springframework.batch.item.support.CompositeItemStream; + +/** + * Manage the offset data between the last successful commit and updates made to an input + * chunk. Only works with single threaded steps because it has to use a + * {@link ThreadLocal} to manage the state and coordinate between the caller and the + * wrapped {@link ItemStream}. + * + * @author Dave Syer + * @since 2.0 + */ +public class ChunkMonitor extends ItemStreamSupport { + + private Log logger = LogFactory.getLog(getClass()); + + private boolean streamsRegistered = false; + + public static class ChunkMonitorData { + + public int offset; + + public int chunkSize; + + public ChunkMonitorData(int offset, int chunkSize) { + this.offset = offset; + this.chunkSize = chunkSize; + } + + } + + private static final String OFFSET = "OFFSET"; + + private CompositeItemStream stream = new CompositeItemStream(); + + private ThreadLocal holder = new ThreadLocal<>(); + + private ItemReader reader; + + public ChunkMonitor() { + this.setExecutionContextName(ChunkMonitor.class.getName()); + } + + /** + * @param stream the stream to set + */ + public void registerItemStream(ItemStream stream) { + streamsRegistered = true; + this.stream.register(stream); + } + + /** + * @param reader the reader to set + */ + public void setItemReader(ItemReader reader) { + this.reader = reader; + } + + public void incrementOffset() { + ChunkMonitorData data = getData(); + data.offset++; + if (data.offset >= data.chunkSize) { + resetOffset(); + } + } + + public int getOffset() { + return getData().offset; + } + + public void resetOffset() { + getData().offset = 0; + } + + public void setChunkSize(int chunkSize) { + getData().chunkSize = chunkSize; + resetOffset(); + } + + @Override + public void close() throws ItemStreamException { + super.close(); + holder.set(null); + if (streamsRegistered) { + stream.close(); + } + } + + @Override + public void open(ExecutionContext executionContext) throws ItemStreamException { + super.open(executionContext); + if (streamsRegistered) { + stream.open(executionContext); + ChunkMonitorData data = new ChunkMonitorData(executionContext.getInt(getExecutionContextKey(OFFSET), 0), 0); + holder.set(data); + if (reader == null) { + logger.warn("No ItemReader set (must be concurrent step), so ignoring offset data."); + return; + } + for (int i = 0; i < data.offset; i++) { + try { + reader.read(); + } + catch (Exception e) { + throw new ItemStreamException("Could not position reader with offset: " + data.offset, e); + } + } + + resetOffset(); + } + } + + @Override + public void update(ExecutionContext executionContext) throws ItemStreamException { + super.update(executionContext); + if (streamsRegistered) { + ChunkMonitorData data = getData(); + if (data.offset == 0) { + // Only call the underlying update method if we are on a chunk + // boundary + stream.update(executionContext); + executionContext.remove(getExecutionContextKey(OFFSET)); + } + else { + executionContext.putInt(getExecutionContextKey(OFFSET), data.offset); + } + } + } + + private ChunkMonitorData getData() { + ChunkMonitorData data = holder.get(); + if (data == null) { + if (streamsRegistered) { + logger.warn("ItemStream was opened in a different thread. Restart data could be compromised."); + } + data = new ChunkMonitorData(0, 0); + holder.set(data); + } + return data; + } + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/ChunkOrientedTasklet.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/ChunkOrientedTasklet.java index 5aabc201b..1a7fc7d0a 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/ChunkOrientedTasklet.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/ChunkOrientedTasklet.java @@ -1,97 +1,93 @@ -/* - * Copyright 2006-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.core.step.item; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.batch.core.StepContribution; -import org.springframework.batch.core.scope.context.ChunkContext; -import org.springframework.batch.core.step.tasklet.Tasklet; -import org.springframework.batch.repeat.RepeatStatus; -import org.springframework.lang.Nullable; - -/** - * A {@link Tasklet} implementing variations on read-process-write item - * handling. - * - * @author Dave Syer - * - * @param input item type - */ -public class ChunkOrientedTasklet implements Tasklet { - - private static final String INPUTS_KEY = "INPUTS"; - - private final ChunkProcessor chunkProcessor; - - private final ChunkProvider chunkProvider; - - private boolean buffering = true; - - private static Log logger = LogFactory.getLog(ChunkOrientedTasklet.class); - - public ChunkOrientedTasklet(ChunkProvider chunkProvider, ChunkProcessor chunkProcessor) { - this.chunkProvider = chunkProvider; - this.chunkProcessor = chunkProcessor; - } - - /** - * Flag to indicate that items should be buffered once read. Defaults to - * true, which is appropriate for forward-only, non-transactional item - * readers. Main (or only) use case for setting this flag to false is a - * transactional JMS item reader. - * - * @param buffering indicator - */ - public void setBuffering(boolean buffering) { - this.buffering = buffering; - } - - @Nullable - @Override - public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { - - @SuppressWarnings("unchecked") - Chunk inputs = (Chunk) chunkContext.getAttribute(INPUTS_KEY); - if (inputs == null) { - inputs = chunkProvider.provide(contribution); - if (buffering) { - chunkContext.setAttribute(INPUTS_KEY, inputs); - } - } - - chunkProcessor.process(contribution, inputs); - chunkProvider.postProcess(contribution, inputs); - - // Allow a message coming back from the processor to say that we - // are not done yet - if (inputs.isBusy()) { - logger.debug("Inputs still busy"); - return RepeatStatus.CONTINUABLE; - } - - chunkContext.removeAttribute(INPUTS_KEY); - chunkContext.setComplete(); - - if (logger.isDebugEnabled()) { - logger.debug("Inputs not busy, ended: " + inputs.isEnd()); - } - return RepeatStatus.continueIf(!inputs.isEnd()); - - } - -} +/* + * Copyright 2006-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.core.step.item; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.batch.core.StepContribution; +import org.springframework.batch.core.scope.context.ChunkContext; +import org.springframework.batch.core.step.tasklet.Tasklet; +import org.springframework.batch.repeat.RepeatStatus; +import org.springframework.lang.Nullable; + +/** + * A {@link Tasklet} implementing variations on read-process-write item handling. + * + * @author Dave Syer + * @param input item type + */ +public class ChunkOrientedTasklet implements Tasklet { + + private static final String INPUTS_KEY = "INPUTS"; + + private final ChunkProcessor chunkProcessor; + + private final ChunkProvider chunkProvider; + + private boolean buffering = true; + + private static Log logger = LogFactory.getLog(ChunkOrientedTasklet.class); + + public ChunkOrientedTasklet(ChunkProvider chunkProvider, ChunkProcessor chunkProcessor) { + this.chunkProvider = chunkProvider; + this.chunkProcessor = chunkProcessor; + } + + /** + * Flag to indicate that items should be buffered once read. Defaults to true, which + * is appropriate for forward-only, non-transactional item readers. Main (or only) use + * case for setting this flag to false is a transactional JMS item reader. + * @param buffering indicator + */ + public void setBuffering(boolean buffering) { + this.buffering = buffering; + } + + @Nullable + @Override + public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { + + @SuppressWarnings("unchecked") + Chunk inputs = (Chunk) chunkContext.getAttribute(INPUTS_KEY); + if (inputs == null) { + inputs = chunkProvider.provide(contribution); + if (buffering) { + chunkContext.setAttribute(INPUTS_KEY, inputs); + } + } + + chunkProcessor.process(contribution, inputs); + chunkProvider.postProcess(contribution, inputs); + + // Allow a message coming back from the processor to say that we + // are not done yet + if (inputs.isBusy()) { + logger.debug("Inputs still busy"); + return RepeatStatus.CONTINUABLE; + } + + chunkContext.removeAttribute(INPUTS_KEY); + chunkContext.setComplete(); + + if (logger.isDebugEnabled()) { + logger.debug("Inputs not busy, ended: " + inputs.isEnd()); + } + return RepeatStatus.continueIf(!inputs.isEnd()); + + } + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/ChunkProcessor.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/ChunkProcessor.java index 76a7b7e35..5ca36744d 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/ChunkProcessor.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/ChunkProcessor.java @@ -19,12 +19,12 @@ package org.springframework.batch.core.step.item; import org.springframework.batch.core.StepContribution; /** - * Interface defined for processing {@link Chunk}s. + * Interface defined for processing {@link Chunk}s. * * @since 2.0 */ public interface ChunkProcessor { - + void process(StepContribution contribution, Chunk chunk) throws Exception; } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/ChunkProvider.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/ChunkProvider.java index c87b225a0..36b778d2c 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/ChunkProvider.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/ChunkProvider.java @@ -21,14 +21,14 @@ import org.springframework.batch.core.StepContribution; /** * Interface for providing {@link Chunk}s to be processed, used by the * {@link ChunkOrientedTasklet} - * + * * @since 2.0 * @see ChunkOrientedTasklet */ public interface ChunkProvider { Chunk provide(StepContribution contribution) throws Exception; - + void postProcess(StepContribution contribution, Chunk chunk); - + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/DefaultItemFailureHandler.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/DefaultItemFailureHandler.java index 936da3ed8..77c5c5225 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/DefaultItemFailureHandler.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/DefaultItemFailureHandler.java @@ -22,26 +22,25 @@ import org.apache.commons.logging.LogFactory; import org.springframework.batch.core.listener.ItemListenerSupport; /** - * Default implementation of the {@link ItemListenerSupport} class that - * writes all exceptions via commons logging. Since generics can't be used to - * ensure the list contains exceptions, any non exceptions will be logged out by - * calling toString on the object. - * + * Default implementation of the {@link ItemListenerSupport} class that writes all + * exceptions via commons logging. Since generics can't be used to ensure the list + * contains exceptions, any non exceptions will be logged out by calling toString on the + * object. + * * @author Lucas Ward - * + * */ -public class DefaultItemFailureHandler extends ItemListenerSupport { +public class DefaultItemFailureHandler extends ItemListenerSupport { - protected static final Log logger = LogFactory - .getLog(DefaultItemFailureHandler.class); + protected static final Log logger = LogFactory.getLog(DefaultItemFailureHandler.class); @Override public void onReadError(Exception ex) { try { logger.error("Error encountered while reading", ex); - } catch (Exception exception) { - logger.error("Invalid type for logging: [" + exception.toString() - + "]"); + } + catch (Exception exception) { + logger.error("Invalid type for logging: [" + exception.toString() + "]"); } } @@ -49,9 +48,9 @@ public class DefaultItemFailureHandler extends ItemListenerSupport item) { try { logger.error("Error encountered while writing item: [ " + item + "]", ex); - } catch (Exception exception) { - logger.error("Invalid type for logging: [" + exception.toString() - + "]"); + } + catch (Exception exception) { + logger.error("Invalid type for logging: [" + exception.toString() + "]"); } } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/FaultTolerantChunkProcessor.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/FaultTolerantChunkProcessor.java index cce802a59..dbcdc8370 100755 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/FaultTolerantChunkProcessor.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/FaultTolerantChunkProcessor.java @@ -46,8 +46,8 @@ import org.springframework.retry.RetryException; import org.springframework.retry.support.DefaultRetryState; /** - * FaultTolerant implementation of the {@link ChunkProcessor} interface, that - * allows for skipping or retry of items that cause exceptions during writing. + * FaultTolerant implementation of the {@link ChunkProcessor} interface, that allows for + * skipping or retry of items that cause exceptions during writing. * */ public class FaultTolerantChunkProcessor extends SimpleChunkProcessor { @@ -71,10 +71,9 @@ public class FaultTolerantChunkProcessor extends SimpleChunkProcessor extends SimpleChunkProcessor rollbackClassifier) { @@ -113,11 +111,10 @@ public class FaultTolerantChunkProcessor extends SimpleChunkProcessor extends SimpleChunkProcessor extends SimpleChunkProcessor inputs) { /* - * Need to remember the write skips across transactions, otherwise they - * keep coming back. Since we register skips with the inputs they will - * not be processed again but the output skips need to be saved for - * registration later with the listeners. The inputs are going to be the - * same for all transactions processing the same chunk, but the outputs - * are not, so we stash them in user data on the inputs. + * Need to remember the write skips across transactions, otherwise they keep + * coming back. Since we register skips with the inputs they will not be processed + * again but the output skips need to be saved for registration later with the + * listeners. The inputs are going to be the same for all transactions processing + * the same chunk, but the outputs are not, so we stash them in user data on the + * inputs. */ @SuppressWarnings("unchecked") @@ -234,7 +230,8 @@ public class FaultTolerantChunkProcessor extends SimpleChunkProcessor extends SimpleChunkProcessor extends SimpleChunkProcessor extends SimpleChunkProcessor extends SimpleChunkProcessor extends SimpleChunkProcessor extends SimpleChunkProcessor extends SimpleChunkProcessor extends SimpleChunkProvider { /** - * Hard limit for number of read skips in the same chunk. Should be - * sufficiently high that it is only encountered in a runaway step where all - * items are skipped before the chunk can complete (leading to a potential - * heap memory problem). + * Hard limit for number of read skips in the same chunk. Should be sufficiently high + * that it is only encountered in a runaway step where all items are skipped before + * the chunk can complete (leading to a potential heap memory problem). */ public static final int DEFAULT_MAX_SKIPS_ON_READ = 100; @@ -63,17 +61,17 @@ public class FaultTolerantChunkProvider extends SimpleChunkProvider { /** * The policy that determines whether exceptions can be skipped on read. - * @param skipPolicy instance of {@link SkipPolicy} to be used by FaultTolerantChunkProvider. + * @param skipPolicy instance of {@link SkipPolicy} to be used by + * FaultTolerantChunkProvider. */ public void setSkipPolicy(SkipPolicy skipPolicy) { this.skipPolicy = skipPolicy; } /** - * Classifier to determine whether exceptions have been marked as - * no-rollback (as opposed to skippable). If encountered they are simply - * ignored, unless also skippable. - * + * Classifier to determine whether exceptions have been marked as no-rollback (as + * opposed to skippable). If encountered they are simply ignored, unless also + * skippable. * @param rollbackClassifier the rollback classifier to set */ public void setRollbackClassifier(Classifier rollbackClassifier) { @@ -125,7 +123,6 @@ public class FaultTolerantChunkProvider extends SimpleChunkProvider { /** * Convenience method for calling process skip policy. - * * @param policy the skip policy * @param e the cause of the skip * @param skipCount the current skip count diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/ForceRollbackForWriteSkipException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/ForceRollbackForWriteSkipException.java index 7c42de7ad..5d192b7f1 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/ForceRollbackForWriteSkipException.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/ForceRollbackForWriteSkipException.java @@ -17,11 +17,11 @@ package org.springframework.batch.core.step.item; /** - * Fatal exception to be thrown when a rollback must be forced, typically after - * catching an exception that otherwise would not cause a rollback. - * + * Fatal exception to be thrown when a rollback must be forced, typically after catching + * an exception that otherwise would not cause a rollback. + * * @author Dave Syer - * + * */ @SuppressWarnings("serial") public class ForceRollbackForWriteSkipException extends RuntimeException { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/KeyGenerator.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/KeyGenerator.java index 49da956d2..77851c9a9 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/KeyGenerator.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/KeyGenerator.java @@ -1,30 +1,29 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.step.item; - -/** - * Interface for defining keys to uniquely identify items. - * this can be useful if the item itself cannot be modified to - * properly override equals. - * - * @author Dave Syer - * - */ -public interface KeyGenerator { - - Object getKey(Object item); - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.step.item; + +/** + * Interface for defining keys to uniquely identify items. this can be useful if the item + * itself cannot be modified to properly override equals. + * + * @author Dave Syer + * + */ +public interface KeyGenerator { + + Object getKey(Object item); + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/SimpleChunkProcessor.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/SimpleChunkProcessor.java index f5be9ee11..0799d2453 100755 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/SimpleChunkProcessor.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/SimpleChunkProcessor.java @@ -33,9 +33,8 @@ import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** - * Simple implementation of the {@link ChunkProcessor} interface that handles - * basic item writing and processing. Any exceptions encountered will be - * rethrown. + * Simple implementation of the {@link ChunkProcessor} interface that handles basic item + * writing and processing. Any exceptions encountered will be rethrown. * * @see ChunkOrientedTasklet */ @@ -55,7 +54,8 @@ public class SimpleChunkProcessor implements ChunkProcessor, Initializi this(null, null); } - public SimpleChunkProcessor(@Nullable ItemProcessor itemProcessor, ItemWriter itemWriter) { + public SimpleChunkProcessor(@Nullable ItemProcessor itemProcessor, + ItemWriter itemWriter) { this.itemProcessor = itemProcessor; this.itemWriter = itemWriter; } @@ -89,9 +89,8 @@ public class SimpleChunkProcessor implements ChunkProcessor, Initializi } /** - * Register some {@link StepListener}s with the handler. Each will get the - * callbacks in the order specified at the correct stage. - * + * Register some {@link StepListener}s with the handler. Each will get the callbacks + * in the order specified at the correct stage. * @param listeners list of {@link StepListener} instances. */ public void setListeners(List listeners) { @@ -102,7 +101,6 @@ public class SimpleChunkProcessor implements ChunkProcessor, Initializi /** * Register a listener for callbacks at the appropriate stages in a process. - * * @param listener a {@link StepListener} */ public void registerListener(StepListener listener) { @@ -144,7 +142,6 @@ public class SimpleChunkProcessor implements ChunkProcessor, Initializi /** * Surrounds the actual write call with listener callbacks. - * * @param items list of items to be written. * @throws Exception thrown if error occurs. */ @@ -168,7 +165,6 @@ public class SimpleChunkProcessor implements ChunkProcessor, Initializi /** * Call the listener's after write method. - * * @param items list of items that were just written. */ protected final void doAfterWrite(List items) { @@ -219,14 +215,12 @@ public class SimpleChunkProcessor implements ChunkProcessor, Initializi } /** - * Extension point for subclasses to allow them to memorise the contents of - * the inputs, in case they are needed for accounting purposes later. The - * default implementation sets up some user data to remember the original - * size of the inputs. If this method is overridden then some or all of - * {@link #isComplete(Chunk)}, {@link #getFilterCount(Chunk, Chunk)} and - * {@link #getAdjustedOutputs(Chunk, Chunk)} might also need to be, to - * ensure that the user data is handled consistently. - * + * Extension point for subclasses to allow them to memorise the contents of the + * inputs, in case they are needed for accounting purposes later. The default + * implementation sets up some user data to remember the original size of the inputs. + * If this method is overridden then some or all of {@link #isComplete(Chunk)}, + * {@link #getFilterCount(Chunk, Chunk)} and {@link #getAdjustedOutputs(Chunk, Chunk)} + * might also need to be, to ensure that the user data is handled consistently. * @param inputs the inputs for the process */ protected void initializeUserData(Chunk inputs) { @@ -234,12 +228,10 @@ public class SimpleChunkProcessor implements ChunkProcessor, Initializi } /** - * Extension point for subclasses to calculate the filter count. Defaults to - * the difference between input size and output size. - * + * Extension point for subclasses to calculate the filter count. Defaults to the + * difference between input size and output size. * @param inputs the inputs after transformation * @param outputs the outputs after transformation - * * @return the difference in sizes * * @see #initializeUserData(Chunk) @@ -249,9 +241,8 @@ public class SimpleChunkProcessor implements ChunkProcessor, Initializi } /** - * Extension point for subclasses that want to store additional data in the - * inputs. Default just checks if inputs are empty. - * + * Extension point for subclasses that want to store additional data in the inputs. + * Default just checks if inputs are empty. * @param inputs the input chunk * @return true if it is empty * @@ -262,10 +253,9 @@ public class SimpleChunkProcessor implements ChunkProcessor, Initializi } /** - * Extension point for subclasses that want to adjust the outputs based on - * additional saved data in the inputs. Default implementation just returns - * the outputs unchanged. - * + * Extension point for subclasses that want to adjust the outputs based on additional + * saved data in the inputs. Default implementation just returns the outputs + * unchanged. * @param inputs the inputs for the transformation * @param outputs the result of the transformation * @return the outputs unchanged @@ -277,11 +267,10 @@ public class SimpleChunkProcessor implements ChunkProcessor, Initializi } /** - * Simple implementation delegates to the {@link #doWrite(List)} method and - * increments the write count in the contribution. Subclasses can handle - * more complicated scenarios, e.g.with fault tolerance. If output items are - * skipped they should be removed from the inputs as well. - * + * Simple implementation delegates to the {@link #doWrite(List)} method and increments + * the write count in the contribution. Subclasses can handle more complicated + * scenarios, e.g.with fault tolerance. If output items are skipped they should be + * removed from the inputs as well. * @param contribution the current step contribution * @param inputs the inputs that gave rise to the outputs * @param outputs the outputs to write @@ -295,8 +284,8 @@ public class SimpleChunkProcessor implements ChunkProcessor, Initializi } catch (Exception e) { /* - * For a simple chunk processor (no fault tolerance) we are done - * here, so prevent any more processing of these inputs. + * For a simple chunk processor (no fault tolerance) we are done here, so + * prevent any more processing of these inputs. */ inputs.clear(); status = BatchMetrics.STATUS_FAILURE; @@ -320,8 +309,8 @@ public class SimpleChunkProcessor implements ChunkProcessor, Initializi } catch (Exception e) { /* - * For a simple chunk processor (no fault tolerance) we are done - * here, so prevent any more processing of these inputs. + * For a simple chunk processor (no fault tolerance) we are done here, so + * prevent any more processing of these inputs. */ inputs.clear(); status = BatchMetrics.STATUS_FAILURE; @@ -340,13 +329,14 @@ public class SimpleChunkProcessor implements ChunkProcessor, Initializi return outputs; } - protected void stopTimer(Timer.Sample sample, StepExecution stepExecution, String metricName, String status, String description) { + protected void stopTimer(Timer.Sample sample, StepExecution stepExecution, String metricName, String status, + String description) { String fullyQualifiedMetricName = BatchMetrics.METRICS_PREFIX + metricName; sample.stop(BatchMetrics.createTimer(metricName, description + " duration", - Tag.of(fullyQualifiedMetricName + ".job.name", stepExecution.getJobExecution().getJobInstance().getJobName()), + Tag.of(fullyQualifiedMetricName + ".job.name", + stepExecution.getJobExecution().getJobInstance().getJobName()), Tag.of(fullyQualifiedMetricName + ".step.name", stepExecution.getStepName()), - Tag.of(fullyQualifiedMetricName + ".status", status) - )); + Tag.of(fullyQualifiedMetricName + ".status", status))); } } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/SimpleChunkProvider.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/SimpleChunkProvider.java index 910e78175..6bb97894f 100755 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/SimpleChunkProvider.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/SimpleChunkProvider.java @@ -36,8 +36,8 @@ import org.springframework.batch.repeat.RepeatStatus; import org.springframework.lang.Nullable; /** - * Simple implementation of the ChunkProvider interface that does basic chunk - * providing from an {@link ItemReader}. + * Simple implementation of the ChunkProvider interface that does basic chunk providing + * from an {@link ItemReader}. * * @author Dave Syer * @author Michael Minella @@ -60,9 +60,8 @@ public class SimpleChunkProvider implements ChunkProvider { } /** - * Register some {@link StepListener}s with the handler. Each will get the - * callbacks in the order specified at the correct stage. - * + * Register some {@link StepListener}s with the handler. Each will get the callbacks + * in the order specified at the correct stage. * @param listeners list of {@link StepListener}s. */ public void setListeners(List listeners) { @@ -73,7 +72,6 @@ public class SimpleChunkProvider implements ChunkProvider { /** * Register a listener for callbacks at the appropriate stages in a process. - * * @param listener a {@link StepListener} */ public void registerListener(StepListener listener) { @@ -97,7 +95,7 @@ public class SimpleChunkProvider implements ChunkProvider { try { listener.beforeRead(); I item = itemReader.read(); - if(item != null) { + if (item != null) { listener.afterRead(item); } return item; @@ -152,10 +150,10 @@ public class SimpleChunkProvider implements ChunkProvider { private void stopTimer(Timer.Sample sample, StepExecution stepExecution, String status) { String fullyQualifiedMetricName = BatchMetrics.METRICS_PREFIX + "item.read"; sample.stop(BatchMetrics.createTimer("item.read", "Item reading duration", - Tag.of(fullyQualifiedMetricName + ".job.name", stepExecution.getJobExecution().getJobInstance().getJobName()), + Tag.of(fullyQualifiedMetricName + ".job.name", + stepExecution.getJobExecution().getJobInstance().getJobName()), Tag.of(fullyQualifiedMetricName + ".step.name", stepExecution.getStepName()), - Tag.of(fullyQualifiedMetricName + ".status", status) - )); + Tag.of(fullyQualifiedMetricName + ".status", status))); } @Override @@ -164,16 +162,13 @@ public class SimpleChunkProvider implements ChunkProvider { } /** - * Delegates to {@link #doRead()}. Subclasses can add additional behaviour - * (e.g. exception handling). - * + * Delegates to {@link #doRead()}. Subclasses can add additional behaviour (e.g. + * exception handling). * @param contribution the current step execution contribution * @param chunk the current chunk * @return a new item for processing or {@code null} if the data source is exhausted - * - * @throws SkipOverflowException if specifically the chunk is accumulating - * too much data (e.g. skips) and it wants to force a commit. - * + * @throws SkipOverflowException if specifically the chunk is accumulating too much + * data (e.g. skips) and it wants to force a commit. * @throws Exception if there is a generic issue */ @Nullable diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/SimpleRetryExceptionHandler.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/SimpleRetryExceptionHandler.java index 5fa496813..d02d05019 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/SimpleRetryExceptionHandler.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/SimpleRetryExceptionHandler.java @@ -30,8 +30,8 @@ import java.util.Collection; /** * An {@link ExceptionHandler} that is aware of the retry context so that it can - * distinguish between a fatal exception and one that can be retried. Delegates - * the actual exception handling to another {@link ExceptionHandler}. + * distinguish between a fatal exception and one that can be retried. Delegates the actual + * exception handling to another {@link ExceptionHandler}. * * @author Dave Syer * @@ -53,23 +53,23 @@ public class SimpleRetryExceptionHandler extends RetryListenerSupport implements /** * Create an exception handler from its mandatory properties. - * - * @param retryPolicy the retry policy that will be under effect when an - * exception is encountered - * @param exceptionHandler the delegate to use if an exception actually - * needs to be handled + * @param retryPolicy the retry policy that will be under effect when an exception is + * encountered + * @param exceptionHandler the delegate to use if an exception actually needs to be + * handled * @param fatalExceptionClasses exceptions */ - public SimpleRetryExceptionHandler(RetryPolicy retryPolicy, ExceptionHandler exceptionHandler, Collection> fatalExceptionClasses) { + public SimpleRetryExceptionHandler(RetryPolicy retryPolicy, ExceptionHandler exceptionHandler, + Collection> fatalExceptionClasses) { this.retryPolicy = retryPolicy; this.exceptionHandler = exceptionHandler; this.fatalExceptionClassifier = new BinaryExceptionClassifier(fatalExceptionClasses); } /** - * Check if the exception is going to be retried, and veto the handling if - * it is. If retry is exhausted or the exception is on the fatal list, then - * handle using the delegate. + * Check if the exception is going to be retried, and veto the handling if it is. If + * retry is exhausted or the exception is on the fatal list, then handle using the + * delegate. * * @see ExceptionHandler#handleException(org.springframework.batch.repeat.RepeatContext, * java.lang.Throwable) @@ -88,25 +88,26 @@ public class SimpleRetryExceptionHandler extends RetryListenerSupport implements } /** - * If retry is exhausted set up some state in the context that can be used - * to signal that the exception should be handled. + * If retry is exhausted set up some state in the context that can be used to signal + * that the exception should be handled. * * @see org.springframework.retry.RetryListener#close(org.springframework.retry.RetryContext, * org.springframework.retry.RetryCallback, java.lang.Throwable) */ @Override - public void close(RetryContext context, RetryCallback callback, Throwable throwable) { + public void close(RetryContext context, RetryCallback callback, + Throwable throwable) { if (!retryPolicy.canRetry(context)) { if (logger.isDebugEnabled()) { - logger.debug("Marking retry as exhausted: "+context); + logger.debug("Marking retry as exhausted: " + context); } getRepeatContext().setAttribute(EXHAUSTED, "true"); } } /** - * Get the parent context (the retry is in an inner "chunk" loop and we want - * the exception to be handled at the outer "step" level). + * Get the parent context (the retry is in an inner "chunk" loop and we want the + * exception to be handled at the outer "step" level). * @return the {@link RepeatContext} that should hold the exhausted flag. */ private RepeatContext getRepeatContext() { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/SkipOverflowException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/SkipOverflowException.java index ba77616af..908358d29 100755 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/SkipOverflowException.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/SkipOverflowException.java @@ -1,35 +1,35 @@ -/* - * Copyright 2006-2009 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.core.step.item; - -import org.springframework.batch.core.step.skip.SkipException; - -/** - * @author Dave Syer - * - */ -@SuppressWarnings("serial") -public class SkipOverflowException extends SkipException { - - /** - * @param msg the message for the user - */ - public SkipOverflowException(String msg) { - super(msg); - } - -} +/* + * Copyright 2006-2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.core.step.item; + +import org.springframework.batch.core.step.skip.SkipException; + +/** + * @author Dave Syer + * + */ +@SuppressWarnings("serial") +public class SkipOverflowException extends SkipException { + + /** + * @param msg the message for the user + */ + public SkipOverflowException(String msg) { + super(msg); + } + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/SkipWrapper.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/SkipWrapper.java index f547f0ef9..2ad4eac4b 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/SkipWrapper.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/SkipWrapper.java @@ -20,10 +20,10 @@ import org.springframework.lang.Nullable; /** * Wrapper for an item and its exception if it failed processing. - * + * * @author Dave Syer * @author Mahmoud Ben Hassine - * + * */ public class SkipWrapper { @@ -45,7 +45,6 @@ public class SkipWrapper { this(null, e); } - public SkipWrapper(T item, @Nullable Throwable e) { this.item = item; this.exception = e; diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/job/DefaultJobParametersExtractor.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/job/DefaultJobParametersExtractor.java index 72a1f389c..13d2b3725 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/job/DefaultJobParametersExtractor.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/job/DefaultJobParametersExtractor.java @@ -29,9 +29,9 @@ import org.springframework.batch.core.StepExecution; import org.springframework.batch.item.ExecutionContext; /** - * Simple implementation of {@link JobParametersExtractor} which pulls - * parameters with named keys out of the step execution context and the job - * parameters of the surrounding job. + * Simple implementation of {@link JobParametersExtractor} which pulls parameters with + * named keys out of the step execution context and the job parameters of the surrounding + * job. * * @author Dave Syer * @author Will Schipp @@ -44,16 +44,15 @@ public class DefaultJobParametersExtractor implements JobParametersExtractor { private boolean useAllParentParameters = true; /** - * The key names to pull out of the execution context or job parameters, if - * they exist. If a key doesn't exist in the execution context then the job - * parameters from the enclosing job execution are tried, and if there is - * nothing there either then no parameter is extracted. Key names ending - * with (long), (int), (double), - * (date) or (string) will be assumed to refer to - * values of the respective type and assigned to job parameters accordingly - * (there will be an error if they are not of the right type). Without a - * special suffix in that form a parameter is assumed to be of type String. - * + * The key names to pull out of the execution context or job parameters, if they + * exist. If a key doesn't exist in the execution context then the job parameters from + * the enclosing job execution are tried, and if there is nothing there either then no + * parameter is extracted. Key names ending with (long), + * (int), (double), (date) or + * (string) will be assumed to refer to values of the respective type and + * assigned to job parameters accordingly (there will be an error if they are not of + * the right type). Without a special suffix in that form a parameter is assumed to be + * of type String. * @param keys the keys to set */ public void setKeys(String[] keys) { @@ -133,13 +132,11 @@ public class DefaultJobParametersExtractor implements JobParametersExtractor { /** * setter to support switching off all parent parameters - * - * @param useAllParentParameters if false do not include parent parameters. - * True if all parent parameters need to be included. + * @param useAllParentParameters if false do not include parent parameters. True if + * all parent parameters need to be included. */ public void setUseAllParentParameters(boolean useAllParentParameters) { this.useAllParentParameters = useAllParentParameters; } - } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/job/JobParametersExtractor.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/job/JobParametersExtractor.java index b53951cf8..cbde6704e 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/job/JobParametersExtractor.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/job/JobParametersExtractor.java @@ -20,21 +20,18 @@ import org.springframework.batch.core.JobParameters; import org.springframework.batch.core.StepExecution; /** - * Strategy interface for translating a {@link StepExecution} into - * {@link JobParameters}. - * + * Strategy interface for translating a {@link StepExecution} into {@link JobParameters}. + * * @author Dave Syer - * + * */ public interface JobParametersExtractor { /** - * Extract job parameters from the step execution, for example from the - * execution context or other properties. - * + * Extract job parameters from the step execution, for example from the execution + * context or other properties. * @param job a {@link Job} * @param stepExecution a {@link StepExecution} - * * @return some {@link JobParameters} */ JobParameters getJobParameters(Job job, StepExecution stepExecution); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/job/JobStep.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/job/JobStep.java index 6bd803353..2176fbe73 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/job/JobStep.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/job/JobStep.java @@ -29,21 +29,19 @@ import org.springframework.batch.item.ExecutionContext; import org.springframework.util.Assert; /** - * A {@link Step} that delegates to a {@link Job} to do its work. This is a - * great tool for managing dependencies between jobs, and also to modularise - * complex step logic into something that is testable in isolation. The job is - * executed with parameters that can be extracted from the step execution, hence - * this step can also be usefully used as the worker in a parallel or - * partitioned execution. - * + * A {@link Step} that delegates to a {@link Job} to do its work. This is a great tool for + * managing dependencies between jobs, and also to modularise complex step logic into + * something that is testable in isolation. The job is executed with parameters that can + * be extracted from the step execution, hence this step can also be usefully used as the + * worker in a parallel or partitioned execution. + * * @author Dave Syer - * + * */ public class JobStep extends AbstractStep { /** - * The key for the job parameters in the step execution context. Needed for - * restarts. + * The key for the job parameters in the step execution context. Needed for restarts. */ private static final String JOB_PARAMETERS_KEY = JobStep.class.getName() + ".JOB_PARAMETERS"; @@ -62,7 +60,6 @@ public class JobStep extends AbstractStep { /** * The {@link Job} to delegate to in this step. - * * @param job a {@link Job} */ public void setJob(Job job) { @@ -70,9 +67,7 @@ public class JobStep extends AbstractStep { } /** - * A {@link JobLauncher} is required to be able to run the enclosed - * {@link Job}. - * + * A {@link JobLauncher} is required to be able to run the enclosed {@link Job}. * @param jobLauncher the {@link JobLauncher} to set */ public void setJobLauncher(JobLauncher jobLauncher) { @@ -82,9 +77,8 @@ public class JobStep extends AbstractStep { /** * The {@link JobParametersExtractor} is used to extract * {@link JobParametersExtractor} from the {@link StepExecution} to run the - * {@link Job}. By default an instance will be provided that simply copies - * the {@link JobParameters} from the parent job. - * + * {@link Job}. By default an instance will be provided that simply copies the + * {@link JobParameters} from the parent job. * @param jobParametersExtractor the {@link JobParametersExtractor} to set */ public void setJobParametersExtractor(JobParametersExtractor jobParametersExtractor) { @@ -92,12 +86,11 @@ public class JobStep extends AbstractStep { } /** - * Execute the job provided by delegating to the {@link JobLauncher} to - * prevent duplicate executions. The job parameters will be generated by the - * {@link JobParametersExtractor} provided (if any), otherwise empty. On a - * restart, the job parameters will be the same as the last (failed) - * execution. - * + * Execute the job provided by delegating to the {@link JobLauncher} to prevent + * duplicate executions. The job parameters will be generated by the + * {@link JobParametersExtractor} provided (if any), otherwise empty. On a restart, + * the job parameters will be the same as the last (failed) execution. + * * @see AbstractStep#doExecute(StepExecution) */ @Override @@ -117,29 +110,31 @@ public class JobStep extends AbstractStep { } JobExecution jobExecution = jobLauncher.run(job, jobParameters); - + stepExecution.setExitStatus(determineStepExitStatus(stepExecution, jobExecution)); if (jobExecution.getStatus().isUnsuccessful()) { // AbstractStep will take care of the step execution status throw new UnexpectedJobExecutionException("Step failure: the delegate Job failed in JobStep."); } - else if(jobExecution.getStatus().equals(BatchStatus.STOPPED)) { + else if (jobExecution.getStatus().equals(BatchStatus.STOPPED)) { stepExecution.setStatus(BatchStatus.STOPPED); } } - + /** - * Determines the {@link ExitStatus} taking into consideration the {@link ExitStatus} from - * the {@link StepExecution}, which invoked the {@link JobStep}, and the {@link JobExecution}. - * - * @param stepExecution the {@link StepExecution} which invoked the {@link JobExecution} + * Determines the {@link ExitStatus} taking into consideration the {@link ExitStatus} + * from the {@link StepExecution}, which invoked the {@link JobStep}, and the + * {@link JobExecution}. + * @param stepExecution the {@link StepExecution} which invoked the + * {@link JobExecution} * @param jobExecution the {@link JobExecution} * @return the final {@link ExitStatus} */ private ExitStatus determineStepExitStatus(StepExecution stepExecution, JobExecution jobExecution) { - ExitStatus exitStatus = stepExecution.getExitStatus() != null ? stepExecution.getExitStatus() : ExitStatus.COMPLETED; - + ExitStatus exitStatus = stepExecution.getExitStatus() != null ? stepExecution.getExitStatus() + : ExitStatus.COMPLETED; + return exitStatus.and(jobExecution.getExitStatus()); } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/skip/AlwaysSkipItemSkipPolicy.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/skip/AlwaysSkipItemSkipPolicy.java index 104a7fc8f..cf777cd44 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/skip/AlwaysSkipItemSkipPolicy.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/skip/AlwaysSkipItemSkipPolicy.java @@ -15,10 +15,9 @@ */ package org.springframework.batch.core.step.skip; - /** - * Implementation of the {@link SkipPolicy} interface that - * will always return that an item should be skipped. + * Implementation of the {@link SkipPolicy} interface that will always return that an item + * should be skipped. * * @author Ben Hale * @author Lucas Ward diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/skip/ExceptionClassifierSkipPolicy.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/skip/ExceptionClassifierSkipPolicy.java index 34330c594..b742992f9 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/skip/ExceptionClassifierSkipPolicy.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/skip/ExceptionClassifierSkipPolicy.java @@ -21,12 +21,11 @@ import org.springframework.classify.Classifier; import org.springframework.classify.SubclassClassifier; /** - * A {@link SkipPolicy} that depends on an exception classifier to make its - * decision, and then delegates to the classifier result. + * A {@link SkipPolicy} that depends on an exception classifier to make its decision, and + * then delegates to the classifier result. * * @author Dave Syer * @author Mahmoud Ben Hassine - * * @see SubclassClassifier */ public class ExceptionClassifierSkipPolicy implements SkipPolicy { @@ -35,7 +34,6 @@ public class ExceptionClassifierSkipPolicy implements SkipPolicy { /** * The classifier that will be used to choose a delegate policy. - * * @param classifier the classifier to use to choose a delegate policy */ public void setExceptionClassifier(SubclassClassifier classifier) { @@ -43,24 +41,22 @@ public class ExceptionClassifierSkipPolicy implements SkipPolicy { } /** - * Setter for policy map. This property should not be changed dynamically - - * set it once, e.g. in configuration, and then don't change it during a - * running application. Either this property or the exception classifier - * directly should be set, but not both. - * - * @param policyMap a map of String to {@link SkipPolicy} that will be used - * to create a {@link Classifier} to locate a policy. + * Setter for policy map. This property should not be changed dynamically - set it + * once, e.g. in configuration, and then don't change it during a running application. + * Either this property or the exception classifier directly should be set, but not + * both. + * @param policyMap a map of String to {@link SkipPolicy} that will be used to create + * a {@link Classifier} to locate a policy. */ public void setPolicyMap(Map, SkipPolicy> policyMap) { - SubclassClassifier subclassClassifier = new SubclassClassifier<>( - policyMap, new NeverSkipItemSkipPolicy()); + SubclassClassifier subclassClassifier = new SubclassClassifier<>(policyMap, + new NeverSkipItemSkipPolicy()); this.classifier = subclassClassifier; } /** - * Consult the classifier and find a delegate policy, and then use that to - * determine the outcome. - * + * Consult the classifier and find a delegate policy, and then use that to determine + * the outcome. * @param t the throwable to consider * @param skipCount the current skip count * @return true if the exception can be skipped diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/skip/LimitCheckingItemSkipPolicy.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/skip/LimitCheckingItemSkipPolicy.java index 7bb22560b..fb515ea96 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/skip/LimitCheckingItemSkipPolicy.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/skip/LimitCheckingItemSkipPolicy.java @@ -27,21 +27,20 @@ import org.springframework.classify.Classifier; /** *

      - * {@link SkipPolicy} that determines whether or not reading should continue - * based upon how many items have been skipped. This is extremely useful - * behavior, as it allows you to skip records, but will throw a - * {@link SkipLimitExceededException} if a set limit has been exceeded. For - * example, it is generally advisable to skip {@link FlatFileParseException}s, - * however, if the vast majority of records are causing exceptions, the file is - * likely bad. + * {@link SkipPolicy} that determines whether or not reading should continue based upon + * how many items have been skipped. This is extremely useful behavior, as it allows you + * to skip records, but will throw a {@link SkipLimitExceededException} if a set limit has + * been exceeded. For example, it is generally advisable to skip + * {@link FlatFileParseException}s, however, if the vast majority of records are causing + * exceptions, the file is likely bad. *

      * *

      * Furthermore, it is also likely that you only want to skip certain exceptions. - * {@link FlatFileParseException} is a good example of an exception you will - * likely want to skip, but a {@link FileNotFoundException} should cause - * immediate termination of the {@link Step}. A {@link Classifier} is used to - * determine whether a particular exception is skippable or not. + * {@link FlatFileParseException} is a good example of an exception you will likely want + * to skip, but a {@link FileNotFoundException} should cause immediate termination of the + * {@link Step}. A {@link Classifier} is used to determine whether a particular exception + * is skippable or not. *

      * * @author Ben Hale @@ -61,24 +60,21 @@ public class LimitCheckingItemSkipPolicy implements SkipPolicy { * Convenience constructor that assumes all exception types are fatal. */ public LimitCheckingItemSkipPolicy() { - this(0, Collections., Boolean> emptyMap()); + this(0, Collections., Boolean>emptyMap()); } /** - * @param skipLimit the number of skippable exceptions that are allowed to - * be skipped - * @param skippableExceptions exception classes that can be skipped - * (non-critical) + * @param skipLimit the number of skippable exceptions that are allowed to be skipped + * @param skippableExceptions exception classes that can be skipped (non-critical) */ public LimitCheckingItemSkipPolicy(int skipLimit, Map, Boolean> skippableExceptions) { this(skipLimit, new BinaryExceptionClassifier(skippableExceptions)); } /** - * @param skipLimit the number of skippable exceptions that are allowed to - * be skipped - * @param skippableExceptionClassifier exception classifier for those that - * can be skipped (non-critical) + * @param skipLimit the number of skippable exceptions that are allowed to be skipped + * @param skippableExceptionClassifier exception classifier for those that can be + * skipped (non-critical) */ public LimitCheckingItemSkipPolicy(int skipLimit, Classifier skippableExceptionClassifier) { this.skipLimit = skipLimit; @@ -86,9 +82,8 @@ public class LimitCheckingItemSkipPolicy implements SkipPolicy { } /** - * The absolute number of skips (of skippable exceptions) that can be - * tolerated before a failure. - * + * The absolute number of skips (of skippable exceptions) that can be tolerated before + * a failure. * @param skipLimit the skip limit to set */ public void setSkipLimit(long skipLimit) { @@ -96,20 +91,17 @@ public class LimitCheckingItemSkipPolicy implements SkipPolicy { } /** - * The classifier that will be used to decide on skippability. If an - * exception classifies as "true" then it is skippable, and otherwise not. - * - * @param skippableExceptionClassifier the skippableExceptionClassifier to - * set + * The classifier that will be used to decide on skippability. If an exception + * classifies as "true" then it is skippable, and otherwise not. + * @param skippableExceptionClassifier the skippableExceptionClassifier to set */ public void setSkippableExceptionClassifier(Classifier skippableExceptionClassifier) { this.skippableExceptionClassifier = skippableExceptionClassifier; } /** - * Set up the classifier through a convenient map from throwable class to - * boolean (true if skippable). - * + * Set up the classifier through a convenient map from throwable class to boolean + * (true if skippable). * @param skippableExceptions the skippable exceptions to set */ public void setSkippableExceptionMap(Map, Boolean> skippableExceptions) { @@ -117,12 +109,11 @@ public class LimitCheckingItemSkipPolicy implements SkipPolicy { } /** - * Given the provided exception and skip count, determine whether or not - * processing should continue for the given exception. If the exception is - * not classified as skippable in the classifier, false will be returned. If - * the exception is classified as skippable and {@link StepExecution} - * skipCount is greater than the skipLimit, then a - * {@link SkipLimitExceededException} will be thrown. + * Given the provided exception and skip count, determine whether or not processing + * should continue for the given exception. If the exception is not classified as + * skippable in the classifier, false will be returned. If the exception is classified + * as skippable and {@link StepExecution} skipCount is greater than the skipLimit, + * then a {@link SkipLimitExceededException} will be thrown. */ @Override public boolean shouldSkip(Throwable t, long skipCount) { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/skip/NeverSkipItemSkipPolicy.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/skip/NeverSkipItemSkipPolicy.java index bddbd1808..551695fa1 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/skip/NeverSkipItemSkipPolicy.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/skip/NeverSkipItemSkipPolicy.java @@ -15,15 +15,14 @@ */ package org.springframework.batch.core.step.skip; - /** - * {@link SkipPolicy} implementation that always returns false, - * indicating that an item should not be skipped. + * {@link SkipPolicy} implementation that always returns false, indicating that an item + * should not be skipped. * * @author Lucas Ward * @author Mahmoud Ben Hassine */ -public class NeverSkipItemSkipPolicy implements SkipPolicy{ +public class NeverSkipItemSkipPolicy implements SkipPolicy { @Override public boolean shouldSkip(Throwable t, long skipCount) { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/skip/SkipException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/skip/SkipException.java index f760b327a..235275c7a 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/skip/SkipException.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/skip/SkipException.java @@ -19,7 +19,7 @@ import org.springframework.batch.core.UnexpectedJobExecutionException; /** * Base exception indicating that the skip has failed or caused a failure. - * + * * @author Dave Syer */ @SuppressWarnings("serial") @@ -39,7 +39,5 @@ public abstract class SkipException extends UnexpectedJobExecutionException { public SkipException(String msg) { super(msg); } - - } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/skip/SkipLimitExceededException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/skip/SkipLimitExceededException.java index 501b228a1..c85bc17cd 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/skip/SkipLimitExceededException.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/skip/SkipLimitExceededException.java @@ -15,11 +15,10 @@ */ package org.springframework.batch.core.step.skip; - /** - * Exception indicating that the skip limit for a particular {@link org.springframework.batch.core.Step} has - * been exceeded. - * + * Exception indicating that the skip limit for a particular + * {@link org.springframework.batch.core.Step} has been exceeded. + * * @author Ben Hale * @author Lucas Ward * @author Dave Syer @@ -29,13 +28,14 @@ package org.springframework.batch.core.step.skip; public class SkipLimitExceededException extends SkipException { private final long skipLimit; - + public SkipLimitExceededException(long skipLimit, Throwable t) { super("Skip limit of '" + skipLimit + "' exceeded", t); this.skipLimit = skipLimit; } - + public long getSkipLimit() { - return skipLimit; - } + return skipLimit; + } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/skip/SkipListenerFailedException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/skip/SkipListenerFailedException.java index f7fda85cd..c96ac6afc 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/skip/SkipListenerFailedException.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/skip/SkipListenerFailedException.java @@ -19,12 +19,11 @@ import org.springframework.batch.core.SkipListener; import org.springframework.batch.core.UnexpectedJobExecutionException; /** - * Special exception to indicate a failure in a skip listener. These need - * special treatment in the framework in case a skip sends itself into an - * infinite loop. - * + * Special exception to indicate a failure in a skip listener. These need special + * treatment in the framework in case a skip sends itself into an infinite loop. + * * @author Dave Syer - * + * */ @SuppressWarnings("serial") public class SkipListenerFailedException extends UnexpectedJobExecutionException { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/skip/SkipPolicy.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/skip/SkipPolicy.java index 2c0838d89..800142d31 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/skip/SkipPolicy.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/skip/SkipPolicy.java @@ -17,7 +17,7 @@ package org.springframework.batch.core.step.skip; /** * Policy for determining whether or not some processing should be skipped. - * + * * @author Lucas Ward * @author Dave Syer * @author Mahmoud Ben Hassine @@ -25,13 +25,11 @@ package org.springframework.batch.core.step.skip; public interface SkipPolicy { /** - * Returns true or false, indicating whether or not processing should - * continue with the given throwable. Clients may use - * {@code skipCount<0} to probe for exception types that are skippable, - * so implementations should be able to handle gracefully the case where - * {@code skipCount<0}. Implementations should avoid throwing any + * Returns true or false, indicating whether or not processing should continue with + * the given throwable. Clients may use {@code skipCount<0} to probe for exception + * types that are skippable, so implementations should be able to handle gracefully + * the case where {@code skipCount<0}. Implementations should avoid throwing any * undeclared exceptions. - * * @param t exception encountered while processing * @param skipCount currently running count of skips * @return true if processing should continue, false otherwise. diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/skip/SkipPolicyFailedException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/skip/SkipPolicyFailedException.java index 09d0cde3c..4d90a0820 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/skip/SkipPolicyFailedException.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/skip/SkipPolicyFailedException.java @@ -18,12 +18,11 @@ package org.springframework.batch.core.step.skip; import org.springframework.batch.core.UnexpectedJobExecutionException; /** - * Special exception to indicate a failure in a skip policy. These need - * special treatment in the framework in case a skip sends itself into an - * infinite loop. - * + * Special exception to indicate a failure in a skip policy. These need special treatment + * in the framework in case a skip sends itself into an infinite loop. + * * @author Dave Syer - * + * */ @SuppressWarnings("serial") public class SkipPolicyFailedException extends UnexpectedJobExecutionException { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/CallableTaskletAdapter.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/CallableTaskletAdapter.java index 65e7b2278..120ea42c6 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/CallableTaskletAdapter.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/CallableTaskletAdapter.java @@ -25,8 +25,7 @@ import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** - * Adapts a {@link Callable}<{@link RepeatStatus}> to the {@link Tasklet} - * interface. + * Adapts a {@link Callable}<{@link RepeatStatus}> to the {@link Tasklet} interface. * * @author Dave Syer * @@ -54,8 +53,8 @@ public class CallableTaskletAdapter implements Tasklet, InitializingBean { } /** - * Execute the provided Callable and return its {@link RepeatStatus}. Ignores - * the {@link StepContribution} and the attributes. + * Execute the provided Callable and return its {@link RepeatStatus}. Ignores the + * {@link StepContribution} and the attributes. * @see Tasklet#execute(StepContribution, ChunkContext) */ @Nullable diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/ConfigurableSystemProcessExitCodeMapper.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/ConfigurableSystemProcessExitCodeMapper.java index 4dabb4486..c801d6d25 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/ConfigurableSystemProcessExitCodeMapper.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/ConfigurableSystemProcessExitCodeMapper.java @@ -22,10 +22,10 @@ import org.springframework.batch.core.ExitStatus; import org.springframework.util.Assert; /** - * Maps exit codes to {@link org.springframework.batch.core.ExitStatus} - * according to injected map. The injected map is required to contain a value - * for 'else' key, this value will be returned if the injected map - * does not contain value for the exit code returned by the system process. + * Maps exit codes to {@link org.springframework.batch.core.ExitStatus} according to + * injected map. The injected map is required to contain a value for 'else' key, this + * value will be returned if the injected map does not contain value for the exit code + * returned by the system process. * * @author Robert Kasanicky */ @@ -35,12 +35,13 @@ public class ConfigurableSystemProcessExitCodeMapper implements SystemProcessExi private Map mappings; - @Override + @Override public ExitStatus getExitStatus(int exitCode) { ExitStatus exitStatus = mappings.get(exitCode); if (exitStatus != null) { return exitStatus; - } else { + } + else { return mappings.get(ELSE_KEY); } } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/MethodInvokingTaskletAdapter.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/MethodInvokingTaskletAdapter.java index a90878455..86206538f 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/MethodInvokingTaskletAdapter.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/MethodInvokingTaskletAdapter.java @@ -23,14 +23,12 @@ import org.springframework.batch.repeat.RepeatStatus; import org.springframework.lang.Nullable; /** - * A {@link Tasklet} that wraps a method in a POJO. By default the return - * value is {@link ExitStatus#COMPLETED} unless the delegate POJO itself returns - * an {@link ExitStatus}. The POJO method is usually going to have no arguments, - * but a static argument or array of arguments can be used by setting the - * arguments property. + * A {@link Tasklet} that wraps a method in a POJO. By default the return value is + * {@link ExitStatus#COMPLETED} unless the delegate POJO itself returns an + * {@link ExitStatus}. The POJO method is usually going to have no arguments, but a static + * argument or array of arguments can be used by setting the arguments property. * * @see AbstractMethodInvokingDelegator - * * @author Dave Syer * @author Mahmoud Ben Hassine * @@ -38,9 +36,9 @@ import org.springframework.lang.Nullable; public class MethodInvokingTaskletAdapter extends AbstractMethodInvokingDelegator implements Tasklet { /** - * Delegate execution to the target object and translate the return value to - * an {@link ExitStatus} by invoking a method in the delegate POJO. Ignores - * the {@link StepContribution} and the attributes. + * Delegate execution to the target object and translate the return value to an + * {@link ExitStatus} by invoking a method in the delegate POJO. Ignores the + * {@link StepContribution} and the attributes. * * @see Tasklet#execute(StepContribution, ChunkContext) */ @@ -48,16 +46,15 @@ public class MethodInvokingTaskletAdapter extends AbstractMethodInvokingDelegato @Override public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { if (getArguments() == null) { - setArguments(new Object[]{contribution, chunkContext}); + setArguments(new Object[] { contribution, chunkContext }); } contribution.setExitStatus(mapResult(invokeDelegateMethod())); return RepeatStatus.FINISHED; } /** - * If the result is an {@link ExitStatus} already just return that, - * otherwise return {@link ExitStatus#COMPLETED}. - * + * If the result is an {@link ExitStatus} already just return that, otherwise return + * {@link ExitStatus#COMPLETED}. * @param result the value returned by the delegate method * @return an {@link ExitStatus} consistent with the result */ diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/SimpleSystemProcessExitCodeMapper.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/SimpleSystemProcessExitCodeMapper.java index 81837a977..651b9ff17 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/SimpleSystemProcessExitCodeMapper.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/SimpleSystemProcessExitCodeMapper.java @@ -1,39 +1,41 @@ -/* - * Copyright 2006-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.core.step.tasklet; - -import org.springframework.batch.core.ExitStatus; - -/** - * Simple {@link SystemProcessExitCodeMapper} implementation that performs following mapping: - * - * 0 -> ExitStatus.FINISHED - * else -> ExitStatus.FAILED - * - * @author Robert Kasanicky - */ -public class SimpleSystemProcessExitCodeMapper implements SystemProcessExitCodeMapper { - @Override - public ExitStatus getExitStatus(int exitCode) { - if (exitCode == 0) { - return ExitStatus.COMPLETED; - } else { - return ExitStatus.FAILED; - } - } - -} +/* + * Copyright 2006-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.core.step.tasklet; + +import org.springframework.batch.core.ExitStatus; + +/** + * Simple {@link SystemProcessExitCodeMapper} implementation that performs following + * mapping: + * + * 0 -> ExitStatus.FINISHED else -> ExitStatus.FAILED + * + * @author Robert Kasanicky + */ +public class SimpleSystemProcessExitCodeMapper implements SystemProcessExitCodeMapper { + + @Override + public ExitStatus getExitStatus(int exitCode) { + if (exitCode == 0) { + return ExitStatus.COMPLETED; + } + else { + return ExitStatus.FAILED; + } + } + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/StoppableTasklet.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/StoppableTasklet.java index e7ec8e6a0..4d604afd6 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/StoppableTasklet.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/StoppableTasklet.java @@ -18,15 +18,14 @@ package org.springframework.batch.core.step.tasklet; import org.springframework.batch.core.launch.JobOperator; /** - * An extension to the {@link Tasklet} interface to allow users to - * add logic for stopping a tasklet. It is up to each implementation - * as to how the stop will behave. The only guarantee provided by the - * framework is that a call to {@link JobOperator#stop(long)} will - * attempt to call the stop method on any currently running - * StoppableTasklet. The call to {@link StoppableTasklet#stop()} will - * be from a thread other than the thread executing {@link org.springframework.batch.core.step.tasklet.Tasklet#execute(org.springframework.batch.core.StepContribution, org.springframework.batch.core.scope.context.ChunkContext)} - * so the appropriate thread safety and visibility controls should be - * put in place. + * An extension to the {@link Tasklet} interface to allow users to add logic for stopping + * a tasklet. It is up to each implementation as to how the stop will behave. The only + * guarantee provided by the framework is that a call to {@link JobOperator#stop(long)} + * will attempt to call the stop method on any currently running StoppableTasklet. The + * call to {@link StoppableTasklet#stop()} will be from a thread other than the thread + * executing + * {@link org.springframework.batch.core.step.tasklet.Tasklet#execute(org.springframework.batch.core.StepContribution, org.springframework.batch.core.scope.context.ChunkContext)} + * so the appropriate thread safety and visibility controls should be put in place. * * @author Will Schipp * @since 3.0 @@ -34,8 +33,9 @@ import org.springframework.batch.core.launch.JobOperator; public interface StoppableTasklet extends Tasklet { /** - * Used to signal that the job this {@link Tasklet} is executing - * within has been requested to stop. + * Used to signal that the job this {@link Tasklet} is executing within has been + * requested to stop. */ void stop(); + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/SystemCommandException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/SystemCommandException.java index 646670c0c..4f192bd99 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/SystemCommandException.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/SystemCommandException.java @@ -20,15 +20,16 @@ package org.springframework.batch.core.step.tasklet; * Exception indicating failed execution of system command. */ public class SystemCommandException extends RuntimeException { - + // generated private static final long serialVersionUID = 5139355923336176733L; public SystemCommandException(String message) { super(message); } - + public SystemCommandException(String message, Throwable cause) { super(message, cause); } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/SystemCommandTasklet.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/SystemCommandTasklet.java index 86dd1127a..5884050a9 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/SystemCommandTasklet.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/SystemCommandTasklet.java @@ -42,20 +42,19 @@ import org.springframework.util.Assert; * {@link Tasklet} that executes a system command. * * The system command is executed asynchronously using injected - * {@link #setTaskExecutor(TaskExecutor)} - timeout value is required to be set, - * so that the batch job does not hang forever if the external process hangs. + * {@link #setTaskExecutor(TaskExecutor)} - timeout value is required to be set, so that + * the batch job does not hang forever if the external process hangs. * - * Tasklet periodically checks for termination status (i.e. - * {@link #setCommand(String)} finished its execution or - * {@link #setTimeout(long)} expired or job was interrupted). The check interval - * is given by {@link #setTerminationCheckInterval(long)}. + * Tasklet periodically checks for termination status (i.e. {@link #setCommand(String)} + * finished its execution or {@link #setTimeout(long)} expired or job was interrupted). + * The check interval is given by {@link #setTerminationCheckInterval(long)}. * - * When job interrupt is detected tasklet's execution is terminated immediately - * by throwing {@link JobInterruptedException}. + * When job interrupt is detected tasklet's execution is terminated immediately by + * throwing {@link JobInterruptedException}. * - * {@link #setInterruptOnCancel(boolean)} specifies whether the tasklet should - * attempt to interrupt the thread that executes the system command if it is - * still running when tasklet exits (abnormally). + * {@link #setInterruptOnCancel(boolean)} specifies whether the tasklet should attempt to + * interrupt the thread that executes the system command if it is still running when + * tasklet exits (abnormally). * * @author Robert Kasanicky * @author Will Schipp @@ -112,13 +111,13 @@ public class SystemCommandTasklet implements StepExecutionListener, StoppableTas taskExecutor.execute(systemCommandTask); while (true) { - Thread.sleep(checkInterval);//moved to the end of the logic + Thread.sleep(checkInterval);// moved to the end of the logic - if(stoppable) { - JobExecution jobExecution = - jobExplorer.getJobExecution(chunkContext.getStepContext().getStepExecution().getJobExecutionId()); + if (stoppable) { + JobExecution jobExecution = jobExplorer + .getJobExecution(chunkContext.getStepContext().getStepExecution().getJobExecutionId()); - if(jobExecution.isStopping()) { + if (jobExecution.isStopping()) { stopped = true; } } @@ -151,16 +150,16 @@ public class SystemCommandTasklet implements StepExecutionListener, StoppableTas } /** - * @param envp environment parameter values, inherited from parent process - * when not set (or set to null). + * @param envp environment parameter values, inherited from parent process when not + * set (or set to null). */ public void setEnvironmentParams(String[] envp) { this.environmentParams = envp; } /** - * @param dir working directory of the spawned process, inherited from - * parent process when not set (or set to null). + * @param dir working directory of the spawned process, inherited from parent process + * when not set (or set to null). */ public void setWorkingDirectory(String dir) { if (dir == null) { @@ -197,17 +196,15 @@ public class SystemCommandTasklet implements StepExecutionListener, StoppableTas /** * Timeout in milliseconds. - * @param timeout upper limit for how long the execution of the external - * program is allowed to last. + * @param timeout upper limit for how long the execution of the external program is + * allowed to last. */ public void setTimeout(long timeout) { this.timeout = timeout; } /** - * The time interval how often the tasklet will check for termination - * status. - * + * The time interval how often the tasklet will check for termination status. * @param checkInterval time interval in milliseconds (1 second by default). */ public void setTerminationCheckInterval(long checkInterval) { @@ -215,8 +212,8 @@ public class SystemCommandTasklet implements StepExecutionListener, StoppableTas } /** - * Get a reference to {@link StepExecution} for interrupt checks during - * system command execution. + * Get a reference to {@link StepExecution} for interrupt checks during system command + * execution. */ @Override public void beforeStep(StepExecution stepExecution) { @@ -224,9 +221,8 @@ public class SystemCommandTasklet implements StepExecutionListener, StoppableTas } /** - * Sets the task executor that will be used to execute the system command - * NB! Avoid using a synchronous task executor - * + * Sets the task executor that will be used to execute the system command NB! Avoid + * using a synchronous task executor * @param taskExecutor instance of {@link TaskExecutor}. */ public void setTaskExecutor(TaskExecutor taskExecutor) { @@ -234,10 +230,9 @@ public class SystemCommandTasklet implements StepExecutionListener, StoppableTas } /** - * If true tasklet will attempt to interrupt the thread - * executing the system command if {@link #setTimeout(long)} has been - * exceeded or user interrupts the job. false by default - * + * If true tasklet will attempt to interrupt the thread executing the + * system command if {@link #setTimeout(long)} has been exceeded or user interrupts + * the job. false by default * @param interruptOnCancel boolean determines if process should be interrupted */ public void setInterruptOnCancel(boolean interruptOnCancel) { @@ -246,9 +241,8 @@ public class SystemCommandTasklet implements StepExecutionListener, StoppableTas /** * Will interrupt the thread executing the system command only if - * {@link #setInterruptOnCancel(boolean)} has been set to true. Otherwise - * the underlying command will be allowed to finish before the tasklet - * ends. + * {@link #setInterruptOnCancel(boolean)} has been set to true. Otherwise the + * underlying command will be allowed to finish before the tasklet ends. * * @since 3.0 * @see StoppableTasklet#stop() diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/SystemProcessExitCodeMapper.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/SystemProcessExitCodeMapper.java index 7546f3fb9..e7c5ebf82 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/SystemProcessExitCodeMapper.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/SystemProcessExitCodeMapper.java @@ -20,17 +20,17 @@ import org.springframework.batch.core.ExitStatus; import org.springframework.batch.core.step.tasklet.SystemCommandTasklet; /** - * Maps the exit code of a system process to ExitStatus value - * returned by a system command. Designed for use with the - * {@link SystemCommandTasklet}. - * + * Maps the exit code of a system process to ExitStatus value returned by a system + * command. Designed for use with the {@link SystemCommandTasklet}. + * * @author Robert Kasanicky */ public interface SystemProcessExitCodeMapper { - - /** + + /** * @param exitCode exit code returned by the system process * @return ExitStatus appropriate for the systemExitCode parameter value */ ExitStatus getExitStatus(int exitCode); + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/Tasklet.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/Tasklet.java index 6c79ca351..a15441fcd 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/Tasklet.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/Tasklet.java @@ -22,26 +22,23 @@ import org.springframework.lang.Nullable; /** * Strategy for processing in a step. - * + * * @author Dave Syer * @author Mahmoud Ben Hassine - * + * */ public interface Tasklet { /** - * Given the current context in the form of a step contribution, do whatever - * is necessary to process this unit inside a transaction. Implementations - * return {@link RepeatStatus#FINISHED} if finished. If not they return + * Given the current context in the form of a step contribution, do whatever is + * necessary to process this unit inside a transaction. Implementations return + * {@link RepeatStatus#FINISHED} if finished. If not they return * {@link RepeatStatus#CONTINUABLE}. On failure throws an exception. - * - * @param contribution mutable state to be passed back to update the current - * step execution - * @param chunkContext attributes shared between invocations but not between - * restarts - * @return an {@link RepeatStatus} indicating whether processing is - * continuable. Returning {@code null} is interpreted as {@link RepeatStatus#FINISHED} - * + * @param contribution mutable state to be passed back to update the current step + * execution + * @param chunkContext attributes shared between invocations but not between restarts + * @return an {@link RepeatStatus} indicating whether processing is continuable. + * Returning {@code null} is interpreted as {@link RepeatStatus#FINISHED} * @throws Exception thrown if error occurs during execution. */ @Nullable diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/TaskletStep.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/TaskletStep.java index 9db3acf39..b36b03097 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/TaskletStep.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/TaskletStep.java @@ -53,17 +53,16 @@ import org.springframework.util.Assert; import java.util.concurrent.Semaphore; /** - * Simple implementation of executing the step as a call to a {@link Tasklet}, - * possibly repeated, and each call surrounded by a transaction. The structure - * is therefore that of a loop with transaction boundary inside the loop. The - * loop is controlled by the step operations ( - * {@link #setStepOperations(RepeatOperations)}).
      + * Simple implementation of executing the step as a call to a {@link Tasklet}, possibly + * repeated, and each call surrounded by a transaction. The structure is therefore that of + * a loop with transaction boundary inside the loop. The loop is controlled by the step + * operations ( {@link #setStepOperations(RepeatOperations)}).
      *
      * - * Clients can use interceptors in the step operations to intercept or listen to - * the iteration on a step-wide basis, for instance to get a callback when the - * step is complete. Those that want callbacks at the level of an individual - * tasks, can specify interceptors for the chunk operations. + * Clients can use interceptors in the step operations to intercept or listen to the + * iteration on a step-wide basis, for instance to get a callback when the step is + * complete. Those that want callbacks at the level of an individual tasks, can specify + * interceptors for the chunk operations. * * @author Dave Syer * @author Lucas Ward @@ -119,8 +118,7 @@ public class TaskletStep extends AbstractStep { /* * (non-Javadoc) * - * @see - * org.springframework.batch.core.step.AbstractStep#afterPropertiesSet() + * @see org.springframework.batch.core.step.AbstractStep#afterPropertiesSet() */ @Override public void afterPropertiesSet() throws Exception { @@ -130,7 +128,6 @@ public class TaskletStep extends AbstractStep { /** * Public setter for the {@link PlatformTransactionManager}. - * * @param transactionManager the transaction manager to set */ public void setTransactionManager(PlatformTransactionManager transactionManager) { @@ -139,7 +136,6 @@ public class TaskletStep extends AbstractStep { /** * Public setter for the {@link TransactionAttribute}. - * * @param transactionAttribute the {@link TransactionAttribute} to set */ public void setTransactionAttribute(TransactionAttribute transactionAttribute) { @@ -148,7 +144,6 @@ public class TaskletStep extends AbstractStep { /** * Public setter for the {@link Tasklet}. - * * @param tasklet the {@link Tasklet} to set */ public void setTasklet(Tasklet tasklet) { @@ -159,9 +154,8 @@ public class TaskletStep extends AbstractStep { } /** - * Register a chunk listener for callbacks at the appropriate stages in a - * step execution. - * + * Register a chunk listener for callbacks at the appropriate stages in a step + * execution. * @param listener a {@link ChunkListener} */ public void registerChunkListener(ChunkListener listener) { @@ -170,7 +164,6 @@ public class TaskletStep extends AbstractStep { /** * Register each of the objects as listeners. - * * @param listeners an array of listener objects of known types. */ public void setChunkListeners(ChunkListener[] listeners) { @@ -180,14 +173,12 @@ public class TaskletStep extends AbstractStep { } /** - * Register each of the streams for callbacks at the appropriate time in the - * step. The {@link ItemReader} and {@link ItemWriter} are automatically - * registered, but it doesn't hurt to also register them here. Injected - * dependencies of the reader and writer are not automatically registered, - * so if you implement {@link ItemWriter} using delegation to another object - * which itself is a {@link ItemStream}, you need to register the delegate - * here. - * + * Register each of the streams for callbacks at the appropriate time in the step. The + * {@link ItemReader} and {@link ItemWriter} are automatically registered, but it + * doesn't hurt to also register them here. Injected dependencies of the reader and + * writer are not automatically registered, so if you implement {@link ItemWriter} + * using delegation to another object which itself is a {@link ItemStream}, you need + * to register the delegate here. * @param streams an array of {@link ItemStream} objects. */ public void setStreams(ItemStream[] streams) { @@ -197,9 +188,7 @@ public class TaskletStep extends AbstractStep { } /** - * Register a single {@link ItemStream} for callbacks to the stream - * interface. - * + * Register a single {@link ItemStream} for callbacks to the stream interface. * @param stream instance of {@link ItemStream} */ public void registerStream(ItemStream stream) { @@ -207,10 +196,9 @@ public class TaskletStep extends AbstractStep { } /** - * The {@link RepeatOperations} to use for the outer loop of the batch - * processing. Should be set up by the caller through a factory. Defaults to - * a plain {@link RepeatTemplate}. - * + * The {@link RepeatOperations} to use for the outer loop of the batch processing. + * Should be set up by the caller through a factory. Defaults to a plain + * {@link RepeatTemplate}. * @param stepOperations a {@link RepeatOperations} instance. */ public void setStepOperations(RepeatOperations stepOperations) { @@ -218,10 +206,8 @@ public class TaskletStep extends AbstractStep { } /** - * Setter for the {@link StepInterruptionPolicy}. The policy is used to - * check whether an external request has been made to interrupt the job - * execution. - * + * Setter for the {@link StepInterruptionPolicy}. The policy is used to check whether + * an external request has been made to interrupt the job execution. * @param interruptionPolicy a {@link StepInterruptionPolicy} */ public void setInterruptionPolicy(StepInterruptionPolicy interruptionPolicy) { @@ -229,17 +215,15 @@ public class TaskletStep extends AbstractStep { } /** - * Process the step and update its context so that progress can be monitored - * by the caller. The step is broken down into chunks, each one executing in - * a transaction. The step and its execution and execution context are all - * given an up to date {@link BatchStatus}, and the {@link JobRepository} is - * used to store the result. Various reporting information are also added to - * the current context governing the step execution, which would normally be - * available to the caller through the step's {@link ExecutionContext}.
      - * + * Process the step and update its context so that progress can be monitored by the + * caller. The step is broken down into chunks, each one executing in a transaction. + * The step and its execution and execution context are all given an up to date + * {@link BatchStatus}, and the {@link JobRepository} is used to store the result. + * Various reporting information are also added to the current context governing the + * step execution, which would normally be available to the caller through the step's + * {@link ExecutionContext}.
      * @throws JobInterruptedException if the step or a chunk is interrupted - * @throws RuntimeException if there is an exception during a chunk - * execution + * @throws RuntimeException if there is an exception during a chunk execution * */ @Override @@ -269,7 +253,7 @@ public class TaskletStep extends AbstractStep { RepeatStatus result; try { result = new TransactionTemplate(transactionManager, transactionAttribute) - .execute(new ChunkTransactionCallback(chunkContext, semaphore)); + .execute(new ChunkTransactionCallback(chunkContext, semaphore)); } catch (UncheckedTransactionException e) { // Allow checked exceptions to be thrown inside callback @@ -291,9 +275,8 @@ public class TaskletStep extends AbstractStep { } /** - * Extension point mainly for test purposes so that the behaviour of the - * lock can be manipulated to simulate various pathologies. - * + * Extension point mainly for test purposes so that the behaviour of the lock can be + * manipulated to simulate various pathologies. * @return a semaphore for locking access to the JobRepository */ protected Semaphore createSemaphore() { @@ -319,10 +302,10 @@ public class TaskletStep extends AbstractStep { } /** - * A callback for the transactional work inside a chunk. Also detects - * failures in the transaction commit and rollback, only panicking if the - * transaction status is unknown (i.e. if a commit failure leads to a clean - * rollback then we assume the state is consistent). + * A callback for the transactional work inside a chunk. Also detects failures in the + * transaction commit and rollback, only panicking if the transaction status is + * unknown (i.e. if a commit failure leads to a clean rollback then we assume the + * state is consistent). * * @author Dave Syer * @@ -506,4 +489,5 @@ public class TaskletStep extends AbstractStep { } } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/UncheckedTransactionException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/UncheckedTransactionException.java index 6ad49ea4e..37aef42b1 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/UncheckedTransactionException.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/UncheckedTransactionException.java @@ -16,8 +16,8 @@ package org.springframework.batch.core.step.tasklet; /** - * Convenience wrapper for a checked exception so that it can cause a - * rollback and be extracted afterwards. + * Convenience wrapper for a checked exception so that it can cause a rollback and be + * extracted afterwards. * * @author Dave Syer * @@ -28,4 +28,5 @@ public class UncheckedTransactionException extends RuntimeException { public UncheckedTransactionException(Exception e) { super(e); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/BatchStatusTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/BatchStatusTests.java index 43c0dfd05..bbcfa9da0 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/BatchStatusTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/BatchStatusTests.java @@ -36,8 +36,7 @@ import org.junit.Test; public class BatchStatusTests { /** - * Test method for - * {@link org.springframework.batch.core.BatchStatus#toString()}. + * Test method for {@link org.springframework.batch.core.BatchStatus#toString()}. */ @Test public void testToString() { @@ -46,7 +45,7 @@ public class BatchStatusTests { @Test public void testMaxStatus() { - assertEquals(BatchStatus.FAILED, BatchStatus.max(BatchStatus.FAILED,BatchStatus.COMPLETED)); + assertEquals(BatchStatus.FAILED, BatchStatus.max(BatchStatus.FAILED, BatchStatus.COMPLETED)); assertEquals(BatchStatus.FAILED, BatchStatus.max(BatchStatus.COMPLETED, BatchStatus.FAILED)); assertEquals(BatchStatus.FAILED, BatchStatus.max(BatchStatus.FAILED, BatchStatus.FAILED)); assertEquals(BatchStatus.STARTED, BatchStatus.max(BatchStatus.STARTED, BatchStatus.STARTING)); @@ -99,7 +98,7 @@ public class BatchStatusTests { } } - @Test(expected=NullPointerException.class) + @Test(expected = NullPointerException.class) public void testGetStatusNullCode() { assertNull(BatchStatus.valueOf(null)); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/DefaultJobKeyGeneratorTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/DefaultJobKeyGeneratorTests.java index f01b42543..18958d7be 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/DefaultJobKeyGeneratorTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/DefaultJobKeyGeneratorTests.java @@ -36,11 +36,10 @@ public class DefaultJobKeyGeneratorTests { @Test public void testMixedParameters() { - JobParameters jobParameters1 = new JobParametersBuilder().addString( - "foo", "bar").addString("bar", "foo").toJobParameters(); - JobParameters jobParameters2 = new JobParametersBuilder().addString( - "foo", "bar", true).addString("bar", "foo", true) - .addString("ignoreMe", "irrelevant", false).toJobParameters(); + JobParameters jobParameters1 = new JobParametersBuilder().addString("foo", "bar").addString("bar", "foo") + .toJobParameters(); + JobParameters jobParameters2 = new JobParametersBuilder().addString("foo", "bar", true) + .addString("bar", "foo", true).addString("ignoreMe", "irrelevant", false).toJobParameters(); String key1 = jobKeyGenerator.generateKey(jobParameters1); String key2 = jobKeyGenerator.generateKey(jobParameters2); assertEquals(key1, key2); @@ -48,20 +47,21 @@ public class DefaultJobKeyGeneratorTests { @Test public void testCreateJobKey() { - JobParameters jobParameters = new JobParametersBuilder().addString( - "foo", "bar").addString("bar", "foo").toJobParameters(); + JobParameters jobParameters = new JobParametersBuilder().addString("foo", "bar").addString("bar", "foo") + .toJobParameters(); String key = jobKeyGenerator.generateKey(jobParameters); assertEquals(32, key.length()); } @Test public void testCreateJobKeyOrdering() { - JobParameters jobParameters1 = new JobParametersBuilder().addString( - "foo", "bar").addString("bar", "foo").toJobParameters(); + JobParameters jobParameters1 = new JobParametersBuilder().addString("foo", "bar").addString("bar", "foo") + .toJobParameters(); String key1 = jobKeyGenerator.generateKey(jobParameters1); - JobParameters jobParameters2 = new JobParametersBuilder().addString( - "bar", "foo").addString("foo", "bar").toJobParameters(); + JobParameters jobParameters2 = new JobParametersBuilder().addString("bar", "foo").addString("foo", "bar") + .toJobParameters(); String key2 = jobKeyGenerator.generateKey(jobParameters2); assertEquals(key1, key2); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/EntityTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/EntityTests.java index 477fccd05..9b80fa1c1 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/EntityTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/EntityTests.java @@ -24,7 +24,7 @@ import junit.framework.TestCase; public class EntityTests extends TestCase { Entity entity = new Entity(11L); - + /** * Test method for {@link org.springframework.batch.core.Entity#hashCode()}. */ @@ -39,7 +39,7 @@ public class EntityTests extends TestCase { int withoutNull = entity.hashCode(); entity.setId(null); int withNull = entity.hashCode(); - assertTrue(withoutNull!=withNull); + assertTrue(withoutNull != withNull); } /** @@ -75,54 +75,61 @@ public class EntityTests extends TestCase { } /** - * Test method for {@link org.springframework.batch.core.Entity#equals(java.lang.Object)}. + * Test method for + * {@link org.springframework.batch.core.Entity#equals(java.lang.Object)}. */ public void testEqualsSelf() { - assertEquals(entity, entity); + assertEquals(entity, entity); } /** - * Test method for {@link org.springframework.batch.core.Entity#equals(java.lang.Object)}. + * Test method for + * {@link org.springframework.batch.core.Entity#equals(java.lang.Object)}. */ public void testEqualsSelfWithNullId() { entity = new Entity(null); - assertEquals(entity, entity); + assertEquals(entity, entity); } /** - * Test method for {@link org.springframework.batch.core.Entity#equals(java.lang.Object)}. + * Test method for + * {@link org.springframework.batch.core.Entity#equals(java.lang.Object)}. */ public void testEqualsEntityWithNullId() { entity = new Entity(null); - assertNotSame(entity, new Entity(null)); + assertNotSame(entity, new Entity(null)); } /** - * Test method for {@link org.springframework.batch.core.Entity#equals(java.lang.Object)}. + * Test method for + * {@link org.springframework.batch.core.Entity#equals(java.lang.Object)}. */ public void testEqualsEntity() { - assertEquals(entity, new Entity(entity.getId())); + assertEquals(entity, new Entity(entity.getId())); } /** - * Test method for {@link org.springframework.batch.core.Entity#equals(java.lang.Object)}. + * Test method for + * {@link org.springframework.batch.core.Entity#equals(java.lang.Object)}. */ public void testEqualsEntityWrongId() { - assertFalse(entity.equals(new Entity())); + assertFalse(entity.equals(new Entity())); } /** - * Test method for {@link org.springframework.batch.core.Entity#equals(java.lang.Object)}. + * Test method for + * {@link org.springframework.batch.core.Entity#equals(java.lang.Object)}. */ public void testEqualsObject() { - assertFalse(entity.equals(new Object())); + assertFalse(entity.equals(new Object())); } - + /** - * Test method for {@link org.springframework.batch.core.Entity#equals(java.lang.Object)}. + * Test method for + * {@link org.springframework.batch.core.Entity#equals(java.lang.Object)}. */ public void testEqualsNull() { - assertFalse(entity.equals(null)); + assertFalse(entity.equals(null)); } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/ExitStatusTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/ExitStatusTests.java index 3bba8cf06..4a63d0cab 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/ExitStatusTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/ExitStatusTests.java @@ -55,7 +55,6 @@ public class ExitStatusTests { /** * Test equality of exit statuses. - * * @throws Exception */ @Test @@ -76,7 +75,6 @@ public class ExitStatusTests { /** * Test equality of exit statuses. - * * @throws Exception */ @Test @@ -86,7 +84,6 @@ public class ExitStatusTests { /** * Test equality of exit statuses. - * * @throws Exception */ @Test @@ -141,8 +138,8 @@ public class ExitStatusTests { */ @Test public void testAndExitStatusWhenCustomCompletedAddedToCompleted() { - assertEquals("COMPLETED_CUSTOM", ExitStatus.COMPLETED.and( - ExitStatus.EXECUTING.replaceExitCode("COMPLETED_CUSTOM")).getExitCode()); + assertEquals("COMPLETED_CUSTOM", + ExitStatus.COMPLETED.and(ExitStatus.EXECUTING.replaceExitCode("COMPLETED_CUSTOM")).getExitCode()); } /** @@ -199,8 +196,8 @@ public class ExitStatusTests { ExitStatus status = ExitStatus.EXECUTING.addExitDescription(new RuntimeException("Foo")); assertTrue(ExitStatus.EXECUTING != status); String description = status.getExitDescription(); - assertTrue("Wrong description: "+description, description.contains("Foo")); - assertTrue("Wrong description: "+description, description.contains("RuntimeException")); + assertTrue("Wrong description: " + description, description.contains("Foo")); + assertTrue("Wrong description: " + description, description.contains("RuntimeException")); } @Test @@ -212,7 +209,7 @@ public class ExitStatusTests { @Test public void testAddEmptyExitDescription() throws Exception { - ExitStatus status = ExitStatus.EXECUTING.addExitDescription("Foo").addExitDescription((String)null); + ExitStatus status = ExitStatus.EXECUTING.addExitDescription("Foo").addExitDescription((String) null); assertEquals("Foo", status.getExitDescription()); } @@ -237,4 +234,5 @@ public class ExitStatusTests { ExitStatus restored = (ExitStatus) object; assertEquals(status.getExitCode(), restored.getExitCode()); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/JobExecutionExceptionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/JobExecutionExceptionTests.java index 4e6d747aa..f02e10c41 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/JobExecutionExceptionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/JobExecutionExceptionTests.java @@ -15,23 +15,30 @@ */ package org.springframework.batch.core; - /** * @author Dave Syer * */ public class JobExecutionExceptionTests extends AbstractExceptionTests { - /* (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.io.exception.AbstractExceptionTests#getException(java. + * lang.String) */ @Override public Exception getException(String msg) throws Exception { return new JobExecutionException(msg); } - /* (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String, java.lang.Throwable) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.io.exception.AbstractExceptionTests#getException(java. + * lang.String, java.lang.Throwable) */ @Override public Exception getException(String msg, Throwable t) throws Exception { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/JobExecutionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/JobExecutionTests.java index 927a85710..70ebc749b 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/JobExecutionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/JobExecutionTests.java @@ -36,8 +36,7 @@ import org.springframework.util.SerializationUtils; */ public class JobExecutionTests { - private JobExecution execution = new JobExecution(new JobInstance(11L, "foo"), - 12L, new JobParameters()); + private JobExecution execution = new JobExecution(new JobInstance(11L, "foo"), 12L, new JobParameters()); @Test public void testJobExecution() { @@ -45,8 +44,7 @@ public class JobExecutionTests { } /** - * Test method for - * {@link org.springframework.batch.core.JobExecution#getEndTime()}. + * Test method for {@link org.springframework.batch.core.JobExecution#getEndTime()}. */ @Test public void testGetEndTime() { @@ -56,8 +54,7 @@ public class JobExecutionTests { } /** - * Test method for - * {@link org.springframework.batch.core.JobExecution#getEndTime()}. + * Test method for {@link org.springframework.batch.core.JobExecution#getEndTime()}. */ @Test public void testIsRunning() { @@ -68,8 +65,7 @@ public class JobExecutionTests { } /** - * Test method for - * {@link org.springframework.batch.core.JobExecution#getStartTime()}. + * Test method for {@link org.springframework.batch.core.JobExecution#getStartTime()}. */ @Test public void testGetStartTime() { @@ -78,8 +74,7 @@ public class JobExecutionTests { } /** - * Test method for - * {@link org.springframework.batch.core.JobExecution#getStatus()}. + * Test method for {@link org.springframework.batch.core.JobExecution#getStatus()}. */ @Test public void testGetStatus() { @@ -89,8 +84,7 @@ public class JobExecutionTests { } /** - * Test method for - * {@link org.springframework.batch.core.JobExecution#getStatus()}. + * Test method for {@link org.springframework.batch.core.JobExecution#getStatus()}. */ @Test public void testUpgradeStatus() { @@ -100,8 +94,7 @@ public class JobExecutionTests { } /** - * Test method for - * {@link org.springframework.batch.core.JobExecution#getStatus()}. + * Test method for {@link org.springframework.batch.core.JobExecution#getStatus()}. */ @Test public void testDowngradeStatus() { @@ -111,8 +104,7 @@ public class JobExecutionTests { } /** - * Test method for - * {@link org.springframework.batch.core.JobExecution#getJobId()}. + * Test method for {@link org.springframework.batch.core.JobExecution#getJobId()}. */ @Test public void testGetJobId() { @@ -122,8 +114,7 @@ public class JobExecutionTests { } /** - * Test method for - * {@link org.springframework.batch.core.JobExecution#getJobId()}. + * Test method for {@link org.springframework.batch.core.JobExecution#getJobId()}. */ @Test public void testGetJobIdForNullJob() { @@ -132,8 +123,7 @@ public class JobExecutionTests { } /** - * Test method for - * {@link org.springframework.batch.core.JobExecution#getJobId()}. + * Test method for {@link org.springframework.batch.core.JobExecution#getJobId()}. */ @Test public void testGetJob() { @@ -227,4 +217,5 @@ public class JobExecutionTests { assertTrue(allExceptions.contains(exception)); assertTrue(allExceptions.contains(stepException1)); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/JobInstanceTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/JobInstanceTests.java index 706eeb8e5..056819b17 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/JobInstanceTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/JobInstanceTests.java @@ -30,8 +30,7 @@ public class JobInstanceTests { private JobInstance instance = new JobInstance(11L, "job"); /** - * Test method for - * {@link org.springframework.batch.core.JobInstance#getJobName()}. + * Test method for {@link org.springframework.batch.core.JobInstance#getJobName()}. */ @Test public void testGetName() { @@ -70,4 +69,5 @@ public class JobInstanceTests { public void testGetInstanceId() { assertEquals(11, instance.getInstanceId()); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/JobInterruptedExceptionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/JobInterruptedExceptionTests.java index 0cdb1c594..9d1259e13 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/JobInterruptedExceptionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/JobInterruptedExceptionTests.java @@ -15,23 +15,30 @@ */ package org.springframework.batch.core; - /** * @author Dave Syer * */ public class JobInterruptedExceptionTests extends AbstractExceptionTests { - /* (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.io.exception.AbstractExceptionTests#getException(java. + * lang.String) */ @Override public Exception getException(String msg) throws Exception { return new JobInterruptedException(msg); } - /* (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String, java.lang.Throwable) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.io.exception.AbstractExceptionTests#getException(java. + * lang.String, java.lang.Throwable) */ @Override public Exception getException(String msg, Throwable t) throws Exception { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/JobParameterTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/JobParameterTests.java index e31af299f..c9433f191 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/JobParameterTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/JobParameterTests.java @@ -31,56 +31,56 @@ public class JobParameterTests { JobParameter jobParameter; @Test - public void testStringParameter(){ + public void testStringParameter() { jobParameter = new JobParameter("test", true); assertEquals("test", jobParameter.getValue()); } @Test(expected = IllegalArgumentException.class) - public void testNullStringParameter(){ - jobParameter = new JobParameter((String)null, true); + public void testNullStringParameter() { + jobParameter = new JobParameter((String) null, true); } @Test - public void testLongParameter(){ + public void testLongParameter() { jobParameter = new JobParameter(1L, true); assertEquals(1L, jobParameter.getValue()); } @Test - public void testDoubleParameter(){ + public void testDoubleParameter() { jobParameter = new JobParameter(1.1, true); assertEquals(1.1, jobParameter.getValue()); } @Test - public void testDateParameter(){ + public void testDateParameter() { Date epoch = new Date(0L); jobParameter = new JobParameter(epoch, true); assertEquals(new Date(0L), jobParameter.getValue()); } @Test(expected = IllegalArgumentException.class) - public void testNullDateParameter(){ - jobParameter = new JobParameter((Date)null, true); + public void testNullDateParameter() { + jobParameter = new JobParameter((Date) null, true); } @Test - public void testDateParameterToString(){ + public void testDateParameterToString() { Date epoch = new Date(0L); jobParameter = new JobParameter(epoch, true); assertEquals("0", jobParameter.toString()); } @Test - public void testEquals(){ + public void testEquals() { jobParameter = new JobParameter("test", true); JobParameter testParameter = new JobParameter("test", true); assertTrue(jobParameter.equals(testParameter)); } @Test - public void testHashcode(){ + public void testHashcode() { jobParameter = new JobParameter("test", true); JobParameter testParameter = new JobParameter("test", true); assertEquals(testParameter.hashCode(), jobParameter.hashCode()); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/JobParametersBuilderTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/JobParametersBuilderTests.java index 902aebee5..6ab52e257 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/JobParametersBuilderTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/JobParametersBuilderTests.java @@ -68,20 +68,13 @@ public class JobParametersBuilderTests { @Test public void testAddingExistingJobParameters() { - JobParameters params1 = new JobParametersBuilder() - .addString("foo", "bar") - .addString("bar", "baz") + JobParameters params1 = new JobParametersBuilder().addString("foo", "bar").addString("bar", "baz") .toJobParameters(); - JobParameters params2 = new JobParametersBuilder() - .addString("foo", "baz") - .toJobParameters(); + JobParameters params2 = new JobParametersBuilder().addString("foo", "baz").toJobParameters(); - JobParameters finalParams = new JobParametersBuilder() - .addString("baz", "quix") - .addJobParameters(params1) - .addJobParameters(params2) - .toJobParameters(); + JobParameters finalParams = new JobParametersBuilder().addString("baz", "quix").addJobParameters(params1) + .addJobParameters(params2).toJobParameters(); assertEquals(finalParams.getString("foo"), "baz"); assertEquals(finalParams.getString("bar"), "baz"); @@ -107,7 +100,7 @@ public class JobParametersBuilderTests { } @Test - public void testToJobRuntimeParameters(){ + public void testToJobRuntimeParameters() { this.parametersBuilder.addDate("SCHEDULE_DATE", date); this.parametersBuilder.addLong("LONG", 1L); this.parametersBuilder.addString("STRING", "string value"); @@ -120,7 +113,7 @@ public class JobParametersBuilderTests { } @Test - public void testCopy(){ + public void testCopy() { this.parametersBuilder.addString("STRING", "string value"); this.parametersBuilder = new JobParametersBuilder(this.parametersBuilder.toJobParameters()); Iterator parameters = this.parametersBuilder.toJobParameters().getParameters().keySet().iterator(); @@ -128,7 +121,7 @@ public class JobParametersBuilderTests { } @Test - public void testOrderedTypes(){ + public void testOrderedTypes() { this.parametersBuilder.addDate("SCHEDULE_DATE", date); this.parametersBuilder.addLong("LONG", 1L); this.parametersBuilder.addString("STRING", "string value"); @@ -139,7 +132,7 @@ public class JobParametersBuilderTests { } @Test - public void testOrderedStrings(){ + public void testOrderedStrings() { this.parametersBuilder.addString("foo", "value foo"); this.parametersBuilder.addString("bar", "value bar"); this.parametersBuilder.addString("spam", "value spam"); @@ -150,10 +143,10 @@ public class JobParametersBuilderTests { } @Test - public void testAddJobParameter(){ + public void testAddJobParameter() { JobParameter jobParameter = new JobParameter("bar"); this.parametersBuilder.addParameter("foo", jobParameter); - Map parameters = this.parametersBuilder.toJobParameters().getParameters(); + Map parameters = this.parametersBuilder.toJobParameters().getParameters(); assertEquals(1, parameters.size()); assertEquals("bar", parameters.get("foo").getValue()); } @@ -174,9 +167,8 @@ public class JobParametersBuilderTests { assertFalse(parameters.getParameters().get("STRING").isIdentifying()); } - @Test - public void testGetNextJobParametersFirstRun(){ + public void testGetNextJobParametersFirstRun() { job.setJobParametersIncrementer(new RunIdIncrementer()); initializeForNextJobParameters(); this.parametersBuilder.getNextJobParameters(this.job); @@ -184,7 +176,7 @@ public class JobParametersBuilderTests { } @Test - public void testGetNextJobParametersNoIncrementer(){ + public void testGetNextJobParametersNoIncrementer() { initializeForNextJobParameters(); final Exception expectedException = assertThrows(IllegalArgumentException.class, () -> this.parametersBuilder.getNextJobParameters(this.job)); @@ -192,11 +184,11 @@ public class JobParametersBuilderTests { } @Test - public void testGetNextJobParameters(){ + public void testGetNextJobParameters() { this.job.setJobParametersIncrementer(new RunIdIncrementer()); this.jobInstanceList.add(new JobInstance(1L, "simpleJobInstance")); this.jobExecutionList.add(getJobExecution(this.jobInstanceList.get(0), null)); - when(this.jobExplorer.getJobInstances("simpleJob",0,1)).thenReturn(this.jobInstanceList); + when(this.jobExplorer.getJobInstances("simpleJob", 0, 1)).thenReturn(this.jobInstanceList); when(this.jobExplorer.getJobExecutions(any())).thenReturn(this.jobExecutionList); initializeForNextJobParameters(); this.parametersBuilder.getNextJobParameters(this.job); @@ -204,12 +196,12 @@ public class JobParametersBuilderTests { } @Test - public void testGetNextJobParametersRestartable(){ + public void testGetNextJobParametersRestartable() { this.job.setRestartable(true); this.job.setJobParametersIncrementer(new RunIdIncrementer()); this.jobInstanceList.add(new JobInstance(1L, "simpleJobInstance")); this.jobExecutionList.add(getJobExecution(this.jobInstanceList.get(0), BatchStatus.FAILED)); - when(this.jobExplorer.getJobInstances("simpleJob",0,1)).thenReturn(this.jobInstanceList); + when(this.jobExplorer.getJobInstances("simpleJob", 0, 1)).thenReturn(this.jobInstanceList); when(this.jobExplorer.getJobExecutions(any())).thenReturn(this.jobExecutionList); initializeForNextJobParameters(); this.parametersBuilder.addLong("NON_IDENTIFYING_LONG", 1L, false); @@ -218,10 +210,10 @@ public class JobParametersBuilderTests { } @Test - public void testGetNextJobParametersNoPreviousExecution(){ + public void testGetNextJobParametersNoPreviousExecution() { this.job.setJobParametersIncrementer(new RunIdIncrementer()); this.jobInstanceList.add(new JobInstance(1L, "simpleJobInstance")); - when(this.jobExplorer.getJobInstances("simpleJob",0,1)).thenReturn(this.jobInstanceList); + when(this.jobExplorer.getJobInstances("simpleJob", 0, 1)).thenReturn(this.jobInstanceList); when(this.jobExplorer.getJobExecutions(any())).thenReturn(this.jobExecutionList); initializeForNextJobParameters(); this.parametersBuilder.getNextJobParameters(this.job); @@ -244,6 +236,7 @@ public class JobParametersBuilderTests { baseJobParametersVerify(parameters, paramCount); assertEquals("1", parameters.getString("run.id")); } + private void baseJobParametersVerify(JobParameters parameters, int paramCount) { assertEquals(date, parameters.getDate("SCHEDULE_DATE")); assertEquals(1L, parameters.getLong("LONG").longValue()); @@ -253,10 +246,11 @@ public class JobParametersBuilderTests { private JobExecution getJobExecution(JobInstance jobInstance, BatchStatus batchStatus) { JobExecution jobExecution = new JobExecution(jobInstance, 1L, null); - if(batchStatus != null) { + if (batchStatus != null) { jobExecution.setStatus(batchStatus); } return jobExecution; } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/JobParametersTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/JobParametersTests.java index fe8c09bae..6cd12d483 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/JobParametersTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/JobParametersTests.java @@ -66,7 +66,6 @@ public class JobParametersTests { return new JobParameters(parameterMap); } - @Test public void testGetString() { assertEquals("value1", parameters.getString("string.key1")); @@ -186,29 +185,28 @@ public class JobParametersTests { public void testSerialization() { JobParameters params = getNewParameters(); - byte[] serialized = - SerializationUtils.serialize(params); + byte[] serialized = SerializationUtils.serialize(params); assertEquals(params, SerializationUtils.deserialize(serialized)); } @Test - public void testLongReturnsNullWhenKeyDoesntExit(){ + public void testLongReturnsNullWhenKeyDoesntExit() { assertNull(new JobParameters().getLong("keythatdoesntexist")); } @Test - public void testStringReturnsNullWhenKeyDoesntExit(){ + public void testStringReturnsNullWhenKeyDoesntExit() { assertNull(new JobParameters().getString("keythatdoesntexist")); } @Test - public void testDoubleReturnsNullWhenKeyDoesntExit(){ + public void testDoubleReturnsNullWhenKeyDoesntExit() { assertNull(new JobParameters().getDouble("keythatdoesntexist")); } @Test - public void testDateReturnsNullWhenKeyDoesntExit(){ + public void testDateReturnsNullWhenKeyDoesntExit() { assertNull(new JobParameters().getDate("keythatdoesntexist")); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/PooledEmbeddedDataSource.java b/spring-batch-core/src/test/java/org/springframework/batch/core/PooledEmbeddedDataSource.java index 0da5b4413..8b6c16340 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/PooledEmbeddedDataSource.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/PooledEmbeddedDataSource.java @@ -23,11 +23,10 @@ import java.util.logging.Logger; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; /** - * As of Spring 3.2, when a context is closed, the shutdown method is - * called on any beans that are registered. With an embedded database - * that uses a connection pool, this can leave the connection pool open - * with stale connections. This wraps an {@link EmbeddedDatabase} and - * ignores calls to {@link EmbeddedDatabase#shutdown()}. + * As of Spring 3.2, when a context is closed, the shutdown method is called on any beans + * that are registered. With an embedded database that uses a connection pool, this can + * leave the connection pool open with stale connections. This wraps an + * {@link EmbeddedDatabase} and ignores calls to {@link EmbeddedDatabase#shutdown()}. * * @author Phil Webb * @since 3.0 @@ -43,7 +42,9 @@ public class PooledEmbeddedDataSource implements EmbeddedDatabase { this.dataSource = dataSource; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see javax.sql.DataSource#getConnection() */ @Override @@ -51,7 +52,9 @@ public class PooledEmbeddedDataSource implements EmbeddedDatabase { return this.dataSource.getConnection(); } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see javax.sql.DataSource#getConnection(java.lang.String, java.lang.String) */ @Override @@ -59,7 +62,9 @@ public class PooledEmbeddedDataSource implements EmbeddedDatabase { return this.dataSource.getConnection(username, password); } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see javax.sql.CommonDataSource#getLogWriter() */ @Override @@ -67,7 +72,9 @@ public class PooledEmbeddedDataSource implements EmbeddedDatabase { return this.dataSource.getLogWriter(); } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see javax.sql.CommonDataSource#setLogWriter(java.io.PrintWriter) */ @Override @@ -75,7 +82,9 @@ public class PooledEmbeddedDataSource implements EmbeddedDatabase { this.dataSource.setLogWriter(out); } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see javax.sql.CommonDataSource#getLoginTimeout() */ @Override @@ -83,7 +92,9 @@ public class PooledEmbeddedDataSource implements EmbeddedDatabase { return this.dataSource.getLoginTimeout(); } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see javax.sql.CommonDataSource#setLoginTimeout(int) */ @Override @@ -91,7 +102,9 @@ public class PooledEmbeddedDataSource implements EmbeddedDatabase { this.dataSource.setLoginTimeout(seconds); } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see java.sql.Wrapper#unwrap(java.lang.Class) */ @Override @@ -99,7 +112,9 @@ public class PooledEmbeddedDataSource implements EmbeddedDatabase { return this.dataSource.unwrap(iface); } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see java.sql.Wrapper#isWrapperFor(java.lang.Class) */ @Override @@ -111,10 +126,13 @@ public class PooledEmbeddedDataSource implements EmbeddedDatabase { return Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.springframework.jdbc.datasource.embedded.EmbeddedDatabase#shutdown() */ @Override public void shutdown() { } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/SpringBeanJobTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/SpringBeanJobTests.java index 923b41771..1df1f85ff 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/SpringBeanJobTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/SpringBeanJobTests.java @@ -33,13 +33,11 @@ public class SpringBeanJobTests { public void testBeanName() throws Exception { StaticApplicationContext context = new StaticApplicationContext(); JobSupport configuration = new JobSupport(); - context.getAutowireCapableBeanFactory().initializeBean(configuration, - "bean"); + context.getAutowireCapableBeanFactory().initializeBean(configuration, "bean"); context.refresh(); assertNotNull(configuration.getName()); configuration.setBeanName("foo"); - context.getAutowireCapableBeanFactory().initializeBean(configuration, - "bean"); + context.getAutowireCapableBeanFactory().initializeBean(configuration, "bean"); assertEquals("bean", configuration.getName()); context.close(); } @@ -49,12 +47,10 @@ public class SpringBeanJobTests { GenericApplicationContext context = new GenericApplicationContext(); ConstructorArgumentValues args = new ConstructorArgumentValues(); args.addGenericArgumentValue("foo"); - context.registerBeanDefinition("bean", new RootBeanDefinition( - JobSupport.class, args, null)); + context.registerBeanDefinition("bean", new RootBeanDefinition(JobSupport.class, args, null)); context.refresh(); - JobSupport configuration = (JobSupport) context - .getBean("bean"); + JobSupport configuration = (JobSupport) context.getBean("bean"); assertNotNull(configuration.getName()); assertEquals("foo", configuration.getName()); configuration.setBeanName("bar"); @@ -67,12 +63,10 @@ public class SpringBeanJobTests { GenericApplicationContext context = new GenericApplicationContext(); ConstructorArgumentValues args = new ConstructorArgumentValues(); args.addGenericArgumentValue("bar"); - context.registerBeanDefinition("parent", new RootBeanDefinition( - JobSupport.class, args, null)); + context.registerBeanDefinition("parent", new RootBeanDefinition(JobSupport.class, args, null)); context.registerBeanDefinition("bean", new ChildBeanDefinition("parent")); context.refresh(); - JobSupport configuration = (JobSupport) context - .getBean("bean"); + JobSupport configuration = (JobSupport) context.getBean("bean"); assertNotNull(configuration.getName()); assertEquals("bar", configuration.getName()); configuration.setBeanName("foo"); @@ -81,4 +75,5 @@ public class SpringBeanJobTests { assertEquals("foo", configuration.getName()); context.close(); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/StepContributionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/StepContributionTests.java index 19b8f0ed5..d5deab2a3 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/StepContributionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/StepContributionTests.java @@ -21,7 +21,7 @@ import org.junit.Test; /** * @author Dave Syer - * + * */ public class StepContributionTests extends TestCase { @@ -31,8 +31,7 @@ public class StepContributionTests extends TestCase { /** * Test method for - * {@link org.springframework.batch.core.StepContribution#incrementFilterCount(int)} - * . + * {@link org.springframework.batch.core.StepContribution#incrementFilterCount(int)} . */ public void testIncrementFilterCount() { assertEquals(0, contribution.getFilterCount()); @@ -50,4 +49,5 @@ public class StepContributionTests extends TestCase { assertEquals(new StepExecution("foo", null).createStepContribution(), contribution); assertEquals(new StepExecution("foo", null).createStepContribution().hashCode(), contribution.hashCode()); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/StepExecutionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/StepExecutionTests.java index 1513cc1df..313bf1e07 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/StepExecutionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/StepExecutionTests.java @@ -45,8 +45,6 @@ public class StepExecutionTests { private ExecutionContext foobarEc = new ExecutionContext(); - - @Before public void setUp() throws Exception { foobarEc.put("foo", "bar"); @@ -59,12 +57,11 @@ public class StepExecutionTests { @Test public void testStepExecutionWithNullId() { - assertNull(new StepExecution("stepName", new JobExecution(new JobInstance(null,"foo"), null)).getId()); + assertNull(new StepExecution("stepName", new JobExecution(new JobInstance(null, "foo"), null)).getId()); } /** - * Test method for - * {@link org.springframework.batch.core.JobExecution#getEndTime()}. + * Test method for {@link org.springframework.batch.core.JobExecution#getEndTime()}. */ @Test public void testGetEndTime() { @@ -74,8 +71,7 @@ public class StepExecutionTests { } /** - * Test method for - * {@link StepExecution#getCreateTime()}. + * Test method for {@link StepExecution#getCreateTime()}. */ @Test public void testGetCreateTime() { @@ -85,8 +81,7 @@ public class StepExecutionTests { } /** - * Test method for - * {@link org.springframework.batch.core.JobExecution#getStatus()}. + * Test method for {@link org.springframework.batch.core.JobExecution#getStatus()}. */ @Test public void testGetStatus() { @@ -96,8 +91,7 @@ public class StepExecutionTests { } /** - * Test method for - * {@link org.springframework.batch.core.JobExecution#getJobId()}. + * Test method for {@link org.springframework.batch.core.JobExecution#getJobId()}. */ @Test public void testGetJobId() { @@ -192,8 +186,8 @@ public class StepExecutionTests { @Test public void testEqualsWithSameName() throws Exception { Step step = new StepSupport("stepName"); - Entity stepExecution1 = newStepExecution(step,11L,4L); - Entity stepExecution2 = newStepExecution(step,11L,5L); + Entity stepExecution1 = newStepExecution(step, 11L, 4L); + Entity stepExecution2 = newStepExecution(step, 11L, 5L); assertFalse(stepExecution1.equals(stepExecution2)); } @@ -251,8 +245,8 @@ public class StepExecutionTests { @Test public void testHashCodeWithNullIds() throws Exception { - assertTrue("Hash code not same as parent", new Entity(execution.getId()).hashCode() != blankExecution - .hashCode()); + assertTrue("Hash code not same as parent", + new Entity(execution.getId()).hashCode() != blankExecution.hashCode()); } @Test @@ -280,7 +274,7 @@ public class StepExecutionTests { } @Test - public void testAddException() throws Exception{ + public void testAddException() throws Exception { RuntimeException exception = new RuntimeException(); assertEquals(0, execution.getFailureExceptions().size()); @@ -290,8 +284,7 @@ public class StepExecutionTests { } /** - * Test method for - * {@link org.springframework.batch.core.JobExecution#getStatus()}. + * Test method for {@link org.springframework.batch.core.JobExecution#getStatus()}. */ @Test public void testDowngradeStatus() { @@ -306,7 +299,8 @@ public class StepExecutionTests { private StepExecution newStepExecution(Step step, Long jobExecutionId, long stepExecutionId) { JobInstance job = new JobInstance(3L, "testJob"); - StepExecution execution = new StepExecution(step.getName(), new JobExecution(job, jobExecutionId, new JobParameters()), stepExecutionId); + StepExecution execution = new StepExecution(step.getName(), + new JobExecution(job, jobExecutionId, new JobParameters()), stepExecutionId); return execution; } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/DuplicateJobExceptionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/DuplicateJobExceptionTests.java index fe134af6e..50c28e19e 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/DuplicateJobExceptionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/DuplicateJobExceptionTests.java @@ -25,7 +25,10 @@ public class DuplicateJobExceptionTests extends AbstractExceptionTests { /* * (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String) + * + * @see + * org.springframework.batch.io.exception.AbstractExceptionTests#getException(java. + * lang.String) */ @Override public Exception getException(String msg) throws Exception { @@ -34,8 +37,10 @@ public class DuplicateJobExceptionTests extends AbstractExceptionTests { /* * (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String, - * java.lang.Throwable) + * + * @see + * org.springframework.batch.io.exception.AbstractExceptionTests#getException(java. + * lang.String, java.lang.Throwable) */ @Override public Exception getException(String msg, Throwable t) throws Exception { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/DataSourceConfiguration.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/DataSourceConfiguration.java index 7330e529e..f130764e4 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/DataSourceConfiguration.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/DataSourceConfiguration.java @@ -38,16 +38,15 @@ public class DataSourceConfiguration { @PostConstruct protected void initialize() { ResourceDatabasePopulator populator = new ResourceDatabasePopulator(); - populator.addScript(resourceLoader.getResource(ClassUtils.addResourcePathToPackagePath(Step.class, "schema-hsqldb.sql"))); + populator.addScript( + resourceLoader.getResource(ClassUtils.addResourcePathToPackagePath(Step.class, "schema-hsqldb.sql"))); populator.setContinueOnError(true); DatabasePopulatorUtils.execute(populator, dataSource()); } @Bean public DataSource dataSource() { - return new EmbeddedDatabaseBuilder() - .generateUniqueName(true) - .build(); + return new EmbeddedDatabaseBuilder().generateUniqueName(true).build(); } @Bean diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/InlineDataSourceDefinitionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/InlineDataSourceDefinitionTests.java index d9a5d07b8..393565490 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/InlineDataSourceDefinitionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/InlineDataSourceDefinitionTests.java @@ -45,47 +45,43 @@ import org.springframework.test.context.junit4.SpringRunner; @ContextConfiguration public class InlineDataSourceDefinitionTests { - @Test - public void testInlineDataSourceDefinition() throws Exception { - ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyJobConfiguration.class); - Job job = applicationContext.getBean(Job.class); - JobLauncher jobLauncher = applicationContext.getBean(JobLauncher.class); - JobExecution jobExecution = jobLauncher.run(job, new JobParameters()); - Assert.assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus()); - } + @Test + public void testInlineDataSourceDefinition() throws Exception { + ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyJobConfiguration.class); + Job job = applicationContext.getBean(Job.class); + JobLauncher jobLauncher = applicationContext.getBean(JobLauncher.class); + JobExecution jobExecution = jobLauncher.run(job, new JobParameters()); + Assert.assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus()); + } - @Configuration - @EnableBatchProcessing - static class MyJobConfiguration { + @Configuration + @EnableBatchProcessing + static class MyJobConfiguration { - private JobBuilderFactory jobs; - private StepBuilderFactory steps; + private JobBuilderFactory jobs; - public MyJobConfiguration(JobBuilderFactory jobs, StepBuilderFactory steps) { - this.jobs = jobs; - this.steps = steps; - } + private StepBuilderFactory steps; - @Bean - public Job job() { - return jobs.get("job") - .start(steps.get("step") - .tasklet((contribution, chunkContext) -> { - System.out.println("hello world"); - return RepeatStatus.FINISHED; - }) - .build()) - .build(); - } + public MyJobConfiguration(JobBuilderFactory jobs, StepBuilderFactory steps) { + this.jobs = jobs; + this.steps = steps; + } + + @Bean + public Job job() { + return jobs.get("job").start(steps.get("step").tasklet((contribution, chunkContext) -> { + System.out.println("hello world"); + return RepeatStatus.FINISHED; + }).build()).build(); + } + + @Bean + public DataSource dataSource() { + return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2) + .addScript("/org/springframework/batch/core/schema-drop-h2.sql") + .addScript("/org/springframework/batch/core/schema-h2.sql").generateUniqueName(true).build(); + } + + } - @Bean - public DataSource dataSource() { - return new EmbeddedDatabaseBuilder() - .setType(EmbeddedDatabaseType.H2) - .addScript("/org/springframework/batch/core/schema-drop-h2.sql") - .addScript("/org/springframework/batch/core/schema-h2.sql") - .generateUniqueName(true) - .build(); - } - } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/JobBuilderConfigurationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/JobBuilderConfigurationTests.java index 734ecf4aa..29085b42c 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/JobBuilderConfigurationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/JobBuilderConfigurationTests.java @@ -97,9 +97,8 @@ public class JobBuilderConfigurationTests { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(configs); Job job = jobName == null ? context.getBean(Job.class) : context.getBean(jobName, Job.class); JobLauncher jobLauncher = context.getBean(JobLauncher.class); - execution = jobLauncher - .run(job, new JobParametersBuilder().addLong("run.id", (long) (Math.random() * Long.MAX_VALUE)) - .toJobParameters()); + execution = jobLauncher.run(job, new JobParametersBuilder() + .addLong("run.id", (long) (Math.random() * Long.MAX_VALUE)).toJobParameters()); assertEquals(status, execution.getStatus()); assertEquals(stepExecutionCount, execution.getStepExecutions().size()); context.close(); @@ -146,6 +145,7 @@ public class JobBuilderConfigurationTests { } }; } + } @Configuration @@ -247,14 +247,13 @@ public class JobBuilderConfigurationTests { @Configuration static class DataSourceConfiguration { + @Bean public DataSource dataSource() { - return new EmbeddedDatabaseBuilder() - .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("/org/springframework/batch/core/schema-hsqldb.sql") - .generateUniqueName(true) - .build(); + return new EmbeddedDatabaseBuilder().addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") + .addScript("/org/springframework/batch/core/schema-hsqldb.sql").generateUniqueName(true).build(); } + } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/JobLoaderConfigurationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/JobLoaderConfigurationTests.java index d80db01ff..6d961b71c 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/JobLoaderConfigurationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/JobLoaderConfigurationTests.java @@ -47,7 +47,7 @@ import org.springframework.lang.Nullable; /** * @author Dave Syer * @author Mahmoud Ben Hassine - * + * */ public class JobLoaderConfigurationTests { @@ -72,9 +72,8 @@ public class JobLoaderConfigurationTests { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(configs); Job job = jobName == null ? context.getBean(Job.class) : context.getBean(JobLocator.class).getJob(jobName); JobLauncher jobLauncher = context.getBean(JobLauncher.class); - execution = jobLauncher - .run(job, new JobParametersBuilder().addLong("run.id", (long) (Math.random() * Long.MAX_VALUE)) - .toJobParameters()); + execution = jobLauncher.run(job, new JobParametersBuilder() + .addLong("run.id", (long) (Math.random() * Long.MAX_VALUE)).toJobParameters()); assertEquals(status, execution.getStatus()); assertEquals(stepExecutionCount, execution.getStepExecutions().size()); JobExplorer jobExplorer = context.getBean(JobExplorer.class); @@ -84,7 +83,7 @@ public class JobLoaderConfigurationTests { } @Configuration - @EnableBatchProcessing(modular=true) + @EnableBatchProcessing(modular = true) public static class LoaderFactoryConfiguration { @Bean @@ -101,7 +100,7 @@ public class JobLoaderConfigurationTests { } @Configuration - @EnableBatchProcessing(modular=true) + @EnableBatchProcessing(modular = true) public static class LoaderRegistrarConfiguration { @Autowired @@ -120,7 +119,8 @@ public class JobLoaderConfigurationTests { @Bean public ApplicationObjectSupport fakeApplicationObjectSupport() { - return new ApplicationObjectSupport() {}; + return new ApplicationObjectSupport() { + }; } @Autowired @@ -155,6 +155,7 @@ public class JobLoaderConfigurationTests { } }; } + } @Configuration @@ -182,6 +183,7 @@ public class JobLoaderConfigurationTests { } }).build(); } + } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/JobScopeConfigurationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/JobScopeConfigurationTests.java index d373a1429..3f09ea839 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/JobScopeConfigurationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/JobScopeConfigurationTests.java @@ -177,6 +177,7 @@ public class JobScopeConfigurationTests { } public static class SimpleCallable implements Callable { + private final String value; private SimpleCallable(String value) { @@ -187,9 +188,11 @@ public class JobScopeConfigurationTests { public String call() throws Exception { return value; } + } public static class SimpleHolder { + private final String value; protected SimpleHolder() { @@ -203,6 +206,7 @@ public class JobScopeConfigurationTests { public String call() throws Exception { return value; } + } public static class Wrapper { @@ -226,6 +230,7 @@ public class JobScopeConfigurationTests { public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { return RepeatStatus.FINISHED; } + } @Configuration @@ -251,9 +256,8 @@ public class JobScopeConfigurationTests { } @Bean - @Scope(value="job", proxyMode = ScopedProxyMode.TARGET_CLASS) - protected SimpleHolder value(@Value("#{jobName}") - final String value) { + @Scope(value = "job", proxyMode = ScopedProxyMode.TARGET_CLASS) + protected SimpleHolder value(@Value("#{jobName}") final String value) { return new SimpleHolder(value); } @@ -264,9 +268,8 @@ public class JobScopeConfigurationTests { public static class JobScopeConfigurationRequiringProxyTargetClass { @Bean - @Scope(value="job", proxyMode = ScopedProxyMode.TARGET_CLASS) - protected SimpleHolder value(@Value("#{jobName}") - final String value) { + @Scope(value = "job", proxyMode = ScopedProxyMode.TARGET_CLASS) + protected SimpleHolder value(@Value("#{jobName}") final String value) { return new SimpleHolder(value); } @@ -278,8 +281,7 @@ public class JobScopeConfigurationTests { @Bean @JobScope - protected Callable value(@Value("#{jobName}") - final String value) { + protected Callable value(@Value("#{jobName}") final String value) { return new SimpleCallable(value); } @@ -290,9 +292,8 @@ public class JobScopeConfigurationTests { public static class JobScopeConfigurationForcingInterfaceProxy { @Bean - @Scope(value="job", proxyMode = ScopedProxyMode.INTERFACES) - protected SimpleHolder value(@Value("#{jobName}") - final String value) { + @Scope(value = "job", proxyMode = ScopedProxyMode.INTERFACES) + protected SimpleHolder value(@Value("#{jobName}") final String value) { return new SimpleHolder(value); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/StepScopeConfigurationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/StepScopeConfigurationTests.java index d2d3a9ed8..994c1b403 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/StepScopeConfigurationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/StepScopeConfigurationTests.java @@ -177,6 +177,7 @@ public class StepScopeConfigurationTests { } public static class SimpleCallable implements Callable { + private final String value; private SimpleCallable(String value) { @@ -187,9 +188,11 @@ public class StepScopeConfigurationTests { public String call() throws Exception { return value; } + } public static class SimpleHolder { + private final String value; protected SimpleHolder() { @@ -203,6 +206,7 @@ public class StepScopeConfigurationTests { public String call() throws Exception { return value; } + } public static class Wrapper { @@ -226,8 +230,7 @@ public class StepScopeConfigurationTests { @Bean @StepScope - protected SimpleHolder javaValue(@Value("#{stepExecution.stepName}") - final String value) { + protected SimpleHolder javaValue(@Value("#{stepExecution.stepName}") final String value) { return new SimpleHolder(value); } @@ -243,9 +246,8 @@ public class StepScopeConfigurationTests { } @Bean - @Scope(value="step", proxyMode = ScopedProxyMode.TARGET_CLASS) - protected SimpleHolder value(@Value("#{stepExecution.stepName}") - final String value) { + @Scope(value = "step", proxyMode = ScopedProxyMode.TARGET_CLASS) + protected SimpleHolder value(@Value("#{stepExecution.stepName}") final String value) { return new SimpleHolder(value); } @@ -256,9 +258,8 @@ public class StepScopeConfigurationTests { public static class StepScopeConfigurationRequiringProxyTargetClass { @Bean - @Scope(value="step", proxyMode = ScopedProxyMode.TARGET_CLASS) - protected SimpleHolder value(@Value("#{stepExecution.stepName}") - final String value) { + @Scope(value = "step", proxyMode = ScopedProxyMode.TARGET_CLASS) + protected SimpleHolder value(@Value("#{stepExecution.stepName}") final String value) { return new SimpleHolder(value); } @@ -270,8 +271,7 @@ public class StepScopeConfigurationTests { @Bean @StepScope - protected Callable value(@Value("#{stepExecution.stepName}") - final String value) { + protected Callable value(@Value("#{stepExecution.stepName}") final String value) { return new SimpleCallable(value); } @@ -282,9 +282,8 @@ public class StepScopeConfigurationTests { public static class StepScopeConfigurationForcingInterfaceProxy { @Bean - @Scope(value="step", proxyMode = ScopedProxyMode.INTERFACES) - protected SimpleHolder value(@Value("#{stepExecution.stepName}") - final String value) { + @Scope(value = "step", proxyMode = ScopedProxyMode.INTERFACES) + protected SimpleHolder value(@Value("#{stepExecution.stepName}") final String value) { return new SimpleHolder(value); } @@ -297,5 +296,7 @@ public class StepScopeConfigurationTests { public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { return RepeatStatus.FINISHED; } + } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/TransactionManagerConfigurationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/TransactionManagerConfigurationTests.java index 183c8f515..4597bfa6e 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/TransactionManagerConfigurationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/TransactionManagerConfigurationTests.java @@ -43,13 +43,18 @@ public abstract class TransactionManagerConfigurationTests { protected static PlatformTransactionManager transactionManager2; /* - * The transaction manager set on JobRepositoryFactoryBean in DefaultBatchConfigurer.createJobRepository - * ends up in the TransactionInterceptor advise applied to the (proxied) JobRepository. - * This method extracts the advise from the proxy and returns the transaction manager. + * The transaction manager set on JobRepositoryFactoryBean in + * DefaultBatchConfigurer.createJobRepository ends up in the TransactionInterceptor + * advise applied to the (proxied) JobRepository. This method extracts the advise from + * the proxy and returns the transaction manager. */ PlatformTransactionManager getTransactionManagerSetOnJobRepository(JobRepository jobRepository) throws Exception { - TargetSource targetSource = ((Advised) jobRepository).getTargetSource(); // proxy created in SimpleBatchConfiguration.createLazyProxy - Advised target = (Advised) targetSource.getTarget(); // initial proxy created in AbstractJobRepositoryFactoryBean.initializeProxy + TargetSource targetSource = ((Advised) jobRepository).getTargetSource(); // proxy + // created + // in + // SimpleBatchConfiguration.createLazyProxy + Advised target = (Advised) targetSource.getTarget(); // initial proxy created in + // AbstractJobRepositoryFactoryBean.initializeProxy Advisor[] advisors = target.getAdvisors(); for (Advisor advisor : advisors) { if (advisor.getAdvice() instanceof TransactionInterceptor) { @@ -63,8 +68,8 @@ public abstract class TransactionManagerConfigurationTests { static DataSource createDataSource() { return new EmbeddedDatabaseBuilder() .addScript("classpath:org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("classpath:org/springframework/batch/core/schema-hsqldb.sql") - .generateUniqueName(true) + .addScript("classpath:org/springframework/batch/core/schema-hsqldb.sql").generateUniqueName(true) .build(); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/TransactionManagerConfigurationWithBatchConfigurerTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/TransactionManagerConfigurationWithBatchConfigurerTests.java index 445dae97d..5dbda44fe 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/TransactionManagerConfigurationWithBatchConfigurerTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/TransactionManagerConfigurationWithBatchConfigurerTests.java @@ -40,29 +40,35 @@ public class TransactionManagerConfigurationWithBatchConfigurerTests extends Tra @Test public void testConfigurationWithDataSourceAndNoTransactionManager() throws Exception { - ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BatchConfigurationWithDataSourceAndNoTransactionManager.class); + ApplicationContext applicationContext = new AnnotationConfigApplicationContext( + BatchConfigurationWithDataSourceAndNoTransactionManager.class); BatchConfigurer batchConfigurer = applicationContext.getBean(BatchConfigurer.class); PlatformTransactionManager platformTransactionManager = batchConfigurer.getTransactionManager(); Assert.assertTrue(platformTransactionManager instanceof DataSourceTransactionManager); - DataSourceTransactionManager dataSourceTransactionManager = AopTestUtils.getTargetObject(platformTransactionManager); + DataSourceTransactionManager dataSourceTransactionManager = AopTestUtils + .getTargetObject(platformTransactionManager); Assert.assertEquals(applicationContext.getBean(DataSource.class), dataSourceTransactionManager.getDataSource()); - Assert.assertSame(getTransactionManagerSetOnJobRepository(applicationContext.getBean(JobRepository.class)), platformTransactionManager); + Assert.assertSame(getTransactionManagerSetOnJobRepository(applicationContext.getBean(JobRepository.class)), + platformTransactionManager); } @Test public void testConfigurationWithDataSourceAndTransactionManager() throws Exception { - ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BatchConfigurationWithDataSourceAndTransactionManager.class); + ApplicationContext applicationContext = new AnnotationConfigApplicationContext( + BatchConfigurationWithDataSourceAndTransactionManager.class); BatchConfigurer batchConfigurer = applicationContext.getBean(BatchConfigurer.class); PlatformTransactionManager platformTransactionManager = batchConfigurer.getTransactionManager(); Assert.assertSame(transactionManager, platformTransactionManager); - Assert.assertSame(getTransactionManagerSetOnJobRepository(applicationContext.getBean(JobRepository.class)), transactionManager); + Assert.assertSame(getTransactionManagerSetOnJobRepository(applicationContext.getBean(JobRepository.class)), + transactionManager); } @Configuration @EnableBatchProcessing public static class BatchConfigurationWithDataSourceAndNoTransactionManager { + @Bean public DataSource dataSource() { return createDataSource(); @@ -72,6 +78,7 @@ public class TransactionManagerConfigurationWithBatchConfigurerTests extends Tra public BatchConfigurer batchConfigurer(DataSource dataSource) { return new DefaultBatchConfigurer(dataSource); } + } @Configuration diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/TransactionManagerConfigurationWithoutBatchConfigurerTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/TransactionManagerConfigurationWithoutBatchConfigurerTests.java index c384a2e5e..4785f5624 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/TransactionManagerConfigurationWithoutBatchConfigurerTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/TransactionManagerConfigurationWithoutBatchConfigurerTests.java @@ -42,8 +42,10 @@ public class TransactionManagerConfigurationWithoutBatchConfigurerTests extends @Test(expected = IllegalStateException.class) public void testConfigurationWithNoDataSourceAndNoTransactionManager() { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BatchConfigurationWithNoDataSourceAndNoTransactionManager.class); - // beans created by `@EnableBatchProcessing` are lazy proxies, SimpleBatchConfiguration.initialize is only triggered + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( + BatchConfigurationWithNoDataSourceAndNoTransactionManager.class); + // beans created by `@EnableBatchProcessing` are lazy proxies, + // SimpleBatchConfiguration.initialize is only triggered // when a method is called on one of these proxies JobRepository jobRepository = context.getBean(JobRepository.class); Assert.assertFalse(jobRepository.isJobInstanceExists("myJob", new JobParameters())); @@ -51,8 +53,10 @@ public class TransactionManagerConfigurationWithoutBatchConfigurerTests extends @Test(expected = IllegalStateException.class) public void testConfigurationWithNoDataSourceAndTransactionManager() { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BatchConfigurationWithNoDataSourceAndTransactionManager.class); - // beans created by `@EnableBatchProcessing` are lazy proxies, SimpleBatchConfiguration.initialize is only triggered + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( + BatchConfigurationWithNoDataSourceAndTransactionManager.class); + // beans created by `@EnableBatchProcessing` are lazy proxies, + // SimpleBatchConfiguration.initialize is only triggered // when a method is called on one of these proxies JobRepository jobRepository = context.getBean(JobRepository.class); Assert.assertFalse(jobRepository.isJobInstanceExists("myJob", new JobParameters())); @@ -60,8 +64,10 @@ public class TransactionManagerConfigurationWithoutBatchConfigurerTests extends @Test public void testConfigurationWithDataSourceAndNoTransactionManager() throws Exception { - ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BatchConfigurationWithDataSourceAndNoTransactionManager.class); - PlatformTransactionManager platformTransactionManager = getTransactionManagerSetOnJobRepository(applicationContext.getBean(JobRepository.class)); + ApplicationContext applicationContext = new AnnotationConfigApplicationContext( + BatchConfigurationWithDataSourceAndNoTransactionManager.class); + PlatformTransactionManager platformTransactionManager = getTransactionManagerSetOnJobRepository( + applicationContext.getBean(JobRepository.class)); Assert.assertTrue(platformTransactionManager instanceof DataSourceTransactionManager); DataSourceTransactionManager dataSourceTransactionManager = (DataSourceTransactionManager) platformTransactionManager; Assert.assertEquals(applicationContext.getBean(DataSource.class), dataSourceTransactionManager.getDataSource()); @@ -69,22 +75,30 @@ public class TransactionManagerConfigurationWithoutBatchConfigurerTests extends @Test public void testConfigurationWithDataSourceAndOneTransactionManager() throws Exception { - ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BatchConfigurationWithDataSourceAndOneTransactionManager.class); - PlatformTransactionManager platformTransactionManager = applicationContext.getBean(PlatformTransactionManager.class); + ApplicationContext applicationContext = new AnnotationConfigApplicationContext( + BatchConfigurationWithDataSourceAndOneTransactionManager.class); + PlatformTransactionManager platformTransactionManager = applicationContext + .getBean(PlatformTransactionManager.class); Assert.assertSame(transactionManager, platformTransactionManager); - // In this case, the supplied transaction manager won't be used by batch and a DataSourceTransactionManager will be used instead. + // In this case, the supplied transaction manager won't be used by batch and a + // DataSourceTransactionManager will be used instead. // The user has to provide a custom BatchConfigurer. - Assert.assertTrue(getTransactionManagerSetOnJobRepository(applicationContext.getBean(JobRepository.class)) instanceof DataSourceTransactionManager); + Assert.assertTrue(getTransactionManagerSetOnJobRepository( + applicationContext.getBean(JobRepository.class)) instanceof DataSourceTransactionManager); } @Test public void testConfigurationWithDataSourceAndMultipleTransactionManagers() throws Exception { - ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BatchConfigurationWithDataSourceAndMultipleTransactionManagers.class); - PlatformTransactionManager platformTransactionManager = applicationContext.getBean(PlatformTransactionManager.class); + ApplicationContext applicationContext = new AnnotationConfigApplicationContext( + BatchConfigurationWithDataSourceAndMultipleTransactionManagers.class); + PlatformTransactionManager platformTransactionManager = applicationContext + .getBean(PlatformTransactionManager.class); Assert.assertSame(transactionManager2, platformTransactionManager); - // In this case, the supplied primary transaction manager won't be used by batch and a DataSourceTransactionManager will be used instead. + // In this case, the supplied primary transaction manager won't be used by batch + // and a DataSourceTransactionManager will be used instead. // The user has to provide a custom BatchConfigurer. - Assert.assertTrue(getTransactionManagerSetOnJobRepository(applicationContext.getBean(JobRepository.class)) instanceof DataSourceTransactionManager); + Assert.assertTrue(getTransactionManagerSetOnJobRepository( + applicationContext.getBean(JobRepository.class)) instanceof DataSourceTransactionManager); } @Configuration @@ -101,6 +115,7 @@ public class TransactionManagerConfigurationWithoutBatchConfigurerTests extends public PlatformTransactionManager transactionManager() { return transactionManager; } + } @Configuration @@ -111,6 +126,7 @@ public class TransactionManagerConfigurationWithoutBatchConfigurerTests extends public DataSource dataSource() { return createDataSource(); } + } @Configuration @@ -126,6 +142,7 @@ public class TransactionManagerConfigurationWithoutBatchConfigurerTests extends public PlatformTransactionManager transactionManager() { return transactionManager; } + } @Configuration @@ -147,5 +164,7 @@ public class TransactionManagerConfigurationWithoutBatchConfigurerTests extends public PlatformTransactionManager transactionManager2() { return transactionManager2; } + } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/ApplicationContextJobFactoryTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/ApplicationContextJobFactoryTests.java index 784e8b363..794dd3914 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/ApplicationContextJobFactoryTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/ApplicationContextJobFactoryTests.java @@ -1,83 +1,85 @@ -/* - * Copyright 2008-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.configuration.support; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import org.junit.Test; -import org.springframework.batch.core.job.JobSupport; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.config.BeanPostProcessor; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.support.StaticApplicationContext; - -public class ApplicationContextJobFactoryTests { - - @Test - public void testFactoryContext() throws Exception { - ApplicationContextJobFactory factory = new ApplicationContextJobFactory("job", - new StubApplicationContextFactory()); - assertNotNull(factory.createJob()); - } - - @Test - public void testPostProcessing() throws Exception { - ApplicationContextJobFactory factory = new ApplicationContextJobFactory("job", - new PostProcessingApplicationContextFactory()); - assertEquals("bar", factory.getJobName()); - } - - private static class StubApplicationContextFactory implements ApplicationContextFactory { - @Override - public ConfigurableApplicationContext createApplicationContext() { - StaticApplicationContext context = new StaticApplicationContext(); - context.registerSingleton("job", JobSupport.class); - return context; - } - - } - - private static class PostProcessingApplicationContextFactory implements ApplicationContextFactory { - @Override - public ConfigurableApplicationContext createApplicationContext() { - StaticApplicationContext context = new StaticApplicationContext(); - context.registerSingleton("job", JobSupport.class); - context.registerSingleton("postProcessor", TestBeanPostProcessor.class); - context.refresh(); - return context; - } - - } - - private static class TestBeanPostProcessor implements BeanPostProcessor { - - @Override - public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { - if (bean instanceof JobSupport) { - ((JobSupport) bean).setName("bar"); - } - return bean; - } - - @Override - public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { - return bean; - } - - } - -} +/* + * Copyright 2008-2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.configuration.support; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.junit.Test; +import org.springframework.batch.core.job.JobSupport; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.support.StaticApplicationContext; + +public class ApplicationContextJobFactoryTests { + + @Test + public void testFactoryContext() throws Exception { + ApplicationContextJobFactory factory = new ApplicationContextJobFactory("job", + new StubApplicationContextFactory()); + assertNotNull(factory.createJob()); + } + + @Test + public void testPostProcessing() throws Exception { + ApplicationContextJobFactory factory = new ApplicationContextJobFactory("job", + new PostProcessingApplicationContextFactory()); + assertEquals("bar", factory.getJobName()); + } + + private static class StubApplicationContextFactory implements ApplicationContextFactory { + + @Override + public ConfigurableApplicationContext createApplicationContext() { + StaticApplicationContext context = new StaticApplicationContext(); + context.registerSingleton("job", JobSupport.class); + return context; + } + + } + + private static class PostProcessingApplicationContextFactory implements ApplicationContextFactory { + + @Override + public ConfigurableApplicationContext createApplicationContext() { + StaticApplicationContext context = new StaticApplicationContext(); + context.registerSingleton("job", JobSupport.class); + context.registerSingleton("postProcessor", TestBeanPostProcessor.class); + context.refresh(); + return context; + } + + } + + private static class TestBeanPostProcessor implements BeanPostProcessor { + + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + if (bean instanceof JobSupport) { + ((JobSupport) bean).setName("bar"); + } + return bean; + } + + @Override + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + return bean; + } + + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/AutomaticJobRegistrarContextTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/AutomaticJobRegistrarContextTests.java index 54c715cc9..eae166649 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/AutomaticJobRegistrarContextTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/AutomaticJobRegistrarContextTests.java @@ -29,8 +29,6 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** - * - * * @author Dave Syer * */ @@ -40,17 +38,17 @@ public class AutomaticJobRegistrarContextTests { @Autowired private JobRegistry registry; - + @Test - public void testLocateJob() throws Exception{ - + public void testLocateJob() throws Exception { + Collection names = registry.getJobNames(); assertEquals(2, names.size()); assertTrue(names.contains("test-job")); - + Job job = registry.getJob("test-job"); assertEquals("test-job", job.getName()); } - + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/AutomaticJobRegistrarTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/AutomaticJobRegistrarTests.java index 65d7fe7be..722435519 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/AutomaticJobRegistrarTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/AutomaticJobRegistrarTests.java @@ -36,11 +36,10 @@ import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; /** - * * @author Dave Syer * @author Lucas Ward * @author Mahmoud Ben Hassine - * + * */ public class AutomaticJobRegistrarTests { @@ -58,7 +57,7 @@ public class AutomaticJobRegistrarTests { @SuppressWarnings("cast") @Test public void testOrderedImplemented() throws Exception { - + assertTrue(registrar instanceof Ordered); assertEquals(Ordered.LOWEST_PRECEDENCE, registrar.getOrder()); registrar.setOrder(1); @@ -108,8 +107,8 @@ public class AutomaticJobRegistrarTests { @Test public void testNoJobFound() throws Exception { - Resource[] jobPaths = new Resource[] { new ClassPathResource( - "org/springframework/batch/core/launch/support/test-environment.xml") }; + Resource[] jobPaths = new Resource[] { + new ClassPathResource("org/springframework/batch/core/launch/support/test-environment.xml") }; @SuppressWarnings("resource") GenericApplicationContext applicationContext = new GenericApplicationContext(); applicationContext.refresh(); @@ -121,8 +120,8 @@ public class AutomaticJobRegistrarTests { @Test public void testDuplicateJobsInFile() throws Exception { - Resource[] jobPaths = new Resource[] { new ClassPathResource( - "org/springframework/batch/core/launch/support/2jobs.xml") }; + Resource[] jobPaths = new Resource[] { + new ClassPathResource("org/springframework/batch/core/launch/support/2jobs.xml") }; @SuppressWarnings("resource") GenericApplicationContext applicationContext = new GenericApplicationContext(); applicationContext.refresh(); @@ -135,8 +134,8 @@ public class AutomaticJobRegistrarTests { @Test public void testChildContextOverridesBeanPostProcessor() throws Exception { - Resource[] jobPaths = new Resource[] { new ClassPathResource( - "org/springframework/batch/core/launch/support/2jobs.xml") }; + Resource[] jobPaths = new Resource[] { + new ClassPathResource("org/springframework/batch/core/launch/support/2jobs.xml") }; @SuppressWarnings("resource") ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext( "/org/springframework/batch/core/launch/support/test-environment-with-registry-and-auto-register.xml"); @@ -165,8 +164,8 @@ public class AutomaticJobRegistrarTests { @Test public void testClear() throws Exception { - Resource[] jobPaths = new Resource[] { new ClassPathResource( - "org/springframework/batch/core/launch/support/2jobs.xml") }; + Resource[] jobPaths = new Resource[] { + new ClassPathResource("org/springframework/batch/core/launch/support/2jobs.xml") }; setUpApplicationContextFactories(jobPaths, null); registrar.start(); assertEquals(2, registry.getJobNames().size()); @@ -178,8 +177,8 @@ public class AutomaticJobRegistrarTests { @Test public void testStartStopRunning() throws Exception { - Resource[] jobPaths = new Resource[] { new ClassPathResource( - "org/springframework/batch/core/launch/support/2jobs.xml") }; + Resource[] jobPaths = new Resource[] { + new ClassPathResource("org/springframework/batch/core/launch/support/2jobs.xml") }; setUpApplicationContextFactories(jobPaths, null); registrar.start(); assertTrue(registrar.isRunning()); @@ -194,8 +193,8 @@ public class AutomaticJobRegistrarTests { public void testStartStopRunningWithCallback() throws Exception { Runnable callback = Mockito.mock(Runnable.class); - Resource[] jobPaths = new Resource[] { new ClassPathResource( - "org/springframework/batch/core/launch/support/2jobs.xml") }; + Resource[] jobPaths = new Resource[] { + new ClassPathResource("org/springframework/batch/core/launch/support/2jobs.xml") }; setUpApplicationContextFactories(jobPaths, null); registrar.start(); assertTrue(registrar.isRunning()); @@ -215,8 +214,8 @@ public class AutomaticJobRegistrarTests { factory.setApplicationContext(parent); applicationContextFactories.add(factory); } - registrar.setApplicationContextFactories(applicationContextFactories - .toArray(new ApplicationContextFactory[jobPaths.length])); + registrar.setApplicationContextFactories( + applicationContextFactories.toArray(new ApplicationContextFactory[jobPaths.length])); } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/DefaultJobLoaderTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/DefaultJobLoaderTests.java index 592787148..c7316a73f 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/DefaultJobLoaderTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/DefaultJobLoaderTests.java @@ -47,24 +47,25 @@ import org.springframework.test.util.ReflectionTestUtils; public class DefaultJobLoaderTests { /** - * The name of the job as defined in the test context used in this test. - */ - private static final String TEST_JOB_NAME = "test-job"; + * The name of the job as defined in the test context used in this test. + */ + private static final String TEST_JOB_NAME = "test-job"; - /** - * The name of the step as defined in the test context used in this test. - */ - private static final String TEST_STEP_NAME = "test-step"; + /** + * The name of the step as defined in the test context used in this test. + */ + private static final String TEST_STEP_NAME = "test-step"; - private JobRegistry jobRegistry = new MapJobRegistry(); - private StepRegistry stepRegistry = new MapStepRegistry(); + private JobRegistry jobRegistry = new MapJobRegistry(); - private DefaultJobLoader jobLoader = new DefaultJobLoader(jobRegistry, stepRegistry); + private StepRegistry stepRegistry = new MapStepRegistry(); + + private DefaultJobLoader jobLoader = new DefaultJobLoader(jobRegistry, stepRegistry); @Test public void testClear() throws Exception { - GenericApplicationContextFactory factory = new GenericApplicationContextFactory(new ByteArrayResource( - JOB_XML.getBytes())); + GenericApplicationContextFactory factory = new GenericApplicationContextFactory( + new ByteArrayResource(JOB_XML.getBytes())); jobLoader.load(factory); assertEquals(1, ((Map) ReflectionTestUtils.getField(jobLoader, "contexts")).size()); assertEquals(1, ((Map) ReflectionTestUtils.getField(jobLoader, "contextToJobNames")).size()); @@ -75,202 +76,208 @@ public class DefaultJobLoaderTests { @Test public void testLoadWithExplicitName() throws Exception { - GenericApplicationContextFactory factory = new GenericApplicationContextFactory(new ByteArrayResource( - JOB_XML.getBytes())); + GenericApplicationContextFactory factory = new GenericApplicationContextFactory( + new ByteArrayResource(JOB_XML.getBytes())); jobLoader.load(factory); assertEquals(1, jobRegistry.getJobNames().size()); jobLoader.reload(factory); assertEquals(1, jobRegistry.getJobNames().size()); } - @Test - public void createWithBothRegistries() { - final DefaultJobLoader loader = new DefaultJobLoader(); - loader.setJobRegistry(jobRegistry); - loader.setStepRegistry(stepRegistry); + @Test + public void createWithBothRegistries() { + final DefaultJobLoader loader = new DefaultJobLoader(); + loader.setJobRegistry(jobRegistry); + loader.setStepRegistry(stepRegistry); - loader.afterPropertiesSet(); - } + loader.afterPropertiesSet(); + } - @Test - public void createWithOnlyJobRegistry() { - final DefaultJobLoader loader = new DefaultJobLoader(); - loader.setJobRegistry(jobRegistry); + @Test + public void createWithOnlyJobRegistry() { + final DefaultJobLoader loader = new DefaultJobLoader(); + loader.setJobRegistry(jobRegistry); - loader.afterPropertiesSet(); - } + loader.afterPropertiesSet(); + } - @Test - public void testRegistryUpdated() throws DuplicateJobException { - GenericApplicationContextFactory factory = new GenericApplicationContextFactory( - new ClassPathResource("trivial-context.xml", getClass())); - jobLoader.load(factory); - assertEquals(1, jobRegistry.getJobNames().size()); - assertStepExist(TEST_JOB_NAME, TEST_STEP_NAME); - } + @Test + public void testRegistryUpdated() throws DuplicateJobException { + GenericApplicationContextFactory factory = new GenericApplicationContextFactory( + new ClassPathResource("trivial-context.xml", getClass())); + jobLoader.load(factory); + assertEquals(1, jobRegistry.getJobNames().size()); + assertStepExist(TEST_JOB_NAME, TEST_STEP_NAME); + } - @Test - public void testMultipleJobsInTheSameContext() throws DuplicateJobException { - GenericApplicationContextFactory factory = new GenericApplicationContextFactory( - new ClassPathResource("job-context-with-steps.xml", getClass())); - jobLoader.load(factory); - assertEquals(2, jobRegistry.getJobNames().size()); - assertStepExist("job1", "step11", "step12"); - assertStepDoNotExist("job1", "step21", "step22"); - assertStepExist("job2", "step21", "step22"); - assertStepDoNotExist("job2", "step11", "step12"); - } + @Test + public void testMultipleJobsInTheSameContext() throws DuplicateJobException { + GenericApplicationContextFactory factory = new GenericApplicationContextFactory( + new ClassPathResource("job-context-with-steps.xml", getClass())); + jobLoader.load(factory); + assertEquals(2, jobRegistry.getJobNames().size()); + assertStepExist("job1", "step11", "step12"); + assertStepDoNotExist("job1", "step21", "step22"); + assertStepExist("job2", "step21", "step22"); + assertStepDoNotExist("job2", "step11", "step12"); + } - @Test - public void testMultipleJobsInTheSameContextWithSeparateSteps() throws DuplicateJobException { - GenericApplicationContextFactory factory = new GenericApplicationContextFactory( - new ClassPathResource("job-context-with-separate-steps.xml", getClass())); - jobLoader.load(factory); - assertEquals(2, jobRegistry.getJobNames().size()); - assertStepExist("job1", "step11", "step12", "genericStep1", "genericStep2"); - assertStepDoNotExist("job1", "step21", "step22"); - assertStepExist("job2", "step21", "step22", "genericStep1", "genericStep2"); - assertStepDoNotExist("job2", "step11", "step12"); - } + @Test + public void testMultipleJobsInTheSameContextWithSeparateSteps() throws DuplicateJobException { + GenericApplicationContextFactory factory = new GenericApplicationContextFactory( + new ClassPathResource("job-context-with-separate-steps.xml", getClass())); + jobLoader.load(factory); + assertEquals(2, jobRegistry.getJobNames().size()); + assertStepExist("job1", "step11", "step12", "genericStep1", "genericStep2"); + assertStepDoNotExist("job1", "step21", "step22"); + assertStepExist("job2", "step21", "step22", "genericStep1", "genericStep2"); + assertStepDoNotExist("job2", "step11", "step12"); + } - @Test - public void testNoStepRegistryAvailable() throws DuplicateJobException { - final JobLoader loader = new DefaultJobLoader(jobRegistry); - GenericApplicationContextFactory factory = new GenericApplicationContextFactory( - new ClassPathResource("job-context-with-steps.xml", getClass())); - loader.load(factory); - // No step registry available so just registering the jobs - assertEquals(2, jobRegistry.getJobNames().size()); - } + @Test + public void testNoStepRegistryAvailable() throws DuplicateJobException { + final JobLoader loader = new DefaultJobLoader(jobRegistry); + GenericApplicationContextFactory factory = new GenericApplicationContextFactory( + new ClassPathResource("job-context-with-steps.xml", getClass())); + loader.load(factory); + // No step registry available so just registering the jobs + assertEquals(2, jobRegistry.getJobNames().size()); + } - @Test - public void testLoadWithJobThatIsNotAStepLocator() throws DuplicateJobException { - GenericApplicationContextFactory factory = new GenericApplicationContextFactory( - new ByteArrayResource(BASIC_JOB_XML.getBytes())); - try { - jobLoader.load(factory); - fail("Should have failed with a ["+UnsupportedOperationException.class.getName()+"] as job does not" + - "implement StepLocator."); - } catch (UnsupportedOperationException e) { - // Job is not a step locator, can't register steps - } + @Test + public void testLoadWithJobThatIsNotAStepLocator() throws DuplicateJobException { + GenericApplicationContextFactory factory = new GenericApplicationContextFactory( + new ByteArrayResource(BASIC_JOB_XML.getBytes())); + try { + jobLoader.load(factory); + fail("Should have failed with a [" + UnsupportedOperationException.class.getName() + "] as job does not" + + "implement StepLocator."); + } + catch (UnsupportedOperationException e) { + // Job is not a step locator, can't register steps + } - } + } - @Test - public void testLoadWithJobThatIsNotAStepLocatorNoStepRegistry() throws DuplicateJobException { - final JobLoader loader = new DefaultJobLoader(jobRegistry); - GenericApplicationContextFactory factory = new GenericApplicationContextFactory( - new ByteArrayResource(BASIC_JOB_XML.getBytes())); - try { - loader.load(factory); - } catch (UnsupportedOperationException e) { - fail("Should not have failed with a [" + UnsupportedOperationException.class.getName() + "] as " + - "stepRegistry is not available for this JobLoader instance."); - } - } + @Test + public void testLoadWithJobThatIsNotAStepLocatorNoStepRegistry() throws DuplicateJobException { + final JobLoader loader = new DefaultJobLoader(jobRegistry); + GenericApplicationContextFactory factory = new GenericApplicationContextFactory( + new ByteArrayResource(BASIC_JOB_XML.getBytes())); + try { + loader.load(factory); + } + catch (UnsupportedOperationException e) { + fail("Should not have failed with a [" + UnsupportedOperationException.class.getName() + "] as " + + "stepRegistry is not available for this JobLoader instance."); + } + } - @Test - public void testReload() throws Exception { - GenericApplicationContextFactory factory = new GenericApplicationContextFactory(new ClassPathResource( - "trivial-context.xml", getClass())); - jobLoader.load(factory); - assertEquals(1, jobRegistry.getJobNames().size()); - assertStepExist(TEST_JOB_NAME, TEST_STEP_NAME); - jobLoader.reload(factory); - assertEquals(1, jobRegistry.getJobNames().size()); - assertStepExist(TEST_JOB_NAME, TEST_STEP_NAME); - } + @Test + public void testReload() throws Exception { + GenericApplicationContextFactory factory = new GenericApplicationContextFactory( + new ClassPathResource("trivial-context.xml", getClass())); + jobLoader.load(factory); + assertEquals(1, jobRegistry.getJobNames().size()); + assertStepExist(TEST_JOB_NAME, TEST_STEP_NAME); + jobLoader.reload(factory); + assertEquals(1, jobRegistry.getJobNames().size()); + assertStepExist(TEST_JOB_NAME, TEST_STEP_NAME); + } - @Test - public void testReloadWithAutoRegister() throws Exception { - GenericApplicationContextFactory factory = new GenericApplicationContextFactory(new ClassPathResource( - "trivial-context-autoregister.xml", getClass())); - jobLoader.load(factory); - assertEquals(1, jobRegistry.getJobNames().size()); - assertStepExist(TEST_JOB_NAME, TEST_STEP_NAME); - jobLoader.reload(factory); - assertEquals(1, jobRegistry.getJobNames().size()); - assertStepExist(TEST_JOB_NAME, TEST_STEP_NAME); - } + @Test + public void testReloadWithAutoRegister() throws Exception { + GenericApplicationContextFactory factory = new GenericApplicationContextFactory( + new ClassPathResource("trivial-context-autoregister.xml", getClass())); + jobLoader.load(factory); + assertEquals(1, jobRegistry.getJobNames().size()); + assertStepExist(TEST_JOB_NAME, TEST_STEP_NAME); + jobLoader.reload(factory); + assertEquals(1, jobRegistry.getJobNames().size()); + assertStepExist(TEST_JOB_NAME, TEST_STEP_NAME); + } - protected void assertStepExist(String jobName, String... stepNames) { - for (String stepName : stepNames) { - try { - stepRegistry.getStep(jobName, stepName); - } catch (NoSuchJobException e) { - fail("Job with name [" + jobName + "] should have been found."); - } catch (NoSuchStepException e) { - fail("Step with name [" + stepName + "] for job [" + jobName + "] should have been found."); - } - } - } + protected void assertStepExist(String jobName, String... stepNames) { + for (String stepName : stepNames) { + try { + stepRegistry.getStep(jobName, stepName); + } + catch (NoSuchJobException e) { + fail("Job with name [" + jobName + "] should have been found."); + } + catch (NoSuchStepException e) { + fail("Step with name [" + stepName + "] for job [" + jobName + "] should have been found."); + } + } + } - protected void assertStepDoNotExist(String jobName, String... stepNames) { - for (String stepName : stepNames) { - try { - final Step step = stepRegistry.getStep(jobName, stepName); - fail("Step with name [" + stepName + "] for job [" + jobName + "] should " + - "not have been found but got [" + step + "]"); - } catch (NoSuchJobException e) { - fail("Job with name [" + jobName + "] should have been found."); - } catch (NoSuchStepException e) { - // OK - } - } - } + protected void assertStepDoNotExist(String jobName, String... stepNames) { + for (String stepName : stepNames) { + try { + final Step step = stepRegistry.getStep(jobName, stepName); + fail("Step with name [" + stepName + "] for job [" + jobName + "] should " + + "not have been found but got [" + step + "]"); + } + catch (NoSuchJobException e) { + fail("Job with name [" + jobName + "] should have been found."); + } + catch (NoSuchStepException e) { + // OK + } + } + } - private static final String BASIC_JOB_XML = String - .format( - "", - DefaultJobLoaderTests.class.getName()); + private static final String BASIC_JOB_XML = String.format( + "", + DefaultJobLoaderTests.class.getName()); - private static final String JOB_XML = String - .format( - "", - DefaultJobLoaderTests.class.getName()); + private static final String JOB_XML = String.format( + "", + DefaultJobLoaderTests.class.getName()); - public static class BasicStubJob implements Job { + public static class BasicStubJob implements Job { - @Override + @Override public void execute(JobExecution execution) { - } + } - @Nullable + @Nullable @Override public JobParametersIncrementer getJobParametersIncrementer() { - return null; - } + return null; + } - @Override + @Override public String getName() { - return "job"; - } + return "job"; + } - @Override + @Override public boolean isRestartable() { - return false; - } + return false; + } - @Override + @Override public JobParametersValidator getJobParametersValidator() { - return null; - } - } + return null; + } - public static class StubJob extends BasicStubJob implements StepLocator { + } - @Override + public static class StubJob extends BasicStubJob implements StepLocator { + + @Override public Collection getStepNames() { - return Collections.emptyList(); - } + return Collections.emptyList(); + } @Override public Step getStep(String stepName) throws NoSuchStepException { - throw new NoSuchStepException("Step [" + stepName + "] does not exist"); - } - } + throw new NoSuchStepException("Step [" + stepName + "] does not exist"); + } + + } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/GenericApplicationContextFactoryTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/GenericApplicationContextFactoryTests.java index 961294fd5..d9da01b88 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/GenericApplicationContextFactoryTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/GenericApplicationContextFactoryTests.java @@ -45,7 +45,7 @@ import org.springframework.util.ClassUtils; /** * @author Dave Syer * @author Mahmoud Ben Hassine - * + * */ public class GenericApplicationContextFactoryTests { @@ -71,8 +71,8 @@ public class GenericApplicationContextFactoryTests { public void testParentConfigurationInherited() { GenericApplicationContextFactory factory = new GenericApplicationContextFactory( new ClassPathResource(ClassUtils.addResourcePathToPackagePath(getClass(), "child-context.xml"))); - factory.setApplicationContext(new ClassPathXmlApplicationContext(ClassUtils.addResourcePathToPackagePath( - getClass(), "parent-context.xml"))); + factory.setApplicationContext(new ClassPathXmlApplicationContext( + ClassUtils.addResourcePathToPackagePath(getClass(), "parent-context.xml"))); ConfigurableApplicationContext context = factory.createApplicationContext(); assertEquals("test-job", context.getBeanNamesForType(Job.class)[0]); assertEquals("bar", context.getBean("test-job", Job.class).getName()); @@ -84,21 +84,22 @@ public class GenericApplicationContextFactoryTests { public void testBeanFactoryPostProcessorOrderRespected() { GenericApplicationContextFactory factory = new GenericApplicationContextFactory( new ClassPathResource(ClassUtils.addResourcePathToPackagePath(getClass(), "placeholder-context.xml"))); - factory.setApplicationContext(new ClassPathXmlApplicationContext(ClassUtils.addResourcePathToPackagePath( - getClass(), "parent-context.xml"))); + factory.setApplicationContext(new ClassPathXmlApplicationContext( + ClassUtils.addResourcePathToPackagePath(getClass(), "parent-context.xml"))); ConfigurableApplicationContext context = factory.createApplicationContext(); assertEquals("test-job", context.getBeanNamesForType(Job.class)[0]); assertEquals("spam", context.getBean("test-job", Job.class).getName()); } @Test - @Ignore // FIXME replacing PropertyPlaceholderConfigurer with PropertySourcesPlaceholderConfigurer does not seem to inherit profiles + @Ignore // FIXME replacing PropertyPlaceholderConfigurer with + // PropertySourcesPlaceholderConfigurer does not seem to inherit profiles public void testBeanFactoryProfileRespected() { GenericApplicationContextFactory factory = new GenericApplicationContextFactory( new ClassPathResource(ClassUtils.addResourcePathToPackagePath(getClass(), "profiles.xml"))); @SuppressWarnings("resource") - ClassPathXmlApplicationContext parentContext = new ClassPathXmlApplicationContext(ClassUtils.addResourcePathToPackagePath( - getClass(), "parent-context.xml")); + ClassPathXmlApplicationContext parentContext = new ClassPathXmlApplicationContext( + ClassUtils.addResourcePathToPackagePath(getClass(), "parent-context.xml")); parentContext.getEnvironment().setActiveProfiles("preferred"); factory.setApplicationContext(parentContext); @SuppressWarnings("resource") @@ -112,8 +113,8 @@ public class GenericApplicationContextFactoryTests { public void testBeanFactoryPostProcessorsNotCopied() { GenericApplicationContextFactory factory = new GenericApplicationContextFactory( new ClassPathResource(ClassUtils.addResourcePathToPackagePath(getClass(), "child-context.xml"))); - factory.setApplicationContext(new ClassPathXmlApplicationContext(ClassUtils.addResourcePathToPackagePath( - getClass(), "parent-context.xml"))); + factory.setApplicationContext(new ClassPathXmlApplicationContext( + ClassUtils.addResourcePathToPackagePath(getClass(), "parent-context.xml"))); @SuppressWarnings("unchecked") Class[] classes = (Class[]) new Class[0]; factory.setBeanFactoryPostProcessorClasses(classes); @@ -126,10 +127,10 @@ public class GenericApplicationContextFactoryTests { @SuppressWarnings("resource") @Test public void testBeanFactoryConfigurationNotCopied() { - GenericApplicationContextFactory factory = new GenericApplicationContextFactory(new ClassPathResource(ClassUtils.addResourcePathToPackagePath(getClass(), - "child-context.xml"))); - factory.setApplicationContext(new ClassPathXmlApplicationContext(ClassUtils.addResourcePathToPackagePath( - getClass(), "parent-context.xml"))); + GenericApplicationContextFactory factory = new GenericApplicationContextFactory( + new ClassPathResource(ClassUtils.addResourcePathToPackagePath(getClass(), "child-context.xml"))); + factory.setApplicationContext(new ClassPathXmlApplicationContext( + ClassUtils.addResourcePathToPackagePath(getClass(), "parent-context.xml"))); factory.setCopyConfiguration(false); ConfigurableApplicationContext context = factory.createApplicationContext(); assertEquals("test-job", context.getBeanNamesForType(Job.class)[0]); @@ -141,20 +142,20 @@ public class GenericApplicationContextFactoryTests { @Test public void testEquals() throws Exception { - Resource resource = new ClassPathResource(ClassUtils.addResourcePathToPackagePath(getClass(), - "child-context.xml")); + Resource resource = new ClassPathResource( + ClassUtils.addResourcePathToPackagePath(getClass(), "child-context.xml")); GenericApplicationContextFactory factory = new GenericApplicationContextFactory(resource); GenericApplicationContextFactory other = new GenericApplicationContextFactory(resource); assertEquals(other, factory); assertEquals(other.hashCode(), factory.hashCode()); } - + @Test public void testEqualsMultipleConfigs() throws Exception { - Resource resource1 = new ClassPathResource(ClassUtils.addResourcePathToPackagePath(getClass(), - "abstract-context.xml")); - Resource resource2 = new ClassPathResource(ClassUtils.addResourcePathToPackagePath(getClass(), - "child-context-with-abstract-job.xml")); + Resource resource1 = new ClassPathResource( + ClassUtils.addResourcePathToPackagePath(getClass(), "abstract-context.xml")); + Resource resource2 = new ClassPathResource( + ClassUtils.addResourcePathToPackagePath(getClass(), "child-context-with-abstract-job.xml")); GenericApplicationContextFactory factory = new GenericApplicationContextFactory(resource1, resource2); GenericApplicationContextFactory other = new GenericApplicationContextFactory(resource1, resource2); assertEquals(other, factory); @@ -163,10 +164,10 @@ public class GenericApplicationContextFactoryTests { @Test public void testParentConfigurationInheritedMultipleConfigs() { - Resource resource1 = new ClassPathResource(ClassUtils.addResourcePathToPackagePath(getClass(), - "abstract-context.xml")); - Resource resource2 = new ClassPathResource(ClassUtils.addResourcePathToPackagePath(getClass(), - "child-context-with-abstract-job.xml")); + Resource resource1 = new ClassPathResource( + ClassUtils.addResourcePathToPackagePath(getClass(), "abstract-context.xml")); + Resource resource2 = new ClassPathResource( + ClassUtils.addResourcePathToPackagePath(getClass(), "child-context-with-abstract-job.xml")); GenericApplicationContextFactory factory = new GenericApplicationContextFactory(resource1, resource2); ConfigurableApplicationContext context = factory.createApplicationContext(); assertEquals("concrete-job", context.getBeanNamesForType(Job.class)[0]); @@ -175,7 +176,8 @@ public class GenericApplicationContextFactoryTests { assertNotNull(context.getBean("concrete-job", JobSupport.class).getStep("step31")); assertNotNull(context.getBean("concrete-job", JobSupport.class).getStep("step32")); boolean autowiredFound = false; - for (BeanPostProcessor postProcessor : ((AbstractBeanFactory) context.getBeanFactory()).getBeanPostProcessors()) { + for (BeanPostProcessor postProcessor : ((AbstractBeanFactory) context.getBeanFactory()) + .getBeanPostProcessors()) { if (postProcessor instanceof AutowiredAnnotationBeanPostProcessor) { autowiredFound = true; } @@ -185,15 +187,17 @@ public class GenericApplicationContextFactoryTests { @Test(expected = IllegalArgumentException.class) public void testDifferentResourceTypes() throws Exception { - Resource resource1 = new ClassPathResource(ClassUtils.addResourcePathToPackagePath(getClass(), - "abstract-context.xml")); - GenericApplicationContextFactory factory = new GenericApplicationContextFactory(resource1, Configuration1.class); + Resource resource1 = new ClassPathResource( + ClassUtils.addResourcePathToPackagePath(getClass(), "abstract-context.xml")); + GenericApplicationContextFactory factory = new GenericApplicationContextFactory(resource1, + Configuration1.class); factory.createApplicationContext(); } @Test public void testPackageScanning() throws Exception { - GenericApplicationContextFactory factory = new GenericApplicationContextFactory("org.springframework.batch.core.configuration.support"); + GenericApplicationContextFactory factory = new GenericApplicationContextFactory( + "org.springframework.batch.core.configuration.support"); ConfigurableApplicationContext context = factory.createApplicationContext(); assertEquals(context.getBean("bean1"), "bean1"); @@ -204,7 +208,8 @@ public class GenericApplicationContextFactoryTests { @Test public void testMultipleConfigurationClasses() throws Exception { - GenericApplicationContextFactory factory = new GenericApplicationContextFactory(Configuration1.class, Configuration2.class); + GenericApplicationContextFactory factory = new GenericApplicationContextFactory(Configuration1.class, + Configuration2.class); ConfigurableApplicationContext context = factory.createApplicationContext(); assertEquals(context.getBean("bean1"), "bean1"); @@ -224,18 +229,19 @@ public class GenericApplicationContextFactoryTests { assertEquals(1, bean.counter2); } - - public static class Foo { + private double[] values; public void setValues(double[] values) { this.values = values; } + } @Configuration public static class Configuration1 { + @Bean public String bean1() { return "bean1"; @@ -245,10 +251,12 @@ public class GenericApplicationContextFactoryTests { public String bean2() { return "bean2"; } + } @Configuration public static class Configuration2 { + @Bean public String bean3() { return "bean3"; @@ -258,22 +266,26 @@ public class GenericApplicationContextFactoryTests { public String bean4() { return "bean4"; } + } @Configuration public static class ParentContext implements ApplicationContextAware { + @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { } + } - @Configuration - public static class ChildContextConfiguration { + public static class ChildContextConfiguration { + @Bean public ChildBean childBean() { return new ChildBean(); } + } public static class ChildBean implements ApplicationContextAware, EnvironmentAware { @@ -291,7 +303,7 @@ public class GenericApplicationContextFactoryTests { public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { counter1++; } + } - } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/GroupAwareJobTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/GroupAwareJobTests.java index e68f183b3..113489511 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/GroupAwareJobTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/GroupAwareJobTests.java @@ -23,7 +23,7 @@ import org.springframework.batch.core.job.JobSupport; /** * @author Dave Syer - * + * */ public class GroupAwareJobTests { @@ -46,4 +46,5 @@ public class GroupAwareJobTests { GroupAwareJob result = new GroupAwareJob("jobs", job); assertEquals("JobSupport: [name=jobs.foo]", result.toString()); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/JobRegistryIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/JobRegistryIntegrationTests.java index b1285f448..05368b8fc 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/JobRegistryIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/JobRegistryIntegrationTests.java @@ -27,7 +27,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * @author Dave Syer - * + * */ @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) @@ -35,7 +35,7 @@ public class JobRegistryIntegrationTests { @Autowired private JobRegistry jobRegistry; - + @Autowired private Job job; @@ -44,5 +44,5 @@ public class JobRegistryIntegrationTests { assertEquals(1, jobRegistry.getJobNames().size()); assertEquals(job.getName(), jobRegistry.getJobNames().iterator().next()); } - + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/MapJobRegistryTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/MapJobRegistryTests.java index 4921c32db..2fc3affa0 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/MapJobRegistryTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/MapJobRegistryTests.java @@ -29,12 +29,13 @@ import org.springframework.batch.core.launch.NoSuchJobException; * */ public class MapJobRegistryTests extends TestCase { - + private MapJobRegistry registry = new MapJobRegistry(); /** - * Test method for {@link org.springframework.batch.core.configuration.support.MapJobRegistry#unregister(String)}. - * @throws Exception + * Test method for + * {@link org.springframework.batch.core.configuration.support.MapJobRegistry#unregister(String)}. + * @throws Exception */ public void testUnregister() throws Exception { registry.register(new ReferenceJobFactory(new JobSupport("foo"))); @@ -46,26 +47,29 @@ public class MapJobRegistryTests extends TestCase { } catch (NoSuchJobException e) { // expected - assertTrue(e.getMessage().indexOf("foo")>=0); + assertTrue(e.getMessage().indexOf("foo") >= 0); } } /** - * Test method for {@link org.springframework.batch.core.configuration.support.MapJobRegistry#getJob(java.lang.String)}. + * Test method for + * {@link org.springframework.batch.core.configuration.support.MapJobRegistry#getJob(java.lang.String)}. */ public void testReplaceDuplicateConfiguration() throws Exception { registry.register(new ReferenceJobFactory(new JobSupport("foo"))); try { registry.register(new ReferenceJobFactory(new JobSupport("foo"))); fail("Expected DuplicateJobConfigurationException"); - } catch (DuplicateJobException e) { + } + catch (DuplicateJobException e) { // unexpected: even if the job is different we want a DuplicateJobException - assertTrue(e.getMessage().indexOf("foo")>=0); + assertTrue(e.getMessage().indexOf("foo") >= 0); } } /** - * Test method for {@link org.springframework.batch.core.configuration.support.MapJobRegistry#getJob(java.lang.String)}. + * Test method for + * {@link org.springframework.batch.core.configuration.support.MapJobRegistry#getJob(java.lang.String)}. */ public void testRealDuplicateConfiguration() throws Exception { JobFactory jobFactory = new ReferenceJobFactory(new JobSupport("foo")); @@ -73,15 +77,17 @@ public class MapJobRegistryTests extends TestCase { try { registry.register(jobFactory); fail("Unexpected DuplicateJobConfigurationException"); - } catch (DuplicateJobException e) { + } + catch (DuplicateJobException e) { // expected - assertTrue(e.getMessage().indexOf("foo")>=0); + assertTrue(e.getMessage().indexOf("foo") >= 0); } } /** - * Test method for {@link org.springframework.batch.core.configuration.support.MapJobRegistry#getJobNames()}. - * @throws Exception + * Test method for + * {@link org.springframework.batch.core.configuration.support.MapJobRegistry#getJobNames()}. + * @throws Exception */ public void testGetJobConfigurations() throws Exception { JobFactory jobFactory = new ReferenceJobFactory(new JobSupport("foo")); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/MapStepRegistryTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/MapStepRegistryTests.java index 16c9e8dbd..f812945ff 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/MapStepRegistryTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/MapStepRegistryTests.java @@ -35,221 +35,211 @@ import org.springframework.batch.core.step.tasklet.TaskletStep; */ public class MapStepRegistryTests { - private static final String EXCEPTION_NOT_THROWN_MSG = "An exception should have been thrown"; + private static final String EXCEPTION_NOT_THROWN_MSG = "An exception should have been thrown"; - @Test - public void registerStepEmptyCollection() throws DuplicateJobException { - final StepRegistry stepRegistry = createRegistry(); + @Test + public void registerStepEmptyCollection() throws DuplicateJobException { + final StepRegistry stepRegistry = createRegistry(); - launchRegisterGetRegistered(stepRegistry, "myJob", getStepCollection()); - } + launchRegisterGetRegistered(stepRegistry, "myJob", getStepCollection()); + } - @Test - public void registerStepNullJobName() throws DuplicateJobException { - final StepRegistry stepRegistry = createRegistry(); + @Test + public void registerStepNullJobName() throws DuplicateJobException { + final StepRegistry stepRegistry = createRegistry(); - try { - stepRegistry.register(null, new HashSet<>()); - Assert.fail(EXCEPTION_NOT_THROWN_MSG); - } catch (IllegalArgumentException e) { - } - } + try { + stepRegistry.register(null, new HashSet<>()); + Assert.fail(EXCEPTION_NOT_THROWN_MSG); + } + catch (IllegalArgumentException e) { + } + } - @Test - public void registerStepNullSteps() throws DuplicateJobException { - final StepRegistry stepRegistry = createRegistry(); + @Test + public void registerStepNullSteps() throws DuplicateJobException { + final StepRegistry stepRegistry = createRegistry(); - try { - stepRegistry.register("fdsfsd", null); - Assert.fail(EXCEPTION_NOT_THROWN_MSG); - } catch (IllegalArgumentException e) { - } - } + try { + stepRegistry.register("fdsfsd", null); + Assert.fail(EXCEPTION_NOT_THROWN_MSG); + } + catch (IllegalArgumentException e) { + } + } - @Test - public void registerStepGetStep() throws DuplicateJobException { - final StepRegistry stepRegistry = createRegistry(); + @Test + public void registerStepGetStep() throws DuplicateJobException { + final StepRegistry stepRegistry = createRegistry(); - launchRegisterGetRegistered(stepRegistry, "myJob", - getStepCollection( - createStep("myStep"), - createStep("myOtherStep"), - createStep("myThirdStep") - )); - } + launchRegisterGetRegistered(stepRegistry, "myJob", + getStepCollection(createStep("myStep"), createStep("myOtherStep"), createStep("myThirdStep"))); + } - @Test - public void getJobNotRegistered() throws DuplicateJobException { - final StepRegistry stepRegistry = createRegistry(); + @Test + public void getJobNotRegistered() throws DuplicateJobException { + final StepRegistry stepRegistry = createRegistry(); - final String aStepName = "myStep"; - launchRegisterGetRegistered(stepRegistry, "myJob", - getStepCollection( - createStep(aStepName), - createStep("myOtherStep"), - createStep("myThirdStep") - )); + final String aStepName = "myStep"; + launchRegisterGetRegistered(stepRegistry, "myJob", + getStepCollection(createStep(aStepName), createStep("myOtherStep"), createStep("myThirdStep"))); - assertJobNotRegistered(stepRegistry, "a ghost"); - } + assertJobNotRegistered(stepRegistry, "a ghost"); + } - @Test - public void getJobNotRegisteredNoRegistration() { - final StepRegistry stepRegistry = createRegistry(); + @Test + public void getJobNotRegisteredNoRegistration() { + final StepRegistry stepRegistry = createRegistry(); - assertJobNotRegistered(stepRegistry, "a ghost"); - } + assertJobNotRegistered(stepRegistry, "a ghost"); + } - @Test - public void getStepNotRegistered() throws DuplicateJobException { - final StepRegistry stepRegistry = createRegistry(); + @Test + public void getStepNotRegistered() throws DuplicateJobException { + final StepRegistry stepRegistry = createRegistry(); - final String jobName = "myJob"; - launchRegisterGetRegistered(stepRegistry, jobName, - getStepCollection( - createStep("myStep"), - createStep("myOtherStep"), - createStep("myThirdStep") - )); + final String jobName = "myJob"; + launchRegisterGetRegistered(stepRegistry, jobName, + getStepCollection(createStep("myStep"), createStep("myOtherStep"), createStep("myThirdStep"))); - assertStepNameNotRegistered(stepRegistry, jobName, "fsdfsdfsdfsd"); - } + assertStepNameNotRegistered(stepRegistry, jobName, "fsdfsdfsdfsd"); + } - @Test - public void registerTwice() throws DuplicateJobException { - final StepRegistry stepRegistry = createRegistry(); + @Test + public void registerTwice() throws DuplicateJobException { + final StepRegistry stepRegistry = createRegistry(); - final String jobName = "myJob"; - final Collection stepsFirstRegistration = getStepCollection( - createStep("myStep"), - createStep("myOtherStep"), - createStep("myThirdStep") - ); + final String jobName = "myJob"; + final Collection stepsFirstRegistration = getStepCollection(createStep("myStep"), + createStep("myOtherStep"), createStep("myThirdStep")); - // first registration - launchRegisterGetRegistered(stepRegistry, jobName, stepsFirstRegistration); + // first registration + launchRegisterGetRegistered(stepRegistry, jobName, stepsFirstRegistration); + // Second registration with same name should fail + try { + stepRegistry.register(jobName, getStepCollection(createStep("myFourthStep"), createStep("lastOne"))); + fail("Should have failed with a " + DuplicateJobException.class.getSimpleName()); + } + catch (DuplicateJobException e) { + // OK + } + } - // Second registration with same name should fail - try { - stepRegistry.register(jobName, getStepCollection( - createStep("myFourthStep"), - createStep("lastOne"))); - fail("Should have failed with a "+DuplicateJobException.class.getSimpleName()); - } catch (DuplicateJobException e) { - // OK - } - } + @Test + public void getStepNullJobName() throws NoSuchJobException { + final StepRegistry stepRegistry = createRegistry(); - @Test - public void getStepNullJobName() throws NoSuchJobException { - final StepRegistry stepRegistry = createRegistry(); + try { + stepRegistry.getStep(null, "a step"); + Assert.fail(EXCEPTION_NOT_THROWN_MSG); + } + catch (IllegalArgumentException e) { + } + } - try { - stepRegistry.getStep(null, "a step"); - Assert.fail(EXCEPTION_NOT_THROWN_MSG); - } catch (IllegalArgumentException e) { - } - } + @Test + public void getStepNullStepName() throws NoSuchJobException, DuplicateJobException { + final StepRegistry stepRegistry = createRegistry(); - @Test - public void getStepNullStepName() throws NoSuchJobException, DuplicateJobException { - final StepRegistry stepRegistry = createRegistry(); + final String stepName = "myStep"; + launchRegisterGetRegistered(stepRegistry, "myJob", getStepCollection(createStep(stepName))); - final String stepName = "myStep"; - launchRegisterGetRegistered(stepRegistry, "myJob", getStepCollection(createStep(stepName))); + try { + stepRegistry.getStep(null, stepName); + Assert.fail(EXCEPTION_NOT_THROWN_MSG); + } + catch (IllegalArgumentException e) { + } + } - try { - stepRegistry.getStep(null, stepName); - Assert.fail(EXCEPTION_NOT_THROWN_MSG); - } catch (IllegalArgumentException e) { - } - } + @Test + public void registerStepUnregisterJob() throws DuplicateJobException { + final StepRegistry stepRegistry = createRegistry(); - @Test - public void registerStepUnregisterJob() throws DuplicateJobException { - final StepRegistry stepRegistry = createRegistry(); + final Collection steps = getStepCollection(createStep("myStep"), createStep("myOtherStep"), + createStep("myThirdStep")); - final Collection steps = getStepCollection( - createStep("myStep"), - createStep("myOtherStep"), - createStep("myThirdStep") - ); + final String jobName = "myJob"; + launchRegisterGetRegistered(stepRegistry, jobName, steps); - final String jobName = "myJob"; - launchRegisterGetRegistered(stepRegistry, jobName, steps); + stepRegistry.unregisterStepsFromJob(jobName); + assertJobNotRegistered(stepRegistry, jobName); + } - stepRegistry.unregisterStepsFromJob(jobName); - assertJobNotRegistered(stepRegistry, jobName); - } + @Test + public void unregisterJobNameNull() { + final StepRegistry stepRegistry = createRegistry(); - @Test - public void unregisterJobNameNull() { - final StepRegistry stepRegistry = createRegistry(); + try { + stepRegistry.unregisterStepsFromJob(null); + Assert.fail(EXCEPTION_NOT_THROWN_MSG); + } + catch (IllegalArgumentException e) { + } + } - try { - stepRegistry.unregisterStepsFromJob(null); - Assert.fail(EXCEPTION_NOT_THROWN_MSG); - } catch (IllegalArgumentException e) { - } - } + @Test + public void unregisterNoRegistration() { + final StepRegistry stepRegistry = createRegistry(); - @Test - public void unregisterNoRegistration() { - final StepRegistry stepRegistry = createRegistry(); + assertJobNotRegistered(stepRegistry, "a job"); + } - assertJobNotRegistered(stepRegistry, "a job"); - } + protected StepRegistry createRegistry() { + return new MapStepRegistry(); + } - protected StepRegistry createRegistry() { - return new MapStepRegistry(); - } + protected Step createStep(String stepName) { + return new TaskletStep(stepName); + } - protected Step createStep(String stepName) { - return new TaskletStep(stepName); - } + protected Collection getStepCollection(Step... steps) { + return Arrays.asList(steps); + } - protected Collection getStepCollection(Step... steps) { - return Arrays.asList(steps); - } + protected void launchRegisterGetRegistered(StepRegistry stepRegistry, String jobName, Collection steps) + throws DuplicateJobException { + stepRegistry.register(jobName, steps); + assertStepsRegistered(stepRegistry, jobName, steps); + } - protected void launchRegisterGetRegistered(StepRegistry stepRegistry, String jobName, Collection steps) - throws DuplicateJobException { - stepRegistry.register(jobName, steps); - assertStepsRegistered(stepRegistry, jobName, steps); - } + protected void assertJobNotRegistered(StepRegistry stepRegistry, String jobName) { + try { + stepRegistry.getStep(jobName, "a step"); + Assert.fail(EXCEPTION_NOT_THROWN_MSG); + } + catch (NoSuchJobException e) { + } + } - protected void assertJobNotRegistered(StepRegistry stepRegistry, String jobName) { - try { - stepRegistry.getStep(jobName, "a step"); - Assert.fail(EXCEPTION_NOT_THROWN_MSG); - } catch (NoSuchJobException e) { - } - } + protected void assertStepsRegistered(StepRegistry stepRegistry, String jobName, Collection steps) { + for (Step step : steps) { + try { + stepRegistry.getStep(jobName, step.getName()); + } + catch (NoSuchJobException e) { + Assert.fail("Unexpected exception " + e); + } + } + } - protected void assertStepsRegistered(StepRegistry stepRegistry, String jobName, Collection steps) { - for (Step step : steps) { - try { - stepRegistry.getStep(jobName, step.getName()); - } catch (NoSuchJobException e) { - Assert.fail("Unexpected exception " + e); - } - } - } + protected void assertStepsNotRegistered(StepRegistry stepRegistry, String jobName, Collection steps) { + for (Step step : steps) { + assertStepNameNotRegistered(stepRegistry, jobName, step.getName()); + } + } - protected void assertStepsNotRegistered(StepRegistry stepRegistry, String jobName, Collection steps) { - for (Step step : steps) { - assertStepNameNotRegistered(stepRegistry, jobName, step.getName()); - } - } + protected void assertStepNameNotRegistered(StepRegistry stepRegistry, String jobName, String stepName) { + try { + stepRegistry.getStep(jobName, stepName); + Assert.fail(EXCEPTION_NOT_THROWN_MSG); + } + catch (NoSuchJobException e) { + Assert.fail("Unexpected exception"); + } + catch (NoSuchStepException e) { + } + } - protected void assertStepNameNotRegistered(StepRegistry stepRegistry, String jobName, String stepName) { - try { - stepRegistry.getStep(jobName, stepName); - Assert.fail(EXCEPTION_NOT_THROWN_MSG); - } catch (NoSuchJobException e) { - Assert.fail("Unexpected exception"); - } catch (NoSuchStepException e) { - } - } } \ No newline at end of file diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/ReferenceJobFactoryTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/ReferenceJobFactoryTests.java index 88bfeefaf..bee25289e 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/ReferenceJobFactoryTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/ReferenceJobFactoryTests.java @@ -25,7 +25,7 @@ import org.springframework.batch.core.job.JobSupport; * */ public class ReferenceJobFactoryTests { - + @Test public void testGroupName() throws Exception { ReferenceJobFactory factory = new ReferenceJobFactory(new JobSupport("foo")); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/AbstractJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/AbstractJobParserTests.java index 0869f4a96..bd9510f5d 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/AbstractJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/AbstractJobParserTests.java @@ -55,9 +55,10 @@ public abstract class AbstractJobParserTests { /** * @return JobExecution */ - protected JobExecution createJobExecution() throws JobInstanceAlreadyCompleteException, JobRestartException, - JobExecutionAlreadyRunningException { - return jobRepository.createJobExecution(job.getName(), new JobParametersBuilder().addLong("key1", 1L).toJobParameters()); + protected JobExecution createJobExecution() + throws JobInstanceAlreadyCompleteException, JobRestartException, JobExecutionAlreadyRunningException { + return jobRepository.createJobExecution(job.getName(), + new JobParametersBuilder().addLong("key1", 1L).toJobParameters()); } protected StepExecution getStepExecution(JobExecution jobExecution, String stepName) { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/AutoRegisteringJobScopeTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/AutoRegisteringJobScopeTests.java index c8b334491..ffd360cf5 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/AutoRegisteringJobScopeTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/AutoRegisteringJobScopeTests.java @@ -24,7 +24,6 @@ import org.springframework.batch.core.scope.JobScope; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; - /** * @author Thomas Risberg * @author Jimmy Praet @@ -34,9 +33,8 @@ public class AutoRegisteringJobScopeTests { @Test @SuppressWarnings("resource") public void testJobElement() throws Exception { - ConfigurableApplicationContext ctx = - new ClassPathXmlApplicationContext( - "org/springframework/batch/core/configuration/xml/AutoRegisteringJobScopeForJobElementTests-context.xml"); + ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext( + "org/springframework/batch/core/configuration/xml/AutoRegisteringJobScopeForJobElementTests-context.xml"); Map beans = ctx.getBeansOfType(JobScope.class); assertTrue("JobScope not defined properly", beans.size() == 1); } @@ -44,9 +42,8 @@ public class AutoRegisteringJobScopeTests { @Test @SuppressWarnings("resource") public void testStepElement() throws Exception { - ConfigurableApplicationContext ctx = - new ClassPathXmlApplicationContext( - "org/springframework/batch/core/configuration/xml/AutoRegisteringJobScopeForStepElementTests-context.xml"); + ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext( + "org/springframework/batch/core/configuration/xml/AutoRegisteringJobScopeForStepElementTests-context.xml"); Map beans = ctx.getBeansOfType(JobScope.class); assertTrue("JobScope not defined properly", beans.size() == 1); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/AutoRegisteringStepScopeTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/AutoRegisteringStepScopeTests.java index 8fcf60c25..015a9ee2d 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/AutoRegisteringStepScopeTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/AutoRegisteringStepScopeTests.java @@ -24,17 +24,16 @@ import java.util.Map; import static org.junit.Assert.assertTrue; - /** * @author Thomas Risberg */ public class AutoRegisteringStepScopeTests { - + @Test @SuppressWarnings("resource") public void testJobElement() throws Exception { - ConfigurableApplicationContext ctx = - new ClassPathXmlApplicationContext("org/springframework/batch/core/configuration/xml/AutoRegisteringStepScopeForJobElementTests-context.xml"); + ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext( + "org/springframework/batch/core/configuration/xml/AutoRegisteringStepScopeForJobElementTests-context.xml"); Map beans = ctx.getBeansOfType(StepScope.class); assertTrue("StepScope not defined properly", beans.size() == 1); } @@ -42,8 +41,8 @@ public class AutoRegisteringStepScopeTests { @Test @SuppressWarnings("resource") public void testStepElement() throws Exception { - ConfigurableApplicationContext ctx = - new ClassPathXmlApplicationContext("org/springframework/batch/core/configuration/xml/AutoRegisteringStepScopeForStepElementTests-context.xml"); + ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext( + "org/springframework/batch/core/configuration/xml/AutoRegisteringStepScopeForStepElementTests-context.xml"); Map beans = ctx.getBeansOfType(StepScope.class); assertTrue("StepScope not defined properly", beans.size() == 1); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/BeanDefinitionOverrideTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/BeanDefinitionOverrideTests.java index fc2292279..93e724de3 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/BeanDefinitionOverrideTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/BeanDefinitionOverrideTests.java @@ -24,10 +24,12 @@ import org.springframework.context.support.ClassPathXmlApplicationContext; *

      */ public class BeanDefinitionOverrideTests { + @Test public void testAllowBeanOverride() { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(); - applicationContext.setConfigLocation("org/springframework/batch/core/configuration/xml/BeanDefinitionOverrideTests-context.xml"); + applicationContext.setConfigLocation( + "org/springframework/batch/core/configuration/xml/BeanDefinitionOverrideTests-context.xml"); applicationContext.refresh(); } @@ -35,7 +37,9 @@ public class BeanDefinitionOverrideTests { public void testAllowBeanOverrideFalse() { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(); applicationContext.setAllowBeanDefinitionOverriding(false); - applicationContext.setConfigLocation("org/springframework/batch/core/configuration/xml/BeanDefinitionOverrideTests-context.xml"); + applicationContext.setConfigLocation( + "org/springframework/batch/core/configuration/xml/BeanDefinitionOverrideTests-context.xml"); applicationContext.refresh(); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/ChunkElementParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/ChunkElementParserTests.java index 9386ad7d8..d28c86368 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/ChunkElementParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/ChunkElementParserTests.java @@ -93,11 +93,12 @@ public class ChunkElementParserTests { public void testIllegalSkipAndRetryAttributes() throws Exception { try { ConfigurableApplicationContext context = new ClassPathXmlApplicationContext( - "org/springframework/batch/core/configuration/xml/ChunkElementIllegalSkipAndRetryAttributeParserTests-context.xml"); - Step step = context.getBean("s1", Step.class); - assertNotNull("Step not parsed", step); - fail("Expected BeanCreationException"); - } catch (BeanCreationException e) { + "org/springframework/batch/core/configuration/xml/ChunkElementIllegalSkipAndRetryAttributeParserTests-context.xml"); + Step step = context.getBean("s1", Step.class); + assertNotNull("Step not parsed", step); + fail("Expected BeanCreationException"); + } + catch (BeanCreationException e) { // expected } } @@ -180,8 +181,8 @@ public class ChunkElementParserTests { } catch (BeanCreationException e) { String msg = e.getMessage(); - assertTrue("Wrong message: " + msg, msg - .contains("The field 'processor-transactional' cannot be false if 'reader-transactional")); + assertTrue("Wrong message: " + msg, + msg.contains("The field 'processor-transactional' cannot be false if 'reader-transactional")); } } @@ -295,8 +296,7 @@ public class ChunkElementParserTests { "skippableExceptionClassifier"); } - private SkipPolicy getSkipPolicy(String stepName, - ApplicationContext ctx) throws Exception { + private SkipPolicy getSkipPolicy(String stepName, ApplicationContext ctx) throws Exception { return (SkipPolicy) getNestedPathInStep(stepName, ctx, "tasklet.chunkProvider.skipPolicy"); } @@ -358,8 +358,8 @@ public class ChunkElementParserTests { return object; } - private void containsClassified(Map, Boolean> classified, - Class cls, boolean include) { + private void containsClassified(Map, Boolean> classified, Class cls, + boolean include) { assertTrue(classified.containsKey(cls)); assertEquals(include, classified.get(cls)); } @@ -396,4 +396,5 @@ public class ChunkElementParserTests { return new ClassPathXmlApplicationContext( "org/springframework/batch/core/configuration/xml/ChunkElementParentAttributeParserTests-context.xml"); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DecisionJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DecisionJobParserTests.java index 70bab1020..bdb2cba7e 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DecisionJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DecisionJobParserTests.java @@ -59,10 +59,12 @@ public class DecisionJobParserTests { } public static class TestDecider implements JobExecutionDecider { + @Override public FlowExecutionStatus decide(JobExecution jobExecution, @Nullable StepExecution stepExecution) { return new FlowExecutionStatus("FOO"); } + } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DefaultFailureJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DefaultFailureJobParserTests.java index 9a9770ac0..42477f6db 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DefaultFailureJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DefaultFailureJobParserTests.java @@ -1,60 +1,60 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.configuration.xml; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.StepExecution; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -/** - * @author Dan Garrette - * @since 2.0 - */ -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -public class DefaultFailureJobParserTests extends AbstractJobParserTests { - - @Test - public void testDefaultFailure() throws Exception { - - JobExecution jobExecution = createJobExecution(); - job.execute(jobExecution); - assertEquals(2, stepNamesList.size()); - assertTrue(stepNamesList.contains("s1")); - assertTrue(stepNamesList.contains("fail")); - - assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); - assertEquals(ExitStatus.FAILED.getExitCode(), jobExecution.getExitStatus().getExitCode()); - - StepExecution stepExecution1 = getStepExecution(jobExecution, "s1"); - assertEquals(BatchStatus.COMPLETED, stepExecution1.getStatus()); - assertEquals(ExitStatus.COMPLETED, stepExecution1.getExitStatus()); - - StepExecution stepExecution2 = getStepExecution(jobExecution, "fail"); - assertEquals(BatchStatus.FAILED, stepExecution2.getStatus()); - assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution2.getExitStatus().getExitCode()); - - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.configuration.xml; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.StepExecution; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Dan Garrette + * @since 2.0 + */ +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class DefaultFailureJobParserTests extends AbstractJobParserTests { + + @Test + public void testDefaultFailure() throws Exception { + + JobExecution jobExecution = createJobExecution(); + job.execute(jobExecution); + assertEquals(2, stepNamesList.size()); + assertTrue(stepNamesList.contains("s1")); + assertTrue(stepNamesList.contains("fail")); + + assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); + assertEquals(ExitStatus.FAILED.getExitCode(), jobExecution.getExitStatus().getExitCode()); + + StepExecution stepExecution1 = getStepExecution(jobExecution, "s1"); + assertEquals(BatchStatus.COMPLETED, stepExecution1.getStatus()); + assertEquals(ExitStatus.COMPLETED, stepExecution1.getExitStatus()); + + StepExecution stepExecution2 = getStepExecution(jobExecution, "fail"); + assertEquals(BatchStatus.FAILED, stepExecution2.getStatus()); + assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution2.getExitStatus().getExitCode()); + + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DefaultSuccessJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DefaultSuccessJobParserTests.java index 74e77cfdf..07f955f91 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DefaultSuccessJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DefaultSuccessJobParserTests.java @@ -1,58 +1,58 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.configuration.xml; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.StepExecution; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -/** - * @author Dan Garrette - * @since 2.0 - */ -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -public class DefaultSuccessJobParserTests extends AbstractJobParserTests { - - @Test - public void testDefaultSuccess() throws Exception { - - JobExecution jobExecution = createJobExecution(); - job.execute(jobExecution); - assertEquals(2, stepNamesList.size()); - assertEquals("[s1, s2]", stepNamesList.toString()); - - assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); - assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus()); - - StepExecution stepExecution1 = getStepExecution(jobExecution, "s1"); - assertEquals(BatchStatus.COMPLETED, stepExecution1.getStatus()); - assertEquals(ExitStatus.COMPLETED, stepExecution1.getExitStatus()); - - StepExecution stepExecution2 = getStepExecution(jobExecution, "s2"); - assertEquals(BatchStatus.COMPLETED, stepExecution2.getStatus()); - assertEquals(ExitStatus.COMPLETED, stepExecution2.getExitStatus()); - - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.configuration.xml; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.StepExecution; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Dan Garrette + * @since 2.0 + */ +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class DefaultSuccessJobParserTests extends AbstractJobParserTests { + + @Test + public void testDefaultSuccess() throws Exception { + + JobExecution jobExecution = createJobExecution(); + job.execute(jobExecution); + assertEquals(2, stepNamesList.size()); + assertEquals("[s1, s2]", stepNamesList.toString()); + + assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); + assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus()); + + StepExecution stepExecution1 = getStepExecution(jobExecution, "s1"); + assertEquals(BatchStatus.COMPLETED, stepExecution1.getStatus()); + assertEquals(ExitStatus.COMPLETED, stepExecution1.getExitStatus()); + + StepExecution stepExecution2 = getStepExecution(jobExecution, "s2"); + assertEquals(BatchStatus.COMPLETED, stepExecution2.getStatus()); + assertEquals(ExitStatus.COMPLETED, stepExecution2.getExitStatus()); + + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DefaultUnknownJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DefaultUnknownJobParserTests.java index 505bb5a62..18c099229 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DefaultUnknownJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DefaultUnknownJobParserTests.java @@ -1,70 +1,72 @@ -/* - * Copyright 2006-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.configuration.xml; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.StepExecutionListener; -import org.springframework.lang.Nullable; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -/** - * @author Dan Garrette - * @author Mahmoud Ben Hassine - * @since 2.0 - */ -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -public class DefaultUnknownJobParserTests extends AbstractJobParserTests { - - @Test - public void testDefaultUnknown() throws Exception { - - JobExecution jobExecution = createJobExecution(); - job.execute(jobExecution); - assertEquals(2, stepNamesList.size()); - assertEquals("[s1, unknown]", stepNamesList.toString()); - - assertEquals(BatchStatus.UNKNOWN, jobExecution.getStatus()); - assertEquals(ExitStatus.UNKNOWN, jobExecution.getExitStatus()); - - StepExecution stepExecution1 = getStepExecution(jobExecution, "s1"); - assertEquals(BatchStatus.COMPLETED, stepExecution1.getStatus()); - assertEquals(ExitStatus.COMPLETED, stepExecution1.getExitStatus()); - - StepExecution stepExecution2 = getStepExecution(jobExecution, "unknown"); - assertEquals(BatchStatus.UNKNOWN, stepExecution2.getStatus()); - assertEquals(ExitStatus.UNKNOWN, stepExecution2.getExitStatus()); - - } - - public static class UnknownListener implements StepExecutionListener { - @Nullable - @Override - public ExitStatus afterStep(StepExecution stepExecution) { - stepExecution.setStatus(BatchStatus.UNKNOWN); - return ExitStatus.UNKNOWN; - } - } - -} +/* + * Copyright 2006-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.configuration.xml; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.StepExecutionListener; +import org.springframework.lang.Nullable; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Dan Garrette + * @author Mahmoud Ben Hassine + * @since 2.0 + */ +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class DefaultUnknownJobParserTests extends AbstractJobParserTests { + + @Test + public void testDefaultUnknown() throws Exception { + + JobExecution jobExecution = createJobExecution(); + job.execute(jobExecution); + assertEquals(2, stepNamesList.size()); + assertEquals("[s1, unknown]", stepNamesList.toString()); + + assertEquals(BatchStatus.UNKNOWN, jobExecution.getStatus()); + assertEquals(ExitStatus.UNKNOWN, jobExecution.getExitStatus()); + + StepExecution stepExecution1 = getStepExecution(jobExecution, "s1"); + assertEquals(BatchStatus.COMPLETED, stepExecution1.getStatus()); + assertEquals(ExitStatus.COMPLETED, stepExecution1.getExitStatus()); + + StepExecution stepExecution2 = getStepExecution(jobExecution, "unknown"); + assertEquals(BatchStatus.UNKNOWN, stepExecution2.getStatus()); + assertEquals(ExitStatus.UNKNOWN, stepExecution2.getExitStatus()); + + } + + public static class UnknownListener implements StepExecutionListener { + + @Nullable + @Override + public ExitStatus afterStep(StepExecution stepExecution) { + stepExecution.setStatus(BatchStatus.UNKNOWN); + return ExitStatus.UNKNOWN; + } + + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyChunkListener.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyChunkListener.java index 90000e5d3..88dc42869 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyChunkListener.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyChunkListener.java @@ -21,4 +21,5 @@ import org.springframework.batch.core.ChunkListener; * @author Mahmoud Ben Hassine */ public class DummyChunkListener implements ChunkListener { + } \ No newline at end of file diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyItemHandlerAdapter.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyItemHandlerAdapter.java index a0c3887f4..34f8ad2ea 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyItemHandlerAdapter.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyItemHandlerAdapter.java @@ -1,35 +1,35 @@ -/* - * Copyright 2009 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.configuration.xml; - -/** - * @author Dan Garrette - * @since 2.1 - */ -public class DummyItemHandlerAdapter { - - public Object dummyRead() { - return null; - } - - public Object dummyProcess(Object o) { - return null; - } - - public void dummyWrite(Object o) { - } - -} +/* + * Copyright 2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.configuration.xml; + +/** + * @author Dan Garrette + * @since 2.1 + */ +public class DummyItemHandlerAdapter { + + public Object dummyRead() { + return null; + } + + public Object dummyProcess(Object o) { + return null; + } + + public void dummyWrite(Object o) { + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyItemProcessor.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyItemProcessor.java index b36c6de45..faf7d12b4 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyItemProcessor.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyItemProcessor.java @@ -22,7 +22,7 @@ import org.springframework.lang.Nullable; * @author Dave Syer * @since 2.1 */ -public class DummyItemProcessor implements ItemProcessor { +public class DummyItemProcessor implements ItemProcessor { @Nullable @Override diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyJobExecutionListener.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyJobExecutionListener.java index 95cc024ef..81898be73 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyJobExecutionListener.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyJobExecutionListener.java @@ -21,4 +21,5 @@ import org.springframework.batch.core.JobExecutionListener; * @author Mahmoud Ben Hassine */ public class DummyJobExecutionListener implements JobExecutionListener { + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyJobRepository.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyJobRepository.java index 1883b9222..a2f9cfa2d 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyJobRepository.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyJobRepository.java @@ -1,108 +1,107 @@ -/* - * Copyright 2006-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.configuration.xml; - -import java.util.Collection; - -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobInstance; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException; -import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException; -import org.springframework.batch.core.repository.JobRepository; -import org.springframework.batch.core.repository.JobRestartException; -import org.springframework.beans.factory.BeanNameAware; -import org.springframework.lang.Nullable; - -/** - * @author Dan Garrette - * @author David Turanski - * @author Mahmoud Ben Hassine - * @since 2.0.1 - */ -public class DummyJobRepository implements JobRepository, BeanNameAware { - - private String name; - - public String getName() { - return name; - } - - @Override - public void setBeanName(String name) { - this.name = name; - } - - @Override - public void add(StepExecution stepExecution) { - } - - @Override - public JobExecution createJobExecution(String jobName, JobParameters jobParameters) - throws JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException { - return null; - } - - @Nullable - @Override - public JobExecution getLastJobExecution(String jobName, JobParameters jobParameters) { - return null; - } - - @Nullable - @Override - public StepExecution getLastStepExecution(JobInstance jobInstance, String stepName) { - return null; - } - - @Override - public int getStepExecutionCount(JobInstance jobInstance, String stepName) { - return 0; - } - - @Override - public boolean isJobInstanceExists(String jobName, JobParameters jobParameters) { - return false; - } - - @Override - public void update(JobExecution jobExecution) { - } - - @Override - public void update(StepExecution stepExecution) { - } - - @Override - public void updateExecutionContext(StepExecution stepExecution) { - } - - @Override - public void updateExecutionContext(JobExecution jobExecution) { - } - - @Override - public void addAll(Collection stepExecutions) { - } - - @Override - public JobInstance createJobInstance(String jobName, - JobParameters jobParameters) { - return null; - } - -} +/* + * Copyright 2006-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.configuration.xml; + +import java.util.Collection; + +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobInstance; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException; +import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.core.repository.JobRestartException; +import org.springframework.beans.factory.BeanNameAware; +import org.springframework.lang.Nullable; + +/** + * @author Dan Garrette + * @author David Turanski + * @author Mahmoud Ben Hassine + * @since 2.0.1 + */ +public class DummyJobRepository implements JobRepository, BeanNameAware { + + private String name; + + public String getName() { + return name; + } + + @Override + public void setBeanName(String name) { + this.name = name; + } + + @Override + public void add(StepExecution stepExecution) { + } + + @Override + public JobExecution createJobExecution(String jobName, JobParameters jobParameters) + throws JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException { + return null; + } + + @Nullable + @Override + public JobExecution getLastJobExecution(String jobName, JobParameters jobParameters) { + return null; + } + + @Nullable + @Override + public StepExecution getLastStepExecution(JobInstance jobInstance, String stepName) { + return null; + } + + @Override + public int getStepExecutionCount(JobInstance jobInstance, String stepName) { + return 0; + } + + @Override + public boolean isJobInstanceExists(String jobName, JobParameters jobParameters) { + return false; + } + + @Override + public void update(JobExecution jobExecution) { + } + + @Override + public void update(StepExecution stepExecution) { + } + + @Override + public void updateExecutionContext(StepExecution stepExecution) { + } + + @Override + public void updateExecutionContext(JobExecution jobExecution) { + } + + @Override + public void addAll(Collection stepExecutions) { + } + + @Override + public JobInstance createJobInstance(String jobName, JobParameters jobParameters) { + return null; + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyPlatformTransactionManager.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyPlatformTransactionManager.java index 7abe4530c..f1b423c08 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyPlatformTransactionManager.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyPlatformTransactionManager.java @@ -1,53 +1,54 @@ -/* - * Copyright 2006-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.configuration.xml; - -import org.springframework.beans.factory.BeanNameAware; -import org.springframework.transaction.PlatformTransactionManager; -import org.springframework.transaction.TransactionDefinition; -import org.springframework.transaction.TransactionException; -import org.springframework.transaction.TransactionStatus; - -/** - * @author Dan Garrette - * @since 2.0.1 - */ -public class DummyPlatformTransactionManager implements PlatformTransactionManager, BeanNameAware { - - private String name; - - public String getName() { - return name; - } - - @Override - public void setBeanName(String name) { - this.name = name; - } - - @Override - public void commit(TransactionStatus status) throws TransactionException { - } - - @Override - public void rollback(TransactionStatus status) throws TransactionException { - } - - @Override - public TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException { - return null; - } -} +/* + * Copyright 2006-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.configuration.xml; + +import org.springframework.beans.factory.BeanNameAware; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.TransactionDefinition; +import org.springframework.transaction.TransactionException; +import org.springframework.transaction.TransactionStatus; + +/** + * @author Dan Garrette + * @since 2.0.1 + */ +public class DummyPlatformTransactionManager implements PlatformTransactionManager, BeanNameAware { + + private String name; + + public String getName() { + return name; + } + + @Override + public void setBeanName(String name) { + this.name = name; + } + + @Override + public void commit(TransactionStatus status) throws TransactionException { + } + + @Override + public void rollback(TransactionStatus status) throws TransactionException { + } + + @Override + public TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException { + return null; + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyPojoStepExecutionListener.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyPojoStepExecutionListener.java index 0caf866e7..4bcc635b7 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyPojoStepExecutionListener.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyPojoStepExecutionListener.java @@ -15,7 +15,6 @@ */ package org.springframework.batch.core.configuration.xml; - /** * @author Dave Syer * @since 2.1.2 diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyRetryListener.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyRetryListener.java index 80dc4c04d..b2be498d6 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyRetryListener.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyRetryListener.java @@ -31,11 +31,13 @@ public class DummyRetryListener implements RetryListener { } @Override - public void close(RetryContext context, RetryCallback callback, Throwable throwable) { + public void close(RetryContext context, RetryCallback callback, + Throwable throwable) { } @Override - public void onError(RetryContext context, RetryCallback callback, Throwable throwable) { + public void onError(RetryContext context, RetryCallback callback, + Throwable throwable) { } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyStep.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyStep.java index 4b2c36b68..cfa2222f7 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyStep.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyStep.java @@ -1,55 +1,56 @@ -/* - * Copyright 2006-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.configuration.xml; - -import org.springframework.batch.core.JobInterruptedException; -import org.springframework.batch.core.Step; -import org.springframework.batch.core.StepExecution; -import org.springframework.beans.factory.BeanNameAware; - -/** - * @author Dan Garrette - * @since 2.0.1 - */ -public class DummyStep implements Step, BeanNameAware { - - private String name; - - @Override - public String getName() { - return name; - } - - @Override - public void setBeanName(String name) { - this.name = name; - } - - @Override - public void execute(StepExecution stepExecution) throws JobInterruptedException { - System.out.println("EXECUTING " + getName()); - } - - @Override - public int getStartLimit() { - return 100; - } - - @Override - public boolean isAllowStartIfComplete() { - return false; - } -} +/* + * Copyright 2006-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.configuration.xml; + +import org.springframework.batch.core.JobInterruptedException; +import org.springframework.batch.core.Step; +import org.springframework.batch.core.StepExecution; +import org.springframework.beans.factory.BeanNameAware; + +/** + * @author Dan Garrette + * @since 2.0.1 + */ +public class DummyStep implements Step, BeanNameAware { + + private String name; + + @Override + public String getName() { + return name; + } + + @Override + public void setBeanName(String name) { + this.name = name; + } + + @Override + public void execute(StepExecution stepExecution) throws JobInterruptedException { + System.out.println("EXECUTING " + getName()); + } + + @Override + public int getStartLimit() { + return 100; + } + + @Override + public boolean isAllowStartIfComplete() { + return false; + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyStepExecutionListener.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyStepExecutionListener.java index e543f78c5..2479d5085 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyStepExecutionListener.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DummyStepExecutionListener.java @@ -21,4 +21,5 @@ import org.springframework.batch.core.StepExecutionListener; * @author Mahmoud Ben Hassine */ public class DummyStepExecutionListener implements StepExecutionListener { + } \ No newline at end of file diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DuplicateTransitionJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DuplicateTransitionJobParserTests.java index 159b2838d..064aa3b4a 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DuplicateTransitionJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/DuplicateTransitionJobParserTests.java @@ -1,44 +1,44 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.configuration.xml; - -import org.junit.Test; -import org.springframework.beans.factory.BeanDefinitionStoreException; -import org.springframework.context.support.ClassPathXmlApplicationContext; -import org.springframework.util.ClassUtils; - -/** - * @author Dan Garrette - * @author Dave Syer - * @since 2.0 - */ -public class DuplicateTransitionJobParserTests { - - @Test(expected = BeanDefinitionStoreException.class) - @SuppressWarnings("resource") - public void testNextAttributeWithNestedElement() throws Exception { - new ClassPathXmlApplicationContext(ClassUtils.addResourcePathToPackagePath(getClass(), - "NextAttributeMultipleFinalJobParserTests-context.xml")); - } - - @Test(expected = BeanDefinitionStoreException.class) - @SuppressWarnings("resource") - public void testDuplicateTransition() throws Exception { - new ClassPathXmlApplicationContext(ClassUtils.addResourcePathToPackagePath(getClass(), - "DuplicateTransitionJobParserTests-context.xml")); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.configuration.xml; + +import org.junit.Test; +import org.springframework.beans.factory.BeanDefinitionStoreException; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.util.ClassUtils; + +/** + * @author Dan Garrette + * @author Dave Syer + * @since 2.0 + */ +public class DuplicateTransitionJobParserTests { + + @Test(expected = BeanDefinitionStoreException.class) + @SuppressWarnings("resource") + public void testNextAttributeWithNestedElement() throws Exception { + new ClassPathXmlApplicationContext(ClassUtils.addResourcePathToPackagePath(getClass(), + "NextAttributeMultipleFinalJobParserTests-context.xml")); + } + + @Test(expected = BeanDefinitionStoreException.class) + @SuppressWarnings("resource") + public void testDuplicateTransition() throws Exception { + new ClassPathXmlApplicationContext( + ClassUtils.addResourcePathToPackagePath(getClass(), "DuplicateTransitionJobParserTests-context.xml")); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/EndTransitionDefaultStatusJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/EndTransitionDefaultStatusJobParserTests.java index 2cee9723f..0e8f67847 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/EndTransitionDefaultStatusJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/EndTransitionDefaultStatusJobParserTests.java @@ -1,54 +1,55 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.configuration.xml; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.StepExecution; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -/** - * @author Dan Garrette - * @since 2.0 - */ -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -public class EndTransitionDefaultStatusJobParserTests extends AbstractJobParserTests { - - @Test - public void testEndTransitionDefaultStatus() throws Exception { - - JobExecution jobExecution = createJobExecution(); - job.execute(jobExecution); - assertEquals(1, stepNamesList.size()); - assertTrue(stepNamesList.contains("fail")); - - assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); - assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus()); - - StepExecution stepExecution1 = getStepExecution(jobExecution, "fail"); - assertEquals(BatchStatus.FAILED, stepExecution1.getStatus()); - assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution1.getExitStatus().getExitCode()); - - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.configuration.xml; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.StepExecution; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Dan Garrette + * @since 2.0 + */ +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class EndTransitionDefaultStatusJobParserTests extends AbstractJobParserTests { + + @Test + public void testEndTransitionDefaultStatus() throws Exception { + + JobExecution jobExecution = createJobExecution(); + job.execute(jobExecution); + assertEquals(1, stepNamesList.size()); + assertTrue(stepNamesList.contains("fail")); + + assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); + assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus()); + + StepExecution stepExecution1 = getStepExecution(jobExecution, "fail"); + assertEquals(BatchStatus.FAILED, stepExecution1.getStatus()); + assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution1.getExitStatus().getExitCode()); + + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/EndTransitionJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/EndTransitionJobParserTests.java index ad03e7462..d4d919086 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/EndTransitionJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/EndTransitionJobParserTests.java @@ -1,77 +1,79 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.configuration.xml; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -/** - * @author Dan Garrette - * @since 2.0 - */ -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -public class EndTransitionJobParserTests extends AbstractJobParserTests { - - @Test - public void testEndTransition() throws Exception { - - // - // First Launch - // - JobExecution jobExecution = createJobExecution(); - job.execute(jobExecution); - assertEquals(2, stepNamesList.size()); - assertTrue(stepNamesList.contains("s1")); - assertTrue(stepNamesList.contains("fail")); - - assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); - assertEquals("EARLY TERMINATION", jobExecution.getExitStatus().getExitCode()); - - StepExecution stepExecution1 = getStepExecution(jobExecution, "s1"); - assertEquals(BatchStatus.COMPLETED, stepExecution1.getStatus()); - assertEquals(ExitStatus.COMPLETED, stepExecution1.getExitStatus()); - - StepExecution stepExecution2 = getStepExecution(jobExecution, "fail"); - assertEquals(BatchStatus.FAILED, stepExecution2.getStatus()); - assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution2.getExitStatus().getExitCode()); - - // - // Second Launch - // - stepNamesList.clear(); - try { - jobExecution = createJobExecution(); - fail("JobInstanceAlreadyCompleteException expected"); - } catch (JobInstanceAlreadyCompleteException e) { - // - // Expected - // - } - - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.configuration.xml; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Dan Garrette + * @since 2.0 + */ +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class EndTransitionJobParserTests extends AbstractJobParserTests { + + @Test + public void testEndTransition() throws Exception { + + // + // First Launch + // + JobExecution jobExecution = createJobExecution(); + job.execute(jobExecution); + assertEquals(2, stepNamesList.size()); + assertTrue(stepNamesList.contains("s1")); + assertTrue(stepNamesList.contains("fail")); + + assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); + assertEquals("EARLY TERMINATION", jobExecution.getExitStatus().getExitCode()); + + StepExecution stepExecution1 = getStepExecution(jobExecution, "s1"); + assertEquals(BatchStatus.COMPLETED, stepExecution1.getStatus()); + assertEquals(ExitStatus.COMPLETED, stepExecution1.getExitStatus()); + + StepExecution stepExecution2 = getStepExecution(jobExecution, "fail"); + assertEquals(BatchStatus.FAILED, stepExecution2.getStatus()); + assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution2.getExitStatus().getExitCode()); + + // + // Second Launch + // + stepNamesList.clear(); + try { + jobExecution = createJobExecution(); + fail("JobInstanceAlreadyCompleteException expected"); + } + catch (JobInstanceAlreadyCompleteException e) { + // + // Expected + // + } + + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/FailTransitionDefaultStatusJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/FailTransitionDefaultStatusJobParserTests.java index 48fa90071..3214388d1 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/FailTransitionDefaultStatusJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/FailTransitionDefaultStatusJobParserTests.java @@ -1,55 +1,55 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.configuration.xml; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.StepExecution; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -/** - * @author Dan Garrette - * @since 2.0 - */ -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -public class FailTransitionDefaultStatusJobParserTests extends AbstractJobParserTests { - - @Test - public void testFailTransitionDefaultStatus() throws Exception { - - JobExecution jobExecution = createJobExecution(); - job.execute(jobExecution); - assertEquals(1, stepNamesList.size()); - assertTrue(stepNamesList.contains("s1")); - - assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); - assertEquals(ExitStatus.FAILED, jobExecution.getExitStatus()); - - StepExecution stepExecution1 = getStepExecution(jobExecution, "s1"); - assertEquals(BatchStatus.COMPLETED, stepExecution1.getStatus()); - assertEquals(ExitStatus.COMPLETED, stepExecution1.getExitStatus()); - - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.configuration.xml; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.StepExecution; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Dan Garrette + * @since 2.0 + */ +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class FailTransitionDefaultStatusJobParserTests extends AbstractJobParserTests { + + @Test + public void testFailTransitionDefaultStatus() throws Exception { + + JobExecution jobExecution = createJobExecution(); + job.execute(jobExecution); + assertEquals(1, stepNamesList.size()); + assertTrue(stepNamesList.contains("s1")); + + assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); + assertEquals(ExitStatus.FAILED, jobExecution.getExitStatus()); + + StepExecution stepExecution1 = getStepExecution(jobExecution, "s1"); + assertEquals(BatchStatus.COMPLETED, stepExecution1.getStatus()); + assertEquals(ExitStatus.COMPLETED, stepExecution1.getExitStatus()); + + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/FailTransitionJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/FailTransitionJobParserTests.java index d6a80fb60..f6de0552f 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/FailTransitionJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/FailTransitionJobParserTests.java @@ -1,75 +1,73 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.configuration.xml; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.StepExecution; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -/** - * @author Dan Garrette - * @since 2.0 - */ -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -public class FailTransitionJobParserTests extends AbstractJobParserTests { - - @Test - public void testFailTransition() throws Exception { - - // - // First Launch - // - JobExecution jobExecution = createJobExecution(); - job.execute(jobExecution); - assertEquals(2, stepNamesList.size()); - assertTrue(stepNamesList.contains("s1")); - assertTrue(stepNamesList.contains("fail")); - - assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); - assertEquals("EARLY TERMINATION", jobExecution.getExitStatus() - .getExitCode()); - - StepExecution stepExecution1 = getStepExecution(jobExecution, "s1"); - assertEquals(BatchStatus.COMPLETED, stepExecution1.getStatus()); - assertEquals(ExitStatus.COMPLETED, stepExecution1.getExitStatus()); - - StepExecution stepExecution2 = getStepExecution(jobExecution, "fail"); - assertEquals(BatchStatus.FAILED, stepExecution2.getStatus()); - assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution2 - .getExitStatus().getExitCode()); - - // - // Second Launch - // - stepNamesList.clear(); - jobExecution = createJobExecution(); - job.execute(jobExecution); - assertEquals(1, stepNamesList.size()); - assertTrue(stepNamesList.contains("fail")); - assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); - - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.configuration.xml; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.StepExecution; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Dan Garrette + * @since 2.0 + */ +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class FailTransitionJobParserTests extends AbstractJobParserTests { + + @Test + public void testFailTransition() throws Exception { + + // + // First Launch + // + JobExecution jobExecution = createJobExecution(); + job.execute(jobExecution); + assertEquals(2, stepNamesList.size()); + assertTrue(stepNamesList.contains("s1")); + assertTrue(stepNamesList.contains("fail")); + + assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); + assertEquals("EARLY TERMINATION", jobExecution.getExitStatus().getExitCode()); + + StepExecution stepExecution1 = getStepExecution(jobExecution, "s1"); + assertEquals(BatchStatus.COMPLETED, stepExecution1.getStatus()); + assertEquals(ExitStatus.COMPLETED, stepExecution1.getExitStatus()); + + StepExecution stepExecution2 = getStepExecution(jobExecution, "fail"); + assertEquals(BatchStatus.FAILED, stepExecution2.getStatus()); + assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution2.getExitStatus().getExitCode()); + + // + // Second Launch + // + stepNamesList.clear(); + jobExecution = createJobExecution(); + job.execute(jobExecution); + assertEquals(1, stepNamesList.size()); + assertTrue(stepNamesList.contains("fail")); + assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); + + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/FailingTasklet.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/FailingTasklet.java index cfd414039..3935809b2 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/FailingTasklet.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/FailingTasklet.java @@ -1,40 +1,40 @@ -/* - * Copyright 2006-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.configuration.xml; - -import org.springframework.batch.core.StepContribution; -import org.springframework.batch.core.scope.context.ChunkContext; -import org.springframework.batch.repeat.RepeatStatus; -import org.springframework.lang.Nullable; - -/** - * This tasklet will call - * {@link NameStoringTasklet#execute(StepContribution, ChunkContext)} and then - * throw an exception. - * - * @author Dan Garrette - * @since 2.0 - */ -public class FailingTasklet extends NameStoringTasklet { - - @Nullable - @Override - public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { - super.execute(contribution, chunkContext); - throw new RuntimeException(); - } - -} +/* + * Copyright 2006-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.configuration.xml; + +import org.springframework.batch.core.StepContribution; +import org.springframework.batch.core.scope.context.ChunkContext; +import org.springframework.batch.repeat.RepeatStatus; +import org.springframework.lang.Nullable; + +/** + * This tasklet will call + * {@link NameStoringTasklet#execute(StepContribution, ChunkContext)} and then throw an + * exception. + * + * @author Dan Garrette + * @since 2.0 + */ +public class FailingTasklet extends NameStoringTasklet { + + @Nullable + @Override + public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { + super.execute(contribution, chunkContext); + throw new RuntimeException(); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/FlowJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/FlowJobParserTests.java index 90711e18d..01e16fbb8 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/FlowJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/FlowJobParserTests.java @@ -34,7 +34,6 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - /** * @author Dave Syer * @author Mahmoud Ben Hassine @@ -43,7 +42,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) public class FlowJobParserTests { - + @Autowired @Qualifier("job1") private Job job1; diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/FlowStepParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/FlowStepParserTests.java index 591b49626..c86fb2c5d 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/FlowStepParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/FlowStepParserTests.java @@ -138,4 +138,5 @@ public class FlowStepParserTests { } } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/InlineItemHandlerParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/InlineItemHandlerParserTests.java index b24ee8a29..858d06fa6 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/InlineItemHandlerParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/InlineItemHandlerParserTests.java @@ -1,112 +1,112 @@ -/* - * Copyright 2009-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.configuration.xml; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.util.Map; - -import org.junit.After; -import org.junit.Test; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.scope.context.StepSynchronizationManager; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.adapter.ItemProcessorAdapter; -import org.springframework.batch.item.adapter.ItemReaderAdapter; -import org.springframework.batch.item.adapter.ItemWriterAdapter; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.support.ClassPathXmlApplicationContext; -import org.springframework.test.util.ReflectionTestUtils; - -/** - * @author Dan Garrette - * @since 2.1 - */ -public class InlineItemHandlerParserTests { - - private ConfigurableApplicationContext context; - - @After - public void close() { - if (context != null) { - context.close(); - } - StepSynchronizationManager.release(); - } - - @Test - public void testInlineHandlers() throws Exception { - context = new ClassPathXmlApplicationContext( - "org/springframework/batch/core/configuration/xml/InlineItemHandlerParserTests-context.xml"); - Object step = context.getBean("inlineHandlers"); - Object tasklet = ReflectionTestUtils.getField(step, "tasklet"); - Object chunkProvider = ReflectionTestUtils.getField(tasklet, "chunkProvider"); - Object reader = ReflectionTestUtils.getField(chunkProvider, "itemReader"); - Object chunkProcessor = ReflectionTestUtils.getField(tasklet, "chunkProcessor"); - Object processor = ReflectionTestUtils.getField(chunkProcessor, "itemProcessor"); - Object writer = ReflectionTestUtils.getField(chunkProcessor, "itemWriter"); - - assertTrue(reader instanceof TestReader); - assertTrue(processor instanceof TestProcessor); - assertTrue(writer instanceof TestWriter); - } - - @Test - public void testInlineAdapters() throws Exception { - context = new ClassPathXmlApplicationContext( - "org/springframework/batch/core/configuration/xml/InlineItemHandlerParserTests-context.xml"); - Object step = context.getBean("inlineAdapters"); - Object tasklet = ReflectionTestUtils.getField(step, "tasklet"); - Object chunkProvider = ReflectionTestUtils.getField(tasklet, "chunkProvider"); - Object reader = ReflectionTestUtils.getField(chunkProvider, "itemReader"); - Object chunkProcessor = ReflectionTestUtils.getField(tasklet, "chunkProcessor"); - Object processor = ReflectionTestUtils.getField(chunkProcessor, "itemProcessor"); - Object writer = ReflectionTestUtils.getField(chunkProcessor, "itemWriter"); - - assertTrue(reader instanceof ItemReaderAdapter); - Object readerObject = ReflectionTestUtils.getField(reader, "targetObject"); - assertTrue(readerObject instanceof DummyItemHandlerAdapter); - Object readerMethod = ReflectionTestUtils.getField(reader, "targetMethod"); - assertEquals("dummyRead", readerMethod); - - assertTrue(processor instanceof ItemProcessorAdapter); - Object processorObject = ReflectionTestUtils.getField(processor, "targetObject"); - assertTrue(processorObject instanceof DummyItemHandlerAdapter); - Object processorMethod = ReflectionTestUtils.getField(processor, "targetMethod"); - assertEquals("dummyProcess", processorMethod); - - assertTrue(writer instanceof ItemWriterAdapter); - Object writerObject = ReflectionTestUtils.getField(writer, "targetObject"); - assertTrue(writerObject instanceof DummyItemHandlerAdapter); - Object writerMethod = ReflectionTestUtils.getField(writer, "targetMethod"); - assertEquals("dummyWrite", writerMethod); - } - - @Test - public void testInlineHandlersWithStepScope() throws Exception { - context = new ClassPathXmlApplicationContext( - "org/springframework/batch/core/configuration/xml/InlineItemHandlerWithStepScopeParserTests-context.xml"); - StepSynchronizationManager.register(new StepExecution("step", new JobExecution(123L))); - - @SuppressWarnings({ "rawtypes" }) - Map readers = context.getBeansOfType(ItemReader.class); - // Should be 2 each (proxy and target) for the two readers in the steps defined - assertEquals(4, readers.size()); - } - -} +/* + * Copyright 2009-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.configuration.xml; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Map; + +import org.junit.After; +import org.junit.Test; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.scope.context.StepSynchronizationManager; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.adapter.ItemProcessorAdapter; +import org.springframework.batch.item.adapter.ItemReaderAdapter; +import org.springframework.batch.item.adapter.ItemWriterAdapter; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.test.util.ReflectionTestUtils; + +/** + * @author Dan Garrette + * @since 2.1 + */ +public class InlineItemHandlerParserTests { + + private ConfigurableApplicationContext context; + + @After + public void close() { + if (context != null) { + context.close(); + } + StepSynchronizationManager.release(); + } + + @Test + public void testInlineHandlers() throws Exception { + context = new ClassPathXmlApplicationContext( + "org/springframework/batch/core/configuration/xml/InlineItemHandlerParserTests-context.xml"); + Object step = context.getBean("inlineHandlers"); + Object tasklet = ReflectionTestUtils.getField(step, "tasklet"); + Object chunkProvider = ReflectionTestUtils.getField(tasklet, "chunkProvider"); + Object reader = ReflectionTestUtils.getField(chunkProvider, "itemReader"); + Object chunkProcessor = ReflectionTestUtils.getField(tasklet, "chunkProcessor"); + Object processor = ReflectionTestUtils.getField(chunkProcessor, "itemProcessor"); + Object writer = ReflectionTestUtils.getField(chunkProcessor, "itemWriter"); + + assertTrue(reader instanceof TestReader); + assertTrue(processor instanceof TestProcessor); + assertTrue(writer instanceof TestWriter); + } + + @Test + public void testInlineAdapters() throws Exception { + context = new ClassPathXmlApplicationContext( + "org/springframework/batch/core/configuration/xml/InlineItemHandlerParserTests-context.xml"); + Object step = context.getBean("inlineAdapters"); + Object tasklet = ReflectionTestUtils.getField(step, "tasklet"); + Object chunkProvider = ReflectionTestUtils.getField(tasklet, "chunkProvider"); + Object reader = ReflectionTestUtils.getField(chunkProvider, "itemReader"); + Object chunkProcessor = ReflectionTestUtils.getField(tasklet, "chunkProcessor"); + Object processor = ReflectionTestUtils.getField(chunkProcessor, "itemProcessor"); + Object writer = ReflectionTestUtils.getField(chunkProcessor, "itemWriter"); + + assertTrue(reader instanceof ItemReaderAdapter); + Object readerObject = ReflectionTestUtils.getField(reader, "targetObject"); + assertTrue(readerObject instanceof DummyItemHandlerAdapter); + Object readerMethod = ReflectionTestUtils.getField(reader, "targetMethod"); + assertEquals("dummyRead", readerMethod); + + assertTrue(processor instanceof ItemProcessorAdapter); + Object processorObject = ReflectionTestUtils.getField(processor, "targetObject"); + assertTrue(processorObject instanceof DummyItemHandlerAdapter); + Object processorMethod = ReflectionTestUtils.getField(processor, "targetMethod"); + assertEquals("dummyProcess", processorMethod); + + assertTrue(writer instanceof ItemWriterAdapter); + Object writerObject = ReflectionTestUtils.getField(writer, "targetObject"); + assertTrue(writerObject instanceof DummyItemHandlerAdapter); + Object writerMethod = ReflectionTestUtils.getField(writer, "targetMethod"); + assertEquals("dummyWrite", writerMethod); + } + + @Test + public void testInlineHandlersWithStepScope() throws Exception { + context = new ClassPathXmlApplicationContext( + "org/springframework/batch/core/configuration/xml/InlineItemHandlerWithStepScopeParserTests-context.xml"); + StepSynchronizationManager.register(new StepExecution("step", new JobExecution(123L))); + + @SuppressWarnings({ "rawtypes" }) + Map readers = context.getBeansOfType(ItemReader.class); + // Should be 2 each (proxy and target) for the two readers in the steps defined + assertEquals(4, readers.size()); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/InterruptibleTasklet.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/InterruptibleTasklet.java index aac3cf570..54ad4111a 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/InterruptibleTasklet.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/InterruptibleTasklet.java @@ -1,46 +1,46 @@ -/* - * Copyright 2006-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.configuration.xml; - -import org.springframework.batch.core.StepContribution; -import org.springframework.batch.core.scope.context.ChunkContext; -import org.springframework.batch.repeat.RepeatStatus; -import org.springframework.lang.Nullable; - -/** - * This tasklet will call - * {@link NameStoringTasklet#execute(StepContribution, ChunkContext)} and then - * return CONTINUABLE, so it needs to be interrupted for it to stop. - * - * @author Dave Syer - * @since 2.0 - */ -public class InterruptibleTasklet extends NameStoringTasklet { - - private volatile boolean started = false; - - @Nullable - @Override - public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { - if (!started) { - super.execute(contribution, chunkContext); - started = true; - } - Thread.sleep(50L); - return RepeatStatus.CONTINUABLE; - } - -} +/* + * Copyright 2006-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.configuration.xml; + +import org.springframework.batch.core.StepContribution; +import org.springframework.batch.core.scope.context.ChunkContext; +import org.springframework.batch.repeat.RepeatStatus; +import org.springframework.lang.Nullable; + +/** + * This tasklet will call + * {@link NameStoringTasklet#execute(StepContribution, ChunkContext)} and then return + * CONTINUABLE, so it needs to be interrupted for it to stop. + * + * @author Dave Syer + * @since 2.0 + */ +public class InterruptibleTasklet extends NameStoringTasklet { + + private volatile boolean started = false; + + @Nullable + @Override + public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { + if (!started) { + super.execute(contribution, chunkContext); + started = true; + } + Thread.sleep(50L); + return RepeatStatus.CONTINUABLE; + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobExecutionListenerMethodAttributeParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobExecutionListenerMethodAttributeParserTests.java index ad5f59720..06814e530 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobExecutionListenerMethodAttributeParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobExecutionListenerMethodAttributeParserTests.java @@ -36,32 +36,34 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; public class JobExecutionListenerMethodAttributeParserTests { public static boolean beforeCalled = false; + public static boolean afterCalled = false; - + @Autowired Job job; - + @Autowired JobRepository jobRepository; - + @Test - public void testListeners() throws Exception{ - JobExecution jobExecution = jobRepository.createJobExecution("testJob", new JobParametersBuilder().addLong("now", - System.currentTimeMillis()).toJobParameters()); + public void testListeners() throws Exception { + JobExecution jobExecution = jobRepository.createJobExecution("testJob", + new JobParametersBuilder().addLong("now", System.currentTimeMillis()).toJobParameters()); job.execute(jobExecution); assertTrue(beforeCalled); assertTrue(afterCalled); } - - public static class TestComponent{ - - public void before(JobExecution jobExecution){ + + public static class TestComponent { + + public void before(JobExecution jobExecution) { beforeCalled = true; } - - public void after(){ + + public void after() { afterCalled = true; } + } - + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobExecutionListenerParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobExecutionListenerParserTests.java index 23971c56d..f8ee428e2 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobExecutionListenerParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobExecutionListenerParserTests.java @@ -38,34 +38,36 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; public class JobExecutionListenerParserTests { public static boolean beforeCalled = false; + public static boolean afterCalled = false; - + @Autowired Job job; - + @Autowired JobRepository jobRepository; - + @Test - public void testListeners() throws Exception{ - JobExecution jobExecution = jobRepository.createJobExecution("testJob", new JobParametersBuilder().addLong("now", - System.currentTimeMillis()).toJobParameters()); + public void testListeners() throws Exception { + JobExecution jobExecution = jobRepository.createJobExecution("testJob", + new JobParametersBuilder().addLong("now", System.currentTimeMillis()).toJobParameters()); job.execute(jobExecution); assertTrue(beforeCalled); assertTrue(afterCalled); } - - public static class TestComponent{ - + + public static class TestComponent { + @BeforeJob - public void before(JobExecution jobExecution){ + public void before(JobExecution jobExecution) { beforeCalled = true; } - - @AfterJob - public void after(){ + + @AfterJob + public void after() { afterCalled = true; } + } - + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobParserExceptionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobParserExceptionTests.java index e7ce1ac0e..1bddb0f54 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobParserExceptionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobParserExceptionTests.java @@ -24,7 +24,6 @@ import org.springframework.beans.factory.BeanDefinitionStoreException; import org.springframework.beans.factory.parsing.BeanDefinitionParsingException; import org.springframework.context.support.ClassPathXmlApplicationContext; - public class JobParserExceptionTests { @Test @@ -60,7 +59,8 @@ public class JobParserExceptionTests { } catch (BeanCreationException e) { String message = e.getMessage(); - assertTrue("Wrong message: "+message, message.matches(".*Missing state for \\[StateTransition: \\[state=.*s2, pattern=\\*, next=.*s3\\]\\]")); + assertTrue("Wrong message: " + message, message + .matches(".*Missing state for \\[StateTransition: \\[state=.*s2, pattern=\\*, next=.*s3\\]\\]")); } } @@ -73,8 +73,10 @@ public class JobParserExceptionTests { } catch (BeanDefinitionParsingException e) { String message = e.getMessage(); - assertTrue("Wrong message: "+message, message.startsWith("Configuration problem: You are using a version of the spring-batch XSD")); - } catch (BeanDefinitionStoreException e) { + assertTrue("Wrong message: " + message, + message.startsWith("Configuration problem: You are using a version of the spring-batch XSD")); + } + catch (BeanDefinitionStoreException e) { // Probably the internet is not available and the schema validation failed. fail("Wrong exception when schema didn't match: " + e.getMessage()); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobParserJobFactoryBeanTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobParserJobFactoryBeanTests.java index 404c5a6fc..ae91f2e9c 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobParserJobFactoryBeanTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobParserJobFactoryBeanTests.java @@ -19,11 +19,10 @@ import static org.junit.Assert.*; import org.junit.Test; - public class JobParserJobFactoryBeanTests { - + private JobParserJobFactoryBean factory = new JobParserJobFactoryBean("jobFactory"); - + @Test public void testSingleton() throws Exception { assertTrue("Expected singleton", factory.isSingleton()); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobParserParentAttributeTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobParserParentAttributeTests.java index 19f34c60e..93304d431 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobParserParentAttributeTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobParserParentAttributeTests.java @@ -48,24 +48,31 @@ public class JobParserParentAttributeTests { @Autowired @Qualifier("listenerClearingJob") private Job listenerClearingJob; + @Autowired @Qualifier("defaultRepoJob") private Job defaultRepoJob; + @Autowired @Qualifier("specifiedRepoJob") private Job specifiedRepoJob; + @Autowired @Qualifier("inheritSpecifiedRepoJob") private Job inheritSpecifiedRepoJob; + @Autowired @Qualifier("overrideInheritedRepoJob") private Job overrideInheritedRepoJob; + @Autowired @Qualifier("job3") private Job job3; + @Autowired @Qualifier("job2") private Job job2; + @Autowired @Qualifier("job1") private Job job1; diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobParserValidatorTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobParserValidatorTests.java index 73f936b4f..ed1e6e37d 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobParserValidatorTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobParserValidatorTests.java @@ -37,7 +37,7 @@ import org.springframework.test.util.ReflectionTestUtils; /** * @author Dave Syer - * + * */ @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) @@ -55,7 +55,7 @@ public class JobParserValidatorTests { @Qualifier("job3") private Job job3; - @Test(expected=JobParametersInvalidException.class) + @Test(expected = JobParametersInvalidException.class) public void testValidatorAttribute() throws Exception { assertNotNull(job1); JobParametersValidator validator = (JobParametersValidator) ReflectionTestUtils.getField(job1, @@ -64,7 +64,7 @@ public class JobParserValidatorTests { validator.validate(new JobParameters()); } - @Test(expected=JobParametersInvalidException.class) + @Test(expected = JobParametersInvalidException.class) public void testValidatorRef() throws Exception { assertNotNull(job2); JobParametersValidator validator = (JobParametersValidator) ReflectionTestUtils.getField(job2, @@ -73,7 +73,7 @@ public class JobParserValidatorTests { validator.validate(new JobParameters()); } - @Test(expected=JobParametersInvalidException.class) + @Test(expected = JobParametersInvalidException.class) public void testValidatorBean() throws Exception { assertNotNull(job3); JobParametersValidator validator = (JobParametersValidator) ReflectionTestUtils.getField(job3, diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobRegistryJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobRegistryJobParserTests.java index 1a6af802d..151215214 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobRegistryJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobRegistryJobParserTests.java @@ -28,7 +28,6 @@ import org.springframework.context.ApplicationContextAware; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - /** * @author Dave Syer * diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobRepositoryDefaultParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobRepositoryDefaultParserTests.java index d844e7565..6a945b65d 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobRepositoryDefaultParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobRepositoryDefaultParserTests.java @@ -25,7 +25,6 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - /** * @author Dave Syer * @@ -33,11 +32,11 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) public class JobRepositoryDefaultParserTests { - + @Autowired @Qualifier("jobRepository") private JobRepository jobRepository; - + @Test public void testOneStep() throws Exception { assertNotNull(jobRepository); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobRepositoryParserReferenceTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobRepositoryParserReferenceTests.java index 87ecfbed2..cd95693ee 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobRepositoryParserReferenceTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobRepositoryParserReferenceTests.java @@ -1,46 +1,45 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.configuration.xml; - -import static org.junit.Assert.assertNotNull; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.repository.JobRepository; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - - -/** - * @author Dave Syer - * - */ -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -public class JobRepositoryParserReferenceTests { - - @Autowired - @Qualifier("jobRepo1") - private JobRepository jobRepository; - - @Test - public void testOneStep() throws Exception { - assertNotNull(jobRepository); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.configuration.xml; + +import static org.junit.Assert.assertNotNull; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Dave Syer + * + */ +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class JobRepositoryParserReferenceTests { + + @Autowired + @Qualifier("jobRepo1") + private JobRepository jobRepository; + + @Test + public void testOneStep() throws Exception { + assertNotNull(jobRepository); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobRepositoryParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobRepositoryParserTests.java index d4dc67ec4..f0b635367 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobRepositoryParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobRepositoryParserTests.java @@ -25,7 +25,6 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - /** * @author Thomas Risberg * @@ -33,11 +32,11 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) public class JobRepositoryParserTests { - + @Autowired @Qualifier("jobRepo1") private JobRepository jobRepository; - + @Test public void testOneStep() throws Exception { assertNotNull(jobRepository); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobStepParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobStepParserTests.java index b650c4072..bdb8dcc51 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobStepParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobStepParserTests.java @@ -34,7 +34,6 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - /** * @author Dave Syer * @author Mahmoud Ben Hassine diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/NameStoringTasklet.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/NameStoringTasklet.java index a36de68ef..9299154c3 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/NameStoringTasklet.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/NameStoringTasklet.java @@ -35,6 +35,7 @@ import org.springframework.lang.Nullable; public class NameStoringTasklet implements StepExecutionListener, Tasklet { private String stepName = null; + private List stepNamesList = null; @Override diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/NamespacePrefixedJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/NamespacePrefixedJobParserTests.java index 31bbdc399..0bfe06b9e 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/NamespacePrefixedJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/NamespacePrefixedJobParserTests.java @@ -30,7 +30,6 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - /** * @author Dave Syer * @author Mahmoud Ben Hassine diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/NextAttributeJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/NextAttributeJobParserTests.java index 1ce3a3b24..2d679e8ed 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/NextAttributeJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/NextAttributeJobParserTests.java @@ -1,79 +1,79 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.configuration.xml; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.StepExecution; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -/** - * @author Dan Garrette - * @since 2.0 - */ -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -public class NextAttributeJobParserTests extends AbstractJobParserTests { - - @Test - public void testNextAttributeFailedDefault() throws Exception { - - // - // Launch 1 - // - JobExecution jobExecution = createJobExecution(); - job.execute(jobExecution); - assertEquals(2, stepNamesList.size()); //s2 is not executed - assertTrue(stepNamesList.contains("s1")); - assertTrue(stepNamesList.contains("fail")); - - assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); - assertEquals("FAILED", jobExecution.getExitStatus().getExitCode()); - - StepExecution stepExecution1 = getStepExecution(jobExecution, "s1"); - assertEquals(BatchStatus.COMPLETED, stepExecution1.getStatus()); - assertEquals(ExitStatus.COMPLETED, stepExecution1.getExitStatus()); - - StepExecution stepExecution2 = getStepExecution(jobExecution, "fail"); - assertEquals(BatchStatus.FAILED, stepExecution2.getStatus()); - assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution2.getExitStatus().getExitCode()); - - // - // Launch 2 - // - stepNamesList.clear(); - jobExecution = createJobExecution(); - job.execute(jobExecution); - assertEquals(1, stepNamesList.size()); //s1,s2 are not executed - assertTrue(stepNamesList.contains("fail")); - - assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); - assertEquals("FAILED", jobExecution.getExitStatus().getExitCode()); - - StepExecution stepExecution3 = getStepExecution(jobExecution, "fail"); - assertEquals(BatchStatus.FAILED, stepExecution3.getStatus()); - assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution3.getExitStatus().getExitCode()); - - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.configuration.xml; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.StepExecution; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Dan Garrette + * @since 2.0 + */ +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class NextAttributeJobParserTests extends AbstractJobParserTests { + + @Test + public void testNextAttributeFailedDefault() throws Exception { + + // + // Launch 1 + // + JobExecution jobExecution = createJobExecution(); + job.execute(jobExecution); + assertEquals(2, stepNamesList.size()); // s2 is not executed + assertTrue(stepNamesList.contains("s1")); + assertTrue(stepNamesList.contains("fail")); + + assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); + assertEquals("FAILED", jobExecution.getExitStatus().getExitCode()); + + StepExecution stepExecution1 = getStepExecution(jobExecution, "s1"); + assertEquals(BatchStatus.COMPLETED, stepExecution1.getStatus()); + assertEquals(ExitStatus.COMPLETED, stepExecution1.getExitStatus()); + + StepExecution stepExecution2 = getStepExecution(jobExecution, "fail"); + assertEquals(BatchStatus.FAILED, stepExecution2.getStatus()); + assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution2.getExitStatus().getExitCode()); + + // + // Launch 2 + // + stepNamesList.clear(); + jobExecution = createJobExecution(); + job.execute(jobExecution); + assertEquals(1, stepNamesList.size()); // s1,s2 are not executed + assertTrue(stepNamesList.contains("fail")); + + assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); + assertEquals("FAILED", jobExecution.getExitStatus().getExitCode()); + + StepExecution stepExecution3 = getStepExecution(jobExecution, "fail"); + assertEquals(BatchStatus.FAILED, stepExecution3.getStatus()); + assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution3.getExitStatus().getExitCode()); + + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/NextAttributeUnknownJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/NextAttributeUnknownJobParserTests.java index ebe596fd4..2d496260e 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/NextAttributeUnknownJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/NextAttributeUnknownJobParserTests.java @@ -1,70 +1,72 @@ -/* - * Copyright 2006-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.configuration.xml; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.StepExecutionListener; -import org.springframework.lang.Nullable; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -/** - * @author Dave Syer - * @author Mahmoud Ben Hassine - * @since 2.1.9 - */ -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -public class NextAttributeUnknownJobParserTests extends AbstractJobParserTests { - - @Test - public void testDefaultUnknown() throws Exception { - - JobExecution jobExecution = createJobExecution(); - job.execute(jobExecution); - assertEquals(3, stepNamesList.size()); - assertEquals("[s1, unknown, s2]", stepNamesList.toString()); - - assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); - assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus()); - - StepExecution stepExecution1 = getStepExecution(jobExecution, "s1"); - assertEquals(BatchStatus.COMPLETED, stepExecution1.getStatus()); - assertEquals(ExitStatus.COMPLETED, stepExecution1.getExitStatus()); - - StepExecution stepExecution2 = getStepExecution(jobExecution, "unknown"); - assertEquals(BatchStatus.UNKNOWN, stepExecution2.getStatus()); - assertEquals(ExitStatus.UNKNOWN, stepExecution2.getExitStatus()); - - } - - public static class UnknownListener implements StepExecutionListener { - @Nullable - @Override - public ExitStatus afterStep(StepExecution stepExecution) { - stepExecution.setStatus(BatchStatus.UNKNOWN); - return ExitStatus.UNKNOWN; - } - } - -} +/* + * Copyright 2006-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.configuration.xml; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.StepExecutionListener; +import org.springframework.lang.Nullable; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Dave Syer + * @author Mahmoud Ben Hassine + * @since 2.1.9 + */ +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class NextAttributeUnknownJobParserTests extends AbstractJobParserTests { + + @Test + public void testDefaultUnknown() throws Exception { + + JobExecution jobExecution = createJobExecution(); + job.execute(jobExecution); + assertEquals(3, stepNamesList.size()); + assertEquals("[s1, unknown, s2]", stepNamesList.toString()); + + assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); + assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus()); + + StepExecution stepExecution1 = getStepExecution(jobExecution, "s1"); + assertEquals(BatchStatus.COMPLETED, stepExecution1.getStatus()); + assertEquals(ExitStatus.COMPLETED, stepExecution1.getExitStatus()); + + StepExecution stepExecution2 = getStepExecution(jobExecution, "unknown"); + assertEquals(BatchStatus.UNKNOWN, stepExecution2.getStatus()); + assertEquals(ExitStatus.UNKNOWN, stepExecution2.getExitStatus()); + + } + + public static class UnknownListener implements StepExecutionListener { + + @Nullable + @Override + public ExitStatus afterStep(StepExecution stepExecution) { + stepExecution.setStatus(BatchStatus.UNKNOWN); + return ExitStatus.UNKNOWN; + } + + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/NoopTasklet.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/NoopTasklet.java index 2d6682c9f..25e37694e 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/NoopTasklet.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/NoopTasklet.java @@ -23,11 +23,12 @@ import org.springframework.lang.Nullable; public class NoopTasklet extends NameStoringTasklet { - @Nullable + @Nullable @Override - public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { - super.execute(contribution, chunkContext); - contribution.setExitStatus(ExitStatus.NOOP); - return RepeatStatus.FINISHED; - } + public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { + super.execute(contribution, chunkContext); + contribution.setExitStatus(ExitStatus.NOOP); + return RepeatStatus.FINISHED; + } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/OneStepJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/OneStepJobParserTests.java index cc8a396a5..0d38be1af 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/OneStepJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/OneStepJobParserTests.java @@ -30,7 +30,6 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - /** * @author Dave Syer * @@ -38,14 +37,14 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) public class OneStepJobParserTests { - + @Autowired @Qualifier("job") private Job job; @Autowired private JobRepository jobRepository; - + @Test public void testOneStep() throws Exception { assertNotNull(job); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/PartitionStepParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/PartitionStepParserTests.java index df171f6ac..fa0ef1318 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/PartitionStepParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/PartitionStepParserTests.java @@ -109,7 +109,6 @@ public class PartitionStepParserTests implements ApplicationContextAware { return val; } - @Test public void testDefaultHandlerStep() throws Exception { assertNotNull(job1); @@ -138,9 +137,9 @@ public class PartitionStepParserTests implements ApplicationContextAware { } /** - * BATCH-1509 we now support the ability define steps inline for partitioned - * steps. this demonstrates that the execution proceeds as expected and that - * the partition handler has a reference to the inline step definition + * BATCH-1509 we now support the ability define steps inline for partitioned steps. + * this demonstrates that the execution proceeds as expected and that the partition + * handler has a reference to the inline step definition */ @Test public void testNestedPartitionStepStepReference() throws Throwable { @@ -166,16 +165,20 @@ public class PartitionStepParserTests implements ApplicationContextAware { } assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); Collections.sort(savedStepNames); - assertEquals("[j3s1:partition0, j3s1:partition1, j3s1:partition2, j3s1:partition3, j3s1:partition4, j3s1:partition5]", savedStepNames.toString()); + assertEquals( + "[j3s1:partition0, j3s1:partition1, j3s1:partition2, j3s1:partition3, j3s1:partition4, j3s1:partition5]", + savedStepNames.toString()); List stepNames = getStepNames(jobExecution); assertEquals(7, stepNames.size()); - assertEquals("[j3s1, j3s1:partition0, j3s1:partition1, j3s1:partition2, j3s1:partition3, j3s1:partition4, j3s1:partition5]", stepNames.toString()); + assertEquals( + "[j3s1, j3s1:partition0, j3s1:partition1, j3s1:partition2, j3s1:partition3, j3s1:partition4, j3s1:partition5]", + stepNames.toString()); } /** - * BATCH-1509 we now support the ability define steps inline for partitioned - * steps. this demonstrates that the execution proceeds as expected and that - * the partition handler has a reference to the inline step definition + * BATCH-1509 we now support the ability define steps inline for partitioned steps. + * this demonstrates that the execution proceeds as expected and that the partition + * handler has a reference to the inline step definition */ @Test public void testNestedPartitionStep() throws Throwable { @@ -205,7 +208,9 @@ public class PartitionStepParserTests implements ApplicationContextAware { assertEquals("[]", savedStepNames.toString()); List stepNames = getStepNames(jobExecution); assertEquals(7, stepNames.size()); - assertEquals("[j4s1, j4s1:partition0, j4s1:partition1, j4s1:partition2, j4s1:partition3, j4s1:partition4, j4s1:partition5]", stepNames.toString()); + assertEquals( + "[j4s1, j4s1:partition0, j4s1:partition1, j4s1:partition2, j4s1:partition3, j4s1:partition4, j4s1:partition5]", + stepNames.toString()); } @Test @@ -246,4 +251,5 @@ public class PartitionStepParserTests implements ApplicationContextAware { } } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/PartitionStepWithFlowParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/PartitionStepWithFlowParserTests.java index c9b3ff1cf..88b2eaffc 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/PartitionStepWithFlowParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/PartitionStepWithFlowParserTests.java @@ -69,15 +69,17 @@ public class PartitionStepWithFlowParserTests { @Test public void testRepeatedFlowStep() throws Exception { assertNotNull(job1); - JobExecution jobExecution = jobRepository.createJobExecution(job1.getName(), new JobParametersBuilder() - .addLong("gridSize", 1L).toJobParameters()); + JobExecution jobExecution = jobRepository.createJobExecution(job1.getName(), + new JobParametersBuilder().addLong("gridSize", 1L).toJobParameters()); job1.execute(jobExecution); assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); Collections.sort(savedStepNames); assertEquals("[s2, s2, s2, s2, s3, s3, s3, s3]", savedStepNames.toString()); List stepNames = getStepNames(jobExecution); assertEquals(14, stepNames.size()); - assertEquals("[s1, s1, s1:partition0, s1:partition0, s1:partition1, s1:partition1, s2, s2, s2, s2, s3, s3, s3, s3]", stepNames.toString()); + assertEquals( + "[s1, s1, s1:partition0, s1:partition0, s1:partition1, s1:partition1, s2, s2, s2, s2, s3, s3, s3, s3]", + stepNames.toString()); } private List getStepNames(JobExecution jobExecution) { @@ -92,9 +94,10 @@ public class PartitionStepWithFlowParserTests { public static class Decider implements JobExecutionDecider { int count = 0; + @Override public FlowExecutionStatus decide(JobExecution jobExecution, @Nullable StepExecution stepExecution) { - if (count++<2) { + if (count++ < 2) { return new FlowExecutionStatus("OK"); } return new FlowExecutionStatus("END"); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/PartitionStepWithLateBindingParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/PartitionStepWithLateBindingParserTests.java index 659cfb402..c964bae2c 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/PartitionStepWithLateBindingParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/PartitionStepWithLateBindingParserTests.java @@ -66,8 +66,8 @@ public class PartitionStepWithLateBindingParserTests { @Test public void testExplicitHandlerStep() throws Exception { assertNotNull(job1); - JobExecution jobExecution = jobRepository.createJobExecution(job1.getName(), new JobParametersBuilder() - .addLong("gridSize", 1L).toJobParameters()); + JobExecution jobExecution = jobRepository.createJobExecution(job1.getName(), + new JobParametersBuilder().addLong("gridSize", 1L).toJobParameters()); job1.execute(jobExecution); assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); Collections.sort(savedStepNames); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/PartitionStepWithNonDefaultTransactionManagerParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/PartitionStepWithNonDefaultTransactionManagerParserTests.java index f5484d26b..454d256bf 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/PartitionStepWithNonDefaultTransactionManagerParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/PartitionStepWithNonDefaultTransactionManagerParserTests.java @@ -29,7 +29,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - /** * @author Dave Syer * @author Mahmoud Ben Hassine @@ -38,7 +37,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) public class PartitionStepWithNonDefaultTransactionManagerParserTests { - + @Autowired private Job job; @@ -53,5 +52,4 @@ public class PartitionStepWithNonDefaultTransactionManagerParserTests { assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); } - } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/RepositoryJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/RepositoryJobParserTests.java index 561ff07de..f4526f906 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/RepositoryJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/RepositoryJobParserTests.java @@ -30,7 +30,6 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - /** * @author Dave Syer * @@ -38,14 +37,14 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) public class RepositoryJobParserTests { - + @Autowired @Qualifier("job") private Job job; @Autowired private JobRepository jobRepository; - + @Test public void testTaskletStepWithBadListener() throws Exception { assertNotNull(job); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/SplitDifferentResultsFailFirstJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/SplitDifferentResultsFailFirstJobParserTests.java index 06c346557..c04ebb49b 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/SplitDifferentResultsFailFirstJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/SplitDifferentResultsFailFirstJobParserTests.java @@ -1,58 +1,58 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.configuration.xml; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.StepExecution; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -/** - * @author Dan Garrette - * @since 2.0 - */ -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -public class SplitDifferentResultsFailFirstJobParserTests extends AbstractJobParserTests { - - @Test - public void testSplitDifferentResultsFailFirst() throws Exception { - - JobExecution jobExecution = createJobExecution(); - job.execute(jobExecution); - assertEquals(2, stepNamesList.size()); - assertEquals("Wrong step names: "+stepNamesList, "[fail, s1]", stepNamesList.toString()); - - assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); - assertEquals(ExitStatus.FAILED, jobExecution.getExitStatus()); - - StepExecution stepExecution1 = getStepExecution(jobExecution, "s1"); - assertEquals(BatchStatus.COMPLETED, stepExecution1.getStatus()); - assertEquals(ExitStatus.COMPLETED, stepExecution1.getExitStatus()); - - StepExecution stepExecution2 = getStepExecution(jobExecution, "fail"); - assertEquals(BatchStatus.FAILED, stepExecution2.getStatus()); - assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution2.getExitStatus().getExitCode()); - - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.configuration.xml; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.StepExecution; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Dan Garrette + * @since 2.0 + */ +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class SplitDifferentResultsFailFirstJobParserTests extends AbstractJobParserTests { + + @Test + public void testSplitDifferentResultsFailFirst() throws Exception { + + JobExecution jobExecution = createJobExecution(); + job.execute(jobExecution); + assertEquals(2, stepNamesList.size()); + assertEquals("Wrong step names: " + stepNamesList, "[fail, s1]", stepNamesList.toString()); + + assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); + assertEquals(ExitStatus.FAILED, jobExecution.getExitStatus()); + + StepExecution stepExecution1 = getStepExecution(jobExecution, "s1"); + assertEquals(BatchStatus.COMPLETED, stepExecution1.getStatus()); + assertEquals(ExitStatus.COMPLETED, stepExecution1.getExitStatus()); + + StepExecution stepExecution2 = getStepExecution(jobExecution, "fail"); + assertEquals(BatchStatus.FAILED, stepExecution2.getStatus()); + assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution2.getExitStatus().getExitCode()); + + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/SplitDifferentResultsFailSecondJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/SplitDifferentResultsFailSecondJobParserTests.java index d684bf2a3..c66a86949 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/SplitDifferentResultsFailSecondJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/SplitDifferentResultsFailSecondJobParserTests.java @@ -1,66 +1,66 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.configuration.xml; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.StepExecution; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -/** - * @author Dan Garrette - * @since 2.0 - */ -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -public class SplitDifferentResultsFailSecondJobParserTests extends AbstractJobParserTests { - - @Test - public void testSplitDifferentResultsFailSecond() throws Exception { - - JobExecution jobExecution = createJobExecution(); - job.execute(jobExecution); - assertEquals("Wrong step names: "+stepNamesList, 3, stepNamesList.size()); - assertTrue("Wrong step names: "+stepNamesList, stepNamesList.contains("s1")); - assertTrue("Wrong step names: "+stepNamesList, stepNamesList.contains("fail")); - assertTrue(stepNamesList.contains("s3")); - - assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); - // You can't suppress a FAILED exit status - assertEquals(ExitStatus.FAILED, jobExecution.getExitStatus()); - - StepExecution stepExecution1 = getStepExecution(jobExecution, "s1"); - assertEquals(BatchStatus.COMPLETED, stepExecution1.getStatus()); - assertEquals(ExitStatus.COMPLETED, stepExecution1.getExitStatus()); - - StepExecution stepExecution2 = getStepExecution(jobExecution, "fail"); - assertEquals(BatchStatus.FAILED, stepExecution2.getStatus()); - assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution2.getExitStatus().getExitCode()); - - StepExecution stepExecution3 = getStepExecution(jobExecution, "s3"); - assertEquals(BatchStatus.COMPLETED, stepExecution3.getStatus()); - assertEquals(ExitStatus.COMPLETED, stepExecution3.getExitStatus()); - - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.configuration.xml; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.StepExecution; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Dan Garrette + * @since 2.0 + */ +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class SplitDifferentResultsFailSecondJobParserTests extends AbstractJobParserTests { + + @Test + public void testSplitDifferentResultsFailSecond() throws Exception { + + JobExecution jobExecution = createJobExecution(); + job.execute(jobExecution); + assertEquals("Wrong step names: " + stepNamesList, 3, stepNamesList.size()); + assertTrue("Wrong step names: " + stepNamesList, stepNamesList.contains("s1")); + assertTrue("Wrong step names: " + stepNamesList, stepNamesList.contains("fail")); + assertTrue(stepNamesList.contains("s3")); + + assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); + // You can't suppress a FAILED exit status + assertEquals(ExitStatus.FAILED, jobExecution.getExitStatus()); + + StepExecution stepExecution1 = getStepExecution(jobExecution, "s1"); + assertEquals(BatchStatus.COMPLETED, stepExecution1.getStatus()); + assertEquals(ExitStatus.COMPLETED, stepExecution1.getExitStatus()); + + StepExecution stepExecution2 = getStepExecution(jobExecution, "fail"); + assertEquals(BatchStatus.FAILED, stepExecution2.getStatus()); + assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution2.getExitStatus().getExitCode()); + + StepExecution stepExecution3 = getStepExecution(jobExecution, "s3"); + assertEquals(BatchStatus.COMPLETED, stepExecution3.getStatus()); + assertEquals(ExitStatus.COMPLETED, stepExecution3.getExitStatus()); + + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/SplitInterruptedJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/SplitInterruptedJobParserTests.java index 8a144b247..6ba4adea6 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/SplitInterruptedJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/SplitInterruptedJobParserTests.java @@ -1,71 +1,71 @@ -/* - * Copyright 2006-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.configuration.xml; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.StepExecution; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -/** - * @author Dave Syer - * @since 2.0 - */ -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -public class SplitInterruptedJobParserTests extends AbstractJobParserTests { - - @Test - public void testSplitInterrupted() throws Exception { - - final JobExecution jobExecution = createJobExecution(); - new Thread(new Runnable() { - @Override - public void run() { - job.execute(jobExecution); - } - }).start(); - - Thread.sleep(100L); - jobExecution.setStatus(BatchStatus.STOPPING); - Thread.sleep(200L); - int count = 0; - while(jobExecution.getStatus()==BatchStatus.STOPPING && count++<10) { - Thread.sleep(200L); - } - assertTrue("Timed out waiting for job to stop: "+jobExecution, count<10); - - assertEquals(BatchStatus.STOPPED, jobExecution.getStatus()); - assertEquals(ExitStatus.STOPPED.getExitCode(), jobExecution.getExitStatus().getExitCode()); - - assertTrue("Wrong step names: "+stepNamesList, stepNamesList.contains("stop")); - - StepExecution stepExecution = getStepExecution(jobExecution, "stop"); - assertEquals(BatchStatus.STOPPED, stepExecution.getStatus()); - assertEquals(ExitStatus.STOPPED.getExitCode(), stepExecution.getExitStatus().getExitCode()); - - assertEquals(1, stepNamesList.size()); - - } - -} +/* + * Copyright 2006-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.configuration.xml; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.StepExecution; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Dave Syer + * @since 2.0 + */ +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class SplitInterruptedJobParserTests extends AbstractJobParserTests { + + @Test + public void testSplitInterrupted() throws Exception { + + final JobExecution jobExecution = createJobExecution(); + new Thread(new Runnable() { + @Override + public void run() { + job.execute(jobExecution); + } + }).start(); + + Thread.sleep(100L); + jobExecution.setStatus(BatchStatus.STOPPING); + Thread.sleep(200L); + int count = 0; + while (jobExecution.getStatus() == BatchStatus.STOPPING && count++ < 10) { + Thread.sleep(200L); + } + assertTrue("Timed out waiting for job to stop: " + jobExecution, count < 10); + + assertEquals(BatchStatus.STOPPED, jobExecution.getStatus()); + assertEquals(ExitStatus.STOPPED.getExitCode(), jobExecution.getExitStatus().getExitCode()); + + assertTrue("Wrong step names: " + stepNamesList, stepNamesList.contains("stop")); + + StepExecution stepExecution = getStepExecution(jobExecution, "stop"); + assertEquals(BatchStatus.STOPPED, stepExecution.getStatus()); + assertEquals(ExitStatus.STOPPED.getExitCode(), stepExecution.getExitStatus().getExitCode()); + + assertEquals(1, stepNamesList.size()); + + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/SplitJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/SplitJobParserTests.java index a34823497..83a029818 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/SplitJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/SplitJobParserTests.java @@ -34,7 +34,6 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - /** * @author Dave Syer * @@ -42,14 +41,14 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) public class SplitJobParserTests { - + @Autowired @Qualifier("job") private Job job; @Autowired private JobRepository jobRepository; - + @Test public void testSplitJob() throws Exception { assertNotNull(job); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepListenerInStepParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepListenerInStepParserTests.java index b27e3b05b..d69653294 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepListenerInStepParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepListenerInStepParserTests.java @@ -51,7 +51,7 @@ public class StepListenerInStepParserTests { Step step = (Step) beanFactory.getBean("s1"); List list = getListeners(step); assertEquals(1, list.size()); - assertTrue(list.get(0) instanceof DummyStepExecutionListener ); + assertTrue(list.get(0) instanceof DummyStepExecutionListener); } @Test @@ -87,8 +87,7 @@ public class StepListenerInStepParserTests { Object compositeListener = ReflectionTestUtils.getField(step, "stepExecutionListener"); Object composite = ReflectionTestUtils.getField(compositeListener, "list"); - List proxiedListeners = (List) ReflectionTestUtils.getField( - composite, "list"); + List proxiedListeners = (List) ReflectionTestUtils.getField(composite, "list"); List r = new ArrayList<>(); for (Object listener : proxiedListeners) { while (listener instanceof Advised) { @@ -107,8 +106,8 @@ public class StepListenerInStepParserTests { } try { compositeListener = ReflectionTestUtils.getField( - ReflectionTestUtils.getField(ReflectionTestUtils.getField( - ReflectionTestUtils.getField(step, "tasklet"), "chunkProvider"), "listener"), + ReflectionTestUtils.getField(ReflectionTestUtils + .getField(ReflectionTestUtils.getField(step, "tasklet"), "chunkProvider"), "listener"), "itemReadListener"); composite = ReflectionTestUtils.getField(compositeListener, "listeners"); proxiedListeners = (List) ReflectionTestUtils.getField(composite, "list"); @@ -124,4 +123,5 @@ public class StepListenerInStepParserTests { } return r; } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepListenerMethodAttributeParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepListenerMethodAttributeParserTests.java index e027cec58..d830259d8 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepListenerMethodAttributeParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepListenerMethodAttributeParserTests.java @@ -40,7 +40,7 @@ import org.springframework.test.util.ReflectionTestUtils; @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) public class StepListenerMethodAttributeParserTests { - + @Autowired @Qualifier("s1") private Step step1; @@ -57,8 +57,8 @@ public class StepListenerMethodAttributeParserTests { Object compositeListener = ReflectionTestUtils.getField(step, "stepExecutionListener"); Object composite = ReflectionTestUtils.getField(compositeListener, "list"); - List proxiedListeners = (List) ReflectionTestUtils.getField( - composite, "list"); + List proxiedListeners = (List) ReflectionTestUtils + .getField(composite, "list"); List r = new ArrayList<>(); for (Object listener : proxiedListeners) { while (listener instanceof Advised) { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepListenerParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepListenerParserTests.java index 06331860b..c2975350c 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepListenerParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepListenerParserTests.java @@ -43,7 +43,7 @@ import org.springframework.test.util.ReflectionTestUtils; @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) public class StepListenerParserTests { - + @Autowired @Qualifier("s1") private Step step1; @@ -127,8 +127,7 @@ public class StepListenerParserTests { Object compositeListener = ReflectionTestUtils.getField(step, "stepExecutionListener"); Object composite = ReflectionTestUtils.getField(compositeListener, "list"); - List proxiedListeners = (List) ReflectionTestUtils.getField( - composite, "list"); + List proxiedListeners = (List) ReflectionTestUtils.getField(composite, "list"); List r = new ArrayList<>(); for (Object listener : proxiedListeners) { while (listener instanceof Advised) { @@ -147,8 +146,8 @@ public class StepListenerParserTests { } try { compositeListener = ReflectionTestUtils.getField( - ReflectionTestUtils.getField(ReflectionTestUtils.getField( - ReflectionTestUtils.getField(step, "tasklet"), "chunkProvider"), "listener"), + ReflectionTestUtils.getField(ReflectionTestUtils + .getField(ReflectionTestUtils.getField(step, "tasklet"), "chunkProvider"), "listener"), "itemReadListener"); composite = ReflectionTestUtils.getField(compositeListener, "listeners"); proxiedListeners = (List) ReflectionTestUtils.getField(composite, "list"); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepNameTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepNameTests.java index 52281c0f6..41d41ad28 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepNameTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepNameTests.java @@ -66,10 +66,11 @@ public class StepNameTests { Collection stepNames = stepLocator.getStepNames(); Job job = (Job) context.getBean(name); String jobName = job.getName(); - assertTrue("Job has no steps: "+jobName, !stepNames.isEmpty()); + assertTrue("Job has no steps: " + jobName, !stepNames.isEmpty()); for (String registeredName : stepNames) { String stepName = stepLocator.getStep(registeredName).getName(); - assertEquals("Step name not equal to registered value: " + stepName + "!=" + registeredName + ", " + jobName, + assertEquals( + "Step name not equal to registered value: " + stepName + "!=" + registeredName + ", " + jobName, stepName, registeredName); } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBeanTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBeanTests.java index 76c7aff4e..6358d7813 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBeanTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBeanTests.java @@ -109,7 +109,8 @@ public class StepParserStepFactoryBeanTests { fb.setStartLimit(5); fb.setTasklet(new DummyTasklet()); fb.setTransactionManager(new ResourcelessTransactionManager()); - fb.setListeners(new StepExecutionListener[] { new StepExecutionListener() {} }); + fb.setListeners(new StepExecutionListener[] { new StepExecutionListener() { + } }); fb.setIsolation(Isolation.DEFAULT); fb.setTransactionTimeout(-1); fb.setPropagation(Propagation.REQUIRED); @@ -141,7 +142,8 @@ public class StepParserStepFactoryBeanTests { fb.setJobRepository(new JobRepositorySupport()); fb.setStartLimit(5); fb.setTransactionManager(new ResourcelessTransactionManager()); - fb.setListeners(new StepListener[] { new StepExecutionListener() {} }); + fb.setListeners(new StepListener[] { new StepExecutionListener() { + } }); fb.setIsolation(Isolation.DEFAULT); fb.setTransactionTimeout(-1); fb.setPropagation(Propagation.REQUIRED); @@ -150,7 +152,7 @@ public class StepParserStepFactoryBeanTests { fb.setTaskExecutor(new SyncTaskExecutor()); fb.setItemReader(new DummyItemReader()); fb.setItemWriter(new DummyItemWriter()); - fb.setStreams(new ItemStream[] {new FlatFileItemReader<>() }); + fb.setStreams(new ItemStream[] { new FlatFileItemReader<>() }); fb.setHasChunkElement(true); Object step = fb.getObject(); @@ -167,7 +169,8 @@ public class StepParserStepFactoryBeanTests { fb.setJobRepository(new JobRepositorySupport()); fb.setStartLimit(5); fb.setTransactionManager(new ResourcelessTransactionManager()); - fb.setListeners(new StepListener[] { new StepExecutionListener() {} }); + fb.setListeners(new StepListener[] { new StepExecutionListener() { + } }); fb.setIsolation(Isolation.DEFAULT); fb.setTransactionTimeout(-1); fb.setPropagation(Propagation.REQUIRED); @@ -176,7 +179,7 @@ public class StepParserStepFactoryBeanTests { fb.setTaskExecutor(new SyncTaskExecutor()); fb.setItemReader(new DummyItemReader()); fb.setItemWriter(new DummyItemWriter()); - fb.setStreams(new ItemStream[] {new FlatFileItemReader<>() }); + fb.setStreams(new ItemStream[] { new FlatFileItemReader<>() }); fb.setCacheCapacity(5); fb.setIsReaderTransactionalQueue(true); fb.setRetryLimit(5); @@ -201,7 +204,8 @@ public class StepParserStepFactoryBeanTests { fb.setJobRepository(new JobRepositorySupport()); fb.setStartLimit(5); fb.setTransactionManager(new ResourcelessTransactionManager()); - fb.setListeners(new StepListener[] { new StepExecutionListener() {} }); + fb.setListeners(new StepListener[] { new StepExecutionListener() { + } }); fb.setIsolation(Isolation.DEFAULT); fb.setTransactionTimeout(-1); fb.setPropagation(Propagation.REQUIRED); @@ -210,7 +214,7 @@ public class StepParserStepFactoryBeanTests { fb.setItemReader(new DummyItemReader()); fb.setItemProcessor(new PassThroughItemProcessor<>()); fb.setItemWriter(new DummyItemWriter()); - fb.setStreams(new ItemStream[] {new FlatFileItemReader<>() }); + fb.setStreams(new ItemStream[] { new FlatFileItemReader<>() }); Object step = fb.getObject(); assertTrue(step instanceof TaskletStep); @@ -227,13 +231,14 @@ public class StepParserStepFactoryBeanTests { fb.setJobRepository(new JobRepositorySupport()); fb.setStartLimit(5); fb.setTransactionManager(new ResourcelessTransactionManager()); - fb.setListeners(new StepListener[] { new StepExecutionListener(){} }); + fb.setListeners(new StepListener[] { new StepExecutionListener() { + } }); fb.setChunkCompletionPolicy(new DummyCompletionPolicy()); fb.setTaskExecutor(new SyncTaskExecutor()); fb.setItemReader(new DummyItemReader()); fb.setItemProcessor(new PassThroughItemProcessor<>()); fb.setItemWriter(new DummyItemWriter()); - fb.setStreams(new ItemStream[] {new FlatFileItemReader<>() }); + fb.setStreams(new ItemStream[] { new FlatFileItemReader<>() }); fb.setCacheCapacity(5); fb.setIsReaderTransactionalQueue(true); fb.setRetryLimit(5); @@ -247,7 +252,8 @@ public class StepParserStepFactoryBeanTests { Object step = fb.getObject(); assertTrue(step instanceof TaskletStep); - Object throttleLimit = ReflectionTestUtils.getField(ReflectionTestUtils.getField(step, "stepOperations"), "throttleLimit"); + Object throttleLimit = ReflectionTestUtils.getField(ReflectionTestUtils.getField(step, "stepOperations"), + "throttleLimit"); assertEquals(Integer.valueOf(10), throttleLimit); Object tasklet = ReflectionTestUtils.getField(step, "tasklet"); assertTrue(tasklet instanceof ChunkOrientedTasklet); @@ -265,7 +271,8 @@ public class StepParserStepFactoryBeanTests { fb.setAllowStartIfComplete(true); fb.setJobRepository(new JobRepositorySupport()); fb.setStartLimit(5); - fb.setListeners(new StepListener[] { new StepExecutionListener(){} }); + fb.setListeners(new StepListener[] { new StepExecutionListener() { + } }); fb.setTaskExecutor(new SyncTaskExecutor()); SimplePartitioner partitioner = new SimplePartitioner(); @@ -285,7 +292,8 @@ public class StepParserStepFactoryBeanTests { fb.setAllowStartIfComplete(true); fb.setJobRepository(new JobRepositorySupport()); fb.setStartLimit(5); - fb.setListeners(new StepListener[] { new StepExecutionListener(){} }); + fb.setListeners(new StepListener[] { new StepExecutionListener() { + } }); fb.setTaskExecutor(new SyncTaskExecutor()); SimplePartitioner partitioner = new SimplePartitioner(); @@ -308,7 +316,8 @@ public class StepParserStepFactoryBeanTests { fb.setAllowStartIfComplete(true); fb.setJobRepository(new JobRepositorySupport()); fb.setStartLimit(5); - fb.setListeners(new StepListener[] { new StepExecutionListener(){} }); + fb.setListeners(new StepListener[] { new StepExecutionListener() { + } }); fb.setTaskExecutor(new SyncTaskExecutor()); fb.setFlow(new SimpleFlow("foo")); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepParserTests.java index c1af94d3d..4195537cc 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepParserTests.java @@ -223,8 +223,8 @@ public class StepParserTests { assertTrue(step instanceof TaskletStep); Object compositeListener = ReflectionTestUtils.getField(step, "stepExecutionListener"); Object composite = ReflectionTestUtils.getField(compositeListener, "list"); - List list = (List) ReflectionTestUtils - .getField(composite, "list"); + List list = (List) ReflectionTestUtils.getField(composite, + "list"); List unwrappedList = new ArrayList<>(); for (StepExecutionListener listener : list) { while (listener instanceof Advised) { @@ -306,7 +306,8 @@ public class StepParserTests { assertDummyTransactionManager("overrideTxMgrOnParentStep", "dummyTxMgr2", ctx); } - private void assertDummyJobRepository(String beanName, String jobRepoName, ApplicationContext ctx) throws Exception { + private void assertDummyJobRepository(String beanName, String jobRepoName, ApplicationContext ctx) + throws Exception { JobRepository jobRepository = getJobRepository(beanName, ctx); assertTrue(jobRepository instanceof DummyJobRepository); assertEquals(jobRepoName, ((DummyJobRepository) jobRepository).getName()); @@ -357,7 +358,7 @@ public class StepParserTests { assertTrue(ctx.containsBean("&s12")); Object factoryBean = ctx.getBean("&s12"); - assertTrue(factoryBean instanceof StepParserStepFactoryBean); + assertTrue(factoryBean instanceof StepParserStepFactoryBean); assertTrue(ctx.containsBean("dummyStep")); Object dummyStep = ctx.getBean("dummyStep"); @@ -374,7 +375,7 @@ public class StepParserTests { assertTrue(ctx.containsBean("&s13")); Object factoryBean = ctx.getBean("&s13"); - assertTrue(factoryBean instanceof StepParserStepFactoryBean); + assertTrue(factoryBean instanceof StepParserStepFactoryBean); assertTrue(ctx.containsBean("s13")); Object bean = ctx.getBean("s13"); @@ -382,7 +383,7 @@ public class StepParserTests { assertTrue(ctx.containsBean("&dummyStepWithTaskletOnParent")); Object dummyStepFb = ctx.getBean("&dummyStepWithTaskletOnParent"); - assertTrue(dummyStepFb instanceof StepParserStepFactoryBean); + assertTrue(dummyStepFb instanceof StepParserStepFactoryBean); assertTrue(ctx.containsBean("dummyStepWithTaskletOnParent")); Object dummyStep = ctx.getBean("dummyStepWithTaskletOnParent"); @@ -390,7 +391,7 @@ public class StepParserTests { assertTrue(ctx.containsBean("&standaloneStepWithTasklet")); Object standaloneStepFb = ctx.getBean("&standaloneStepWithTasklet"); - assertTrue(standaloneStepFb instanceof StepParserStepFactoryBean); + assertTrue(standaloneStepFb instanceof StepParserStepFactoryBean); assertTrue(ctx.containsBean("standaloneStepWithTasklet")); Object standaloneStep = ctx.getBean("standaloneStepWithTasklet"); @@ -403,7 +404,7 @@ public class StepParserTests { assertTrue(ctx.containsBean("&s14")); Object factoryBean = ctx.getBean("&s14"); - assertTrue(factoryBean instanceof StepParserStepFactoryBean); + assertTrue(factoryBean instanceof StepParserStepFactoryBean); assertTrue(ctx.containsBean("s12")); Object bean = ctx.getBean("s12"); @@ -411,7 +412,7 @@ public class StepParserTests { assertTrue(ctx.containsBean("&standaloneStepWithTaskletAndDummyParent")); Object standaloneWithTaskletFb = ctx.getBean("&standaloneStepWithTaskletAndDummyParent"); - assertTrue(standaloneWithTaskletFb instanceof StepParserStepFactoryBean); + assertTrue(standaloneWithTaskletFb instanceof StepParserStepFactoryBean); assertTrue(ctx.containsBean("standaloneStepWithTaskletAndDummyParent")); Object standaloneWithTasklet = ctx.getBean("standaloneStepWithTaskletAndDummyParent"); @@ -451,7 +452,8 @@ public class StepParserTests { Map, Boolean> retryableFound = getExceptionMap(fb, "retryableExceptionClasses"); ItemStream[] streamsFound = (ItemStream[]) ReflectionTestUtils.getField(fb, "streams"); RetryListener[] retryListenersFound = (RetryListener[]) ReflectionTestUtils.getField(fb, "retryListeners"); - Set stepListenersFound = (Set) ReflectionTestUtils.getField(fb, "stepExecutionListeners"); + Set stepListenersFound = (Set) ReflectionTestUtils.getField(fb, + "stepExecutionListeners"); Collection> noRollbackFound = getExceptionList(fb, "noRollbackExceptionClasses"); assertSameMaps(skippable, skippableFound); @@ -485,7 +487,8 @@ public class StepParserTests { Map, Boolean> retryableFound = getExceptionMap(fb, "retryableExceptionClasses"); ItemStream[] streamsFound = (ItemStream[]) ReflectionTestUtils.getField(fb, "streams"); RetryListener[] retryListenersFound = (RetryListener[]) ReflectionTestUtils.getField(fb, "retryListeners"); - Set stepListenersFound = (Set) ReflectionTestUtils.getField(fb, "stepExecutionListeners"); + Set stepListenersFound = (Set) ReflectionTestUtils.getField(fb, + "stepExecutionListeners"); Collection> noRollbackFound = getExceptionList(fb, "noRollbackExceptionClasses"); assertSameMaps(skippable, skippableFound); @@ -508,7 +511,8 @@ public class StepParserTests { assertEquals(1, getExceptionMap(fb, "retryableExceptionClasses").size()); assertEquals(0, ((ItemStream[]) ReflectionTestUtils.getField(fb, "streams")).length); assertEquals(0, ((RetryListener[]) ReflectionTestUtils.getField(fb, "retryListeners")).length); - assertEquals(0, ((Set) ReflectionTestUtils.getField(fb, "stepExecutionListeners")).size()); + assertEquals(0, + ((Set) ReflectionTestUtils.getField(fb, "stepExecutionListeners")).size()); assertEquals(0, getExceptionList(fb, "noRollbackExceptionClasses").size()); } @@ -553,4 +557,5 @@ public class StepParserTests { } return out; } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepWithBasicProcessTaskJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepWithBasicProcessTaskJobParserTests.java index 9e5e9f5af..d38cac967 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepWithBasicProcessTaskJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepWithBasicProcessTaskJobParserTests.java @@ -36,7 +36,6 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.util.ReflectionTestUtils; - /** * @author Thomas Risberg * @@ -65,7 +64,7 @@ public class StepWithBasicProcessTaskJobParserTests { private TestWriter writer; @Autowired - private StepParserStepFactoryBean factory; + private StepParserStepFactoryBean factory; @SuppressWarnings("unchecked") @Test @@ -74,9 +73,9 @@ public class StepWithBasicProcessTaskJobParserTests { Object ci = ReflectionTestUtils.getField(factory, "commitInterval"); assertEquals("wrong chunk-size:", 10, ci); Object listeners = ReflectionTestUtils.getField(factory, "stepExecutionListeners"); - assertEquals("wrong number of listeners:", 2, ((Set)listeners).size()); + assertEquals("wrong number of listeners:", 2, ((Set) listeners).size()); Object streams = ReflectionTestUtils.getField(factory, "streams"); - assertEquals("wrong number of streams:", 1, ((ItemStream[])streams).length); + assertEquals("wrong number of streams:", 1, ((ItemStream[]) streams).length); JobExecution jobExecution = jobRepository.createJobExecution(job.getName(), new JobParameters()); job.execute(jobExecution); assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); @@ -87,4 +86,5 @@ public class StepWithBasicProcessTaskJobParserTests { assertTrue(writer.isExecuted()); assertTrue(listener.isExecuted()); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepWithFaultTolerantProcessTaskJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepWithFaultTolerantProcessTaskJobParserTests.java index 6f0f6f27a..e01454b38 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepWithFaultTolerantProcessTaskJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepWithFaultTolerantProcessTaskJobParserTests.java @@ -111,4 +111,5 @@ public class StepWithFaultTolerantProcessTaskJobParserTests { assertTrue(listener.isExecuted()); assertTrue(retryListener.isExecuted()); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepWithPojoListenerJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepWithPojoListenerJobParserTests.java index cfcd8d93a..6224ca599 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepWithPojoListenerJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepWithPojoListenerJobParserTests.java @@ -33,7 +33,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * @author Dave Syer - * + * */ @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) @@ -67,4 +67,5 @@ public class StepWithPojoListenerJobParserTests { assertTrue(writer.isExecuted()); assertTrue(listener.isExecuted()); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepWithSimpleTaskJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepWithSimpleTaskJobParserTests.java index 58bab495c..1c5c872f4 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepWithSimpleTaskJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepWithSimpleTaskJobParserTests.java @@ -78,7 +78,7 @@ public class StepWithSimpleTaskJobParserTests { private TestTasklet assertTasklet(Job job, String stepName, String taskletName) { System.err.println(((FlowJob) job).getStepNames()); Step step = ((FlowJob) job).getStep(stepName); - assertTrue("Wrong type for step name="+stepName+": "+step, step instanceof TaskletStep); + assertTrue("Wrong type for step name=" + stepName + ": " + step, step instanceof TaskletStep); Object tasklet = ReflectionTestUtils.getField(step, "tasklet"); assertTrue(tasklet instanceof TestTasklet); TestTasklet testTasklet = (TestTasklet) tasklet; @@ -86,4 +86,5 @@ public class StepWithSimpleTaskJobParserTests { assertTrue(!testTasklet.isExecuted()); return testTasklet; } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StopAndRestartFailedJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StopAndRestartFailedJobParserTests.java index 36335aa89..b8be653d6 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StopAndRestartFailedJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StopAndRestartFailedJobParserTests.java @@ -32,11 +32,12 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * @author Dave Syer * @author Mahmoud Ben Hassine - * + * */ @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) -// FIXME this test fails when upgrading the batch xsd from 2.2 to 3.0: https://github.com/spring-projects/spring-batch/issues/1287 +// FIXME this test fails when upgrading the batch xsd from 2.2 to 3.0: +// https://github.com/spring-projects/spring-batch/issues/1287 public class StopAndRestartFailedJobParserTests extends AbstractJobParserTests { @Test @@ -61,8 +62,8 @@ public class StopAndRestartFailedJobParserTests extends AbstractJobParserTests { } - private JobExecution launchAndAssert(String stepNames) throws JobInstanceAlreadyCompleteException, JobRestartException, - JobExecutionAlreadyRunningException { + private JobExecution launchAndAssert(String stepNames) + throws JobInstanceAlreadyCompleteException, JobRestartException, JobExecutionAlreadyRunningException { JobExecution jobExecution = createJobExecution(); job.execute(jobExecution); assertEquals(stepNames, stepNamesList.toString()); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StopAndRestartJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StopAndRestartJobParserTests.java index 348416795..58054176d 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StopAndRestartJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StopAndRestartJobParserTests.java @@ -28,11 +28,12 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * @author Dave Syer * @author Mahmoud Ben Hassine - * + * */ @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) -// FIXME this test fails when upgrading the batch xsd from 2.2 to 3.0: https://github.com/spring-projects/spring-batch/issues/1287 +// FIXME this test fails when upgrading the batch xsd from 2.2 to 3.0: +// https://github.com/spring-projects/spring-batch/issues/1287 public class StopAndRestartJobParserTests extends AbstractJobParserTests { @Test diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StopCustomStatusJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StopCustomStatusJobParserTests.java index 3fe8c1fb3..077c1907d 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StopCustomStatusJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StopCustomStatusJobParserTests.java @@ -28,11 +28,12 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * @author Dave Syer * @author Mahmoud Ben Hassine - * + * */ @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) -// FIXME this test fails when upgrading the batch xsd from 2.2 to 3.0: https://github.com/spring-projects/spring-batch/issues/1287 +// FIXME this test fails when upgrading the batch xsd from 2.2 to 3.0: +// https://github.com/spring-projects/spring-batch/issues/1287 public class StopCustomStatusJobParserTests extends AbstractJobParserTests { @Test @@ -44,7 +45,7 @@ public class StopCustomStatusJobParserTests extends AbstractJobParserTests { JobExecution jobExecution = createJobExecution(); job.execute(jobExecution); assertEquals(1, stepNamesList.size()); - assertEquals("Wrong steps executed: "+stepNamesList, "[stop]", stepNamesList.toString()); + assertEquals("Wrong steps executed: " + stepNamesList, "[stop]", stepNamesList.toString()); assertEquals(BatchStatus.STOPPED, jobExecution.getStatus()); assertEquals(ExitStatus.STOPPED.getExitCode(), jobExecution.getExitStatus().getExitCode()); @@ -60,7 +61,7 @@ public class StopCustomStatusJobParserTests extends AbstractJobParserTests { jobExecution = createJobExecution(); job.execute(jobExecution); assertEquals(1, stepNamesList.size()); // step1 is not executed - assertEquals("Wrong steps executed: "+stepNamesList, "[s2]", stepNamesList.toString()); + assertEquals("Wrong steps executed: " + stepNamesList, "[s2]", stepNamesList.toString()); assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus()); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StopIncompleteJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StopIncompleteJobParserTests.java index 90dd99135..207aedff8 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StopIncompleteJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StopIncompleteJobParserTests.java @@ -28,11 +28,12 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * @author Dave Syer * @author Mahmoud Ben Hassine - * + * */ @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) -// FIXME this test fails when upgrading the batch xsd from 2.2 to 3.0: https://github.com/spring-projects/spring-batch/issues/1287 +// FIXME this test fails when upgrading the batch xsd from 2.2 to 3.0: +// https://github.com/spring-projects/spring-batch/issues/1287 public class StopIncompleteJobParserTests extends AbstractJobParserTests { @Test @@ -44,7 +45,7 @@ public class StopIncompleteJobParserTests extends AbstractJobParserTests { JobExecution jobExecution = createJobExecution(); job.execute(jobExecution); assertEquals(1, stepNamesList.size()); - assertEquals("Wrong steps executed: "+stepNamesList, "[fail]", stepNamesList.toString()); + assertEquals("Wrong steps executed: " + stepNamesList, "[fail]", stepNamesList.toString()); assertEquals(BatchStatus.STOPPED, jobExecution.getStatus()); assertEquals(ExitStatus.STOPPED.getExitCode(), jobExecution.getExitStatus().getExitCode()); @@ -60,7 +61,7 @@ public class StopIncompleteJobParserTests extends AbstractJobParserTests { jobExecution = createJobExecution(); job.execute(jobExecution); assertEquals(1, stepNamesList.size()); // step1 is not executed - assertEquals("Wrong steps executed: "+stepNamesList, "[s2]", stepNamesList.toString()); + assertEquals("Wrong steps executed: " + stepNamesList, "[s2]", stepNamesList.toString()); assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus()); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StopJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StopJobParserTests.java index cadaa6759..ea4870bd0 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StopJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StopJobParserTests.java @@ -37,7 +37,8 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; */ @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) -// FIXME this test fails when upgrading the batch xsd from 2.2 to 3.0: https://github.com/spring-projects/spring-batch/issues/1287 +// FIXME this test fails when upgrading the batch xsd from 2.2 to 3.0: +// https://github.com/spring-projects/spring-batch/issues/1287 public class StopJobParserTests extends AbstractJobParserTests { @Test @@ -77,10 +78,12 @@ public class StopJobParserTests extends AbstractJobParserTests { } public static class TestDecider implements JobExecutionDecider { + @Override public FlowExecutionStatus decide(JobExecution jobExecution, @Nullable StepExecution stepExecution) { return new FlowExecutionStatus("FOO"); } + } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StopRestartOnCompletedStepJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StopRestartOnCompletedStepJobParserTests.java index ac7fb2418..5c45322e3 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StopRestartOnCompletedStepJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StopRestartOnCompletedStepJobParserTests.java @@ -31,7 +31,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * @author Dave Syer - * + * */ @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) @@ -53,8 +53,8 @@ public class StopRestartOnCompletedStepJobParserTests extends AbstractJobParserT } - private void launchAndAssert(String stepNames) throws JobInstanceAlreadyCompleteException, JobRestartException, - JobExecutionAlreadyRunningException { + private void launchAndAssert(String stepNames) + throws JobInstanceAlreadyCompleteException, JobRestartException, JobExecutionAlreadyRunningException { JobExecution jobExecution = createJobExecution(); job.execute(jobExecution); assertEquals(stepNames, stepNamesList.toString()); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StopRestartOnFailedStepJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StopRestartOnFailedStepJobParserTests.java index f05a2c67f..cd125b840 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StopRestartOnFailedStepJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StopRestartOnFailedStepJobParserTests.java @@ -31,7 +31,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * @author Dave Syer - * + * */ @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) @@ -53,8 +53,8 @@ public class StopRestartOnFailedStepJobParserTests extends AbstractJobParserTest } - private void launchAndAssert(String stepNames) throws JobInstanceAlreadyCompleteException, JobRestartException, - JobExecutionAlreadyRunningException { + private void launchAndAssert(String stepNames) + throws JobInstanceAlreadyCompleteException, JobRestartException, JobExecutionAlreadyRunningException { JobExecution jobExecution = createJobExecution(); job.execute(jobExecution); assertEquals(stepNames, stepNamesList.toString()); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TaskletParserAdapterTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TaskletParserAdapterTests.java index 3368e5d75..19b1470ee 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TaskletParserAdapterTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TaskletParserAdapterTests.java @@ -30,7 +30,6 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - /** * @author Dave Syer * @author Mahmoud Ben Hassine @@ -39,7 +38,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) public class TaskletParserAdapterTests { - + @Autowired @Qualifier("job1") private Job job1; @@ -66,4 +65,5 @@ public class TaskletParserAdapterTests { job2.execute(jobExecution); assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TaskletParserBeanPropertiesTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TaskletParserBeanPropertiesTests.java index 63f1b5d3e..1ef5187a2 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TaskletParserBeanPropertiesTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TaskletParserBeanPropertiesTests.java @@ -37,7 +37,6 @@ import org.springframework.util.ReflectionUtils; import static org.junit.Assert.*; - /** * @author Dave Syer * @author Mahmoud Ben Hassine @@ -46,7 +45,7 @@ import static org.junit.Assert.*; @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) public class TaskletParserBeanPropertiesTests { - + @Autowired @Qualifier("job1") private Job job1; @@ -59,7 +58,6 @@ public class TaskletParserBeanPropertiesTests { @Qualifier("job3") private Job job3; - @Autowired @Qualifier("job4") private Job job4; @@ -87,7 +85,7 @@ public class TaskletParserBeanPropertiesTests { job2.execute(jobExecution); Step step = job2.getStep("step2"); tasklet = (TestTasklet) ReflectionTestUtils.getField(step, "tasklet"); - assertEquals("foo", tasklet.getName()); + assertEquals("foo", tasklet.getName()); assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); } @@ -118,4 +116,5 @@ public class TaskletParserBeanPropertiesTests { assertEquals(DummyNamespaceHandler.LABEL, tasklet.getName()); assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); } + } \ No newline at end of file diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TaskletStepAllowStartIfCompleteTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TaskletStepAllowStartIfCompleteTests.java index 97da480c2..c2379b217 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TaskletStepAllowStartIfCompleteTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TaskletStepAllowStartIfCompleteTests.java @@ -49,7 +49,7 @@ public class TaskletStepAllowStartIfCompleteTests { @Test public void test() throws Exception { - //retrieve the step from the context and see that it's allow is set + // retrieve the step from the context and see that it's allow is set AbstractStep abstractStep = (AbstractStep) context.getBean("simpleJob.step1"); assertTrue(abstractStep.isAllowStartIfComplete()); } @@ -68,4 +68,5 @@ public class TaskletStepAllowStartIfCompleteTests { int count = jobRepository.getStepExecutionCount(jobExecution.getJobInstance(), "simpleJob.step1"); assertEquals(2, count); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TestIncrementer.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TestIncrementer.java index 90250f84a..97927c944 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TestIncrementer.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TestIncrementer.java @@ -19,7 +19,7 @@ import org.springframework.batch.core.JobParameters; import org.springframework.batch.core.JobParametersIncrementer; import org.springframework.lang.Nullable; -public class TestIncrementer implements JobParametersIncrementer{ +public class TestIncrementer implements JobParametersIncrementer { @Override public JobParameters getNext(@Nullable JobParameters parameters) { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TestJobListener.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TestJobListener.java index 8b87a9e81..23ac5d034 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TestJobListener.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TestJobListener.java @@ -20,11 +20,12 @@ import org.springframework.batch.core.annotation.BeforeJob; public class TestJobListener { @BeforeJob - public void beforeJob(){ - + public void beforeJob() { + } - - public void afterJob(){ - + + public void afterJob() { + } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TestListener.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TestListener.java index 4fa621acd..fecb31502 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TestListener.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TestListener.java @@ -40,7 +40,7 @@ public class TestListener extends AbstractTestComponent implements StepExecution } @AfterRead - public void logItem(){ + public void logItem() { } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TestPojoListener.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TestPojoListener.java index 3ae78dc12..51628e3b3 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TestPojoListener.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TestPojoListener.java @@ -22,7 +22,7 @@ import org.springframework.batch.core.annotation.AfterWrite; public class TestPojoListener extends AbstractTestComponent { @AfterWrite - public void after(List items){ + public void after(List items) { executed = true; } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TestProcessor.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TestProcessor.java index 71010c67e..99838e6b0 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TestProcessor.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TestProcessor.java @@ -18,7 +18,7 @@ package org.springframework.batch.core.configuration.xml; import org.springframework.batch.item.ItemProcessor; import org.springframework.lang.Nullable; -public class TestProcessor extends AbstractTestComponent implements ItemProcessor{ +public class TestProcessor extends AbstractTestComponent implements ItemProcessor { @Nullable @Override diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TestTasklet.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TestTasklet.java index c5618b3ce..cab9cf1e9 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TestTasklet.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TestTasklet.java @@ -27,8 +27,7 @@ public class TestTasklet extends AbstractTestComponent implements Tasklet { @Nullable @Override - public RepeatStatus execute(StepContribution contribution, - ChunkContext chunkContext) throws Exception { + public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { executed = true; return RepeatStatus.FINISHED; } @@ -40,4 +39,5 @@ public class TestTasklet extends AbstractTestComponent implements Tasklet { public void setName(String name) { this.name = name; } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TwoStepJobParserTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TwoStepJobParserTests.java index d8123956e..d92f29d26 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TwoStepJobParserTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/TwoStepJobParserTests.java @@ -29,7 +29,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - /** * @author Dave Syer * @@ -37,13 +36,13 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) public class TwoStepJobParserTests { - + @Autowired private Job job; @Autowired private JobRepository jobRepository; - + @Test public void testTwoStep() throws Exception { assertNotNull(job); @@ -52,4 +51,5 @@ public class TwoStepJobParserTests { assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); assertEquals(2, jobExecution.getStepExecutions().size()); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/converter/DefaultJobParametersConverterTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/converter/DefaultJobParametersConverterTests.java index c6c996593..37d789369 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/converter/DefaultJobParametersConverterTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/converter/DefaultJobParametersConverterTests.java @@ -269,7 +269,7 @@ public class DefaultJobParametersConverterTests { public void testRoundTrip() throws Exception { String[] args = new String[] { "schedule.date(date)=2008/01/23", "job.key=myKey", "vendor.id(long)=33243243", - "double.key(double)=1.23" }; + "double.key(double)=1.23" }; JobParameters parameters = factory.getJobParameters(StringUtils.splitArrayElementsIntoProperties(args, "=")); @@ -285,7 +285,7 @@ public class DefaultJobParametersConverterTests { public void testRoundTripWithIdentifyingAndNonIdentifying() throws Exception { String[] args = new String[] { "schedule.date(date)=2008/01/23", "+job.key=myKey", "-vendor.id(long)=33243243", - "double.key(double)=1.23" }; + "double.key(double)=1.23" }; JobParameters parameters = factory.getJobParameters(StringUtils.splitArrayElementsIntoProperties(args, "=")); @@ -301,7 +301,7 @@ public class DefaultJobParametersConverterTests { public void testRoundTripWithNumberFormat() throws Exception { String[] args = new String[] { "schedule.date(date)=2008/01/23", "job.key=myKey", "vendor.id(long)=33243243", - "double.key(double)=1,23" }; + "double.key(double)=1,23" }; NumberFormat format = NumberFormat.getInstance(Locale.GERMAN); factory.setNumberFormat(format); @@ -331,4 +331,5 @@ public class DefaultJobParametersConverterTests { private boolean contains(String str, String searchStr) { return str.indexOf(searchStr) != -1; } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/converter/JobParametersConverterSupport.java b/spring-batch-core/src/test/java/org/springframework/batch/core/converter/JobParametersConverterSupport.java index ac06c9de1..4438ec472 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/converter/JobParametersConverterSupport.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/converter/JobParametersConverterSupport.java @@ -29,9 +29,9 @@ public class JobParametersConverterSupport implements JobParametersConverter { public JobParameters getJobParameters(@Nullable Properties properties) { JobParametersBuilder builder = new JobParametersBuilder(); - if(properties != null) { + if (properties != null) { for (Map.Entry curParameter : properties.entrySet()) { - if(curParameter.getValue() != null) { + if (curParameter.getValue() != null) { builder.addString(curParameter.getKey().toString(), curParameter.getValue().toString(), false); } } @@ -40,19 +40,24 @@ public class JobParametersConverterSupport implements JobParametersConverter { return builder.toJobParameters(); } - /* (non-Javadoc) - * @see org.springframework.batch.core.converter.JobParametersConverter#getProperties(org.springframework.batch.core.JobParameters) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.core.converter.JobParametersConverter#getProperties(org. + * springframework.batch.core.JobParameters) */ @Override public Properties getProperties(@Nullable JobParameters params) { Properties properties = new Properties(); - if(params != null) { - for(Map.Entry curParameter: params.getParameters().entrySet()) { + if (params != null) { + for (Map.Entry curParameter : params.getParameters().entrySet()) { properties.setProperty(curParameter.getKey(), curParameter.getValue().getValue().toString()); } } return properties; } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/explore/support/JobExplorerFactoryBeanTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/explore/support/JobExplorerFactoryBeanTests.java index 305ed2dc4..7a04983f6 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/explore/support/JobExplorerFactoryBeanTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/explore/support/JobExplorerFactoryBeanTests.java @@ -33,7 +33,7 @@ import org.springframework.test.util.ReflectionTestUtils; /** * @author Dave Syer * @author Will Schipp - * + * */ public class JobExplorerFactoryBeanTests { @@ -52,24 +52,23 @@ public class JobExplorerFactoryBeanTests { factory.setTablePrefix(tablePrefix); } - - + @Test public void testDefaultJdbcOperations() throws Exception { - + factory.afterPropertiesSet(); JdbcOperations jdbcOperations = (JdbcOperations) ReflectionTestUtils.getField(factory, "jdbcOperations"); assertTrue(jdbcOperations instanceof JdbcTemplate); - } + } @Test public void testCustomJdbcOperations() throws Exception { - + JdbcOperations customJdbcOperations = mock(JdbcOperations.class); factory.setJdbcOperations(customJdbcOperations); factory.afterPropertiesSet(); assertEquals(customJdbcOperations, ReflectionTestUtils.getField(factory, "jdbcOperations")); - } + } @Test public void testMissingDataSource() throws Exception { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/explore/support/SimpleJobExplorerIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/explore/support/SimpleJobExplorerIntegrationTests.java index d7bc8078c..23b3f6739 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/explore/support/SimpleJobExplorerIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/explore/support/SimpleJobExplorerIntegrationTests.java @@ -60,23 +60,23 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; /** - * Integration test for the BATCH-2034 issue. - * The {@link FlowStep} execution should not fail in the remote partitioning use case because the {@link SimpleJobExplorer} - * doesn't retrieve the {@link JobInstance} from the {@link JobRepository}. - * To illustrate the issue the test simulates the behavior of the {@code StepExecutionRequestHandler} - * from the spring-batch-integration project. - * + * Integration test for the BATCH-2034 issue. The {@link FlowStep} execution should not + * fail in the remote partitioning use case because the {@link SimpleJobExplorer} doesn't + * retrieve the {@link JobInstance} from the {@link JobRepository}. To illustrate the + * issue the test simulates the behavior of the {@code StepExecutionRequestHandler} from + * the spring-batch-integration project. + * * @author Sergey Shcherbakov * @author Mahmoud Ben Hassine */ -@ContextConfiguration(classes={SimpleJobExplorerIntegrationTests.Config.class}) +@ContextConfiguration(classes = { SimpleJobExplorerIntegrationTests.Config.class }) @RunWith(SpringJUnit4ClassRunner.class) public class SimpleJobExplorerIntegrationTests { - + @Configuration @EnableBatchProcessing static class Config { - + @Autowired private StepBuilderFactory steps; @@ -84,14 +84,14 @@ public class SimpleJobExplorerIntegrationTests { public JobExplorer jobExplorer() throws Exception { return jobExplorerFactoryBean().getObject(); } - + @Bean public JobExplorerFactoryBean jobExplorerFactoryBean() { JobExplorerFactoryBean jobExplorerFactoryBean = new JobExplorerFactoryBean(); jobExplorerFactoryBean.setDataSource(dataSource()); return jobExplorerFactoryBean; } - + @Bean public Step flowStep() throws Exception { return steps.get("flowStep").flow(simpleFlow()).build(); @@ -107,11 +107,12 @@ public class SimpleJobExplorerIntegrationTests { SimpleFlow simpleFlow = new SimpleFlow("simpleFlow"); List transitions = new ArrayList<>(); transitions.add(StateTransition.createStateTransition(new StepState(dummyStep()), "end0")); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); + transitions + .add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); simpleFlow.setStateTransitions(transitions); return simpleFlow; } - + @Bean public BasicDataSource dataSource() { BasicDataSource dataSource = new BasicDataSource(); @@ -121,24 +122,22 @@ public class SimpleJobExplorerIntegrationTests { dataSource.setPassword(""); return dataSource; } - + @Bean public DataSourceInitializer dataSourceInitializer() { DataSourceInitializer dataSourceInitializer = new DataSourceInitializer(); dataSourceInitializer.setDataSource(dataSource()); - dataSourceInitializer.setInitScripts(new Resource[] { - new ClassPathResource("org/springframework/batch/core/schema-drop-hsqldb.sql"), - new ClassPathResource("org/springframework/batch/core/schema-hsqldb.sql") - }); + dataSourceInitializer.setInitScripts( + new Resource[] { new ClassPathResource("org/springframework/batch/core/schema-drop-hsqldb.sql"), + new ClassPathResource("org/springframework/batch/core/schema-hsqldb.sql") }); return dataSourceInitializer; } @Bean public Job job(JobBuilderFactory jobBuilderFactory) { - return jobBuilderFactory.get("job") - .start(dummyStep()) - .build(); + return jobBuilderFactory.get("job").start(dummyStep()).build(); } + } @Autowired @@ -155,19 +154,21 @@ public class SimpleJobExplorerIntegrationTests { @Autowired private Job job; - + @Test - public void testGetStepExecution() throws JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException, JobInterruptedException, UnexpectedJobExecutionException { + public void testGetStepExecution() throws JobExecutionAlreadyRunningException, JobRestartException, + JobInstanceAlreadyCompleteException, JobInterruptedException, UnexpectedJobExecutionException { // Prepare the jobRepository for the test JobExecution jobExecution = jobRepository.createJobExecution("myJob", new JobParameters()); StepExecution stepExecution = jobExecution.createStepExecution("flowStep"); jobRepository.add(stepExecution); - + // Executed on the remote end in remote partitioning use case - StepExecution jobExplorerStepExecution = jobExplorer.getStepExecution(jobExecution.getId(), stepExecution.getId()); + StepExecution jobExplorerStepExecution = jobExplorer.getStepExecution(jobExecution.getId(), + stepExecution.getId()); flowStep.execute(jobExplorerStepExecution); - + assertEquals(BatchStatus.COMPLETED, jobExplorerStepExecution.getStatus()); } @@ -180,4 +181,5 @@ public class SimpleJobExplorerIntegrationTests { StepExecution stepExecution = lastJobExecution.getStepExecutions().iterator().next(); assertNotNull(stepExecution.getExecutionContext()); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/explore/support/SimpleJobExplorerTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/explore/support/SimpleJobExplorerTests.java index fcdb50afd..3d9c9ff5f 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/explore/support/SimpleJobExplorerTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/explore/support/SimpleJobExplorerTests.java @@ -69,16 +69,14 @@ public class SimpleJobExplorerTests { stepExecutionDao = mock(StepExecutionDao.class); ecDao = mock(ExecutionContextDao.class); - jobExplorer = new SimpleJobExplorer(jobInstanceDao, jobExecutionDao, - stepExecutionDao, ecDao); + jobExplorer = new SimpleJobExplorer(jobInstanceDao, jobExecutionDao, stepExecutionDao, ecDao); } @Test public void testGetJobExecution() throws Exception { when(jobExecutionDao.getJobExecution(123L)).thenReturn(jobExecution); - when(jobInstanceDao.getJobInstance(jobExecution)).thenReturn( - jobInstance); + when(jobInstanceDao.getJobInstance(jobExecution)).thenReturn(jobInstance); stepExecutionDao.addStepExecutions(jobExecution); jobExplorer.getJobExecution(123L); } @@ -101,13 +99,11 @@ public class SimpleJobExplorerTests { when(jobExecutionDao.getJobExecution(jobExecution.getId())).thenReturn(jobExecution); when(jobInstanceDao.getJobInstance(jobExecution)).thenReturn(jobInstance); StepExecution stepExecution = jobExecution.createStepExecution("foo"); - when(stepExecutionDao.getStepExecution(jobExecution, 123L)) - .thenReturn(stepExecution); + when(stepExecutionDao.getStepExecution(jobExecution, 123L)).thenReturn(stepExecution); when(ecDao.getExecutionContext(stepExecution)).thenReturn(null); stepExecution = jobExplorer.getStepExecution(jobExecution.getId(), 123L); - assertEquals(jobInstance, - stepExecution.getJobExecution().getJobInstance()); + assertEquals(jobInstance, stepExecution.getJobExecution().getJobInstance()); verify(jobInstanceDao).getJobInstance(jobExecution); } @@ -115,8 +111,7 @@ public class SimpleJobExplorerTests { @Test public void testGetStepExecutionMissing() throws Exception { when(jobExecutionDao.getJobExecution(jobExecution.getId())).thenReturn(jobExecution); - when(stepExecutionDao.getStepExecution(jobExecution, 123L)) - .thenReturn(null); + when(stepExecutionDao.getStepExecution(jobExecution, 123L)).thenReturn(null); assertNull(jobExplorer.getStepExecution(jobExecution.getId(), 123L)); } @@ -129,10 +124,8 @@ public class SimpleJobExplorerTests { @Test public void testFindRunningJobExecutions() throws Exception { StepExecution stepExecution = jobExecution.createStepExecution("step"); - when(jobExecutionDao.findRunningJobExecutions("job")).thenReturn( - Collections.singleton(jobExecution)); - when(jobInstanceDao.getJobInstance(jobExecution)).thenReturn( - jobInstance); + when(jobExecutionDao.findRunningJobExecutions("job")).thenReturn(Collections.singleton(jobExecution)); + when(jobInstanceDao.getJobInstance(jobExecution)).thenReturn(jobInstance); stepExecutionDao.addStepExecutions(jobExecution); when(ecDao.getExecutionContext(jobExecution)).thenReturn(null); when(ecDao.getExecutionContext(stepExecution)).thenReturn(null); @@ -142,10 +135,8 @@ public class SimpleJobExplorerTests { @Test public void testFindJobExecutions() throws Exception { StepExecution stepExecution = jobExecution.createStepExecution("step"); - when(jobExecutionDao.findJobExecutions(jobInstance)).thenReturn( - Collections.singletonList(jobExecution)); - when(jobInstanceDao.getJobInstance(jobExecution)).thenReturn( - jobInstance); + when(jobExecutionDao.findJobExecutions(jobInstance)).thenReturn(Collections.singletonList(jobExecution)); + when(jobInstanceDao.getJobInstance(jobExecution)).thenReturn(jobInstance); stepExecutionDao.addStepExecutions(jobExecution); when(ecDao.getExecutionContext(jobExecution)).thenReturn(null); when(ecDao.getExecutionContext(stepExecution)).thenReturn(null); @@ -184,10 +175,11 @@ public class SimpleJobExplorerTests { assertEquals(4, jobExplorer.getJobInstanceCount("myJob")); } - @Test(expected=NoSuchJobException.class) + @Test(expected = NoSuchJobException.class) public void testGetJobInstanceCountException() throws Exception { when(jobInstanceDao.getJobInstanceCount("throwException")).thenThrow(new NoSuchJobException("expected")); jobExplorer.getJobInstanceCount("throwException"); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/CompositeJobParametersValidatorTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/CompositeJobParametersValidatorTests.java index 5e4b812a8..b6427ecd2 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/CompositeJobParametersValidatorTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/CompositeJobParametersValidatorTests.java @@ -29,40 +29,41 @@ import org.springframework.batch.core.JobParametersValidator; public class CompositeJobParametersValidatorTests { private CompositeJobParametersValidator compositeJobParametersValidator; + private JobParameters parameters = new JobParameters(); - + @Before - public void setUp(){ + public void setUp() { compositeJobParametersValidator = new CompositeJobParametersValidator(); } - - @Test(expected=IllegalArgumentException.class) - public void testValidatorsCanNotBeNull() throws Exception{ + + @Test(expected = IllegalArgumentException.class) + public void testValidatorsCanNotBeNull() throws Exception { compositeJobParametersValidator.setValidators(null); compositeJobParametersValidator.afterPropertiesSet(); } - - @Test(expected=IllegalArgumentException.class) - public void testValidatorsCanNotBeEmpty() throws Exception{ + + @Test(expected = IllegalArgumentException.class) + public void testValidatorsCanNotBeEmpty() throws Exception { compositeJobParametersValidator.setValidators(new ArrayList<>()); compositeJobParametersValidator.afterPropertiesSet(); } - + @Test - public void testDelegateIsInvoked() throws JobParametersInvalidException{ + public void testDelegateIsInvoked() throws JobParametersInvalidException { JobParametersValidator validator = mock(JobParametersValidator.class); validator.validate(parameters); compositeJobParametersValidator.setValidators(Arrays.asList(validator)); compositeJobParametersValidator.validate(parameters); } - + @Test - public void testDelegatesAreInvoked() throws JobParametersInvalidException{ + public void testDelegatesAreInvoked() throws JobParametersInvalidException { JobParametersValidator validator = mock(JobParametersValidator.class); validator.validate(parameters); validator.validate(parameters); compositeJobParametersValidator.setValidators(Arrays.asList(validator, validator)); compositeJobParametersValidator.validate(parameters); } - + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/DefaultJobParametersValidatorTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/DefaultJobParametersValidatorTests.java index 0a29a5ac6..fdaeab548 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/DefaultJobParametersValidatorTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/DefaultJobParametersValidatorTests.java @@ -1,76 +1,76 @@ -/* - * Copyright 2009 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.job; - -import org.junit.Test; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.JobParametersInvalidException; - -public class DefaultJobParametersValidatorTests { - - private DefaultJobParametersValidator validator = new DefaultJobParametersValidator(); - - @Test(expected = JobParametersInvalidException.class) - public void testValidateNull() throws Exception { - validator.validate(null); - } - - @Test - public void testValidateNoRequiredValues() throws Exception { - validator.validate(new JobParametersBuilder().addString("name", "foo").toJobParameters()); - } - - @Test - public void testValidateRequiredValues() throws Exception { - validator.setRequiredKeys(new String[] { "name", "value" }); - validator - .validate(new JobParametersBuilder().addString("name", "foo").addLong("value", 111L).toJobParameters()); - } - - @Test(expected = JobParametersInvalidException.class) - public void testValidateRequiredValuesMissing() throws Exception { - validator.setRequiredKeys(new String[] { "name", "value" }); - validator.validate(new JobParameters()); - } - - @Test - public void testValidateOptionalValues() throws Exception { - validator.setOptionalKeys(new String[] { "name", "value" }); - validator.validate(new JobParameters()); - } - - @Test(expected = JobParametersInvalidException.class) - public void testValidateOptionalWithImplicitRequiredKey() throws Exception { - validator.setOptionalKeys(new String[] { "name", "value" }); - validator.validate(new JobParametersBuilder().addString("foo", "bar").toJobParameters()); - } - - @Test - public void testValidateOptionalWithExplicitRequiredKey() throws Exception { - validator.setOptionalKeys(new String[] { "name", "value" }); - validator.setRequiredKeys(new String[] { "foo" }); - validator.validate(new JobParametersBuilder().addString("foo", "bar").toJobParameters()); - } - - @Test(expected = IllegalStateException.class) - public void testOptionalValuesAlsoRequired() throws Exception { - validator.setOptionalKeys(new String[] { "name", "value" }); - validator.setRequiredKeys(new String[] { "foo", "value" }); - validator.afterPropertiesSet(); - } - -} +/* + * Copyright 2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.job; + +import org.junit.Test; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.JobParametersBuilder; +import org.springframework.batch.core.JobParametersInvalidException; + +public class DefaultJobParametersValidatorTests { + + private DefaultJobParametersValidator validator = new DefaultJobParametersValidator(); + + @Test(expected = JobParametersInvalidException.class) + public void testValidateNull() throws Exception { + validator.validate(null); + } + + @Test + public void testValidateNoRequiredValues() throws Exception { + validator.validate(new JobParametersBuilder().addString("name", "foo").toJobParameters()); + } + + @Test + public void testValidateRequiredValues() throws Exception { + validator.setRequiredKeys(new String[] { "name", "value" }); + validator + .validate(new JobParametersBuilder().addString("name", "foo").addLong("value", 111L).toJobParameters()); + } + + @Test(expected = JobParametersInvalidException.class) + public void testValidateRequiredValuesMissing() throws Exception { + validator.setRequiredKeys(new String[] { "name", "value" }); + validator.validate(new JobParameters()); + } + + @Test + public void testValidateOptionalValues() throws Exception { + validator.setOptionalKeys(new String[] { "name", "value" }); + validator.validate(new JobParameters()); + } + + @Test(expected = JobParametersInvalidException.class) + public void testValidateOptionalWithImplicitRequiredKey() throws Exception { + validator.setOptionalKeys(new String[] { "name", "value" }); + validator.validate(new JobParametersBuilder().addString("foo", "bar").toJobParameters()); + } + + @Test + public void testValidateOptionalWithExplicitRequiredKey() throws Exception { + validator.setOptionalKeys(new String[] { "name", "value" }); + validator.setRequiredKeys(new String[] { "foo" }); + validator.validate(new JobParametersBuilder().addString("foo", "bar").toJobParameters()); + } + + @Test(expected = IllegalStateException.class) + public void testOptionalValuesAlsoRequired() throws Exception { + validator.setOptionalKeys(new String[] { "name", "value" }); + validator.setRequiredKeys(new String[] { "foo", "value" }); + validator.afterPropertiesSet(); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/ExtendedAbstractJobTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/ExtendedAbstractJobTests.java index c477ecdf6..e2bfd5e76 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/ExtendedAbstractJobTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/ExtendedAbstractJobTests.java @@ -51,14 +51,14 @@ import static org.junit.Assert.fail; public class ExtendedAbstractJobTests { private AbstractJob job; + private JobRepository jobRepository; @Before public void setUp() throws Exception { EmbeddedDatabase embeddedDatabase = new EmbeddedDatabaseBuilder() .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("/org/springframework/batch/core/schema-hsqldb.sql") - .build(); + .addScript("/org/springframework/batch/core/schema-hsqldb.sql").build(); JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); factory.setDataSource(embeddedDatabase); factory.setTransactionManager(new DataSourceTransactionManager(embeddedDatabase)); @@ -68,8 +68,7 @@ public class ExtendedAbstractJobTests { } /** - * Test method for - * {@link org.springframework.batch.core.job.AbstractJob#getName()}. + * Test method for {@link org.springframework.batch.core.job.AbstractJob#getName()}. */ @Test public void testGetName() { @@ -103,8 +102,7 @@ public class ExtendedAbstractJobTests { /** * Test method for - * {@link org.springframework.batch.core.job.AbstractJob#setRestartable(boolean)} - * . + * {@link org.springframework.batch.core.job.AbstractJob#setRestartable(boolean)} . */ @Test public void testSetRestartable() { @@ -151,7 +149,7 @@ public class ExtendedAbstractJobTests { assertEquals(BatchStatus.FAILED, execution.getStatus()); assertEquals("FOO", execution.getFailureExceptions().get(0).getMessage()); String description = execution.getExitStatus().getExitDescription(); - assertTrue("Wrong description: "+description, description.contains("FOO")); + assertTrue("Wrong description: " + description, description.contains("FOO")); } /** @@ -174,6 +172,7 @@ public class ExtendedAbstractJobTests { public void execute(StepExecution stepExecution) throws JobInterruptedException { stepExecution.getJobExecution().getExecutionContext().put(key, value); } + } job.setJobRepository(this.jobRepository); @@ -198,6 +197,7 @@ public class ExtendedAbstractJobTests { * */ private static class StubJob extends AbstractJob { + /** * @param name * @param jobRepository @@ -230,7 +230,7 @@ public class ExtendedAbstractJobTests { @Override public Collection getStepNames() { - return Collections. emptySet(); + return Collections.emptySet(); } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/JobSupport.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/JobSupport.java index 8a0b14a71..c369285cc 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/JobSupport.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/JobSupport.java @@ -34,10 +34,9 @@ import org.springframework.lang.Nullable; import org.springframework.util.ClassUtils; /** - * Batch domain object representing a job. Job is an explicit abstraction - * representing the configuration of a job specified by a developer. It should - * be noted that restart policy is applied to the job as a whole and not to a - * step. + * Batch domain object representing a job. Job is an explicit abstraction representing the + * configuration of a job specified by a developer. It should be noted that restart policy + * is applied to the job as a whole and not to a step. * * @author Lucas Ward * @author Dave Syer @@ -63,9 +62,7 @@ public class JobSupport implements BeanNameAware, Job, StepLocator { } /** - * Convenience constructor to immediately add name (which is mandatory but - * not final). - * + * Convenience constructor to immediately add name (which is mandatory but not final). * @param name */ public JobSupport(String name) { @@ -74,11 +71,11 @@ public class JobSupport implements BeanNameAware, Job, StepLocator { } /** - * Set the name property if it is not already set. Because of the order of - * the callbacks in a Spring container the name property will be set first - * if it is present. Care is needed with bean definition inheritance - if a - * parent bean has a name, then its children need an explicit name as well, - * otherwise they will not be unique. + * Set the name property if it is not already set. Because of the order of the + * callbacks in a Spring container the name property will be set first if it is + * present. Care is needed with bean definition inheritance - if a parent bean has a + * name, then its children need an explicit name as well, otherwise they will not be + * unique. * * @see org.springframework.beans.factory.BeanNameAware#setBeanName(java.lang.String) */ @@ -90,8 +87,8 @@ public class JobSupport implements BeanNameAware, Job, StepLocator { } /** - * Set the name property. Always overrides the default value if this object - * is a Spring bean. + * Set the name property. Always overrides the default value if this object is a + * Spring bean. * * @see #setBeanName(java.lang.String) */ @@ -157,8 +154,7 @@ public class JobSupport implements BeanNameAware, Job, StepLocator { /* * (non-Javadoc) * - * @see - * org.springframework.batch.core.domain.Job#run(org.springframework.batch + * @see org.springframework.batch.core.domain.Job#run(org.springframework.batch * .core.domain.JobExecution) */ @Override @@ -197,8 +193,10 @@ public class JobSupport implements BeanNameAware, Job, StepLocator { public Step getStep(String stepName) throws NoSuchStepException { final Step step = steps.get(stepName); if (step == null) { - throw new NoSuchStepException("Step ["+stepName+"] does not exist for job with name ["+getName()+"]"); + throw new NoSuchStepException( + "Step [" + stepName + "] does not exist for job with name [" + getName() + "]"); } return step; } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/SimpleJobFailureTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/SimpleJobFailureTests.java index 600fb75bc..eccfaef83 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/SimpleJobFailureTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/SimpleJobFailureTests.java @@ -37,11 +37,11 @@ import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; /** * Test suite for various failure scenarios during job processing. - * + * * @author Lucas Ward * @author Dave Syer * @author Mahmoud Ben Hassine - * + * */ public class SimpleJobFailureTests { @@ -53,8 +53,7 @@ public class SimpleJobFailureTests { public void init() throws Exception { EmbeddedDatabase embeddedDatabase = new EmbeddedDatabaseBuilder() .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("/org/springframework/batch/core/schema-hsqldb.sql") - .build(); + .addScript("/org/springframework/batch/core/schema-hsqldb.sql").build(); JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); factory.setDataSource(embeddedDatabase); factory.setTransactionManager(new DataSourceTransactionManager(embeddedDatabase)); @@ -66,17 +65,17 @@ public class SimpleJobFailureTests { @Test public void testStepFailure() throws Exception { - job.setSteps(Arrays. asList(new StepSupport("step"))); + job.setSteps(Arrays.asList(new StepSupport("step"))); job.execute(execution); assertEquals(BatchStatus.FAILED, execution.getStatus()); } @Test public void testStepStatusUnknown() throws Exception { - job.setSteps(Arrays. asList(new StepSupport("step1") { + job.setSteps(Arrays.asList(new StepSupport("step1") { @Override - public void execute(StepExecution stepExecution) throws JobInterruptedException, - UnexpectedJobExecutionException { + public void execute(StepExecution stepExecution) + throws JobInterruptedException, UnexpectedJobExecutionException { // This is what happens if the repository meta-data cannot be updated stepExecution.setStatus(BatchStatus.UNKNOWN); stepExecution.setTerminateOnly(); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/SimpleJobTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/SimpleJobTests.java index 08939045e..640584f38 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/SimpleJobTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/SimpleJobTests.java @@ -96,9 +96,7 @@ public class SimpleJobTests { public void setUp() throws Exception { EmbeddedDatabase embeddedDatabase = new EmbeddedDatabaseBuilder() .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("/org/springframework/batch/core/schema-hsqldb.sql") - .generateUniqueName(true) - .build(); + .addScript("/org/springframework/batch/core/schema-hsqldb.sql").generateUniqueName(true).build(); DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(embeddedDatabase); JobRepositoryFactoryBean repositoryFactoryBean = new JobRepositoryFactoryBean(); repositoryFactoryBean.setDataSource(embeddedDatabase); @@ -160,12 +158,11 @@ public class SimpleJobTests { } /** - * Test method for - * {@link SimpleJob#addStep(org.springframework.batch.core.Step)}. + * Test method for {@link SimpleJob#addStep(org.springframework.batch.core.Step)}. */ @Test public void testAddStep() { - job.setSteps(Collections. emptyList()); + job.setSteps(Collections.emptyList()); job.addStep(new StepSupport("step")); job.execute(jobExecution); assertEquals(1, jobExecution.getStepExecutions().size()); @@ -220,8 +217,9 @@ public class SimpleJobTests { assertFalse(step2.passedInJobContext.isEmpty()); // Observability - MeterRegistryAssert.assertThat(Metrics.globalRegistry) - .hasTimerWithNameAndTags(BatchJobObservation.BATCH_JOB_OBSERVATION.getName(), Tags.of(Tag.of("error", "none"), Tag.of("spring.batch.job.name", "testJob"), Tag.of("spring.batch.job.status", "COMPLETED"))); + MeterRegistryAssert.assertThat(Metrics.globalRegistry).hasTimerWithNameAndTags( + BatchJobObservation.BATCH_JOB_OBSERVATION.getName(), Tags.of(Tag.of("error", "none"), + Tag.of("spring.batch.job.name", "testJob"), Tag.of("spring.batch.job.status", "COMPLETED"))); } @After @@ -373,9 +371,9 @@ public class SimpleJobTests { steps.add(step1); steps.add(step2); // Two steps with the same name should both be executed, since - // the user might actually want it to happen twice. On a restart + // the user might actually want it to happen twice. On a restart // it would be executed twice again, even if it failed on the - // second execution. This seems reasonable. + // second execution. This seems reasonable. steps.add(step2); job.setSteps(steps); job.execute(jobExecution); @@ -390,8 +388,8 @@ public class SimpleJobTests { job.execute(jobExecution); ExitStatus exitStatus = jobExecution.getExitStatus(); - assertTrue("Wrong message in execution: " + exitStatus, exitStatus.getExitDescription().indexOf( - "no steps configured") >= 0); + assertTrue("Wrong message in execution: " + exitStatus, + exitStatus.getExitDescription().indexOf("no steps configured") >= 0); } @Test @@ -482,7 +480,8 @@ public class SimpleJobTests { * Check JobRepository to ensure status is being saved. */ private void checkRepository(BatchStatus status, ExitStatus exitStatus) { - assertEquals(jobInstance, this.jobRepository.getLastJobExecution(job.getName(), jobParameters).getJobInstance()); + assertEquals(jobInstance, + this.jobRepository.getLastJobExecution(job.getName(), jobParameters).getJobInstance()); JobExecution jobExecution = this.jobExplorer.getJobExecutions(jobInstance).get(0); assertEquals(jobInstance.getId(), jobExecution.getJobId()); assertEquals(status, jobExecution.getStatus()); @@ -536,8 +535,8 @@ public class SimpleJobTests { * springframework.batch.core.StepExecution) */ @Override - public void execute(StepExecution stepExecution) throws JobInterruptedException, - UnexpectedJobExecutionException { + public void execute(StepExecution stepExecution) + throws JobInterruptedException, UnexpectedJobExecutionException { passedInJobContext = new ExecutionContext(stepExecution.getJobExecution().getExecutionContext()); passedInStepContext = new ExecutionContext(stepExecution.getExecutionContext()); @@ -581,4 +580,5 @@ public class SimpleJobTests { } } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/SimpleStepHandlerTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/SimpleStepHandlerTests.java index 634b8b61a..33bacde29 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/SimpleStepHandlerTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/SimpleStepHandlerTests.java @@ -1,100 +1,99 @@ -/* - * Copyright 2006-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.core.job; - -import static org.junit.Assert.assertEquals; - -import org.junit.Before; -import org.junit.Test; -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobInterruptedException; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.repository.JobRepository; -import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; -import org.springframework.batch.core.step.StepSupport; -import org.springframework.jdbc.datasource.DataSourceTransactionManager; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; - -/** - * @author Dave Syer - * @author Mahmoud Ben Hassine - * - */ -public class SimpleStepHandlerTests { - - private JobRepository jobRepository; - - private JobExecution jobExecution; - - private SimpleStepHandler stepHandler; - - @Before - public void setUp() throws Exception { - EmbeddedDatabase embeddedDatabase = new EmbeddedDatabaseBuilder() - .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("/org/springframework/batch/core/schema-hsqldb.sql") - .build(); - JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); - factory.setDataSource(embeddedDatabase); - factory.setTransactionManager(new DataSourceTransactionManager(embeddedDatabase)); - factory.afterPropertiesSet(); - jobRepository = factory.getObject(); - jobExecution = jobRepository.createJobExecution("job", new JobParameters()); - stepHandler = new SimpleStepHandler(jobRepository); - stepHandler.afterPropertiesSet(); - } - - /** - * Test method for {@link SimpleStepHandler#afterPropertiesSet()}. - */ - @Test(expected = IllegalStateException.class) - public void testAfterPropertiesSet() throws Exception { - SimpleStepHandler stepHandler = new SimpleStepHandler(); - stepHandler.afterPropertiesSet(); - } - - /** - * Test method for - * {@link SimpleStepHandler#handleStep(org.springframework.batch.core.Step, org.springframework.batch.core.JobExecution)} - * . - */ - @Test - public void testHandleStep() throws Exception { - StepExecution stepExecution = stepHandler.handleStep(new StubStep("step"), jobExecution); - assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - } - - private class StubStep extends StepSupport { - - private StubStep(String name) { - super(name); - } - - @Override - public void execute(StepExecution stepExecution) throws JobInterruptedException { - stepExecution.setStatus(BatchStatus.COMPLETED); - stepExecution.setExitStatus(ExitStatus.COMPLETED); - jobRepository.update(stepExecution); - } - - } - -} +/* + * Copyright 2006-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.core.job; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobInterruptedException; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; +import org.springframework.batch.core.step.StepSupport; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; + +/** + * @author Dave Syer + * @author Mahmoud Ben Hassine + * + */ +public class SimpleStepHandlerTests { + + private JobRepository jobRepository; + + private JobExecution jobExecution; + + private SimpleStepHandler stepHandler; + + @Before + public void setUp() throws Exception { + EmbeddedDatabase embeddedDatabase = new EmbeddedDatabaseBuilder() + .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") + .addScript("/org/springframework/batch/core/schema-hsqldb.sql").build(); + JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); + factory.setDataSource(embeddedDatabase); + factory.setTransactionManager(new DataSourceTransactionManager(embeddedDatabase)); + factory.afterPropertiesSet(); + jobRepository = factory.getObject(); + jobExecution = jobRepository.createJobExecution("job", new JobParameters()); + stepHandler = new SimpleStepHandler(jobRepository); + stepHandler.afterPropertiesSet(); + } + + /** + * Test method for {@link SimpleStepHandler#afterPropertiesSet()}. + */ + @Test(expected = IllegalStateException.class) + public void testAfterPropertiesSet() throws Exception { + SimpleStepHandler stepHandler = new SimpleStepHandler(); + stepHandler.afterPropertiesSet(); + } + + /** + * Test method for + * {@link SimpleStepHandler#handleStep(org.springframework.batch.core.Step, org.springframework.batch.core.JobExecution)} + * . + */ + @Test + public void testHandleStep() throws Exception { + StepExecution stepExecution = stepHandler.handleStep(new StubStep("step"), jobExecution); + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + } + + private class StubStep extends StepSupport { + + private StubStep(String name) { + super(name); + } + + @Override + public void execute(StepExecution stepExecution) throws JobInterruptedException { + stepExecution.setStatus(BatchStatus.COMPLETED); + stepExecution.setExitStatus(ExitStatus.COMPLETED); + jobRepository.update(stepExecution); + } + + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/builder/FlowBuilderTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/builder/FlowBuilderTests.java index 2c90af41b..4ad546053 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/builder/FlowBuilderTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/builder/FlowBuilderTests.java @@ -39,7 +39,7 @@ import static org.junit.Assert.assertEquals; * @author Dave Syer * @author Michael Minella * @author Mahmoud Ben Hassine - * + * */ public class FlowBuilderTests { @@ -50,8 +50,8 @@ public class FlowBuilderTests { JobExecution execution = jobRepository.createJobExecution("foo", new JobParameters()); builder.start(new StepSupport("step") { @Override - public void execute(StepExecution stepExecution) throws JobInterruptedException, - UnexpectedJobExecutionException { + public void execute(StepExecution stepExecution) + throws JobInterruptedException, UnexpectedJobExecutionException { } }).end().start(new JobFlowExecutor(jobRepository, new SimpleStepHandler(jobRepository), execution)); } @@ -64,30 +64,28 @@ public class FlowBuilderTests { StepSupport stepA = new StepSupport("stepA") { @Override - public void execute(StepExecution stepExecution) throws JobInterruptedException, - UnexpectedJobExecutionException { + public void execute(StepExecution stepExecution) + throws JobInterruptedException, UnexpectedJobExecutionException { stepExecution.setExitStatus(new ExitStatus("FAILED")); } }; StepSupport stepB = new StepSupport("stepB") { @Override - public void execute(StepExecution stepExecution) throws JobInterruptedException, - UnexpectedJobExecutionException { + public void execute(StepExecution stepExecution) + throws JobInterruptedException, UnexpectedJobExecutionException { } }; StepSupport stepC = new StepSupport("stepC") { @Override - public void execute(StepExecution stepExecution) throws JobInterruptedException, - UnexpectedJobExecutionException { + public void execute(StepExecution stepExecution) + throws JobInterruptedException, UnexpectedJobExecutionException { } }; - FlowExecution flowExecution = builder.start(stepA) - .on("*").to(stepB) - .from(stepA).on("FAILED").to(stepC) - .end().start(new JobFlowExecutor(jobRepository, new SimpleStepHandler(jobRepository), execution)); + FlowExecution flowExecution = builder.start(stepA).on("*").to(stepB).from(stepA).on("FAILED").to(stepC).end() + .start(new JobFlowExecutor(jobRepository, new SimpleStepHandler(jobRepository), execution)); Iterator stepExecutions = execution.getStepExecutions().iterator(); StepExecution stepExecutionA = stepExecutions.next(); @@ -95,4 +93,5 @@ public class FlowBuilderTests { StepExecution stepExecutionC = stepExecutions.next(); assertEquals(stepExecutionC.getStepName(), "stepC"); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/builder/FlowJobBuilderTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/builder/FlowJobBuilderTests.java index 12d67c6e6..95b6cd5f9 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/builder/FlowJobBuilderTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/builder/FlowJobBuilderTests.java @@ -69,8 +69,8 @@ public class FlowJobBuilderTests { private StepSupport step1 = new StepSupport("step1") { @Override - public void execute(StepExecution stepExecution) throws JobInterruptedException, - UnexpectedJobExecutionException { + public void execute(StepExecution stepExecution) + throws JobInterruptedException, UnexpectedJobExecutionException { stepExecution.upgradeStatus(BatchStatus.COMPLETED); stepExecution.setExitStatus(ExitStatus.COMPLETED); jobRepository.update(stepExecution); @@ -79,8 +79,8 @@ public class FlowJobBuilderTests { private StepSupport fails = new StepSupport("fails") { @Override - public void execute(StepExecution stepExecution) throws JobInterruptedException, - UnexpectedJobExecutionException { + public void execute(StepExecution stepExecution) + throws JobInterruptedException, UnexpectedJobExecutionException { stepExecution.upgradeStatus(BatchStatus.FAILED); stepExecution.setExitStatus(ExitStatus.FAILED); jobRepository.update(stepExecution); @@ -89,8 +89,8 @@ public class FlowJobBuilderTests { private StepSupport step2 = new StepSupport("step2") { @Override - public void execute(StepExecution stepExecution) throws JobInterruptedException, - UnexpectedJobExecutionException { + public void execute(StepExecution stepExecution) + throws JobInterruptedException, UnexpectedJobExecutionException { stepExecution.upgradeStatus(BatchStatus.COMPLETED); stepExecution.setExitStatus(ExitStatus.COMPLETED); jobRepository.update(stepExecution); @@ -99,8 +99,8 @@ public class FlowJobBuilderTests { private StepSupport step3 = new StepSupport("step3") { @Override - public void execute(StepExecution stepExecution) throws JobInterruptedException, - UnexpectedJobExecutionException { + public void execute(StepExecution stepExecution) + throws JobInterruptedException, UnexpectedJobExecutionException { stepExecution.upgradeStatus(BatchStatus.COMPLETED); stepExecution.setExitStatus(ExitStatus.COMPLETED); jobRepository.update(stepExecution); @@ -111,8 +111,7 @@ public class FlowJobBuilderTests { public void init() throws Exception { EmbeddedDatabase embeddedDatabase = new EmbeddedDatabaseBuilder() .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("/org/springframework/batch/core/schema-hsqldb.sql") - .build(); + .addScript("/org/springframework/batch/core/schema-hsqldb.sql").build(); JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); factory.setDataSource(embeddedDatabase); factory.setTransactionManager(new DataSourceTransactionManager(embeddedDatabase)); @@ -123,8 +122,8 @@ public class FlowJobBuilderTests { @Test public void testBuildOnOneLine() throws Exception { - FlowJobBuilder builder = new JobBuilder("flow").repository(jobRepository).start(step1).on("COMPLETED") - .to(step2).end().preventRestart(); + FlowJobBuilder builder = new JobBuilder("flow").repository(jobRepository).start(step1).on("COMPLETED").to(step2) + .end().preventRestart(); builder.build().execute(execution); assertEquals(BatchStatus.COMPLETED, execution.getStatus()); assertEquals(2, execution.getStepExecutions().size()); @@ -141,8 +140,8 @@ public class FlowJobBuilderTests { @Test public void testBuildOverTwoLines() throws Exception { - FlowJobBuilder builder = new JobBuilder("flow").repository(jobRepository).start(step1).on("COMPLETED") - .to(step2).end(); + FlowJobBuilder builder = new JobBuilder("flow").repository(jobRepository).start(step1).on("COMPLETED").to(step2) + .end(); builder.preventRestart(); builder.build().execute(execution); assertEquals(BatchStatus.COMPLETED, execution.getStatus()); @@ -182,25 +181,27 @@ public class FlowJobBuilderTests { assertEquals(2, execution.getStepExecutions().size()); } - @Test - public void testBuildSplit_BATCH_2282() throws Exception { - Flow flow1 = new FlowBuilder("subflow1").from(step1).end(); - Flow flow2 = new FlowBuilder("subflow2").from(step2).end(); - Flow splitFlow = new FlowBuilder("splitflow").split(new SimpleAsyncTaskExecutor()).add(flow1, flow2).build(); - FlowJobBuilder builder = new JobBuilder("flow").repository(jobRepository).start(splitFlow).end(); - builder.preventRestart().build().execute(execution); - assertEquals(BatchStatus.COMPLETED, execution.getStatus()); - assertEquals(2, execution.getStepExecutions().size()); - } + @Test + public void testBuildSplit_BATCH_2282() throws Exception { + Flow flow1 = new FlowBuilder("subflow1").from(step1).end(); + Flow flow2 = new FlowBuilder("subflow2").from(step2).end(); + Flow splitFlow = new FlowBuilder("splitflow").split(new SimpleAsyncTaskExecutor()).add(flow1, flow2) + .build(); + FlowJobBuilder builder = new JobBuilder("flow").repository(jobRepository).start(splitFlow).end(); + builder.preventRestart().build().execute(execution); + assertEquals(BatchStatus.COMPLETED, execution.getStatus()); + assertEquals(2, execution.getStepExecutions().size()); + } @Test public void testBuildDecision() throws Exception { JobExecutionDecider decider = new JobExecutionDecider() { private int count = 0; + @Override public FlowExecutionStatus decide(JobExecution jobExecution, @Nullable StepExecution stepExecution) { count++; - return count<2 ? new FlowExecutionStatus("ONGOING") : FlowExecutionStatus.COMPLETED; + return count < 2 ? new FlowExecutionStatus("ONGOING") : FlowExecutionStatus.COMPLETED; } }; step1.setAllowStartIfComplete(true); @@ -273,9 +274,7 @@ public class FlowJobBuilderTests { ApplicationContext context = new AnnotationConfigApplicationContext(JobConfiguration.class); JobLauncher jobLauncher = context.getBean(JobLauncher.class); Job job = context.getBean(Job.class); - JobParameters jobParameters = new JobParametersBuilder() - .addLong("chunkSize", 2L) - .toJobParameters(); + JobParameters jobParameters = new JobParametersBuilder().addLong("chunkSize", 2L).toJobParameters(); // when JobExecution jobExecution = jobLauncher.run(job, jobParameters); @@ -291,30 +290,23 @@ public class FlowJobBuilderTests { @Bean @JobScope public Step step(StepBuilderFactory stepBuilderFactory, - @Value("#{jobParameters['chunkSize']}") Integer chunkSize) { - return stepBuilderFactory.get("step") - .chunk(chunkSize) - .reader(new ListItemReader<>(Arrays.asList(1, 2, 3, 4))) - .writer(items -> {}) - .build(); + @Value("#{jobParameters['chunkSize']}") Integer chunkSize) { + return stepBuilderFactory.get("step").chunk(chunkSize) + .reader(new ListItemReader<>(Arrays.asList(1, 2, 3, 4))).writer(items -> { + }).build(); } @Bean public Job job(JobBuilderFactory jobBuilderFactory) { - return jobBuilderFactory.get("job") - .flow(step(null, null)) - .build() - .build(); + return jobBuilderFactory.get("job").flow(step(null, null)).build().build(); } @Bean public DataSource dataSource() { - return new EmbeddedDatabaseBuilder() - .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("/org/springframework/batch/core/schema-hsqldb.sql") - .generateUniqueName(true) - .build(); + return new EmbeddedDatabaseBuilder().addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") + .addScript("/org/springframework/batch/core/schema-hsqldb.sql").generateUniqueName(true).build(); } + } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/builder/JobBuilderTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/builder/JobBuilderTests.java index a7873b9b9..406b39bbb 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/builder/JobBuilderTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/builder/JobBuilderTests.java @@ -67,30 +67,27 @@ public class JobBuilderTests { @Configuration @EnableBatchProcessing static class MyJobConfiguration { + @Bean public Job job(JobBuilderFactory jobs, StepBuilderFactory steps) { - return jobs.get("job") - .listener(new InterfaceBasedJobExecutionListener()) + return jobs.get("job").listener(new InterfaceBasedJobExecutionListener()) .listener(new AnnotationBasedJobExecutionListener()) - .start(steps.get("step") - .tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED) - .build()) + .start(steps.get("step").tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED).build()) .build(); } @Bean public DataSource dataSource() { - return new EmbeddedDatabaseBuilder() - .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("/org/springframework/batch/core/schema-hsqldb.sql") - .generateUniqueName(true) - .build(); + return new EmbeddedDatabaseBuilder().addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") + .addScript("/org/springframework/batch/core/schema-hsqldb.sql").generateUniqueName(true).build(); } + } - + static class InterfaceBasedJobExecutionListener implements JobExecutionListener { public static int beforeJobCount = 0; + public static int afterJobCount = 0; @Override @@ -102,13 +99,15 @@ public class JobBuilderTests { public void afterJob(JobExecution jobExecution) { afterJobCount++; } + } static class AnnotationBasedJobExecutionListener { public static int beforeJobCount = 0; + public static int afterJobCount = 0; - + @BeforeJob public void beforeJob(JobExecution jobExecution) { beforeJobCount++; @@ -118,6 +117,7 @@ public class JobBuilderTests { public void afterJob(JobExecution jobExecution) { afterJobCount++; } + } } \ No newline at end of file diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/FlowExecutionExceptionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/FlowExecutionExceptionTests.java index 04415a3e3..8f281cf69 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/FlowExecutionExceptionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/FlowExecutionExceptionTests.java @@ -36,7 +36,8 @@ public class FlowExecutionExceptionTests { } /** - * Test method for {@link FlowExecutionException#FlowExecutionException(String, Throwable)}. + * Test method for + * {@link FlowExecutionException#FlowExecutionException(String, Throwable)}. */ @Test public void testFlowExecutionExceptionStringThrowable() { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/FlowExecutionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/FlowExecutionTests.java index 112caba58..81056435a 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/FlowExecutionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/FlowExecutionTests.java @@ -23,55 +23,55 @@ import org.springframework.batch.core.job.flow.FlowExecution; /** * @author Dave Syer - * + * */ public class FlowExecutionTests { - + @Test public void testBasicProperties() throws Exception { FlowExecution execution = new FlowExecution("foo", new FlowExecutionStatus("BAR")); - assertEquals("foo",execution.getName()); - assertEquals("BAR",execution.getStatus().getName()); + assertEquals("foo", execution.getName()); + assertEquals("BAR", execution.getStatus().getName()); } @Test public void testAlphaOrdering() throws Exception { FlowExecution first = new FlowExecution("foo", new FlowExecutionStatus("BAR")); FlowExecution second = new FlowExecution("foo", new FlowExecutionStatus("SPAM")); - assertTrue("Should be negative",first.compareTo(second)<0); - assertTrue("Should be positive",second.compareTo(first)>0); + assertTrue("Should be negative", first.compareTo(second) < 0); + assertTrue("Should be positive", second.compareTo(first) > 0); } @Test public void testEnumOrdering() throws Exception { FlowExecution first = new FlowExecution("foo", FlowExecutionStatus.COMPLETED); FlowExecution second = new FlowExecution("foo", FlowExecutionStatus.FAILED); - assertTrue("Should be negative",first.compareTo(second)<0); - assertTrue("Should be positive",second.compareTo(first)>0); + assertTrue("Should be negative", first.compareTo(second) < 0); + assertTrue("Should be positive", second.compareTo(first) > 0); } @Test public void testEnumStartsWithOrdering() throws Exception { FlowExecution first = new FlowExecution("foo", new FlowExecutionStatus("COMPLETED.BAR")); FlowExecution second = new FlowExecution("foo", new FlowExecutionStatus("FAILED.FOO")); - assertTrue("Should be negative",first.compareTo(second)<0); - assertTrue("Should be positive",second.compareTo(first)>0); + assertTrue("Should be negative", first.compareTo(second) < 0); + assertTrue("Should be positive", second.compareTo(first) > 0); } @Test public void testEnumStartsWithAlphaOrdering() throws Exception { FlowExecution first = new FlowExecution("foo", new FlowExecutionStatus("COMPLETED.BAR")); FlowExecution second = new FlowExecution("foo", new FlowExecutionStatus("COMPLETED.FOO")); - assertTrue("Should be negative",first.compareTo(second)<0); - assertTrue("Should be positive",second.compareTo(first)>0); + assertTrue("Should be negative", first.compareTo(second) < 0); + assertTrue("Should be positive", second.compareTo(first) > 0); } @Test public void testEnumAndAlpha() throws Exception { FlowExecution first = new FlowExecution("foo", new FlowExecutionStatus("ZZZZZ")); FlowExecution second = new FlowExecution("foo", new FlowExecutionStatus("FAILED.FOO")); - assertTrue("Should be negative",first.compareTo(second)<0); - assertTrue("Should be positive",second.compareTo(first)>0); + assertTrue("Should be negative", first.compareTo(second) < 0); + assertTrue("Should be positive", second.compareTo(first) > 0); } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/FlowJobFailureTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/FlowJobFailureTests.java index 193bf07ad..2794aa5cd 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/FlowJobFailureTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/FlowJobFailureTests.java @@ -42,11 +42,11 @@ import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; /** * Test suite for various failure scenarios during job processing. - * + * * @author Lucas Ward * @author Dave Syer * @author Mahmoud Ben Hassine - * + * */ public class FlowJobFailureTests { @@ -58,8 +58,7 @@ public class FlowJobFailureTests { public void init() throws Exception { EmbeddedDatabase embeddedDatabase = new EmbeddedDatabaseBuilder() .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("/org/springframework/batch/core/schema-hsqldb.sql") - .build(); + .addScript("/org/springframework/batch/core/schema-hsqldb.sql").build(); JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); factory.setDataSource(embeddedDatabase); factory.setTransactionManager(new DataSourceTransactionManager(embeddedDatabase)); @@ -91,8 +90,8 @@ public class FlowJobFailureTests { List transitions = new ArrayList<>(); StepState step = new StepState(new StepSupport("step") { @Override - public void execute(StepExecution stepExecution) throws JobInterruptedException, - UnexpectedJobExecutionException { + public void execute(StepExecution stepExecution) + throws JobInterruptedException, UnexpectedJobExecutionException { // This is what happens if the repository meta-data cannot be // updated stepExecution.setExitStatus(ExitStatus.UNKNOWN); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/FlowJobTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/FlowJobTests.java index 0b36f4083..780eca10c 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/FlowJobTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/FlowJobTests.java @@ -1,734 +1,734 @@ -/* - * Copyright 2006-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.job.flow; - -import org.junit.Before; -import org.junit.Test; -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobInstance; -import org.springframework.batch.core.JobInterruptedException; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.Step; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.explore.JobExplorer; -import org.springframework.batch.core.explore.support.JobExplorerFactoryBean; -import org.springframework.batch.core.job.flow.support.DefaultStateTransitionComparator; -import org.springframework.batch.core.job.flow.support.SimpleFlow; -import org.springframework.batch.core.job.flow.support.StateTransition; -import org.springframework.batch.core.job.flow.support.state.DecisionState; -import org.springframework.batch.core.job.flow.support.state.EndState; -import org.springframework.batch.core.job.flow.support.state.FlowState; -import org.springframework.batch.core.job.flow.support.state.SplitState; -import org.springframework.batch.core.job.flow.support.state.StepState; -import org.springframework.batch.core.repository.JobRepository; -import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; -import org.springframework.batch.core.step.StepSupport; -import org.springframework.jdbc.datasource.DataSourceTransactionManager; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; -import org.springframework.lang.Nullable; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.fail; - -/** - * @author Dave Syer - * @author Michael Minella - * @author Mahmoud Ben Hassine - * - */ -public class FlowJobTests { - - private FlowJob job = new FlowJob(); - - private JobExecution jobExecution; - - private JobRepository jobRepository; - - private JobExplorer jobExplorer; - - private boolean fail = false; - - @Before - public void setUp() throws Exception { - EmbeddedDatabase embeddedDatabase = new EmbeddedDatabaseBuilder() - .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("/org/springframework/batch/core/schema-hsqldb.sql") - .build(); - JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); - factory.setDataSource(embeddedDatabase); - factory.setTransactionManager(new DataSourceTransactionManager(embeddedDatabase)); - factory.afterPropertiesSet(); - this.jobRepository = factory.getObject(); - job.setJobRepository(this.jobRepository); - this.jobExecution = this.jobRepository.createJobExecution("job", new JobParameters()); - - JobExplorerFactoryBean explorerFactoryBean = new JobExplorerFactoryBean(); - explorerFactoryBean.setDataSource(embeddedDatabase); - explorerFactoryBean.afterPropertiesSet(); - this.jobExplorer = explorerFactoryBean.getObject(); - } - - @Test - public void testGetSteps() throws Exception { - SimpleFlow flow = new SimpleFlow("job"); - List transitions = new ArrayList<>(); - transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "step2")); - transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2")), "end0")); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); - flow.setStateTransitions(transitions); - flow.afterPropertiesSet(); - job.setFlow(flow); - job.afterPropertiesSet(); - assertEquals(2, job.getStepNames().size()); - } - - @Test - public void testTwoSteps() throws Exception { - SimpleFlow flow = new SimpleFlow("job"); - List transitions = new ArrayList<>(); - transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "step2")); - StepState step2 = new StepState(new StubStep("step2")); - transitions.add(StateTransition.createStateTransition(step2, ExitStatus.FAILED.getExitCode(), "end0")); - transitions.add(StateTransition.createStateTransition(step2, ExitStatus.COMPLETED.getExitCode(), "end1")); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end0"))); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end1"))); - flow.setStateTransitions(transitions); - job.setFlow(flow); - job.afterPropertiesSet(); - job.doExecute(jobExecution); - StepExecution stepExecution = getStepExecution(jobExecution, "step2"); - assertEquals(ExitStatus.COMPLETED, stepExecution.getExitStatus()); - assertEquals(2, jobExecution.getStepExecutions().size()); - } - - @Test - public void testFailedStep() throws Exception { - SimpleFlow flow = new SimpleFlow("job"); - List transitions = new ArrayList<>(); - transitions.add(StateTransition.createStateTransition(new StateSupport("step1", FlowExecutionStatus.FAILED), - "step2")); - StepState step2 = new StepState(new StubStep("step2")); - transitions.add(StateTransition.createStateTransition(step2, ExitStatus.FAILED.getExitCode(), "end0")); - transitions.add(StateTransition.createStateTransition(step2, ExitStatus.COMPLETED.getExitCode(), "end1")); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end0"))); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end1"))); - flow.setStateTransitions(transitions); - job.setFlow(flow); - job.afterPropertiesSet(); - job.doExecute(jobExecution); - StepExecution stepExecution = getStepExecution(jobExecution, "step2"); - assertEquals(ExitStatus.COMPLETED, stepExecution.getExitStatus()); - assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - assertEquals(2, jobExecution.getStepExecutions().size()); - } - - @Test - public void testFailedStepRestarted() throws Exception { - SimpleFlow flow = new SimpleFlow("job"); - List transitions = new ArrayList<>(); - transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "step2")); - State step2State = new StateSupport("step2") { - @Override - public FlowExecutionStatus handle(FlowExecutor executor) throws Exception { - JobExecution jobExecution = executor.getJobExecution(); - jobExecution.createStepExecution(getName()); - if (fail) { - return FlowExecutionStatus.FAILED; - } - else { - return FlowExecutionStatus.COMPLETED; - } - } - }; - transitions.add(StateTransition.createStateTransition(step2State, ExitStatus.COMPLETED.getExitCode(), "end0")); - transitions.add(StateTransition.createStateTransition(step2State, ExitStatus.FAILED.getExitCode(), "end1")); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end1"))); - flow.setStateTransitions(transitions); - job.setFlow(flow); - job.afterPropertiesSet(); - fail = true; - job.execute(jobExecution); - assertEquals(ExitStatus.FAILED, jobExecution.getExitStatus()); - assertEquals(2, jobExecution.getStepExecutions().size()); - jobRepository.update(jobExecution); - jobExecution = jobRepository.createJobExecution("job", new JobParameters()); - fail = false; - job.execute(jobExecution); - assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus()); - assertEquals(1, jobExecution.getStepExecutions().size()); - } - - @Test - public void testStoppingStep() throws Exception { - SimpleFlow flow = new SimpleFlow("job"); - List transitions = new ArrayList<>(); - transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "step2")); - State state2 = new StateSupport("step2", FlowExecutionStatus.FAILED); - transitions.add(StateTransition.createStateTransition(state2, ExitStatus.FAILED.getExitCode(), "end0")); - transitions.add(StateTransition.createStateTransition(state2, ExitStatus.COMPLETED.getExitCode(), "end1")); - transitions.add(StateTransition.createStateTransition(new EndState(FlowExecutionStatus.STOPPED, "end0"), - "step3")); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end1"))); - transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step3")), "end2")); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end2"))); - flow.setStateTransitions(transitions); - job.setFlow(flow); - job.afterPropertiesSet(); - job.doExecute(jobExecution); - assertEquals(2, jobExecution.getStepExecutions().size()); - assertEquals(BatchStatus.STOPPED, jobExecution.getStatus()); - } - - @Test - public void testInterrupted() throws Exception { - SimpleFlow flow = new SimpleFlow("job"); - List transitions = new ArrayList<>(); - transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1") { - @Override - public void execute(StepExecution stepExecution) throws JobInterruptedException { - stepExecution.setStatus(BatchStatus.STOPPING); - jobRepository.update(stepExecution); - } - }), "end0")); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); - flow.setStateTransitions(transitions); - flow.afterPropertiesSet(); - job.setFlow(flow); - job.afterPropertiesSet(); - job.execute(jobExecution); - assertEquals(BatchStatus.STOPPED, jobExecution.getStatus()); - checkRepository(BatchStatus.STOPPED, ExitStatus.STOPPED); - assertEquals(1, jobExecution.getAllFailureExceptions().size()); - assertEquals(JobInterruptedException.class, jobExecution.getFailureExceptions().get(0).getClass()); - } - - @Test - public void testUnknownStatusStopsJob() throws Exception { - SimpleFlow flow = new SimpleFlow("job"); - List transitions = new ArrayList<>(); - transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1") { - @Override - public void execute(StepExecution stepExecution) throws JobInterruptedException { - stepExecution.setStatus(BatchStatus.UNKNOWN); - stepExecution.setTerminateOnly(); - jobRepository.update(stepExecution); - } - }), "step2")); - transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2")), "end0")); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); - flow.setStateTransitions(transitions); - flow.afterPropertiesSet(); - job.setFlow(flow); - job.afterPropertiesSet(); - job.execute(jobExecution); - assertEquals(BatchStatus.UNKNOWN, jobExecution.getStatus()); - checkRepository(BatchStatus.UNKNOWN, ExitStatus.STOPPED); - assertEquals(1, jobExecution.getAllFailureExceptions().size()); - assertEquals(JobInterruptedException.class, jobExecution.getFailureExceptions().get(0).getClass()); - } - - @Test - public void testInterruptedSplit() throws Exception { - SimpleFlow flow = new SimpleFlow("job"); - SimpleFlow flow1 = new SimpleFlow("flow1"); - SimpleFlow flow2 = new SimpleFlow("flow2"); - - List transitions = new ArrayList<>(); - transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1") { - @Override - public void execute(StepExecution stepExecution) throws JobInterruptedException { - if (!stepExecution.getJobExecution().getExecutionContext().containsKey("STOPPED")) { - stepExecution.getJobExecution().getExecutionContext().put("STOPPED", true); - stepExecution.setStatus(BatchStatus.STOPPED); - jobRepository.update(stepExecution); - } - else { - fail("The Job should have stopped by now"); - } - } - }), "end0")); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); - flow1.setStateTransitions(new ArrayList<>(transitions)); - flow1.afterPropertiesSet(); - flow2.setStateTransitions(new ArrayList<>(transitions)); - flow2.afterPropertiesSet(); - - transitions = new ArrayList<>(); - transitions.add(StateTransition.createStateTransition(new SplitState(Arrays. asList(flow1, flow2), - "split"), "end0")); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); - flow.setStateTransitions(transitions); - flow.afterPropertiesSet(); - - job.setFlow(flow); - job.afterPropertiesSet(); - job.execute(jobExecution); - assertEquals(BatchStatus.STOPPED, jobExecution.getStatus()); - checkRepository(BatchStatus.STOPPED, ExitStatus.STOPPED); - assertEquals(1, jobExecution.getAllFailureExceptions().size()); - assertEquals(JobInterruptedException.class, jobExecution.getFailureExceptions().get(0).getClass()); - assertEquals(1, jobExecution.getStepExecutions().size()); - for (StepExecution stepExecution : jobExecution.getStepExecutions()) { - assertEquals(BatchStatus.STOPPED, stepExecution.getStatus()); - } - } - - @Test - public void testInterruptedException() throws Exception { - SimpleFlow flow = new SimpleFlow("job"); - List transitions = new ArrayList<>(); - transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1") { - @Override - public void execute(StepExecution stepExecution) throws JobInterruptedException { - throw new JobInterruptedException("Stopped"); - } - }), "end0")); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); - flow.setStateTransitions(transitions); - flow.afterPropertiesSet(); - job.setFlow(flow); - job.afterPropertiesSet(); - job.execute(jobExecution); - assertEquals(BatchStatus.STOPPED, jobExecution.getStatus()); - checkRepository(BatchStatus.STOPPED, ExitStatus.STOPPED); - assertEquals(1, jobExecution.getAllFailureExceptions().size()); - assertEquals(JobInterruptedException.class, jobExecution.getFailureExceptions().get(0).getClass()); - } - - @Test - public void testInterruptedSplitException() throws Exception { - SimpleFlow flow = new SimpleFlow("job"); - SimpleFlow flow1 = new SimpleFlow("flow1"); - SimpleFlow flow2 = new SimpleFlow("flow2"); - - List transitions = new ArrayList<>(); - transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1") { - @Override - public void execute(StepExecution stepExecution) throws JobInterruptedException { - throw new JobInterruptedException("Stopped"); - } - }), "end0")); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); - flow1.setStateTransitions(new ArrayList<>(transitions)); - flow1.afterPropertiesSet(); - flow2.setStateTransitions(new ArrayList<>(transitions)); - flow2.afterPropertiesSet(); - - transitions = new ArrayList<>(); - transitions.add(StateTransition.createStateTransition(new SplitState(Arrays. asList(flow1, flow2), - "split"), "end0")); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); - flow.setStateTransitions(transitions); - flow.afterPropertiesSet(); - - job.setFlow(flow); - job.afterPropertiesSet(); - job.execute(jobExecution); - assertEquals(BatchStatus.STOPPED, jobExecution.getStatus()); - checkRepository(BatchStatus.STOPPED, ExitStatus.STOPPED); - assertEquals(1, jobExecution.getAllFailureExceptions().size()); - assertEquals(JobInterruptedException.class, jobExecution.getFailureExceptions().get(0).getClass()); - } - - @Test - public void testEndStateStopped() throws Exception { - SimpleFlow flow = new SimpleFlow("job"); - List transitions = new ArrayList<>(); - transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "end")); - transitions.add(StateTransition - .createStateTransition(new EndState(FlowExecutionStatus.STOPPED, "end"), "step2")); - StepState step2 = new StepState(new StubStep("step2")); - transitions.add(StateTransition.createStateTransition(step2, ExitStatus.FAILED.getExitCode(), "end0")); - transitions.add(StateTransition.createStateTransition(step2, ExitStatus.COMPLETED.getExitCode(), "end1")); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end0"))); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end1"))); - flow.setStateTransitions(transitions); - job.setFlow(flow); - job.afterPropertiesSet(); - job.doExecute(jobExecution); - assertEquals(1, jobExecution.getStepExecutions().size()); - assertEquals(BatchStatus.STOPPED, jobExecution.getStatus()); - } - - public void testEndStateFailed() throws Exception { - SimpleFlow flow = new SimpleFlow("job"); - List transitions = new ArrayList<>(); - transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "end")); - transitions - .add(StateTransition.createStateTransition(new EndState(FlowExecutionStatus.FAILED, "end"), "step2")); - transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2")), ExitStatus.FAILED - .getExitCode(), "end0")); - transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2")), - ExitStatus.COMPLETED.getExitCode(), "end1")); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end0"))); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end1"))); - flow.setStateTransitions(transitions); - job.setFlow(flow); - job.afterPropertiesSet(); - job.doExecute(jobExecution); - assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); - assertEquals(1, jobExecution.getStepExecutions().size()); - } - - @Test - public void testEndStateStoppedWithRestart() throws Exception { - SimpleFlow flow = new SimpleFlow("job"); - List transitions = new ArrayList<>(); - transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "end")); - transitions.add(StateTransition - .createStateTransition(new EndState(FlowExecutionStatus.STOPPED, "end"), "step2")); - StepState step2 = new StepState(new StubStep("step2")); - transitions.add(StateTransition.createStateTransition(step2, ExitStatus.COMPLETED.getExitCode(), "end0")); - transitions.add(StateTransition.createStateTransition(step2, ExitStatus.FAILED.getExitCode(), "end1")); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end1"))); - flow.setStateTransitions(transitions); - job.setFlow(flow); - job.afterPropertiesSet(); - - // To test a restart we have to use the AbstractJob.execute()... - job.execute(jobExecution); - assertEquals(BatchStatus.STOPPED, jobExecution.getStatus()); - assertEquals(1, jobExecution.getStepExecutions().size()); - - jobExecution = jobRepository.createJobExecution("job", new JobParameters()); - job.execute(jobExecution); - assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); - assertEquals(1, jobExecution.getStepExecutions().size()); - - } - - @Test - public void testBranching() throws Exception { - SimpleFlow flow = new SimpleFlow("job"); - List transitions = new ArrayList<>(); - StepState step1 = new StepState(new StubStep("step1")); - transitions.add(StateTransition.createStateTransition(step1, "step2")); - transitions.add(StateTransition.createStateTransition(step1, "COMPLETED", "step3")); - StepState step2 = new StepState(new StubStep("step2")); - transitions.add(StateTransition.createStateTransition(step2, ExitStatus.COMPLETED.getExitCode(), "end0")); - transitions.add(StateTransition.createStateTransition(step2, ExitStatus.FAILED.getExitCode(), "end1")); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end1"))); - StepState step3 = new StepState(new StubStep("step3")); - transitions.add(StateTransition.createStateTransition(step3, ExitStatus.FAILED.getExitCode(), "end2")); - transitions.add(StateTransition.createStateTransition(step3, ExitStatus.COMPLETED.getExitCode(), "end3")); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end2"))); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end3"))); - flow.setStateTransitions(transitions); - flow.setStateTransitionComparator(new DefaultStateTransitionComparator()); - job.setFlow(flow); - job.afterPropertiesSet(); - job.doExecute(jobExecution); - StepExecution stepExecution = getStepExecution(jobExecution, "step3"); - assertEquals(ExitStatus.COMPLETED, stepExecution.getExitStatus()); - assertEquals(2, jobExecution.getStepExecutions().size()); - } - - @Test - public void testBasicFlow() throws Throwable { - SimpleFlow flow = new SimpleFlow("job"); - List transitions = new ArrayList<>(); - transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step")), "end0")); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); - flow.setStateTransitions(transitions); - job.setFlow(flow); - job.execute(jobExecution); - if (!jobExecution.getAllFailureExceptions().isEmpty()) { - throw jobExecution.getAllFailureExceptions().get(0); - } - assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); - } - - @Test - public void testDecisionFlow() throws Throwable { - - SimpleFlow flow = new SimpleFlow("job"); - JobExecutionDecider decider = new JobExecutionDecider() { - @Override - public FlowExecutionStatus decide(JobExecution jobExecution, @Nullable StepExecution stepExecution) { - assertNotNull(stepExecution); - return new FlowExecutionStatus("SWITCH"); - } - }; - - List transitions = new ArrayList<>(); - transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "decision")); - DecisionState decision = new DecisionState(decider, "decision"); - transitions.add(StateTransition.createStateTransition(decision, "step2")); - transitions.add(StateTransition.createStateTransition(decision, "SWITCH", "step3")); - StepState step2 = new StepState(new StubStep("step2")); - transitions.add(StateTransition.createStateTransition(step2, ExitStatus.COMPLETED.getExitCode(), "end0")); - transitions.add(StateTransition.createStateTransition(step2, ExitStatus.FAILED.getExitCode(), "end1")); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end1"))); - StepState step3 = new StepState(new StubStep("step3")); - transitions.add(StateTransition.createStateTransition(step3, ExitStatus.FAILED.getExitCode(), "end2")); - transitions.add(StateTransition.createStateTransition(step3, ExitStatus.COMPLETED.getExitCode(), "end3")); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end2"))); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end3"))); - flow.setStateTransitions(transitions); - flow.setStateTransitionComparator(new DefaultStateTransitionComparator()); - - job.setFlow(flow); - job.doExecute(jobExecution); - StepExecution stepExecution = getStepExecution(jobExecution, "step3"); - if (!jobExecution.getAllFailureExceptions().isEmpty()) { - throw jobExecution.getAllFailureExceptions().get(0); - } - - assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - assertEquals(2, jobExecution.getStepExecutions().size()); - - } - - @Test - public void testDecisionFlowWithExceptionInDecider() throws Throwable { - - SimpleFlow flow = new SimpleFlow("job"); - JobExecutionDecider decider = new JobExecutionDecider() { - @Override - public FlowExecutionStatus decide(JobExecution jobExecution, @Nullable StepExecution stepExecution) { - assertNotNull(stepExecution); - throw new RuntimeException("Foo"); - } - }; - - List transitions = new ArrayList<>(); - transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "decision")); - DecisionState decision = new DecisionState(decider, "decision"); - transitions.add(StateTransition.createStateTransition(decision, "step2")); - transitions.add(StateTransition.createStateTransition(decision, "SWITCH", "step3")); - StepState step2 = new StepState(new StubStep("step2")); - transitions.add(StateTransition.createStateTransition(step2, ExitStatus.COMPLETED.getExitCode(), "end0")); - transitions.add(StateTransition.createStateTransition(step2, ExitStatus.FAILED.getExitCode(), "end1")); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end1"))); - StepState step3 = new StepState(new StubStep("step3")); - transitions.add(StateTransition.createStateTransition(step3, ExitStatus.FAILED.getExitCode(), "end2")); - transitions.add(StateTransition.createStateTransition(step3, ExitStatus.COMPLETED.getExitCode(), "end3")); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end2"))); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end3"))); - flow.setStateTransitions(transitions); - - job.setFlow(flow); - try { - job.execute(jobExecution); - } - finally { - - assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); - assertEquals(1, jobExecution.getStepExecutions().size()); - - assertEquals(1, jobExecution.getAllFailureExceptions().size()); - assertEquals("Foo", jobExecution.getAllFailureExceptions().get(0).getCause().getCause().getMessage()); - - } - } - - @Test - public void testGetStepExists() throws Exception { - SimpleFlow flow = new SimpleFlow("job"); - List transitions = new ArrayList<>(); - transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "step2")); - transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2")), "end0")); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); - flow.setStateTransitions(transitions); - flow.afterPropertiesSet(); - job.setFlow(flow); - job.afterPropertiesSet(); - - Step step = job.getStep("step2"); - assertNotNull(step); - assertEquals("step2", step.getName()); - } - - @Test - public void testGetStepExistsWithPrefix() throws Exception { - SimpleFlow flow = new SimpleFlow("job"); - List transitions = new ArrayList<>(); - transitions.add(StateTransition.createStateTransition(new StepState("job.step", new StubStep("step")), "end0")); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); - flow.setStateTransitions(transitions); - flow.afterPropertiesSet(); - job.setFlow(flow); - job.setName(flow.getName()); - job.afterPropertiesSet(); - - Step step = job.getStep("step"); - assertNotNull(step); - assertEquals("step", step.getName()); - } - - @Test - public void testGetStepNamesWithPrefix() throws Exception { - SimpleFlow flow = new SimpleFlow("job"); - List transitions = new ArrayList<>(); - transitions.add(StateTransition.createStateTransition(new StepState("job.step", new StubStep("step")), "end0")); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); - flow.setStateTransitions(transitions); - flow.afterPropertiesSet(); - job.setFlow(flow); - job.setName(flow.getName()); - job.afterPropertiesSet(); - - assertEquals("[step]", job.getStepNames().toString()); - } - - @Test - public void testGetStepNotExists() throws Exception { - SimpleFlow flow = new SimpleFlow("job"); - List transitions = new ArrayList<>(); - transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "step2")); - transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2")), "end0")); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); - flow.setStateTransitions(transitions); - flow.afterPropertiesSet(); - job.setFlow(flow); - job.afterPropertiesSet(); - - Step step = job.getStep("foo"); - assertNull(step); - } - - @Test - public void testGetStepNotStepState() throws Exception { - SimpleFlow flow = new SimpleFlow("job"); - List transitions = new ArrayList<>(); - transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "step2")); - transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2")), "end0")); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); - flow.setStateTransitions(transitions); - flow.afterPropertiesSet(); - job.setFlow(flow); - job.afterPropertiesSet(); - - Step step = job.getStep("end0"); - assertNull(step); - } - - @Test - public void testGetStepNestedFlow() throws Exception { - SimpleFlow nested = new SimpleFlow("nested"); - List transitions = new ArrayList<>(); - transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2")), "end1")); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end1"))); - nested.setStateTransitions(transitions); - nested.afterPropertiesSet(); - - SimpleFlow flow = new SimpleFlow("job"); - transitions = new ArrayList<>(); - transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "nested")); - transitions.add(StateTransition.createStateTransition(new FlowState(nested, "nested"), "end0")); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); - flow.setStateTransitions(transitions); - flow.afterPropertiesSet(); - job.setFlow(flow); - job.afterPropertiesSet(); - - List names = new ArrayList<>(job.getStepNames()); - Collections.sort(names); - assertEquals("[step1, step2]", names.toString()); - } - - @Test - public void testGetStepSplitFlow() throws Exception { - SimpleFlow flow = new SimpleFlow("job"); - SimpleFlow flow1 = new SimpleFlow("flow1"); - SimpleFlow flow2 = new SimpleFlow("flow2"); - - List transitions = new ArrayList<>(); - transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "end0")); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); - flow1.setStateTransitions(new ArrayList<>(transitions)); - flow1.afterPropertiesSet(); - transitions = new ArrayList<>(); - transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2")), "end1")); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end1"))); - flow2.setStateTransitions(new ArrayList<>(transitions)); - flow2.afterPropertiesSet(); - - transitions = new ArrayList<>(); - transitions.add(StateTransition.createStateTransition(new SplitState(Arrays. asList(flow1, flow2), - "split"), "end2")); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end2"))); - flow.setStateTransitions(transitions); - flow.afterPropertiesSet(); - - job.setFlow(flow); - job.afterPropertiesSet(); - List names = new ArrayList<>(job.getStepNames()); - Collections.sort(names); - assertEquals("[step1, step2]", names.toString()); - } - - /** - /** - * @author Dave Syer - * - */ - private class StubStep extends StepSupport { - - private StubStep(String name) { - super(name); - } - - @Override - public void execute(StepExecution stepExecution) throws JobInterruptedException { - stepExecution.setStatus(BatchStatus.COMPLETED); - stepExecution.setExitStatus(ExitStatus.COMPLETED); - jobRepository.update(stepExecution); - } - - } - - /** - * @param jobExecution - * @param stepName - * @return the StepExecution corresponding to the specified step - */ - private StepExecution getStepExecution(JobExecution jobExecution, String stepName) { - for (StepExecution stepExecution : jobExecution.getStepExecutions()) { - if (stepExecution.getStepName().equals(stepName)) { - return stepExecution; - } - } - fail("No stepExecution found with name: [" + stepName + "]"); - return null; - } - - private void checkRepository(BatchStatus status, ExitStatus exitStatus) { - JobInstance jobInstance = this.jobExecution.getJobInstance(); - JobExecution other = this.jobExplorer.getJobExecutions(jobInstance).get(0); - assertEquals(jobInstance.getId(), other.getJobId()); - assertEquals(status, other.getStatus()); - if (exitStatus != null) { - assertEquals(exitStatus.getExitCode(), other.getExitStatus().getExitCode()); - } - } - -} +/* + * Copyright 2006-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.job.flow; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobInstance; +import org.springframework.batch.core.JobInterruptedException; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.Step; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.explore.JobExplorer; +import org.springframework.batch.core.explore.support.JobExplorerFactoryBean; +import org.springframework.batch.core.job.flow.support.DefaultStateTransitionComparator; +import org.springframework.batch.core.job.flow.support.SimpleFlow; +import org.springframework.batch.core.job.flow.support.StateTransition; +import org.springframework.batch.core.job.flow.support.state.DecisionState; +import org.springframework.batch.core.job.flow.support.state.EndState; +import org.springframework.batch.core.job.flow.support.state.FlowState; +import org.springframework.batch.core.job.flow.support.state.SplitState; +import org.springframework.batch.core.job.flow.support.state.StepState; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; +import org.springframework.batch.core.step.StepSupport; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.lang.Nullable; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.fail; + +/** + * @author Dave Syer + * @author Michael Minella + * @author Mahmoud Ben Hassine + * + */ +public class FlowJobTests { + + private FlowJob job = new FlowJob(); + + private JobExecution jobExecution; + + private JobRepository jobRepository; + + private JobExplorer jobExplorer; + + private boolean fail = false; + + @Before + public void setUp() throws Exception { + EmbeddedDatabase embeddedDatabase = new EmbeddedDatabaseBuilder() + .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") + .addScript("/org/springframework/batch/core/schema-hsqldb.sql").build(); + JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); + factory.setDataSource(embeddedDatabase); + factory.setTransactionManager(new DataSourceTransactionManager(embeddedDatabase)); + factory.afterPropertiesSet(); + this.jobRepository = factory.getObject(); + job.setJobRepository(this.jobRepository); + this.jobExecution = this.jobRepository.createJobExecution("job", new JobParameters()); + + JobExplorerFactoryBean explorerFactoryBean = new JobExplorerFactoryBean(); + explorerFactoryBean.setDataSource(embeddedDatabase); + explorerFactoryBean.afterPropertiesSet(); + this.jobExplorer = explorerFactoryBean.getObject(); + } + + @Test + public void testGetSteps() throws Exception { + SimpleFlow flow = new SimpleFlow("job"); + List transitions = new ArrayList<>(); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "step2")); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2")), "end0")); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); + flow.setStateTransitions(transitions); + flow.afterPropertiesSet(); + job.setFlow(flow); + job.afterPropertiesSet(); + assertEquals(2, job.getStepNames().size()); + } + + @Test + public void testTwoSteps() throws Exception { + SimpleFlow flow = new SimpleFlow("job"); + List transitions = new ArrayList<>(); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "step2")); + StepState step2 = new StepState(new StubStep("step2")); + transitions.add(StateTransition.createStateTransition(step2, ExitStatus.FAILED.getExitCode(), "end0")); + transitions.add(StateTransition.createStateTransition(step2, ExitStatus.COMPLETED.getExitCode(), "end1")); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end0"))); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end1"))); + flow.setStateTransitions(transitions); + job.setFlow(flow); + job.afterPropertiesSet(); + job.doExecute(jobExecution); + StepExecution stepExecution = getStepExecution(jobExecution, "step2"); + assertEquals(ExitStatus.COMPLETED, stepExecution.getExitStatus()); + assertEquals(2, jobExecution.getStepExecutions().size()); + } + + @Test + public void testFailedStep() throws Exception { + SimpleFlow flow = new SimpleFlow("job"); + List transitions = new ArrayList<>(); + transitions.add( + StateTransition.createStateTransition(new StateSupport("step1", FlowExecutionStatus.FAILED), "step2")); + StepState step2 = new StepState(new StubStep("step2")); + transitions.add(StateTransition.createStateTransition(step2, ExitStatus.FAILED.getExitCode(), "end0")); + transitions.add(StateTransition.createStateTransition(step2, ExitStatus.COMPLETED.getExitCode(), "end1")); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end0"))); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end1"))); + flow.setStateTransitions(transitions); + job.setFlow(flow); + job.afterPropertiesSet(); + job.doExecute(jobExecution); + StepExecution stepExecution = getStepExecution(jobExecution, "step2"); + assertEquals(ExitStatus.COMPLETED, stepExecution.getExitStatus()); + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + assertEquals(2, jobExecution.getStepExecutions().size()); + } + + @Test + public void testFailedStepRestarted() throws Exception { + SimpleFlow flow = new SimpleFlow("job"); + List transitions = new ArrayList<>(); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "step2")); + State step2State = new StateSupport("step2") { + @Override + public FlowExecutionStatus handle(FlowExecutor executor) throws Exception { + JobExecution jobExecution = executor.getJobExecution(); + jobExecution.createStepExecution(getName()); + if (fail) { + return FlowExecutionStatus.FAILED; + } + else { + return FlowExecutionStatus.COMPLETED; + } + } + }; + transitions.add(StateTransition.createStateTransition(step2State, ExitStatus.COMPLETED.getExitCode(), "end0")); + transitions.add(StateTransition.createStateTransition(step2State, ExitStatus.FAILED.getExitCode(), "end1")); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end1"))); + flow.setStateTransitions(transitions); + job.setFlow(flow); + job.afterPropertiesSet(); + fail = true; + job.execute(jobExecution); + assertEquals(ExitStatus.FAILED, jobExecution.getExitStatus()); + assertEquals(2, jobExecution.getStepExecutions().size()); + jobRepository.update(jobExecution); + jobExecution = jobRepository.createJobExecution("job", new JobParameters()); + fail = false; + job.execute(jobExecution); + assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus()); + assertEquals(1, jobExecution.getStepExecutions().size()); + } + + @Test + public void testStoppingStep() throws Exception { + SimpleFlow flow = new SimpleFlow("job"); + List transitions = new ArrayList<>(); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "step2")); + State state2 = new StateSupport("step2", FlowExecutionStatus.FAILED); + transitions.add(StateTransition.createStateTransition(state2, ExitStatus.FAILED.getExitCode(), "end0")); + transitions.add(StateTransition.createStateTransition(state2, ExitStatus.COMPLETED.getExitCode(), "end1")); + transitions + .add(StateTransition.createStateTransition(new EndState(FlowExecutionStatus.STOPPED, "end0"), "step3")); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end1"))); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step3")), "end2")); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end2"))); + flow.setStateTransitions(transitions); + job.setFlow(flow); + job.afterPropertiesSet(); + job.doExecute(jobExecution); + assertEquals(2, jobExecution.getStepExecutions().size()); + assertEquals(BatchStatus.STOPPED, jobExecution.getStatus()); + } + + @Test + public void testInterrupted() throws Exception { + SimpleFlow flow = new SimpleFlow("job"); + List transitions = new ArrayList<>(); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1") { + @Override + public void execute(StepExecution stepExecution) throws JobInterruptedException { + stepExecution.setStatus(BatchStatus.STOPPING); + jobRepository.update(stepExecution); + } + }), "end0")); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); + flow.setStateTransitions(transitions); + flow.afterPropertiesSet(); + job.setFlow(flow); + job.afterPropertiesSet(); + job.execute(jobExecution); + assertEquals(BatchStatus.STOPPED, jobExecution.getStatus()); + checkRepository(BatchStatus.STOPPED, ExitStatus.STOPPED); + assertEquals(1, jobExecution.getAllFailureExceptions().size()); + assertEquals(JobInterruptedException.class, jobExecution.getFailureExceptions().get(0).getClass()); + } + + @Test + public void testUnknownStatusStopsJob() throws Exception { + SimpleFlow flow = new SimpleFlow("job"); + List transitions = new ArrayList<>(); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1") { + @Override + public void execute(StepExecution stepExecution) throws JobInterruptedException { + stepExecution.setStatus(BatchStatus.UNKNOWN); + stepExecution.setTerminateOnly(); + jobRepository.update(stepExecution); + } + }), "step2")); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2")), "end0")); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); + flow.setStateTransitions(transitions); + flow.afterPropertiesSet(); + job.setFlow(flow); + job.afterPropertiesSet(); + job.execute(jobExecution); + assertEquals(BatchStatus.UNKNOWN, jobExecution.getStatus()); + checkRepository(BatchStatus.UNKNOWN, ExitStatus.STOPPED); + assertEquals(1, jobExecution.getAllFailureExceptions().size()); + assertEquals(JobInterruptedException.class, jobExecution.getFailureExceptions().get(0).getClass()); + } + + @Test + public void testInterruptedSplit() throws Exception { + SimpleFlow flow = new SimpleFlow("job"); + SimpleFlow flow1 = new SimpleFlow("flow1"); + SimpleFlow flow2 = new SimpleFlow("flow2"); + + List transitions = new ArrayList<>(); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1") { + @Override + public void execute(StepExecution stepExecution) throws JobInterruptedException { + if (!stepExecution.getJobExecution().getExecutionContext().containsKey("STOPPED")) { + stepExecution.getJobExecution().getExecutionContext().put("STOPPED", true); + stepExecution.setStatus(BatchStatus.STOPPED); + jobRepository.update(stepExecution); + } + else { + fail("The Job should have stopped by now"); + } + } + }), "end0")); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); + flow1.setStateTransitions(new ArrayList<>(transitions)); + flow1.afterPropertiesSet(); + flow2.setStateTransitions(new ArrayList<>(transitions)); + flow2.afterPropertiesSet(); + + transitions = new ArrayList<>(); + transitions.add(StateTransition + .createStateTransition(new SplitState(Arrays.asList(flow1, flow2), "split"), "end0")); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); + flow.setStateTransitions(transitions); + flow.afterPropertiesSet(); + + job.setFlow(flow); + job.afterPropertiesSet(); + job.execute(jobExecution); + assertEquals(BatchStatus.STOPPED, jobExecution.getStatus()); + checkRepository(BatchStatus.STOPPED, ExitStatus.STOPPED); + assertEquals(1, jobExecution.getAllFailureExceptions().size()); + assertEquals(JobInterruptedException.class, jobExecution.getFailureExceptions().get(0).getClass()); + assertEquals(1, jobExecution.getStepExecutions().size()); + for (StepExecution stepExecution : jobExecution.getStepExecutions()) { + assertEquals(BatchStatus.STOPPED, stepExecution.getStatus()); + } + } + + @Test + public void testInterruptedException() throws Exception { + SimpleFlow flow = new SimpleFlow("job"); + List transitions = new ArrayList<>(); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1") { + @Override + public void execute(StepExecution stepExecution) throws JobInterruptedException { + throw new JobInterruptedException("Stopped"); + } + }), "end0")); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); + flow.setStateTransitions(transitions); + flow.afterPropertiesSet(); + job.setFlow(flow); + job.afterPropertiesSet(); + job.execute(jobExecution); + assertEquals(BatchStatus.STOPPED, jobExecution.getStatus()); + checkRepository(BatchStatus.STOPPED, ExitStatus.STOPPED); + assertEquals(1, jobExecution.getAllFailureExceptions().size()); + assertEquals(JobInterruptedException.class, jobExecution.getFailureExceptions().get(0).getClass()); + } + + @Test + public void testInterruptedSplitException() throws Exception { + SimpleFlow flow = new SimpleFlow("job"); + SimpleFlow flow1 = new SimpleFlow("flow1"); + SimpleFlow flow2 = new SimpleFlow("flow2"); + + List transitions = new ArrayList<>(); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1") { + @Override + public void execute(StepExecution stepExecution) throws JobInterruptedException { + throw new JobInterruptedException("Stopped"); + } + }), "end0")); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); + flow1.setStateTransitions(new ArrayList<>(transitions)); + flow1.afterPropertiesSet(); + flow2.setStateTransitions(new ArrayList<>(transitions)); + flow2.afterPropertiesSet(); + + transitions = new ArrayList<>(); + transitions.add(StateTransition + .createStateTransition(new SplitState(Arrays.asList(flow1, flow2), "split"), "end0")); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); + flow.setStateTransitions(transitions); + flow.afterPropertiesSet(); + + job.setFlow(flow); + job.afterPropertiesSet(); + job.execute(jobExecution); + assertEquals(BatchStatus.STOPPED, jobExecution.getStatus()); + checkRepository(BatchStatus.STOPPED, ExitStatus.STOPPED); + assertEquals(1, jobExecution.getAllFailureExceptions().size()); + assertEquals(JobInterruptedException.class, jobExecution.getFailureExceptions().get(0).getClass()); + } + + @Test + public void testEndStateStopped() throws Exception { + SimpleFlow flow = new SimpleFlow("job"); + List transitions = new ArrayList<>(); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "end")); + transitions + .add(StateTransition.createStateTransition(new EndState(FlowExecutionStatus.STOPPED, "end"), "step2")); + StepState step2 = new StepState(new StubStep("step2")); + transitions.add(StateTransition.createStateTransition(step2, ExitStatus.FAILED.getExitCode(), "end0")); + transitions.add(StateTransition.createStateTransition(step2, ExitStatus.COMPLETED.getExitCode(), "end1")); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end0"))); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end1"))); + flow.setStateTransitions(transitions); + job.setFlow(flow); + job.afterPropertiesSet(); + job.doExecute(jobExecution); + assertEquals(1, jobExecution.getStepExecutions().size()); + assertEquals(BatchStatus.STOPPED, jobExecution.getStatus()); + } + + public void testEndStateFailed() throws Exception { + SimpleFlow flow = new SimpleFlow("job"); + List transitions = new ArrayList<>(); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "end")); + transitions + .add(StateTransition.createStateTransition(new EndState(FlowExecutionStatus.FAILED, "end"), "step2")); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2")), + ExitStatus.FAILED.getExitCode(), "end0")); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2")), + ExitStatus.COMPLETED.getExitCode(), "end1")); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end0"))); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end1"))); + flow.setStateTransitions(transitions); + job.setFlow(flow); + job.afterPropertiesSet(); + job.doExecute(jobExecution); + assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); + assertEquals(1, jobExecution.getStepExecutions().size()); + } + + @Test + public void testEndStateStoppedWithRestart() throws Exception { + SimpleFlow flow = new SimpleFlow("job"); + List transitions = new ArrayList<>(); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "end")); + transitions + .add(StateTransition.createStateTransition(new EndState(FlowExecutionStatus.STOPPED, "end"), "step2")); + StepState step2 = new StepState(new StubStep("step2")); + transitions.add(StateTransition.createStateTransition(step2, ExitStatus.COMPLETED.getExitCode(), "end0")); + transitions.add(StateTransition.createStateTransition(step2, ExitStatus.FAILED.getExitCode(), "end1")); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end1"))); + flow.setStateTransitions(transitions); + job.setFlow(flow); + job.afterPropertiesSet(); + + // To test a restart we have to use the AbstractJob.execute()... + job.execute(jobExecution); + assertEquals(BatchStatus.STOPPED, jobExecution.getStatus()); + assertEquals(1, jobExecution.getStepExecutions().size()); + + jobExecution = jobRepository.createJobExecution("job", new JobParameters()); + job.execute(jobExecution); + assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); + assertEquals(1, jobExecution.getStepExecutions().size()); + + } + + @Test + public void testBranching() throws Exception { + SimpleFlow flow = new SimpleFlow("job"); + List transitions = new ArrayList<>(); + StepState step1 = new StepState(new StubStep("step1")); + transitions.add(StateTransition.createStateTransition(step1, "step2")); + transitions.add(StateTransition.createStateTransition(step1, "COMPLETED", "step3")); + StepState step2 = new StepState(new StubStep("step2")); + transitions.add(StateTransition.createStateTransition(step2, ExitStatus.COMPLETED.getExitCode(), "end0")); + transitions.add(StateTransition.createStateTransition(step2, ExitStatus.FAILED.getExitCode(), "end1")); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end1"))); + StepState step3 = new StepState(new StubStep("step3")); + transitions.add(StateTransition.createStateTransition(step3, ExitStatus.FAILED.getExitCode(), "end2")); + transitions.add(StateTransition.createStateTransition(step3, ExitStatus.COMPLETED.getExitCode(), "end3")); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end2"))); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end3"))); + flow.setStateTransitions(transitions); + flow.setStateTransitionComparator(new DefaultStateTransitionComparator()); + job.setFlow(flow); + job.afterPropertiesSet(); + job.doExecute(jobExecution); + StepExecution stepExecution = getStepExecution(jobExecution, "step3"); + assertEquals(ExitStatus.COMPLETED, stepExecution.getExitStatus()); + assertEquals(2, jobExecution.getStepExecutions().size()); + } + + @Test + public void testBasicFlow() throws Throwable { + SimpleFlow flow = new SimpleFlow("job"); + List transitions = new ArrayList<>(); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step")), "end0")); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); + flow.setStateTransitions(transitions); + job.setFlow(flow); + job.execute(jobExecution); + if (!jobExecution.getAllFailureExceptions().isEmpty()) { + throw jobExecution.getAllFailureExceptions().get(0); + } + assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); + } + + @Test + public void testDecisionFlow() throws Throwable { + + SimpleFlow flow = new SimpleFlow("job"); + JobExecutionDecider decider = new JobExecutionDecider() { + @Override + public FlowExecutionStatus decide(JobExecution jobExecution, @Nullable StepExecution stepExecution) { + assertNotNull(stepExecution); + return new FlowExecutionStatus("SWITCH"); + } + }; + + List transitions = new ArrayList<>(); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "decision")); + DecisionState decision = new DecisionState(decider, "decision"); + transitions.add(StateTransition.createStateTransition(decision, "step2")); + transitions.add(StateTransition.createStateTransition(decision, "SWITCH", "step3")); + StepState step2 = new StepState(new StubStep("step2")); + transitions.add(StateTransition.createStateTransition(step2, ExitStatus.COMPLETED.getExitCode(), "end0")); + transitions.add(StateTransition.createStateTransition(step2, ExitStatus.FAILED.getExitCode(), "end1")); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end1"))); + StepState step3 = new StepState(new StubStep("step3")); + transitions.add(StateTransition.createStateTransition(step3, ExitStatus.FAILED.getExitCode(), "end2")); + transitions.add(StateTransition.createStateTransition(step3, ExitStatus.COMPLETED.getExitCode(), "end3")); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end2"))); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end3"))); + flow.setStateTransitions(transitions); + flow.setStateTransitionComparator(new DefaultStateTransitionComparator()); + + job.setFlow(flow); + job.doExecute(jobExecution); + StepExecution stepExecution = getStepExecution(jobExecution, "step3"); + if (!jobExecution.getAllFailureExceptions().isEmpty()) { + throw jobExecution.getAllFailureExceptions().get(0); + } + + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + assertEquals(2, jobExecution.getStepExecutions().size()); + + } + + @Test + public void testDecisionFlowWithExceptionInDecider() throws Throwable { + + SimpleFlow flow = new SimpleFlow("job"); + JobExecutionDecider decider = new JobExecutionDecider() { + @Override + public FlowExecutionStatus decide(JobExecution jobExecution, @Nullable StepExecution stepExecution) { + assertNotNull(stepExecution); + throw new RuntimeException("Foo"); + } + }; + + List transitions = new ArrayList<>(); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "decision")); + DecisionState decision = new DecisionState(decider, "decision"); + transitions.add(StateTransition.createStateTransition(decision, "step2")); + transitions.add(StateTransition.createStateTransition(decision, "SWITCH", "step3")); + StepState step2 = new StepState(new StubStep("step2")); + transitions.add(StateTransition.createStateTransition(step2, ExitStatus.COMPLETED.getExitCode(), "end0")); + transitions.add(StateTransition.createStateTransition(step2, ExitStatus.FAILED.getExitCode(), "end1")); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end1"))); + StepState step3 = new StepState(new StubStep("step3")); + transitions.add(StateTransition.createStateTransition(step3, ExitStatus.FAILED.getExitCode(), "end2")); + transitions.add(StateTransition.createStateTransition(step3, ExitStatus.COMPLETED.getExitCode(), "end3")); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end2"))); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end3"))); + flow.setStateTransitions(transitions); + + job.setFlow(flow); + try { + job.execute(jobExecution); + } + finally { + + assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); + assertEquals(1, jobExecution.getStepExecutions().size()); + + assertEquals(1, jobExecution.getAllFailureExceptions().size()); + assertEquals("Foo", jobExecution.getAllFailureExceptions().get(0).getCause().getCause().getMessage()); + + } + } + + @Test + public void testGetStepExists() throws Exception { + SimpleFlow flow = new SimpleFlow("job"); + List transitions = new ArrayList<>(); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "step2")); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2")), "end0")); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); + flow.setStateTransitions(transitions); + flow.afterPropertiesSet(); + job.setFlow(flow); + job.afterPropertiesSet(); + + Step step = job.getStep("step2"); + assertNotNull(step); + assertEquals("step2", step.getName()); + } + + @Test + public void testGetStepExistsWithPrefix() throws Exception { + SimpleFlow flow = new SimpleFlow("job"); + List transitions = new ArrayList<>(); + transitions.add(StateTransition.createStateTransition(new StepState("job.step", new StubStep("step")), "end0")); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); + flow.setStateTransitions(transitions); + flow.afterPropertiesSet(); + job.setFlow(flow); + job.setName(flow.getName()); + job.afterPropertiesSet(); + + Step step = job.getStep("step"); + assertNotNull(step); + assertEquals("step", step.getName()); + } + + @Test + public void testGetStepNamesWithPrefix() throws Exception { + SimpleFlow flow = new SimpleFlow("job"); + List transitions = new ArrayList<>(); + transitions.add(StateTransition.createStateTransition(new StepState("job.step", new StubStep("step")), "end0")); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); + flow.setStateTransitions(transitions); + flow.afterPropertiesSet(); + job.setFlow(flow); + job.setName(flow.getName()); + job.afterPropertiesSet(); + + assertEquals("[step]", job.getStepNames().toString()); + } + + @Test + public void testGetStepNotExists() throws Exception { + SimpleFlow flow = new SimpleFlow("job"); + List transitions = new ArrayList<>(); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "step2")); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2")), "end0")); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); + flow.setStateTransitions(transitions); + flow.afterPropertiesSet(); + job.setFlow(flow); + job.afterPropertiesSet(); + + Step step = job.getStep("foo"); + assertNull(step); + } + + @Test + public void testGetStepNotStepState() throws Exception { + SimpleFlow flow = new SimpleFlow("job"); + List transitions = new ArrayList<>(); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "step2")); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2")), "end0")); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); + flow.setStateTransitions(transitions); + flow.afterPropertiesSet(); + job.setFlow(flow); + job.afterPropertiesSet(); + + Step step = job.getStep("end0"); + assertNull(step); + } + + @Test + public void testGetStepNestedFlow() throws Exception { + SimpleFlow nested = new SimpleFlow("nested"); + List transitions = new ArrayList<>(); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2")), "end1")); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end1"))); + nested.setStateTransitions(transitions); + nested.afterPropertiesSet(); + + SimpleFlow flow = new SimpleFlow("job"); + transitions = new ArrayList<>(); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "nested")); + transitions.add(StateTransition.createStateTransition(new FlowState(nested, "nested"), "end0")); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); + flow.setStateTransitions(transitions); + flow.afterPropertiesSet(); + job.setFlow(flow); + job.afterPropertiesSet(); + + List names = new ArrayList<>(job.getStepNames()); + Collections.sort(names); + assertEquals("[step1, step2]", names.toString()); + } + + @Test + public void testGetStepSplitFlow() throws Exception { + SimpleFlow flow = new SimpleFlow("job"); + SimpleFlow flow1 = new SimpleFlow("flow1"); + SimpleFlow flow2 = new SimpleFlow("flow2"); + + List transitions = new ArrayList<>(); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "end0")); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); + flow1.setStateTransitions(new ArrayList<>(transitions)); + flow1.afterPropertiesSet(); + transitions = new ArrayList<>(); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step2")), "end1")); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end1"))); + flow2.setStateTransitions(new ArrayList<>(transitions)); + flow2.afterPropertiesSet(); + + transitions = new ArrayList<>(); + transitions.add(StateTransition + .createStateTransition(new SplitState(Arrays.asList(flow1, flow2), "split"), "end2")); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end2"))); + flow.setStateTransitions(transitions); + flow.afterPropertiesSet(); + + job.setFlow(flow); + job.afterPropertiesSet(); + List names = new ArrayList<>(job.getStepNames()); + Collections.sort(names); + assertEquals("[step1, step2]", names.toString()); + } + + /** + * /** + * + * @author Dave Syer + * + */ + private class StubStep extends StepSupport { + + private StubStep(String name) { + super(name); + } + + @Override + public void execute(StepExecution stepExecution) throws JobInterruptedException { + stepExecution.setStatus(BatchStatus.COMPLETED); + stepExecution.setExitStatus(ExitStatus.COMPLETED); + jobRepository.update(stepExecution); + } + + } + + /** + * @param jobExecution + * @param stepName + * @return the StepExecution corresponding to the specified step + */ + private StepExecution getStepExecution(JobExecution jobExecution, String stepName) { + for (StepExecution stepExecution : jobExecution.getStepExecutions()) { + if (stepExecution.getStepName().equals(stepName)) { + return stepExecution; + } + } + fail("No stepExecution found with name: [" + stepName + "]"); + return null; + } + + private void checkRepository(BatchStatus status, ExitStatus exitStatus) { + JobInstance jobInstance = this.jobExecution.getJobInstance(); + JobExecution other = this.jobExplorer.getJobExecutions(jobInstance).get(0); + assertEquals(jobInstance.getId(), other.getJobId()); + assertEquals(status, other.getStatus()); + if (exitStatus != null) { + assertEquals(exitStatus.getExitCode(), other.getExitStatus().getExitCode()); + } + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/FlowStepTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/FlowStepTests.java index fb933c3db..ef4ac81fa 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/FlowStepTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/FlowStepTests.java @@ -1,224 +1,227 @@ -/* - * Copyright 2006-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.core.job.flow; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobInterruptedException; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.job.flow.support.SimpleFlow; -import org.springframework.batch.core.job.flow.support.StateTransition; -import org.springframework.batch.core.job.flow.support.state.EndState; -import org.springframework.batch.core.job.flow.support.state.StepState; -import org.springframework.batch.core.repository.JobRepository; -import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; -import org.springframework.batch.core.step.StepSupport; -import org.springframework.jdbc.datasource.DataSourceTransactionManager; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; - -/** - * @author Dave Syer - * @author Mahmoud Ben Hassine - * - */ -public class FlowStepTests { - - private JobRepository jobRepository; - private JobExecution jobExecution; - - @Before - public void setUp() throws Exception { - EmbeddedDatabase embeddedDatabase = new EmbeddedDatabaseBuilder() - .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("/org/springframework/batch/core/schema-hsqldb.sql") - .build(); - JobRepositoryFactoryBean jobRepositoryFactoryBean = new JobRepositoryFactoryBean(); - jobRepositoryFactoryBean.setDataSource(embeddedDatabase); - jobRepositoryFactoryBean.setTransactionManager(new DataSourceTransactionManager(embeddedDatabase)); - jobRepositoryFactoryBean.afterPropertiesSet(); - jobRepository = jobRepositoryFactoryBean.getObject(); - jobExecution = jobRepository.createJobExecution("job", new JobParameters()); - } - - /** - * Test method for {@link org.springframework.batch.core.job.flow.FlowStep#afterPropertiesSet()}. - */ - @Test(expected=IllegalStateException.class) - public void testAfterPropertiesSet() throws Exception{ - FlowStep step = new FlowStep(); - step.setJobRepository(jobRepository); - step.afterPropertiesSet(); - } - - /** - * Test method for {@link org.springframework.batch.core.job.flow.FlowStep#doExecute(org.springframework.batch.core.StepExecution)}. - */ - @Test - public void testDoExecute() throws Exception { - - FlowStep step = new FlowStep(); - step.setJobRepository(jobRepository); - - SimpleFlow flow = new SimpleFlow("job"); - List transitions = new ArrayList<>(); - transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "step2")); - StepState step2 = new StepState(new StubStep("step2")); - transitions.add(StateTransition.createStateTransition(step2, ExitStatus.FAILED.getExitCode(), "end0")); - transitions.add(StateTransition.createStateTransition(step2, ExitStatus.COMPLETED.getExitCode(), "end1")); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end0"))); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end1"))); - flow.setStateTransitions(transitions); - - step.setFlow(flow); - step.afterPropertiesSet(); - - StepExecution stepExecution = jobExecution.createStepExecution("step"); - jobRepository.add(stepExecution); - step.execute(stepExecution); - - stepExecution = getStepExecution(jobExecution, "step"); - assertEquals(ExitStatus.COMPLETED, stepExecution.getExitStatus()); - stepExecution = getStepExecution(jobExecution, "step2"); - assertEquals(ExitStatus.COMPLETED, stepExecution.getExitStatus()); - assertEquals(3, jobExecution.getStepExecutions().size()); - - } - - // BATCH-1620 - @Test - public void testDoExecuteAndFail() throws Exception { - - FlowStep step = new FlowStep(); - step.setJobRepository(jobRepository); - - SimpleFlow flow = new SimpleFlow("job"); - List transitions = new ArrayList<>(); - transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "step2")); - StepState step2 = new StepState(new StubStep("step2", true)); - transitions.add(StateTransition.createStateTransition(step2, ExitStatus.FAILED.getExitCode(), "end0")); - transitions.add(StateTransition.createStateTransition(step2, ExitStatus.COMPLETED.getExitCode(), "end1")); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end0"))); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end1"))); - flow.setStateTransitions(transitions); - - step.setFlow(flow); - step.afterPropertiesSet(); - - StepExecution stepExecution = jobExecution.createStepExecution("step"); - jobRepository.add(stepExecution); - step.execute(stepExecution); - - stepExecution = getStepExecution(jobExecution, "step1"); - assertEquals(ExitStatus.COMPLETED, stepExecution.getExitStatus()); - stepExecution = getStepExecution(jobExecution, "step2"); - assertEquals(ExitStatus.FAILED, stepExecution.getExitStatus()); - stepExecution = getStepExecution(jobExecution, "step"); - assertEquals(ExitStatus.FAILED, stepExecution.getExitStatus()); - assertEquals(3, jobExecution.getStepExecutions().size()); - - } - - /** - * Test method for {@link org.springframework.batch.core.job.flow.FlowStep#doExecute(org.springframework.batch.core.StepExecution)}. - */ - @Test - public void testExecuteWithParentContext() throws Exception { - - FlowStep step = new FlowStep(); - step.setJobRepository(jobRepository); - - SimpleFlow flow = new SimpleFlow("job"); - List transitions = new ArrayList<>(); - transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "end0")); - transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); - flow.setStateTransitions(transitions); - - step.setFlow(flow); - step.afterPropertiesSet(); - - StepExecution stepExecution = jobExecution.createStepExecution("step"); - stepExecution.getExecutionContext().put("foo", "bar"); - jobRepository.add(stepExecution); - step.execute(stepExecution); - - stepExecution = getStepExecution(jobExecution, "step"); - assertEquals(ExitStatus.COMPLETED, stepExecution.getExitStatus()); - stepExecution = getStepExecution(jobExecution, "step1"); - assertEquals(ExitStatus.COMPLETED, stepExecution.getExitStatus()); - assertEquals("bar", stepExecution.getExecutionContext().get("foo")); - - } - - /** - * @author Dave Syer - * - */ - private class StubStep extends StepSupport { - - private final boolean fail; - - private StubStep(String name) { - this(name, false); - } - - private StubStep(String name, boolean fail) { - super(name); - this.fail = fail; - } - - @Override - public void execute(StepExecution stepExecution) throws JobInterruptedException { - BatchStatus status = BatchStatus.COMPLETED; - ExitStatus exitStatus = ExitStatus.COMPLETED; - if (fail) { - status = BatchStatus.FAILED; - exitStatus = ExitStatus.FAILED; - } - stepExecution.setStatus(status); - stepExecution.setExitStatus(exitStatus); - jobRepository.update(stepExecution); - } - - } - - /** - * @param jobExecution - * @param stepName - * @return the StepExecution corresponding to the specified step - */ - private StepExecution getStepExecution(JobExecution jobExecution, String stepName) { - for (StepExecution stepExecution : jobExecution.getStepExecutions()) { - if (stepExecution.getStepName().equals(stepName)) { - return stepExecution; - } - } - fail("No stepExecution found with name: [" + stepName + "]"); - return null; - } - -} +/* + * Copyright 2006-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.core.job.flow; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobInterruptedException; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.job.flow.support.SimpleFlow; +import org.springframework.batch.core.job.flow.support.StateTransition; +import org.springframework.batch.core.job.flow.support.state.EndState; +import org.springframework.batch.core.job.flow.support.state.StepState; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; +import org.springframework.batch.core.step.StepSupport; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; + +/** + * @author Dave Syer + * @author Mahmoud Ben Hassine + * + */ +public class FlowStepTests { + + private JobRepository jobRepository; + + private JobExecution jobExecution; + + @Before + public void setUp() throws Exception { + EmbeddedDatabase embeddedDatabase = new EmbeddedDatabaseBuilder() + .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") + .addScript("/org/springframework/batch/core/schema-hsqldb.sql").build(); + JobRepositoryFactoryBean jobRepositoryFactoryBean = new JobRepositoryFactoryBean(); + jobRepositoryFactoryBean.setDataSource(embeddedDatabase); + jobRepositoryFactoryBean.setTransactionManager(new DataSourceTransactionManager(embeddedDatabase)); + jobRepositoryFactoryBean.afterPropertiesSet(); + jobRepository = jobRepositoryFactoryBean.getObject(); + jobExecution = jobRepository.createJobExecution("job", new JobParameters()); + } + + /** + * Test method for + * {@link org.springframework.batch.core.job.flow.FlowStep#afterPropertiesSet()}. + */ + @Test(expected = IllegalStateException.class) + public void testAfterPropertiesSet() throws Exception { + FlowStep step = new FlowStep(); + step.setJobRepository(jobRepository); + step.afterPropertiesSet(); + } + + /** + * Test method for + * {@link org.springframework.batch.core.job.flow.FlowStep#doExecute(org.springframework.batch.core.StepExecution)}. + */ + @Test + public void testDoExecute() throws Exception { + + FlowStep step = new FlowStep(); + step.setJobRepository(jobRepository); + + SimpleFlow flow = new SimpleFlow("job"); + List transitions = new ArrayList<>(); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "step2")); + StepState step2 = new StepState(new StubStep("step2")); + transitions.add(StateTransition.createStateTransition(step2, ExitStatus.FAILED.getExitCode(), "end0")); + transitions.add(StateTransition.createStateTransition(step2, ExitStatus.COMPLETED.getExitCode(), "end1")); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end0"))); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end1"))); + flow.setStateTransitions(transitions); + + step.setFlow(flow); + step.afterPropertiesSet(); + + StepExecution stepExecution = jobExecution.createStepExecution("step"); + jobRepository.add(stepExecution); + step.execute(stepExecution); + + stepExecution = getStepExecution(jobExecution, "step"); + assertEquals(ExitStatus.COMPLETED, stepExecution.getExitStatus()); + stepExecution = getStepExecution(jobExecution, "step2"); + assertEquals(ExitStatus.COMPLETED, stepExecution.getExitStatus()); + assertEquals(3, jobExecution.getStepExecutions().size()); + + } + + // BATCH-1620 + @Test + public void testDoExecuteAndFail() throws Exception { + + FlowStep step = new FlowStep(); + step.setJobRepository(jobRepository); + + SimpleFlow flow = new SimpleFlow("job"); + List transitions = new ArrayList<>(); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "step2")); + StepState step2 = new StepState(new StubStep("step2", true)); + transitions.add(StateTransition.createStateTransition(step2, ExitStatus.FAILED.getExitCode(), "end0")); + transitions.add(StateTransition.createStateTransition(step2, ExitStatus.COMPLETED.getExitCode(), "end1")); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.FAILED, "end0"))); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end1"))); + flow.setStateTransitions(transitions); + + step.setFlow(flow); + step.afterPropertiesSet(); + + StepExecution stepExecution = jobExecution.createStepExecution("step"); + jobRepository.add(stepExecution); + step.execute(stepExecution); + + stepExecution = getStepExecution(jobExecution, "step1"); + assertEquals(ExitStatus.COMPLETED, stepExecution.getExitStatus()); + stepExecution = getStepExecution(jobExecution, "step2"); + assertEquals(ExitStatus.FAILED, stepExecution.getExitStatus()); + stepExecution = getStepExecution(jobExecution, "step"); + assertEquals(ExitStatus.FAILED, stepExecution.getExitStatus()); + assertEquals(3, jobExecution.getStepExecutions().size()); + + } + + /** + * Test method for + * {@link org.springframework.batch.core.job.flow.FlowStep#doExecute(org.springframework.batch.core.StepExecution)}. + */ + @Test + public void testExecuteWithParentContext() throws Exception { + + FlowStep step = new FlowStep(); + step.setJobRepository(jobRepository); + + SimpleFlow flow = new SimpleFlow("job"); + List transitions = new ArrayList<>(); + transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1")), "end0")); + transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0"))); + flow.setStateTransitions(transitions); + + step.setFlow(flow); + step.afterPropertiesSet(); + + StepExecution stepExecution = jobExecution.createStepExecution("step"); + stepExecution.getExecutionContext().put("foo", "bar"); + jobRepository.add(stepExecution); + step.execute(stepExecution); + + stepExecution = getStepExecution(jobExecution, "step"); + assertEquals(ExitStatus.COMPLETED, stepExecution.getExitStatus()); + stepExecution = getStepExecution(jobExecution, "step1"); + assertEquals(ExitStatus.COMPLETED, stepExecution.getExitStatus()); + assertEquals("bar", stepExecution.getExecutionContext().get("foo")); + + } + + /** + * @author Dave Syer + * + */ + private class StubStep extends StepSupport { + + private final boolean fail; + + private StubStep(String name) { + this(name, false); + } + + private StubStep(String name, boolean fail) { + super(name); + this.fail = fail; + } + + @Override + public void execute(StepExecution stepExecution) throws JobInterruptedException { + BatchStatus status = BatchStatus.COMPLETED; + ExitStatus exitStatus = ExitStatus.COMPLETED; + if (fail) { + status = BatchStatus.FAILED; + exitStatus = ExitStatus.FAILED; + } + stepExecution.setStatus(status); + stepExecution.setExitStatus(exitStatus); + jobRepository.update(stepExecution); + } + + } + + /** + * @param jobExecution + * @param stepName + * @return the StepExecution corresponding to the specified step + */ + private StepExecution getStepExecution(JobExecution jobExecution, String stepName) { + for (StepExecution stepExecution : jobExecution.getStepExecutions()) { + if (stepExecution.getStepName().equals(stepName)) { + return stepExecution; + } + } + fail("No stepExecution found with name: [" + stepName + "]"); + return null; + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/DefaultStateTransitionComparatorTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/DefaultStateTransitionComparatorTests.java index 6a762f12c..87f167c46 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/DefaultStateTransitionComparatorTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/DefaultStateTransitionComparatorTests.java @@ -27,6 +27,7 @@ import org.springframework.batch.core.job.flow.StateSupport; public class DefaultStateTransitionComparatorTests { private State state = new StateSupport("state1"); + private Comparator comparator; @Before @@ -79,4 +80,5 @@ public class DefaultStateTransitionComparatorTests { assertEquals(1, comparator.compare(transition, other)); assertEquals(-1, comparator.compare(other, transition)); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/JobFlowExecutorSupport.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/JobFlowExecutorSupport.java index a97ec37a3..8a61a173e 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/JobFlowExecutorSupport.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/JobFlowExecutorSupport.java @@ -34,8 +34,8 @@ import org.springframework.lang.Nullable; public class JobFlowExecutorSupport implements FlowExecutor { @Override - public String executeStep(Step step) throws JobInterruptedException, JobRestartException, - StartLimitExceededException { + public String executeStep(Step step) + throws JobInterruptedException, JobRestartException, StartLimitExceededException { return ExitStatus.COMPLETED.getExitCode(); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/SimpleFlowTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/SimpleFlowTests.java index 293a504f5..e11c3cfac 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/SimpleFlowTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/SimpleFlowTests.java @@ -1,239 +1,242 @@ -/* - * Copyright 2006-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.job.flow.support; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; -import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.job.flow.FlowExecution; -import org.springframework.batch.core.job.flow.FlowExecutionException; -import org.springframework.batch.core.job.flow.FlowExecutionStatus; -import org.springframework.batch.core.job.flow.FlowExecutor; -import org.springframework.batch.core.job.flow.State; -import org.springframework.batch.core.job.flow.StateSupport; - -/** - * @author Dave Syer - * @author Michael Minella - * - */ -public class SimpleFlowTests { - - protected SimpleFlow flow; - - protected FlowExecutor executor = new JobFlowExecutorSupport(); - - @Before - public void setUp() { - flow = new SimpleFlow("job"); - } - - @Test(expected = IllegalArgumentException.class) - public void testEmptySteps() throws Exception { - flow.setStateTransitions(Collections. emptyList()); - flow.afterPropertiesSet(); - } - - @Test(expected = IllegalArgumentException.class) - public void testNoNextStepSpecified() throws Exception { - flow.setStateTransitions(Collections.singletonList(StateTransition.createStateTransition(new StateSupport( - "step"), "foo"))); - flow.afterPropertiesSet(); - } - - @Test - public void testStepLoop() throws Exception { - flow.setStateTransitions(collect(StateTransition.createStateTransition(new StateSupport("step"), - ExitStatus.FAILED.getExitCode(), "step"), StateTransition.createEndStateTransition(new StateSupport("step")))); - flow.afterPropertiesSet(); - FlowExecution execution = flow.start(executor); - assertEquals(FlowExecutionStatus.COMPLETED, execution.getStatus()); - assertEquals("step", execution.getName()); - } - - @Test(expected = IllegalArgumentException.class) - public void testNoEndStep() throws Exception { - flow.setStateTransitions(Collections.singletonList(StateTransition.createStateTransition(new StateSupport( - "step"), ExitStatus.FAILED.getExitCode(), "step"))); - flow.afterPropertiesSet(); - } - - @Test - public void testUnconnectedSteps() throws Exception { - flow.setStateTransitions(collect(StateTransition.createEndStateTransition(new StubState("step1")), - StateTransition.createEndStateTransition(new StubState("step2")))); - flow.afterPropertiesSet(); - FlowExecution execution = flow.start(executor); - assertEquals(FlowExecutionStatus.COMPLETED, execution.getStatus()); - assertEquals("step1", execution.getName()); - } - - @Test - public void testNoMatchForNextStep() throws Exception { - flow.setStateTransitions(collect(StateTransition.createStateTransition(new StubState("step1"), "FOO", "step2"), - StateTransition.createEndStateTransition(new StubState("step2")))); - flow.afterPropertiesSet(); - try { - flow.start(executor); - fail("Expected JobExecutionException"); - } - catch (FlowExecutionException e) { - // expected - String message = e.getMessage(); - assertTrue("Wrong message: " + message, message.toLowerCase().contains("next state not found")); - } - } - - @Test - public void testOneStep() throws Exception { - flow.setStateTransitions(Collections.singletonList(StateTransition.createEndStateTransition(new StubState( - "step1")))); - flow.afterPropertiesSet(); - FlowExecution execution = flow.start(executor); - assertEquals(FlowExecutionStatus.COMPLETED, execution.getStatus()); - assertEquals("step1", execution.getName()); - } - - @Test - public void testOneStepWithListenerCallsClose() throws Exception { - flow.setStateTransitions(Collections.singletonList(StateTransition.createEndStateTransition(new StubState( - "step1")))); - flow.afterPropertiesSet(); - final List list = new ArrayList<>(); - executor = new JobFlowExecutorSupport() { - @Override - public void close(FlowExecution result) { - list.add(result); - } - }; - FlowExecution execution = flow.start(executor); - assertEquals(1, list.size()); - assertEquals(FlowExecutionStatus.COMPLETED, execution.getStatus()); - assertEquals("step1", execution.getName()); - } - - @Test - public void testExplicitStartStep() throws Exception { - flow.setStateTransitions(collect(StateTransition.createStateTransition(new StubState("step"), - ExitStatus.FAILED.getExitCode(), "step"), StateTransition.createEndStateTransition(new StubState("step")))); - flow.afterPropertiesSet(); - FlowExecution execution = flow.start(executor); - assertEquals(FlowExecutionStatus.COMPLETED, execution.getStatus()); - assertEquals("step", execution.getName()); - } - - @Test - public void testTwoSteps() throws Exception { - flow.setStateTransitions(collect(StateTransition.createStateTransition(new StubState("step1"), "step2"), - StateTransition.createEndStateTransition(new StubState("step2")))); - flow.afterPropertiesSet(); - FlowExecution execution = flow.start(executor); - assertEquals(FlowExecutionStatus.COMPLETED, execution.getStatus()); - assertEquals("step2", execution.getName()); - } - - @Test - public void testResume() throws Exception { - flow.setStateTransitions(collect(StateTransition.createStateTransition(new StubState("step1"), "step2"), - StateTransition.createEndStateTransition(new StubState("step2")))); - flow.afterPropertiesSet(); - FlowExecution execution = flow.resume("step2", executor); - assertEquals(FlowExecutionStatus.COMPLETED, execution.getStatus()); - assertEquals("step2", execution.getName()); - } - - @Test - public void testFailedStep() throws Exception { - flow.setStateTransitions(collect(StateTransition.createStateTransition(new StubState("step1") { - @Override - public FlowExecutionStatus handle(FlowExecutor executor) { - return FlowExecutionStatus.FAILED; - } - }, "step2"), StateTransition.createEndStateTransition(new StubState("step2")))); - flow.afterPropertiesSet(); - FlowExecution execution = flow.start(executor); - assertEquals(FlowExecutionStatus.COMPLETED, execution.getStatus()); - assertEquals("step2", execution.getName()); - } - - @Test - public void testBranching() throws Exception { - flow.setStateTransitions(collect(StateTransition.createStateTransition(new StubState("step1"), "step2"), - StateTransition.createStateTransition(new StubState("step1"), ExitStatus.COMPLETED.getExitCode(), "step3"), - StateTransition.createEndStateTransition(new StubState("step2")), StateTransition - .createEndStateTransition(new StubState("step3")))); - flow.setStateTransitionComparator(new DefaultStateTransitionComparator()); - flow.afterPropertiesSet(); - FlowExecution execution = flow.start(executor); - assertEquals(FlowExecutionStatus.COMPLETED, execution.getStatus()); - assertEquals("step3", execution.getName()); - } - - @Test - public void testGetStateExists() throws Exception { - flow.setStateTransitions(Collections.singletonList(StateTransition.createEndStateTransition(new StubState( - "step1")))); - flow.afterPropertiesSet(); - State state = flow.getState("step1"); - assertNotNull(state); - assertEquals("step1", state.getName()); - } - - @Test - public void testGetStateDoesNotExist() throws Exception { - flow.setStateTransitions(Collections.singletonList(StateTransition.createEndStateTransition(new StubState( - "step1")))); - flow.afterPropertiesSet(); - State state = flow.getState("bar"); - assertNull(state); - } - - protected List collect(StateTransition... states) { - List list = new ArrayList<>(); - - for (StateTransition stateTransition : states) { - list.add(stateTransition); - } - - return list; - } - - /** - * @author Dave Syer - * - */ - protected static class StubState extends StateSupport { - - /** - * @param string - */ - public StubState(String string) { - super(string); - } - - } - -} +/* + * Copyright 2006-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.job.flow.support; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.job.flow.FlowExecution; +import org.springframework.batch.core.job.flow.FlowExecutionException; +import org.springframework.batch.core.job.flow.FlowExecutionStatus; +import org.springframework.batch.core.job.flow.FlowExecutor; +import org.springframework.batch.core.job.flow.State; +import org.springframework.batch.core.job.flow.StateSupport; + +/** + * @author Dave Syer + * @author Michael Minella + * + */ +public class SimpleFlowTests { + + protected SimpleFlow flow; + + protected FlowExecutor executor = new JobFlowExecutorSupport(); + + @Before + public void setUp() { + flow = new SimpleFlow("job"); + } + + @Test(expected = IllegalArgumentException.class) + public void testEmptySteps() throws Exception { + flow.setStateTransitions(Collections.emptyList()); + flow.afterPropertiesSet(); + } + + @Test(expected = IllegalArgumentException.class) + public void testNoNextStepSpecified() throws Exception { + flow.setStateTransitions( + Collections.singletonList(StateTransition.createStateTransition(new StateSupport("step"), "foo"))); + flow.afterPropertiesSet(); + } + + @Test + public void testStepLoop() throws Exception { + flow.setStateTransitions( + collect(StateTransition.createStateTransition(new StateSupport("step"), ExitStatus.FAILED.getExitCode(), + "step"), StateTransition.createEndStateTransition(new StateSupport("step")))); + flow.afterPropertiesSet(); + FlowExecution execution = flow.start(executor); + assertEquals(FlowExecutionStatus.COMPLETED, execution.getStatus()); + assertEquals("step", execution.getName()); + } + + @Test(expected = IllegalArgumentException.class) + public void testNoEndStep() throws Exception { + flow.setStateTransitions(Collections.singletonList(StateTransition + .createStateTransition(new StateSupport("step"), ExitStatus.FAILED.getExitCode(), "step"))); + flow.afterPropertiesSet(); + } + + @Test + public void testUnconnectedSteps() throws Exception { + flow.setStateTransitions(collect(StateTransition.createEndStateTransition(new StubState("step1")), + StateTransition.createEndStateTransition(new StubState("step2")))); + flow.afterPropertiesSet(); + FlowExecution execution = flow.start(executor); + assertEquals(FlowExecutionStatus.COMPLETED, execution.getStatus()); + assertEquals("step1", execution.getName()); + } + + @Test + public void testNoMatchForNextStep() throws Exception { + flow.setStateTransitions(collect(StateTransition.createStateTransition(new StubState("step1"), "FOO", "step2"), + StateTransition.createEndStateTransition(new StubState("step2")))); + flow.afterPropertiesSet(); + try { + flow.start(executor); + fail("Expected JobExecutionException"); + } + catch (FlowExecutionException e) { + // expected + String message = e.getMessage(); + assertTrue("Wrong message: " + message, message.toLowerCase().contains("next state not found")); + } + } + + @Test + public void testOneStep() throws Exception { + flow.setStateTransitions( + Collections.singletonList(StateTransition.createEndStateTransition(new StubState("step1")))); + flow.afterPropertiesSet(); + FlowExecution execution = flow.start(executor); + assertEquals(FlowExecutionStatus.COMPLETED, execution.getStatus()); + assertEquals("step1", execution.getName()); + } + + @Test + public void testOneStepWithListenerCallsClose() throws Exception { + flow.setStateTransitions( + Collections.singletonList(StateTransition.createEndStateTransition(new StubState("step1")))); + flow.afterPropertiesSet(); + final List list = new ArrayList<>(); + executor = new JobFlowExecutorSupport() { + @Override + public void close(FlowExecution result) { + list.add(result); + } + }; + FlowExecution execution = flow.start(executor); + assertEquals(1, list.size()); + assertEquals(FlowExecutionStatus.COMPLETED, execution.getStatus()); + assertEquals("step1", execution.getName()); + } + + @Test + public void testExplicitStartStep() throws Exception { + flow.setStateTransitions(collect( + StateTransition.createStateTransition(new StubState("step"), ExitStatus.FAILED.getExitCode(), "step"), + StateTransition.createEndStateTransition(new StubState("step")))); + flow.afterPropertiesSet(); + FlowExecution execution = flow.start(executor); + assertEquals(FlowExecutionStatus.COMPLETED, execution.getStatus()); + assertEquals("step", execution.getName()); + } + + @Test + public void testTwoSteps() throws Exception { + flow.setStateTransitions(collect(StateTransition.createStateTransition(new StubState("step1"), "step2"), + StateTransition.createEndStateTransition(new StubState("step2")))); + flow.afterPropertiesSet(); + FlowExecution execution = flow.start(executor); + assertEquals(FlowExecutionStatus.COMPLETED, execution.getStatus()); + assertEquals("step2", execution.getName()); + } + + @Test + public void testResume() throws Exception { + flow.setStateTransitions(collect(StateTransition.createStateTransition(new StubState("step1"), "step2"), + StateTransition.createEndStateTransition(new StubState("step2")))); + flow.afterPropertiesSet(); + FlowExecution execution = flow.resume("step2", executor); + assertEquals(FlowExecutionStatus.COMPLETED, execution.getStatus()); + assertEquals("step2", execution.getName()); + } + + @Test + public void testFailedStep() throws Exception { + flow.setStateTransitions(collect(StateTransition.createStateTransition(new StubState("step1") { + @Override + public FlowExecutionStatus handle(FlowExecutor executor) { + return FlowExecutionStatus.FAILED; + } + }, "step2"), StateTransition.createEndStateTransition(new StubState("step2")))); + flow.afterPropertiesSet(); + FlowExecution execution = flow.start(executor); + assertEquals(FlowExecutionStatus.COMPLETED, execution.getStatus()); + assertEquals("step2", execution.getName()); + } + + @Test + public void testBranching() throws Exception { + flow.setStateTransitions(collect(StateTransition.createStateTransition(new StubState("step1"), "step2"), + StateTransition.createStateTransition(new StubState("step1"), ExitStatus.COMPLETED.getExitCode(), + "step3"), + StateTransition.createEndStateTransition(new StubState("step2")), + StateTransition.createEndStateTransition(new StubState("step3")))); + flow.setStateTransitionComparator(new DefaultStateTransitionComparator()); + flow.afterPropertiesSet(); + FlowExecution execution = flow.start(executor); + assertEquals(FlowExecutionStatus.COMPLETED, execution.getStatus()); + assertEquals("step3", execution.getName()); + } + + @Test + public void testGetStateExists() throws Exception { + flow.setStateTransitions( + Collections.singletonList(StateTransition.createEndStateTransition(new StubState("step1")))); + flow.afterPropertiesSet(); + State state = flow.getState("step1"); + assertNotNull(state); + assertEquals("step1", state.getName()); + } + + @Test + public void testGetStateDoesNotExist() throws Exception { + flow.setStateTransitions( + Collections.singletonList(StateTransition.createEndStateTransition(new StubState("step1")))); + flow.afterPropertiesSet(); + State state = flow.getState("bar"); + assertNull(state); + } + + protected List collect(StateTransition... states) { + List list = new ArrayList<>(); + + for (StateTransition stateTransition : states) { + list.add(stateTransition); + } + + return list; + } + + /** + * @author Dave Syer + * + */ + protected static class StubState extends StateSupport { + + /** + * @param string + */ + public StubState(String string) { + super(string); + } + + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/state/EndStateTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/state/EndStateTests.java index 2eb6dd197..0bc840961 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/state/EndStateTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/state/EndStateTests.java @@ -32,7 +32,7 @@ import org.springframework.batch.core.job.flow.support.JobFlowExecutorSupport; public class EndStateTests { private JobExecution jobExecution; - + @Before public void setUp() { jobExecution = new JobExecution(0L); @@ -40,13 +40,13 @@ public class EndStateTests { /** * Test method for {@link EndState#handle(FlowExecutor)}. - * @throws Exception + * @throws Exception */ @Test public void testHandleRestartSunnyDay() throws Exception { BatchStatus status = jobExecution.getStatus(); - + EndState state = new EndState(FlowExecutionStatus.UNKNOWN, "end"); state.handle(new JobFlowExecutorSupport() { @Override @@ -54,20 +54,20 @@ public class EndStateTests { return jobExecution; } }); - + assertEquals(status, jobExecution.getStatus()); } /** * Test method for {@link EndState#handle(FlowExecutor)}. - * @throws Exception + * @throws Exception */ @Test public void testHandleOngoingSunnyDay() throws Exception { jobExecution.createStepExecution("foo"); - + EndState state = new EndState(FlowExecutionStatus.UNKNOWN, "end"); FlowExecutionStatus status = state.handle(new JobFlowExecutorSupport() { @Override @@ -75,7 +75,7 @@ public class EndStateTests { return jobExecution; } }); - + assertEquals(FlowExecutionStatus.UNKNOWN, status); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/state/SimpleFlowExecutionAggregatorTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/state/SimpleFlowExecutionAggregatorTests.java index fd0677901..d6a3cb226 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/state/SimpleFlowExecutionAggregatorTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/state/SimpleFlowExecutionAggregatorTests.java @@ -27,7 +27,7 @@ import org.springframework.batch.core.job.flow.FlowExecutionStatus; /** * @author Dave Syer - * + * */ public class SimpleFlowExecutionAggregatorTests { @@ -37,14 +37,14 @@ public class SimpleFlowExecutionAggregatorTests { public void testFailed() throws Exception { FlowExecution first = new FlowExecution("foo", FlowExecutionStatus.COMPLETED); FlowExecution second = new FlowExecution("foo", FlowExecutionStatus.FAILED); - assertTrue("Should be negative", first.compareTo(second)<0); - assertTrue("Should be positive", second.compareTo(first)>0); + assertTrue("Should be negative", first.compareTo(second) < 0); + assertTrue("Should be positive", second.compareTo(first) > 0); assertEquals(FlowExecutionStatus.FAILED, aggregator.aggregate(Arrays.asList(first, second))); } @Test public void testEmpty() throws Exception { - assertEquals(FlowExecutionStatus.UNKNOWN, aggregator.aggregate(Collections. emptySet())); + assertEquals(FlowExecutionStatus.UNKNOWN, aggregator.aggregate(Collections.emptySet())); } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/state/SplitStateTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/state/SplitStateTests.java index a4ff7088a..810c7bf35 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/state/SplitStateTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/state/SplitStateTests.java @@ -30,7 +30,6 @@ import org.springframework.batch.core.job.flow.FlowExecutionStatus; import org.springframework.batch.core.job.flow.support.JobFlowExecutorSupport; import org.springframework.core.task.SimpleAsyncTaskExecutor; - /** * @author Dave Syer * @author Will Schipp @@ -43,7 +42,7 @@ public class SplitStateTests { @Test public void testBasicHandling() throws Exception { - Collection flows = new ArrayList<>(); + Collection flows = new ArrayList<>(); Flow flow1 = mock(Flow.class); Flow flow2 = mock(Flow.class); flows.add(flow1); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/EmptyItemWriter.java b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/EmptyItemWriter.java index 18c4f36c0..ae2bd100b 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/EmptyItemWriter.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/EmptyItemWriter.java @@ -25,8 +25,8 @@ import org.springframework.batch.support.transaction.TransactionAwareProxyFactor import org.springframework.beans.factory.InitializingBean; /** - * Mock {@link ItemWriter} that will throw an exception when a certain number of - * items have been written. + * Mock {@link ItemWriter} that will throw an exception when a certain number of items + * have been written. */ public class EmptyItemWriter implements ItemWriter, InitializingBean { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/JobExecutionNotFailedExceptionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/JobExecutionNotFailedExceptionTests.java index a1f1a1307..144e474ca 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/JobExecutionNotFailedExceptionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/JobExecutionNotFailedExceptionTests.java @@ -23,16 +23,24 @@ import org.springframework.batch.core.AbstractExceptionTests; */ public class JobExecutionNotFailedExceptionTests extends AbstractExceptionTests { - /* (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.io.exception.AbstractExceptionTests#getException(java. + * lang.String) */ @Override public Exception getException(String msg) throws Exception { return new JobExecutionNotFailedException(msg); } - /* (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String, java.lang.Throwable) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.io.exception.AbstractExceptionTests#getException(java. + * lang.String, java.lang.Throwable) */ @Override public Exception getException(String msg, Throwable t) throws Exception { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/JobInstanceAlreadyExistsExceptionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/JobInstanceAlreadyExistsExceptionTests.java index 2453e8e98..0f09aeb82 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/JobInstanceAlreadyExistsExceptionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/JobInstanceAlreadyExistsExceptionTests.java @@ -23,16 +23,24 @@ import org.springframework.batch.core.AbstractExceptionTests; */ public class JobInstanceAlreadyExistsExceptionTests extends AbstractExceptionTests { - /* (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.io.exception.AbstractExceptionTests#getException(java. + * lang.String) */ @Override public Exception getException(String msg) throws Exception { return new JobInstanceAlreadyExistsException(msg); } - /* (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String, java.lang.Throwable) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.io.exception.AbstractExceptionTests#getException(java. + * lang.String, java.lang.Throwable) */ @Override public Exception getException(String msg, Throwable t) throws Exception { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/JobLauncherIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/JobLauncherIntegrationTests.java index 0ece416e2..a58590b08 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/JobLauncherIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/JobLauncherIntegrationTests.java @@ -56,12 +56,12 @@ public class JobLauncherIntegrationTests { int before = JdbcTestUtils.countRowsInTable(jdbcTemplate, "BATCH_JOB_INSTANCE"); - JobExecution jobExecution = launch(true,0); + JobExecution jobExecution = launch(true, 0); launch(false, jobExecution.getId()); launch(false, jobExecution.getId()); int after = JdbcTestUtils.countRowsInTable(jdbcTemplate, "BATCH_JOB_INSTANCE"); - assertEquals(before+1, after); + assertEquals(before + 1, after); } @@ -76,7 +76,8 @@ public class JobLauncherIntegrationTests { return jobLauncher.run(job, jobParameters); - } else { + } + else { JdbcJobExecutionDao dao = new JdbcJobExecutionDao(); dao.setJdbcTemplate(jdbcTemplate); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/JobParametersNotFoundExceptionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/JobParametersNotFoundExceptionTests.java index dca7604bd..cb0edbd76 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/JobParametersNotFoundExceptionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/JobParametersNotFoundExceptionTests.java @@ -23,16 +23,24 @@ import org.springframework.batch.core.AbstractExceptionTests; */ public class JobParametersNotFoundExceptionTests extends AbstractExceptionTests { - /* (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.io.exception.AbstractExceptionTests#getException(java. + * lang.String) */ @Override public Exception getException(String msg) throws Exception { return new JobParametersNotFoundException(msg); } - /* (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String, java.lang.Throwable) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.io.exception.AbstractExceptionTests#getException(java. + * lang.String, java.lang.Throwable) */ @Override public Exception getException(String msg, Throwable t) throws Exception { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/NoSuchJobExceptionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/NoSuchJobExceptionTests.java index 8bcafdb37..4344549fa 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/NoSuchJobExceptionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/NoSuchJobExceptionTests.java @@ -20,25 +20,30 @@ import org.springframework.batch.core.launch.NoSuchJobException; /** * @author Dave Syer - * + * */ public class NoSuchJobExceptionTests extends AbstractExceptionTests { /* * (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String) + * + * @see + * org.springframework.batch.io.exception.AbstractExceptionTests#getException(java. + * lang.String) */ - @Override + @Override public Exception getException(String msg) throws Exception { return new NoSuchJobException(msg); } /* * (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String, - * java.lang.Throwable) + * + * @see + * org.springframework.batch.io.exception.AbstractExceptionTests#getException(java. + * lang.String, java.lang.Throwable) */ - @Override + @Override public Exception getException(String msg, Throwable t) throws Exception { return new NoSuchJobException(msg, t); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/NoSuchJobExecutionExceptionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/NoSuchJobExecutionExceptionTests.java index 6d8e62c13..403c95fb3 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/NoSuchJobExecutionExceptionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/NoSuchJobExecutionExceptionTests.java @@ -23,16 +23,24 @@ import org.springframework.batch.core.AbstractExceptionTests; */ public class NoSuchJobExecutionExceptionTests extends AbstractExceptionTests { - /* (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.io.exception.AbstractExceptionTests#getException(java. + * lang.String) */ @Override public Exception getException(String msg) throws Exception { return new NoSuchJobExecutionException(msg); } - /* (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String, java.lang.Throwable) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.io.exception.AbstractExceptionTests#getException(java. + * lang.String, java.lang.Throwable) */ @Override public Exception getException(String msg, Throwable t) throws Exception { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/NoSuchJobInstanceExceptionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/NoSuchJobInstanceExceptionTests.java index fbb55694c..070bfabe6 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/NoSuchJobInstanceExceptionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/NoSuchJobInstanceExceptionTests.java @@ -23,16 +23,24 @@ import org.springframework.batch.core.AbstractExceptionTests; */ public class NoSuchJobInstanceExceptionTests extends AbstractExceptionTests { - /* (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.io.exception.AbstractExceptionTests#getException(java. + * lang.String) */ @Override public Exception getException(String msg) throws Exception { return new NoSuchJobInstanceException(msg); } - /* (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String, java.lang.Throwable) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.io.exception.AbstractExceptionTests#getException(java. + * lang.String, java.lang.Throwable) */ @Override public Exception getException(String msg, Throwable t) throws Exception { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/SimpleJobLauncherTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/SimpleJobLauncherTests.java index 6f164f178..4a9b1f5cf 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/SimpleJobLauncherTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/SimpleJobLauncherTests.java @@ -85,8 +85,8 @@ public class SimpleJobLauncherTests { @Test(expected = JobParametersInvalidException.class) public void testRunWithValidator() throws Exception { - job.setJobParametersValidator(new DefaultJobParametersValidator(new String[] { "missing-and-required" }, - new String[0])); + job.setJobParametersValidator( + new DefaultJobParametersValidator(new String[] { "missing-and-required" }, new String[0])); when(jobRepository.getLastJobExecution(job.getName(), jobParameters)).thenReturn(null); @@ -111,16 +111,16 @@ public class SimpleJobLauncherTests { }; testRun(); - when(jobRepository.getLastJobExecution(job.getName(), jobParameters)).thenReturn( - new JobExecution(new JobInstance(1L, job.getName()), jobParameters)); - when(jobRepository.createJobExecution(job.getName(), jobParameters)).thenReturn( - new JobExecution(new JobInstance(1L, job.getName()), jobParameters)); + when(jobRepository.getLastJobExecution(job.getName(), jobParameters)) + .thenReturn(new JobExecution(new JobInstance(1L, job.getName()), jobParameters)); + when(jobRepository.createJobExecution(job.getName(), jobParameters)) + .thenReturn(new JobExecution(new JobInstance(1L, job.getName()), jobParameters)); jobLauncher.run(job, jobParameters); } /* - * Non-restartable JobInstance can be run only once - attempt to run - * existing non-restartable JobInstance causes error. + * Non-restartable JobInstance can be run only once - attempt to run existing + * non-restartable JobInstance causes error. */ @Test public void testRunNonRestartableJobInstanceTwice() throws Exception { @@ -139,8 +139,8 @@ public class SimpleJobLauncherTests { testRun(); try { - when(jobRepository.getLastJobExecution(job.getName(), jobParameters)).thenReturn( - new JobExecution(new JobInstance(1L, job.getName()), jobParameters)); + when(jobRepository.getLastJobExecution(job.getName(), jobParameters)) + .thenReturn(new JobExecution(new JobInstance(1L, job.getName()), jobParameters)); jobLauncher.run(job, jobParameters); fail("Expected JobRestartException"); } @@ -238,8 +238,8 @@ public class SimpleJobLauncherTests { } catch (IllegalStateException e) { // expected - assertTrue("Message did not contain repository: " + e.getMessage(), contains(e.getMessage().toLowerCase(), - "repository")); + assertTrue("Message did not contain repository: " + e.getMessage(), + contains(e.getMessage().toLowerCase(), "repository")); } } @@ -270,10 +270,10 @@ public class SimpleJobLauncherTests { } /** - * Test to support BATCH-1770 -> throw in parent thread JobRestartException when - * a stepExecution is UNKNOWN + * Test to support BATCH-1770 -> throw in parent thread JobRestartException when a + * stepExecution is UNKNOWN */ - @Test(expected=JobRestartException.class) + @Test(expected = JobRestartException.class) public void testRunStepStatusUnknown() throws Exception { testRestartStepExecutionInvalidStatus(BatchStatus.UNKNOWN); } @@ -296,7 +296,8 @@ public class SimpleJobLauncherTests { private void testRestartStepExecutionInvalidStatus(BatchStatus status) throws Exception { String jobName = "test_job"; JobRepository jobRepository = mock(JobRepository.class); - JobParameters parameters = new JobParametersBuilder().addLong("runtime", System.currentTimeMillis()).toJobParameters(); + JobParameters parameters = new JobParametersBuilder().addLong("runtime", System.currentTimeMillis()) + .toJobParameters(); JobExecution jobExecution = mock(JobExecution.class); Job job = mock(Job.class); JobParametersValidator validator = mock(JobParametersValidator.class); @@ -309,11 +310,12 @@ public class SimpleJobLauncherTests { when(stepExecution.getStatus()).thenReturn(status); when(jobExecution.getStepExecutions()).thenReturn(Arrays.asList(stepExecution)); - //setup launcher + // setup launcher jobLauncher = new SimpleJobLauncher(); jobLauncher.setJobRepository(jobRepository); - //run + // run jobLauncher.run(job, parameters); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/CommandLineJobRunnerTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/CommandLineJobRunnerTests.java index d1b77af39..05db88651 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/CommandLineJobRunnerTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/CommandLineJobRunnerTests.java @@ -124,7 +124,8 @@ public class CommandLineJobRunnerTests { CommandLineJobRunner.main(args); assertEquals(1, StubSystemExiter.status); String errorMessage = CommandLineJobRunner.getErrorMessage(); - assertTrue("Wrong error message: " + errorMessage, errorMessage.contains("At least 2 arguments are required: JobPath/JobClass and jobIdentifier.")); + assertTrue("Wrong error message: " + errorMessage, + errorMessage.contains("At least 2 arguments are required: JobPath/JobClass and jobIdentifier.")); } @Test @@ -133,9 +134,9 @@ public class CommandLineJobRunnerTests { CommandLineJobRunner.main(args); assertEquals(1, StubSystemExiter.status); String errorMessage = CommandLineJobRunner.getErrorMessage(); - assertTrue("Wrong error message: " + errorMessage, (errorMessage - .contains("No bean named 'no-such-job' is defined") || (errorMessage - .contains("No bean named 'no-such-job' available")))); + assertTrue("Wrong error message: " + errorMessage, + (errorMessage.contains("No bean named 'no-such-job' is defined") + || (errorMessage.contains("No bean named 'no-such-job' available")))); } @Test @@ -167,7 +168,7 @@ public class CommandLineJobRunnerTests { @Test public void testWithStdinCommandLine() throws Throwable { System.setIn(new InputStream() { - char[] input = (jobPath+"\n"+jobName+"\nfoo=bar\nspam=bucket").toCharArray(); + char[] input = (jobPath + "\n" + jobName + "\nfoo=bar\nspam=bucket").toCharArray(); int index = 0; @@ -178,18 +179,18 @@ public class CommandLineJobRunnerTests { @Override public int read() { - return index new JobExecution(new JobInstance(123L, job.getName()), 999L, jobParameters)); + jobOperator.setJobLauncher( + (job, jobParameters) -> new JobExecution(new JobInstance(123L, job.getName()), 999L, jobParameters)); jobExplorer = mock(JobExplorer.class); @@ -159,7 +160,8 @@ public class SimpleJobOperatorTests { jobParameters = new JobParameters(); JobInstance jobInstance = new JobInstance(321L, "foo"); when(jobExplorer.getJobInstances("foo", 0, 1)).thenReturn(Collections.singletonList(jobInstance)); - when(jobExplorer.getJobExecutions(jobInstance)).thenReturn(Collections.singletonList(new JobExecution(jobInstance, new JobParameters()))); + when(jobExplorer.getJobExecutions(jobInstance)) + .thenReturn(Collections.singletonList(new JobExecution(jobInstance, new JobParameters()))); Long value = jobOperator.startNextInstance("foo"); assertEquals(999, value.longValue()); } @@ -189,7 +191,8 @@ public class SimpleJobOperatorTests { @Test public void testResumeSunnyDay() throws Exception { jobParameters = new JobParameters(); - when(jobExplorer.getJobExecution(111L)).thenReturn(new JobExecution(new JobInstance(123L, job.getName()), 111L, jobParameters)); + when(jobExplorer.getJobExecution(111L)) + .thenReturn(new JobExecution(new JobInstance(123L, job.getName()), 111L, jobParameters)); jobExplorer.getJobExecution(111L); Long value = jobOperator.restart(111L); assertEquals(999, value.longValue()); @@ -212,7 +215,8 @@ public class SimpleJobOperatorTests { try { jobOperator.getSummary(111L); fail("Expected NoSuchJobExecutionException"); - } catch (NoSuchJobExecutionException e) { + } + catch (NoSuchJobExecutionException e) { // expected } } @@ -237,7 +241,8 @@ public class SimpleJobOperatorTests { try { jobOperator.getStepExecutionSummaries(111L); fail("Expected NoSuchJobExecutionException"); - } catch (NoSuchJobExecutionException e) { + } + catch (NoSuchJobExecutionException e) { // expected } } @@ -259,7 +264,8 @@ public class SimpleJobOperatorTests { try { jobOperator.getRunningExecutions("no-such-job"); fail("Expected NoSuchJobException"); - } catch (NoSuchJobException e) { + } + catch (NoSuchJobException e) { // expected } } @@ -267,7 +273,8 @@ public class SimpleJobOperatorTests { @Test public void testGetJobParametersSunnyDay() throws Exception { final JobParameters jobParameters = new JobParameters(); - when(jobExplorer.getJobExecution(111L)).thenReturn(new JobExecution(new JobInstance(123L, job.getName()), 111L, jobParameters)); + when(jobExplorer.getJobExecution(111L)) + .thenReturn(new JobExecution(new JobInstance(123L, job.getName()), 111L, jobParameters)); String value = jobOperator.getParameters(111L); assertEquals("a=b", value); } @@ -278,7 +285,8 @@ public class SimpleJobOperatorTests { try { jobOperator.getParameters(111L); fail("Expected NoSuchJobExecutionException"); - } catch (NoSuchJobExecutionException e) { + } + catch (NoSuchJobExecutionException e) { // expected } } @@ -337,7 +345,7 @@ public class SimpleJobOperatorTests { } @Test - public void testStop() throws Exception{ + public void testStop() throws Exception { JobInstance jobInstance = new JobInstance(123L, job.getName()); JobExecution jobExecution = new JobExecution(jobInstance, 111L, jobParameters); when(jobExplorer.getJobExecution(111L)).thenReturn(jobExecution); @@ -371,7 +379,7 @@ public class SimpleJobOperatorTests { jobOperator.stop(111L); assertEquals(BatchStatus.STOPPING, jobExecution.getStatus()); } - + @Test public void testStopTaskletWhenJobNotRegistered() throws Exception { JobInstance jobInstance = new JobInstance(123L, job.getName()); @@ -379,11 +387,11 @@ public class SimpleJobOperatorTests { StoppableTasklet tasklet = mock(StoppableTasklet.class); JobRegistry jobRegistry = mock(JobRegistry.class); TaskletStep step = mock(TaskletStep.class); - + when(step.getTasklet()).thenReturn(tasklet); when(jobRegistry.getJob(job.getName())).thenThrow(new NoSuchJobException("Unable to find job")); when(jobExplorer.getJobExecution(111L)).thenReturn(jobExecution); - + jobOperator.setJobRegistry(jobRegistry); jobOperator.stop(111L); assertEquals(BatchStatus.STOPPING, jobExecution.getStatus()); @@ -398,33 +406,33 @@ public class SimpleJobOperatorTests { @Nullable @Override - public RepeatStatus execute(StepContribution contribution, - ChunkContext chunkContext) throws Exception { + public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { return null; } @Override public void stop() { throw new IllegalStateException(); - }}; - TaskletStep taskletStep = new TaskletStep(); - taskletStep.setTasklet(tasklet); - MockJob job = new MockJob(); - job.taskletStep = taskletStep; + } + }; + TaskletStep taskletStep = new TaskletStep(); + taskletStep.setTasklet(tasklet); + MockJob job = new MockJob(); + job.taskletStep = taskletStep; - JobRegistry jobRegistry = mock(JobRegistry.class); - TaskletStep step = mock(TaskletStep.class); + JobRegistry jobRegistry = mock(JobRegistry.class); + TaskletStep step = mock(TaskletStep.class); - when(step.getTasklet()).thenReturn(tasklet); - when(step.getName()).thenReturn("test_job.step1"); - when(jobRegistry.getJob(any(String.class))).thenReturn(job); - when(jobExplorer.getJobExecution(111L)).thenReturn(jobExecution); + when(step.getTasklet()).thenReturn(tasklet); + when(step.getName()).thenReturn("test_job.step1"); + when(jobRegistry.getJob(any(String.class))).thenReturn(job); + when(jobExplorer.getJobExecution(111L)).thenReturn(jobExecution); - jobOperator.setJobRegistry(jobRegistry); - jobExplorer.getJobExecution(111L); - jobRepository.update(jobExecution); - jobOperator.stop(111L); - assertEquals(BatchStatus.STOPPING, jobExecution.getStatus()); + jobOperator.setJobRegistry(jobRegistry); + jobExplorer.getJobExecution(111L); + jobRepository.update(jobExecution); + jobOperator.stop(111L); + assertEquals(BatchStatus.STOPPING, jobExecution.getStatus()); } @Test @@ -469,4 +477,5 @@ public class SimpleJobOperatorTests { } } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/SimpleJvmExitCodeMapperTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/SimpleJvmExitCodeMapperTests.java index 679570c7f..61d0107dc 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/SimpleJvmExitCodeMapperTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/SimpleJvmExitCodeMapperTests.java @@ -26,6 +26,7 @@ import org.springframework.batch.core.ExitStatus; public class SimpleJvmExitCodeMapperTests extends TestCase { private SimpleJvmExitCodeMapper ecm; + private SimpleJvmExitCodeMapper ecm2; @Override @@ -50,41 +51,26 @@ public class SimpleJvmExitCodeMapperTests extends TestCase { } public void testGetExitCodeWithPredefinedCodes() { - assertEquals( - ecm.intValue(ExitStatus.COMPLETED.getExitCode()), - ExitCodeMapper.JVM_EXITCODE_COMPLETED); - assertEquals( - ecm.intValue(ExitStatus.FAILED.getExitCode()), - ExitCodeMapper.JVM_EXITCODE_GENERIC_ERROR); - assertEquals( - ecm.intValue(ExitCodeMapper.JOB_NOT_PROVIDED), - ExitCodeMapper.JVM_EXITCODE_JOB_ERROR); - assertEquals( - ecm.intValue(ExitCodeMapper.NO_SUCH_JOB), - ExitCodeMapper.JVM_EXITCODE_JOB_ERROR); + assertEquals(ecm.intValue(ExitStatus.COMPLETED.getExitCode()), ExitCodeMapper.JVM_EXITCODE_COMPLETED); + assertEquals(ecm.intValue(ExitStatus.FAILED.getExitCode()), ExitCodeMapper.JVM_EXITCODE_GENERIC_ERROR); + assertEquals(ecm.intValue(ExitCodeMapper.JOB_NOT_PROVIDED), ExitCodeMapper.JVM_EXITCODE_JOB_ERROR); + assertEquals(ecm.intValue(ExitCodeMapper.NO_SUCH_JOB), ExitCodeMapper.JVM_EXITCODE_JOB_ERROR); } public void testGetExitCodeWithPredefinedCodesOverridden() { System.out.println(ecm2.intValue(ExitStatus.COMPLETED.getExitCode())); - assertEquals( - ecm2.intValue(ExitStatus.COMPLETED.getExitCode()), -1); - assertEquals( - ecm2.intValue(ExitStatus.FAILED.getExitCode()), -2); - assertEquals( - ecm2.intValue(ExitCodeMapper.JOB_NOT_PROVIDED), -3); - assertEquals( - ecm2.intValue(ExitCodeMapper.NO_SUCH_JOB), -3); + assertEquals(ecm2.intValue(ExitStatus.COMPLETED.getExitCode()), -1); + assertEquals(ecm2.intValue(ExitStatus.FAILED.getExitCode()), -2); + assertEquals(ecm2.intValue(ExitCodeMapper.JOB_NOT_PROVIDED), -3); + assertEquals(ecm2.intValue(ExitCodeMapper.NO_SUCH_JOB), -3); } public void testGetExitCodeWithCustomCode() { - assertEquals(ecm.intValue("MY_CUSTOM_CODE"),3); + assertEquals(ecm.intValue("MY_CUSTOM_CODE"), 3); } public void testGetExitCodeWithDefaultCode() { - assertEquals( - ecm.intValue("UNDEFINED_CUSTOM_CODE"), - ExitCodeMapper.JVM_EXITCODE_GENERIC_ERROR); + assertEquals(ecm.intValue("UNDEFINED_CUSTOM_CODE"), ExitCodeMapper.JVM_EXITCODE_GENERIC_ERROR); } - } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/StubJobLauncher.java b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/StubJobLauncher.java index 5ba5ac2fb..aafbb361a 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/StubJobLauncher.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/StubJobLauncher.java @@ -22,10 +22,9 @@ import org.springframework.batch.core.launch.JobLauncher; import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException; /** - * Mock Job Launcher. Normally, something like EasyMock would - * be used to mock an interface, however, because of the nature - * of launching a batch job from the command line, the mocked - * class cannot be injected. + * Mock Job Launcher. Normally, something like EasyMock would be used to mock an + * interface, however, because of the nature of launching a batch job from the command + * line, the mocked class cannot be injected. * * @author Lucas Ward * @@ -33,10 +32,13 @@ import org.springframework.batch.core.repository.JobExecutionAlreadyRunningExcep public class StubJobLauncher implements JobLauncher { public static final int RUN_NO_ARGS = 0; + public static final int RUN_JOB_NAME = 1; - public static final int RUN_JOB_IDENTIFIER =2 ; + + public static final int RUN_JOB_IDENTIFIER = 2; private int lastRunCalled = RUN_NO_ARGS; + private JobExecution returnValue = null; private boolean isRunning = false; @@ -46,8 +48,7 @@ public class StubJobLauncher implements JobLauncher { } @Override - public JobExecution run(Job job, JobParameters jobParameters) - throws JobExecutionAlreadyRunningException { + public JobExecution run(Job job, JobParameters jobParameters) throws JobExecutionAlreadyRunningException { lastRunCalled = RUN_JOB_IDENTIFIER; return returnValue; } @@ -56,15 +57,16 @@ public class StubJobLauncher implements JobLauncher { } - public void setReturnValue(JobExecution returnValue){ + public void setReturnValue(JobExecution returnValue) { this.returnValue = returnValue; } - public void setIsRunning(boolean isRunning){ + public void setIsRunning(boolean isRunning) { this.isRunning = isRunning; } - public int getLastRunCalled(){ + public int getLastRunCalled() { return lastRunCalled; } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/TestJobParametersIncrementer.java b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/TestJobParametersIncrementer.java index 41008f2fa..1ad3759d8 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/TestJobParametersIncrementer.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/TestJobParametersIncrementer.java @@ -24,7 +24,7 @@ public class TestJobParametersIncrementer implements JobParametersIncrementer { @Override public JobParameters getNext(@Nullable JobParameters parameters) { - return new JobParametersBuilder().addString("foo", "spam").toJobParameters(); + return new JobParametersBuilder().addString("foo", "spam").toJobParameters(); } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/listener/CompositeChunkListenerTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/listener/CompositeChunkListenerTests.java index f9c42d73c..31a034481 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/listener/CompositeChunkListenerTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/listener/CompositeChunkListenerTests.java @@ -31,7 +31,9 @@ import org.springframework.batch.core.scope.context.ChunkContext; public class CompositeChunkListenerTests { ChunkListener listener; + CompositeChunkListener compositeListener; + ChunkContext chunkContext; @Before @@ -43,22 +45,23 @@ public class CompositeChunkListenerTests { } @Test - public void testBeforeChunk(){ + public void testBeforeChunk() { listener.beforeChunk(chunkContext); compositeListener.beforeChunk(chunkContext); } @Test - public void testAfterChunk(){ + public void testAfterChunk() { listener.afterChunk(chunkContext); compositeListener.afterChunk(chunkContext); } @Test - public void testAfterChunkFailed(){ + public void testAfterChunkFailed() { ChunkContext context = new ChunkContext(null); listener.afterChunkError(context); compositeListener.afterChunkError(context); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/listener/CompositeItemProcessListenerTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/listener/CompositeItemProcessListenerTests.java index f9b58d9e8..fccfb23cf 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/listener/CompositeItemProcessListenerTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/listener/CompositeItemProcessListenerTests.java @@ -26,7 +26,7 @@ import org.springframework.batch.core.ItemProcessListener; /** * @author Dave Syer * @author Will Schipp - * + * */ public class CompositeItemProcessListenerTests { @@ -67,8 +67,8 @@ public class CompositeItemProcessListenerTests { @Test public void testSetListeners() throws Exception { - compositeListener.setListeners(Collections - .> singletonList(listener)); + compositeListener + .setListeners(Collections.>singletonList(listener)); listener.beforeProcess(null); compositeListener.beforeProcess(null); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/listener/CompositeItemReadListenerTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/listener/CompositeItemReadListenerTests.java index 13e21a2f8..adeeb7dfe 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/listener/CompositeItemReadListenerTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/listener/CompositeItemReadListenerTests.java @@ -29,10 +29,11 @@ import org.springframework.batch.core.ItemReadListener; * */ public class CompositeItemReadListenerTests { - + ItemReadListener listener; + CompositeItemReadListener compositeListener; - + @SuppressWarnings("unchecked") @Before public void setUp() throws Exception { @@ -40,24 +41,24 @@ public class CompositeItemReadListenerTests { compositeListener = new CompositeItemReadListener<>(); compositeListener.register(listener); } - + @Test - public void testBeforeRead(){ - + public void testBeforeRead() { + listener.beforeRead(); compositeListener.beforeRead(); } - + @Test - public void testAfterRead(){ + public void testAfterRead() { Object item = new Object(); listener.afterRead(item); compositeListener.afterRead(item); } - + @Test - public void testOnReadError(){ - + public void testOnReadError() { + Exception ex = new Exception(); listener.onReadError(ex); compositeListener.onReadError(ex); @@ -74,5 +75,5 @@ public class CompositeItemReadListenerTests { listener.beforeRead(); compositeListener.beforeRead(); } - + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/listener/ExecutionContextPromotionListenerTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/listener/ExecutionContextPromotionListenerTests.java index 673a32628..3b4ec3d96 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/listener/ExecutionContextPromotionListenerTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/listener/ExecutionContextPromotionListenerTests.java @@ -1,260 +1,260 @@ -/* - * Copyright 2009-2010 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.listener; - -import org.junit.Test; - -import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.StepExecution; -import org.springframework.util.Assert; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; - -/** - * Tests for {@link ExecutionContextPromotionListener}. - */ -public class ExecutionContextPromotionListenerTests { - - private static final String key = "testKey"; - - private static final String value = "testValue"; - - private static final String key2 = "testKey2"; - - private static final String value2 = "testValue2"; - - private static final String status = "COMPLETED WITH SKIPS"; - - private static final String status2 = "FAILURE"; - - private static final String statusWildcard = "COMPL*SKIPS"; - - /** - * CONDITION: ExecutionContext contains {key, key2}. keys = {key}. statuses - * is not set (defaults to {COMPLETED}). - * - * EXPECTED: key is promoted. key2 is not. - */ - @Test - public void promoteEntryNullStatuses() throws Exception { - ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener(); - - JobExecution jobExecution = new JobExecution(1L); - StepExecution stepExecution = jobExecution.createStepExecution("step1"); - stepExecution.setExitStatus(ExitStatus.COMPLETED); - - Assert.state(jobExecution.getExecutionContext().isEmpty(), "Job ExecutionContext is not empty"); - Assert.state(stepExecution.getExecutionContext().isEmpty(), "Step ExecutionContext is not empty"); - - stepExecution.getExecutionContext().putString(key, value); - stepExecution.getExecutionContext().putString(key2, value2); - - listener.setKeys(new String[] { key }); - listener.afterPropertiesSet(); - - listener.afterStep(stepExecution); - - assertEquals(value, jobExecution.getExecutionContext().getString(key)); - assertFalse(jobExecution.getExecutionContext().containsKey(key2)); - } - - /** - * CONDITION: ExecutionContext contains {key, key2}. keys = {key, key2}. - * statuses = {status}. ExitStatus = status - * - * EXPECTED: key is promoted. key2 is not. - */ - @Test - public void promoteEntryStatusFound() throws Exception { - ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener(); - listener.setStrict(true); - - JobExecution jobExecution = new JobExecution(1L); - StepExecution stepExecution = jobExecution.createStepExecution("step1"); - stepExecution.setExitStatus(new ExitStatus(status)); - - Assert.state(jobExecution.getExecutionContext().isEmpty(), "Job ExecutionContext is not empty"); - Assert.state(stepExecution.getExecutionContext().isEmpty(), "Step ExecutionContext is not empty"); - - stepExecution.getExecutionContext().putString(key, value); - stepExecution.getExecutionContext().putString(key2, value2); - - listener.setKeys(new String[] { key }); - listener.setStatuses(new String[] { status }); - listener.afterPropertiesSet(); - - listener.afterStep(stepExecution); - - assertEquals(value, jobExecution.getExecutionContext().getString(key)); - assertFalse(jobExecution.getExecutionContext().containsKey(key2)); - } - - /** - * CONDITION: ExecutionContext contains {key, key2}. keys = {key, key2}. - * statuses = {status}. ExitStatus = status2 - * - * EXPECTED: no promotions. - */ - @Test - public void promoteEntryStatusNotFound() throws Exception { - ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener(); - - JobExecution jobExecution = new JobExecution(1L); - StepExecution stepExecution = jobExecution.createStepExecution("step1"); - stepExecution.setExitStatus(new ExitStatus(status2)); - - Assert.state(jobExecution.getExecutionContext().isEmpty(), "Job ExecutionContext is not empty"); - Assert.state(stepExecution.getExecutionContext().isEmpty(), "Step ExecutionContext is not empty"); - - stepExecution.getExecutionContext().putString(key, value); - stepExecution.getExecutionContext().putString(key2, value2); - - listener.setKeys(new String[] { key }); - listener.setStatuses(new String[] { status }); - listener.afterPropertiesSet(); - - listener.afterStep(stepExecution); - - assertFalse(jobExecution.getExecutionContext().containsKey(key)); - assertFalse(jobExecution.getExecutionContext().containsKey(key2)); - } - - /** - * CONDITION: keys = {key, key2}. statuses = {statusWildcard}. ExitStatus = - * status - * - * EXPECTED: key is promoted. key2 is not. - */ - @Test - public void promoteEntryStatusWildcardFound() throws Exception { - ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener(); - - JobExecution jobExecution = new JobExecution(1L); - StepExecution stepExecution = jobExecution.createStepExecution("step1"); - stepExecution.setExitStatus(new ExitStatus(status)); - - Assert.state(jobExecution.getExecutionContext().isEmpty(), "Job ExecutionContext is not empty"); - Assert.state(stepExecution.getExecutionContext().isEmpty(), "Step ExecutionContext is not empty"); - - stepExecution.getExecutionContext().putString(key, value); - stepExecution.getExecutionContext().putString(key2, value2); - - listener.setKeys(new String[] { key }); - listener.setStatuses(new String[] { statusWildcard }); - listener.afterPropertiesSet(); - - listener.afterStep(stepExecution); - - assertEquals(value, jobExecution.getExecutionContext().getString(key)); - assertFalse(jobExecution.getExecutionContext().containsKey(key2)); - } - - /** - * CONDITION: keys = {key, key2}. Only {key} exists in the ExecutionContext. - * - * EXPECTED: key is promoted. key2 is not. - */ - @Test - public void promoteEntriesKeyNotFound() throws Exception { - ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener(); - - JobExecution jobExecution = new JobExecution(1L); - StepExecution stepExecution = jobExecution.createStepExecution("step1"); - stepExecution.setExitStatus(ExitStatus.COMPLETED); - - Assert.state(jobExecution.getExecutionContext().isEmpty(), "Job ExecutionContext is not empty"); - Assert.state(stepExecution.getExecutionContext().isEmpty(), "Step ExecutionContext is not empty"); - - stepExecution.getExecutionContext().putString(key, value); - - listener.setKeys(new String[] { key, key2 }); - listener.afterPropertiesSet(); - - listener.afterStep(stepExecution); - - assertEquals(value, jobExecution.getExecutionContext().getString(key)); - assertFalse(jobExecution.getExecutionContext().containsKey(key2)); - } - - /** - * CONDITION: keys = {key}. key is already in job but not in step. - * - * EXPECTED: key is not erased. - */ - @Test - public void promoteEntriesKeyNotFoundInStep() throws Exception { - ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener(); - - JobExecution jobExecution = new JobExecution(1L); - StepExecution stepExecution = jobExecution.createStepExecution("step1"); - stepExecution.setExitStatus(ExitStatus.COMPLETED); - - Assert.state(jobExecution.getExecutionContext().isEmpty(), "Job ExecutionContext is not empty"); - Assert.state(stepExecution.getExecutionContext().isEmpty(), "Step ExecutionContext is not empty"); - - jobExecution.getExecutionContext().putString(key, value); - - listener.setKeys(new String[] { key }); - listener.afterPropertiesSet(); - - listener.afterStep(stepExecution); - - assertEquals(value, jobExecution.getExecutionContext().getString(key)); - } - - /** - * CONDITION: strict = true. keys = {key, key2}. Only {key} exists in the - * ExecutionContext. - * - * EXPECTED: IllegalArgumentException - */ - @Test(expected = IllegalArgumentException.class) - public void promoteEntriesKeyNotFoundStrict() throws Exception { - ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener(); - listener.setStrict(true); - - JobExecution jobExecution = new JobExecution(1L); - StepExecution stepExecution = jobExecution.createStepExecution("step1"); - stepExecution.setExitStatus(ExitStatus.COMPLETED); - - Assert.state(jobExecution.getExecutionContext().isEmpty(), "Job ExecutionContext is not empty"); - Assert.state(stepExecution.getExecutionContext().isEmpty(), "Step ExecutionContext is not empty"); - - stepExecution.getExecutionContext().putString(key, value); - - listener.setKeys(new String[] { key, key2 }); - listener.afterPropertiesSet(); - - listener.afterStep(stepExecution); - - assertEquals(value, jobExecution.getExecutionContext().getString(key)); - assertFalse(jobExecution.getExecutionContext().containsKey(key2)); - } - - /** - * CONDITION: keys = NULL - * - * EXPECTED: IllegalArgumentException - */ - @Test(expected = IllegalArgumentException.class) - public void keysMustBeSet() throws Exception { - ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener(); - // didn't set the keys, same as listener.setKeys(null); - listener.afterPropertiesSet(); - } -} +/* + * Copyright 2009-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.listener; + +import org.junit.Test; + +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.StepExecution; +import org.springframework.util.Assert; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +/** + * Tests for {@link ExecutionContextPromotionListener}. + */ +public class ExecutionContextPromotionListenerTests { + + private static final String key = "testKey"; + + private static final String value = "testValue"; + + private static final String key2 = "testKey2"; + + private static final String value2 = "testValue2"; + + private static final String status = "COMPLETED WITH SKIPS"; + + private static final String status2 = "FAILURE"; + + private static final String statusWildcard = "COMPL*SKIPS"; + + /** + * CONDITION: ExecutionContext contains {key, key2}. keys = {key}. statuses is not set + * (defaults to {COMPLETED}). + * + * EXPECTED: key is promoted. key2 is not. + */ + @Test + public void promoteEntryNullStatuses() throws Exception { + ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener(); + + JobExecution jobExecution = new JobExecution(1L); + StepExecution stepExecution = jobExecution.createStepExecution("step1"); + stepExecution.setExitStatus(ExitStatus.COMPLETED); + + Assert.state(jobExecution.getExecutionContext().isEmpty(), "Job ExecutionContext is not empty"); + Assert.state(stepExecution.getExecutionContext().isEmpty(), "Step ExecutionContext is not empty"); + + stepExecution.getExecutionContext().putString(key, value); + stepExecution.getExecutionContext().putString(key2, value2); + + listener.setKeys(new String[] { key }); + listener.afterPropertiesSet(); + + listener.afterStep(stepExecution); + + assertEquals(value, jobExecution.getExecutionContext().getString(key)); + assertFalse(jobExecution.getExecutionContext().containsKey(key2)); + } + + /** + * CONDITION: ExecutionContext contains {key, key2}. keys = {key, key2}. statuses = + * {status}. ExitStatus = status + * + * EXPECTED: key is promoted. key2 is not. + */ + @Test + public void promoteEntryStatusFound() throws Exception { + ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener(); + listener.setStrict(true); + + JobExecution jobExecution = new JobExecution(1L); + StepExecution stepExecution = jobExecution.createStepExecution("step1"); + stepExecution.setExitStatus(new ExitStatus(status)); + + Assert.state(jobExecution.getExecutionContext().isEmpty(), "Job ExecutionContext is not empty"); + Assert.state(stepExecution.getExecutionContext().isEmpty(), "Step ExecutionContext is not empty"); + + stepExecution.getExecutionContext().putString(key, value); + stepExecution.getExecutionContext().putString(key2, value2); + + listener.setKeys(new String[] { key }); + listener.setStatuses(new String[] { status }); + listener.afterPropertiesSet(); + + listener.afterStep(stepExecution); + + assertEquals(value, jobExecution.getExecutionContext().getString(key)); + assertFalse(jobExecution.getExecutionContext().containsKey(key2)); + } + + /** + * CONDITION: ExecutionContext contains {key, key2}. keys = {key, key2}. statuses = + * {status}. ExitStatus = status2 + * + * EXPECTED: no promotions. + */ + @Test + public void promoteEntryStatusNotFound() throws Exception { + ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener(); + + JobExecution jobExecution = new JobExecution(1L); + StepExecution stepExecution = jobExecution.createStepExecution("step1"); + stepExecution.setExitStatus(new ExitStatus(status2)); + + Assert.state(jobExecution.getExecutionContext().isEmpty(), "Job ExecutionContext is not empty"); + Assert.state(stepExecution.getExecutionContext().isEmpty(), "Step ExecutionContext is not empty"); + + stepExecution.getExecutionContext().putString(key, value); + stepExecution.getExecutionContext().putString(key2, value2); + + listener.setKeys(new String[] { key }); + listener.setStatuses(new String[] { status }); + listener.afterPropertiesSet(); + + listener.afterStep(stepExecution); + + assertFalse(jobExecution.getExecutionContext().containsKey(key)); + assertFalse(jobExecution.getExecutionContext().containsKey(key2)); + } + + /** + * CONDITION: keys = {key, key2}. statuses = {statusWildcard}. ExitStatus = status + * + * EXPECTED: key is promoted. key2 is not. + */ + @Test + public void promoteEntryStatusWildcardFound() throws Exception { + ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener(); + + JobExecution jobExecution = new JobExecution(1L); + StepExecution stepExecution = jobExecution.createStepExecution("step1"); + stepExecution.setExitStatus(new ExitStatus(status)); + + Assert.state(jobExecution.getExecutionContext().isEmpty(), "Job ExecutionContext is not empty"); + Assert.state(stepExecution.getExecutionContext().isEmpty(), "Step ExecutionContext is not empty"); + + stepExecution.getExecutionContext().putString(key, value); + stepExecution.getExecutionContext().putString(key2, value2); + + listener.setKeys(new String[] { key }); + listener.setStatuses(new String[] { statusWildcard }); + listener.afterPropertiesSet(); + + listener.afterStep(stepExecution); + + assertEquals(value, jobExecution.getExecutionContext().getString(key)); + assertFalse(jobExecution.getExecutionContext().containsKey(key2)); + } + + /** + * CONDITION: keys = {key, key2}. Only {key} exists in the ExecutionContext. + * + * EXPECTED: key is promoted. key2 is not. + */ + @Test + public void promoteEntriesKeyNotFound() throws Exception { + ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener(); + + JobExecution jobExecution = new JobExecution(1L); + StepExecution stepExecution = jobExecution.createStepExecution("step1"); + stepExecution.setExitStatus(ExitStatus.COMPLETED); + + Assert.state(jobExecution.getExecutionContext().isEmpty(), "Job ExecutionContext is not empty"); + Assert.state(stepExecution.getExecutionContext().isEmpty(), "Step ExecutionContext is not empty"); + + stepExecution.getExecutionContext().putString(key, value); + + listener.setKeys(new String[] { key, key2 }); + listener.afterPropertiesSet(); + + listener.afterStep(stepExecution); + + assertEquals(value, jobExecution.getExecutionContext().getString(key)); + assertFalse(jobExecution.getExecutionContext().containsKey(key2)); + } + + /** + * CONDITION: keys = {key}. key is already in job but not in step. + * + * EXPECTED: key is not erased. + */ + @Test + public void promoteEntriesKeyNotFoundInStep() throws Exception { + ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener(); + + JobExecution jobExecution = new JobExecution(1L); + StepExecution stepExecution = jobExecution.createStepExecution("step1"); + stepExecution.setExitStatus(ExitStatus.COMPLETED); + + Assert.state(jobExecution.getExecutionContext().isEmpty(), "Job ExecutionContext is not empty"); + Assert.state(stepExecution.getExecutionContext().isEmpty(), "Step ExecutionContext is not empty"); + + jobExecution.getExecutionContext().putString(key, value); + + listener.setKeys(new String[] { key }); + listener.afterPropertiesSet(); + + listener.afterStep(stepExecution); + + assertEquals(value, jobExecution.getExecutionContext().getString(key)); + } + + /** + * CONDITION: strict = true. keys = {key, key2}. Only {key} exists in the + * ExecutionContext. + * + * EXPECTED: IllegalArgumentException + */ + @Test(expected = IllegalArgumentException.class) + public void promoteEntriesKeyNotFoundStrict() throws Exception { + ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener(); + listener.setStrict(true); + + JobExecution jobExecution = new JobExecution(1L); + StepExecution stepExecution = jobExecution.createStepExecution("step1"); + stepExecution.setExitStatus(ExitStatus.COMPLETED); + + Assert.state(jobExecution.getExecutionContext().isEmpty(), "Job ExecutionContext is not empty"); + Assert.state(stepExecution.getExecutionContext().isEmpty(), "Step ExecutionContext is not empty"); + + stepExecution.getExecutionContext().putString(key, value); + + listener.setKeys(new String[] { key, key2 }); + listener.afterPropertiesSet(); + + listener.afterStep(stepExecution); + + assertEquals(value, jobExecution.getExecutionContext().getString(key)); + assertFalse(jobExecution.getExecutionContext().containsKey(key2)); + } + + /** + * CONDITION: keys = NULL + * + * EXPECTED: IllegalArgumentException + */ + @Test(expected = IllegalArgumentException.class) + public void keysMustBeSet() throws Exception { + ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener(); + // didn't set the keys, same as listener.setKeys(null); + listener.afterPropertiesSet(); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/listener/ItemListenerErrorTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/listener/ItemListenerErrorTests.java index 9193efcae..fd7d765a9 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/listener/ItemListenerErrorTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/listener/ItemListenerErrorTests.java @@ -58,7 +58,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; * @author Mahmoud Ben Hassine */ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = {ItemListenerErrorTests.BatchConfiguration.class}) +@ContextConfiguration(classes = { ItemListenerErrorTests.BatchConfiguration.class }) public class ItemListenerErrorTests { @Autowired @@ -132,35 +132,23 @@ public class ItemListenerErrorTests { @Bean public Job testJob(JobBuilderFactory jobs, Step testStep) { - return jobs.get("testJob") - .incrementer(new RunIdIncrementer()) - .start(testStep) - .build(); + return jobs.get("testJob").incrementer(new RunIdIncrementer()).start(testStep).build(); } @Bean - public Step step1(StepBuilderFactory stepBuilderFactory, - ItemReader fakeItemReader, - ItemProcessor fakeProcessor, - ItemWriter fakeItemWriter, + public Step step1(StepBuilderFactory stepBuilderFactory, ItemReader fakeItemReader, + ItemProcessor fakeProcessor, ItemWriter fakeItemWriter, ItemProcessListener itemProcessListener) { - return stepBuilderFactory.get("testStep").chunk(10) - .reader(fakeItemReader) - .processor(fakeProcessor) - .writer(fakeItemWriter) - .listener(itemProcessListener) - .faultTolerant().skipLimit(50).skip(RuntimeException.class) - .build(); + return stepBuilderFactory.get("testStep").chunk(10).reader(fakeItemReader) + .processor(fakeProcessor).writer(fakeItemWriter).listener(itemProcessListener).faultTolerant() + .skipLimit(50).skip(RuntimeException.class).build(); } @Bean public DataSource dataSource() { - return new EmbeddedDatabaseBuilder() - .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("/org/springframework/batch/core/schema-hsqldb.sql") - .generateUniqueName(true) - .build(); + return new EmbeddedDatabaseBuilder().addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") + .addScript("/org/springframework/batch/core/schema-hsqldb.sql").generateUniqueName(true).build(); } @Bean @@ -182,6 +170,7 @@ public class ItemListenerErrorTests { public FailingItemWriter fakeItemWriter() { return new FailingItemWriter(); } + } public static class FailingItemWriter implements ItemWriter { @@ -190,7 +179,7 @@ public class ItemListenerErrorTests { @Override public void write(List items) throws Exception { - if(goingToFail) { + if (goingToFail) { throw new RuntimeException("failure in the writer"); } else { @@ -203,6 +192,7 @@ public class ItemListenerErrorTests { public void setGoingToFail(boolean goingToFail) { this.goingToFail = goingToFail; } + } public static class FailingItemProcessor implements ItemProcessor { @@ -212,7 +202,7 @@ public class ItemListenerErrorTests { @Nullable @Override public String process(String item) throws Exception { - if(goingToFail) { + if (goingToFail) { throw new RuntimeException("failure in the processor"); } else { @@ -223,6 +213,7 @@ public class ItemListenerErrorTests { public void setGoingToFail(boolean goingToFail) { this.goingToFail = goingToFail; } + } public static class FailingItemReader implements ItemReader { @@ -237,7 +228,7 @@ public class ItemListenerErrorTests { @Override public String read() throws Exception { count++; - if(goingToFail) { + if (goingToFail) { throw new RuntimeException("failure in the reader"); } else { @@ -252,6 +243,7 @@ public class ItemListenerErrorTests { public int getCount() { return count; } + } public static class FailingListener extends ItemListenerSupport { @@ -324,5 +316,7 @@ public class ItemListenerErrorTests { throw new RuntimeException("onWriteError caused this Exception"); } } + } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/listener/JobListenerFactoryBeanTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/listener/JobListenerFactoryBeanTests.java index c25f8ed48..3f92116bf 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/listener/JobListenerFactoryBeanTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/listener/JobListenerFactoryBeanTests.java @@ -265,5 +265,7 @@ public class JobListenerFactoryBeanTests { public void after() { afterJobCalled = true; } + } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/listener/JobParameterExecutionContextCopyListenerTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/listener/JobParameterExecutionContextCopyListenerTests.java index 84fc48036..03bbc5419 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/listener/JobParameterExecutionContextCopyListenerTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/listener/JobParameterExecutionContextCopyListenerTests.java @@ -1,58 +1,58 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.listener; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; - -import org.junit.Before; -import org.junit.Test; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobInstance; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.StepExecution; - -/** - * @author Dave Syer - * - */ -public class JobParameterExecutionContextCopyListenerTests { - - private JobParameterExecutionContextCopyListener listener = new JobParameterExecutionContextCopyListener(); - - private StepExecution stepExecution; - - @Before - public void createExecution() { - JobParameters jobParameters = new JobParametersBuilder().addString("foo", "bar").toJobParameters(); - stepExecution = new StepExecution("foo", new JobExecution(new JobInstance(123L, "job"), jobParameters)); - } - - @Test - public void testBeforeStep() { - listener.beforeStep(stepExecution); - assertEquals("bar", stepExecution.getExecutionContext().get("foo")); - } - - @Test - public void testSetKeys() { - listener.setKeys(new String[]{}); - listener.beforeStep(stepExecution); - assertFalse(stepExecution.getExecutionContext().containsKey("foo")); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.listener; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobInstance; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.JobParametersBuilder; +import org.springframework.batch.core.StepExecution; + +/** + * @author Dave Syer + * + */ +public class JobParameterExecutionContextCopyListenerTests { + + private JobParameterExecutionContextCopyListener listener = new JobParameterExecutionContextCopyListener(); + + private StepExecution stepExecution; + + @Before + public void createExecution() { + JobParameters jobParameters = new JobParametersBuilder().addString("foo", "bar").toJobParameters(); + stepExecution = new StepExecution("foo", new JobExecution(new JobInstance(123L, "job"), jobParameters)); + } + + @Test + public void testBeforeStep() { + listener.beforeStep(stepExecution); + assertEquals("bar", stepExecution.getExecutionContext().get("foo")); + } + + @Test + public void testSetKeys() { + listener.setKeys(new String[] {}); + listener.beforeStep(stepExecution); + assertFalse(stepExecution.getExecutionContext().containsKey("foo")); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/listener/MulticasterBatchListenerTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/listener/MulticasterBatchListenerTests.java index dada2f44a..51167118c 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/listener/MulticasterBatchListenerTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/listener/MulticasterBatchListenerTests.java @@ -402,7 +402,7 @@ public class MulticasterBatchListenerTests { */ @Test public void testOnSkipInRead() { - multicast.register(new SkipListener() { + multicast.register(new SkipListener() { @Override public void onSkipInRead(Throwable t) { count++; @@ -419,7 +419,7 @@ public class MulticasterBatchListenerTests { */ @Test public void testOnSkipInReadFails() { - multicast.register(new SkipListener() { + multicast.register(new SkipListener() { @Override public void onSkipInRead(Throwable t) { count++; @@ -445,7 +445,7 @@ public class MulticasterBatchListenerTests { */ @Test public void testOnSkipInWrite() { - multicast.register(new SkipListener() { + multicast.register(new SkipListener() { @Override public void onSkipInWrite(Object item, Throwable t) { count++; @@ -462,7 +462,7 @@ public class MulticasterBatchListenerTests { */ @Test public void testOnSkipInWriteFails() { - multicast.register(new SkipListener() { + multicast.register(new SkipListener() { @Override public void onSkipInWrite(Object item, Throwable t) { count++; @@ -488,7 +488,7 @@ public class MulticasterBatchListenerTests { */ @Test public void testOnSkipInProcess() { - multicast.register(new SkipListener() { + multicast.register(new SkipListener() { @Override public void onSkipInProcess(Object item, Throwable t) { count++; @@ -505,7 +505,7 @@ public class MulticasterBatchListenerTests { */ @Test public void testOnSkipInProcessFails() { - multicast.register(new SkipListener() { + multicast.register(new SkipListener() { @Override public void onSkipInProcess(Object item, Throwable t) { count++; @@ -532,7 +532,8 @@ public class MulticasterBatchListenerTests { try { multicast.beforeRead(); fail("Expected StepListenerFailedException"); - } catch (StepListenerFailedException e) { + } + catch (StepListenerFailedException e) { // expected Throwable cause = e.getCause(); String message = cause.getMessage(); @@ -549,7 +550,8 @@ public class MulticasterBatchListenerTests { try { multicast.afterRead(null); fail("Expected StepListenerFailedException"); - } catch (StepListenerFailedException e) { + } + catch (StepListenerFailedException e) { // expected Throwable cause = e.getCause(); String message = cause.getMessage(); @@ -566,7 +568,8 @@ public class MulticasterBatchListenerTests { try { multicast.beforeProcess(null); fail("Expected StepListenerFailedException"); - } catch (StepListenerFailedException e) { + } + catch (StepListenerFailedException e) { // expected Throwable cause = e.getCause(); String message = cause.getMessage(); @@ -583,7 +586,8 @@ public class MulticasterBatchListenerTests { try { multicast.afterProcess(null, null); fail("Expected StepListenerFailedException"); - } catch (StepListenerFailedException e) { + } + catch (StepListenerFailedException e) { // expected Throwable cause = e.getCause(); String message = cause.getMessage(); @@ -600,7 +604,8 @@ public class MulticasterBatchListenerTests { try { multicast.beforeWrite(null); fail("Expected StepListenerFailedException"); - } catch (StepListenerFailedException e) { + } + catch (StepListenerFailedException e) { // expected Throwable cause = e.getCause(); String message = cause.getMessage(); @@ -617,7 +622,8 @@ public class MulticasterBatchListenerTests { try { multicast.afterWrite(null); fail("Expected StepListenerFailedException"); - } catch (StepListenerFailedException e) { + } + catch (StepListenerFailedException e) { // expected Throwable cause = e.getCause(); String message = cause.getMessage(); @@ -634,7 +640,8 @@ public class MulticasterBatchListenerTests { try { multicast.beforeChunk(null); fail("Expected StepListenerFailedException"); - } catch (StepListenerFailedException e) { + } + catch (StepListenerFailedException e) { // expected Throwable cause = e.getCause(); String message = cause.getMessage(); @@ -651,7 +658,8 @@ public class MulticasterBatchListenerTests { try { multicast.afterChunk(null); fail("Expected StepListenerFailedException"); - } catch (StepListenerFailedException e) { + } + catch (StepListenerFailedException e) { // expected Throwable cause = e.getCause(); String message = cause.getMessage(); @@ -711,6 +719,7 @@ public class MulticasterBatchListenerTests { * */ private final class CountingStepListenerSupport extends StepListenerSupport { + @Override public void onReadError(Exception ex) { count++; @@ -723,9 +732,7 @@ public class MulticasterBatchListenerTests { /* * (non-Javadoc) * - * @see - * org.springframework.batch.core.listener.StepListenerSupport#afterChunk - * () + * @see org.springframework.batch.core.listener.StepListenerSupport#afterChunk () */ @Override public void afterChunk(ChunkContext context) { @@ -739,8 +746,7 @@ public class MulticasterBatchListenerTests { /* * (non-Javadoc) * - * @see - * org.springframework.batch.core.listener.StepListenerSupport#afterRead + * @see org.springframework.batch.core.listener.StepListenerSupport#afterRead * (java.lang.Object) */ @Override @@ -755,8 +761,7 @@ public class MulticasterBatchListenerTests { /* * (non-Javadoc) * - * @see - * org.springframework.batch.core.listener.StepListenerSupport#afterStep + * @see org.springframework.batch.core.listener.StepListenerSupport#afterStep * (org.springframework.batch.core.StepExecution) */ @Nullable @@ -772,9 +777,7 @@ public class MulticasterBatchListenerTests { /* * (non-Javadoc) * - * @see - * org.springframework.batch.core.listener.StepListenerSupport#beforeChunk - * () + * @see org.springframework.batch.core.listener.StepListenerSupport#beforeChunk () */ @Override public void beforeChunk(ChunkContext context) { @@ -788,9 +791,7 @@ public class MulticasterBatchListenerTests { /* * (non-Javadoc) * - * @see - * org.springframework.batch.core.listener.StepListenerSupport#beforeRead - * () + * @see org.springframework.batch.core.listener.StepListenerSupport#beforeRead () */ @Override public void beforeRead() { @@ -804,8 +805,7 @@ public class MulticasterBatchListenerTests { /* * (non-Javadoc) * - * @see - * org.springframework.batch.core.listener.StepListenerSupport#beforeStep + * @see org.springframework.batch.core.listener.StepListenerSupport#beforeStep * (org.springframework.batch.core.StepExecution) */ @Override @@ -820,8 +820,7 @@ public class MulticasterBatchListenerTests { /* * (non-Javadoc) * - * @see - * org.springframework.batch.core.listener.StepListenerSupport#afterWrite + * @see org.springframework.batch.core.listener.StepListenerSupport#afterWrite * (java.util.List) */ @Override @@ -836,8 +835,7 @@ public class MulticasterBatchListenerTests { /* * (non-Javadoc) * - * @see - * org.springframework.batch.core.listener.StepListenerSupport#beforeWrite + * @see org.springframework.batch.core.listener.StepListenerSupport#beforeWrite * (java.util.List) */ @Override @@ -852,8 +850,7 @@ public class MulticasterBatchListenerTests { /* * (non-Javadoc) * - * @see - * org.springframework.batch.core.listener.StepListenerSupport#onWriteError + * @see org.springframework.batch.core.listener.StepListenerSupport#onWriteError * (java.lang.Exception, java.util.List) */ @Override diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/listener/StepListenerFactoryBeanTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/listener/StepListenerFactoryBeanTests.java index 9bd1a3dd7..d216d66ae 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/listener/StepListenerFactoryBeanTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/listener/StepListenerFactoryBeanTests.java @@ -86,10 +86,10 @@ public class StepListenerFactoryBeanTests { public void testStepAndChunk() throws Exception { TestListener testListener = new TestListener(); factoryBean.setDelegate(testListener); - // Map metaDataMap = new HashMap(); - // metaDataMap.put(AFTER_STEP.getPropertyName(), "destroy"); - // metaDataMap.put(AFTER_CHUNK.getPropertyName(), "afterChunk"); - // factoryBean.setMetaDataMap(metaDataMap); + // Map metaDataMap = new HashMap(); + // metaDataMap.put(AFTER_STEP.getPropertyName(), "destroy"); + // metaDataMap.put(AFTER_CHUNK.getPropertyName(), "afterChunk"); + // factoryBean.setMetaDataMap(metaDataMap); String readItem = "item"; Integer writeItem = 2; List writeItems = Arrays.asList(writeItem); @@ -547,4 +547,5 @@ public class StepListenerFactoryBeanTests { } } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/listener/StepListenerFailedExceptionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/listener/StepListenerFailedExceptionTests.java index 3ec79ba5b..0bcc6d365 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/listener/StepListenerFailedExceptionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/listener/StepListenerFailedExceptionTests.java @@ -19,8 +19,6 @@ import static org.junit.Assert.assertEquals; import org.junit.Test; - - /** * @author Dave Syer * @author Michael Minella @@ -33,4 +31,5 @@ public class StepListenerFailedExceptionTests { Exception exception = new StepListenerFailedException("foo", new IllegalStateException("bar")); assertEquals("foo", exception.getMessage().substring(0, 3)); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/listener/StepListenerMethodInterceptorTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/listener/StepListenerMethodInterceptorTests.java index fbbc36eb3..77041cfee 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/listener/StepListenerMethodInterceptorTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/listener/StepListenerMethodInterceptorTests.java @@ -1,147 +1,154 @@ -/* - * Copyright 2008-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.listener; - -import static org.junit.Assert.assertEquals; - -import java.lang.reflect.AccessibleObject; -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import org.aopalliance.intercept.MethodInvocation; -import org.junit.Before; -import org.junit.Test; -import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.support.MethodInvoker; -import org.springframework.batch.support.MethodInvokerUtils; -import org.springframework.batch.support.SimpleMethodInvoker; - -public class StepListenerMethodInterceptorTests { - - MethodInvokerMethodInterceptor interceptor; - TestClass testClass; - - @Before - public void setUp(){ - testClass = new TestClass(); - } - - @Test - public void testNormalCase() throws Throwable{ - - Map> invokerMap = new HashMap<>(); - for(Method method : TestClass.class.getMethods()){ - invokerMap.put(method.getName(), asSet( new SimpleMethodInvoker(testClass, method))); - } - interceptor = new MethodInvokerMethodInterceptor(invokerMap); - interceptor.invoke(new StubMethodInvocation(TestClass.class.getMethod("method1"))); - assertEquals(1, testClass.method1Count); - interceptor.invoke(new StubMethodInvocation(TestClass.class.getMethod("method2"))); - assertEquals(1, testClass.method2Count); - } - - @Test - public void testMultipleInvokersPerName() throws Throwable{ - - Map> invokerMap = new HashMap<>(); - Set invokers = asSet(MethodInvokerUtils.getMethodInvokerByName(testClass, "method1", false)); - invokers.add(MethodInvokerUtils.getMethodInvokerByName(testClass, "method2", false)); - invokerMap.put("method1", invokers); - interceptor = new MethodInvokerMethodInterceptor(invokerMap); - interceptor.invoke(new StubMethodInvocation(TestClass.class.getMethod("method1"))); - assertEquals(1, testClass.method1Count); - interceptor.invoke(new StubMethodInvocation(TestClass.class.getMethod("method2"))); - assertEquals(1, testClass.method2Count); - } - - @Test - public void testExitStatusReturn() throws Throwable{ - Map> invokerMap = new HashMap<>(); - Set invokers = asSet(MethodInvokerUtils.getMethodInvokerByName(testClass, "method3", false)); - invokers.add(MethodInvokerUtils.getMethodInvokerByName(testClass, "method3", false)); - invokerMap.put("method3", invokers); - interceptor = new MethodInvokerMethodInterceptor(invokerMap); - assertEquals(ExitStatus.COMPLETED, interceptor.invoke(new StubMethodInvocation(TestClass.class.getMethod("method3")))); - } - - public Set asSet(MethodInvoker methodInvoker){ - Set invokerSet = new HashSet<>(); - invokerSet.add(methodInvoker); - return invokerSet; - } - - @SuppressWarnings("unused") - private class TestClass{ - - int method1Count = 0; - int method2Count = 0; - int method3Count = 0; - - public void method1(){ - method1Count++; - } - - public void method2(){ - method2Count++; - } - - public ExitStatus method3(){ - method3Count++; - return ExitStatus.COMPLETED; - } - } - - @SuppressWarnings("unused") - private class StubMethodInvocation implements MethodInvocation{ - - Method method; - Object[] args; - - public StubMethodInvocation(Method method, Object... args) { - this.method = method; - this.args = args; - } - - @Override - public Method getMethod() { - return method; - } - - @Override - public Object[] getArguments() { - return null; - } - - @Override - public AccessibleObject getStaticPart() { - return null; - } - - @Override - public Object getThis() { - return null; - } - - @Override - public Object proceed() throws Throwable { - return null; - } - - } -} +/* + * Copyright 2008-2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.listener; + +import static org.junit.Assert.assertEquals; + +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.aopalliance.intercept.MethodInvocation; +import org.junit.Before; +import org.junit.Test; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.support.MethodInvoker; +import org.springframework.batch.support.MethodInvokerUtils; +import org.springframework.batch.support.SimpleMethodInvoker; + +public class StepListenerMethodInterceptorTests { + + MethodInvokerMethodInterceptor interceptor; + + TestClass testClass; + + @Before + public void setUp() { + testClass = new TestClass(); + } + + @Test + public void testNormalCase() throws Throwable { + + Map> invokerMap = new HashMap<>(); + for (Method method : TestClass.class.getMethods()) { + invokerMap.put(method.getName(), asSet(new SimpleMethodInvoker(testClass, method))); + } + interceptor = new MethodInvokerMethodInterceptor(invokerMap); + interceptor.invoke(new StubMethodInvocation(TestClass.class.getMethod("method1"))); + assertEquals(1, testClass.method1Count); + interceptor.invoke(new StubMethodInvocation(TestClass.class.getMethod("method2"))); + assertEquals(1, testClass.method2Count); + } + + @Test + public void testMultipleInvokersPerName() throws Throwable { + + Map> invokerMap = new HashMap<>(); + Set invokers = asSet(MethodInvokerUtils.getMethodInvokerByName(testClass, "method1", false)); + invokers.add(MethodInvokerUtils.getMethodInvokerByName(testClass, "method2", false)); + invokerMap.put("method1", invokers); + interceptor = new MethodInvokerMethodInterceptor(invokerMap); + interceptor.invoke(new StubMethodInvocation(TestClass.class.getMethod("method1"))); + assertEquals(1, testClass.method1Count); + interceptor.invoke(new StubMethodInvocation(TestClass.class.getMethod("method2"))); + assertEquals(1, testClass.method2Count); + } + + @Test + public void testExitStatusReturn() throws Throwable { + Map> invokerMap = new HashMap<>(); + Set invokers = asSet(MethodInvokerUtils.getMethodInvokerByName(testClass, "method3", false)); + invokers.add(MethodInvokerUtils.getMethodInvokerByName(testClass, "method3", false)); + invokerMap.put("method3", invokers); + interceptor = new MethodInvokerMethodInterceptor(invokerMap); + assertEquals(ExitStatus.COMPLETED, + interceptor.invoke(new StubMethodInvocation(TestClass.class.getMethod("method3")))); + } + + public Set asSet(MethodInvoker methodInvoker) { + Set invokerSet = new HashSet<>(); + invokerSet.add(methodInvoker); + return invokerSet; + } + + @SuppressWarnings("unused") + private class TestClass { + + int method1Count = 0; + + int method2Count = 0; + + int method3Count = 0; + + public void method1() { + method1Count++; + } + + public void method2() { + method2Count++; + } + + public ExitStatus method3() { + method3Count++; + return ExitStatus.COMPLETED; + } + + } + + @SuppressWarnings("unused") + private class StubMethodInvocation implements MethodInvocation { + + Method method; + + Object[] args; + + public StubMethodInvocation(Method method, Object... args) { + this.method = method; + this.args = args; + } + + @Override + public Method getMethod() { + return method; + } + + @Override + public Object[] getArguments() { + return null; + } + + @Override + public AccessibleObject getStaticPart() { + return null; + } + + @Override + public Object getThis() { + return null; + } + + @Override + public Object proceed() throws Throwable { + return null; + } + + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/observability/BatchMetricsTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/observability/BatchMetricsTests.java index 391dd3526..40306f34f 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/observability/BatchMetricsTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/observability/BatchMetricsTests.java @@ -62,11 +62,8 @@ public class BatchMetricsTests { @Test public void testCalculateDuration() { LocalDateTime startTime = LocalDateTime.now(); - LocalDateTime endTime = startTime - .plus(2, ChronoUnit.HOURS) - .plus(31, ChronoUnit.MINUTES) - .plus(12, ChronoUnit.SECONDS) - .plus(42, ChronoUnit.MILLIS); + LocalDateTime endTime = startTime.plus(2, ChronoUnit.HOURS).plus(31, ChronoUnit.MINUTES) + .plus(12, ChronoUnit.SECONDS).plus(42, ChronoUnit.MILLIS); Duration duration = BatchMetrics.calculateDuration(toDate(startTime), toDate(endTime)); Duration expectedDuration = Duration.ofMillis(42).plusSeconds(12).plusMinutes(31).plusHours(2); @@ -154,127 +151,114 @@ public class BatchMetricsTests { // Job metrics try { - Metrics.globalRegistry.get("spring.batch.job") - .tag("spring.batch.job.name", "job") - .tag("spring.batch.job.status", "COMPLETED") - .timer(); - } catch (Exception e) { - fail("There should be a meter of type TIMER named spring.batch.job " + - "registered in the global registry: " + e.getMessage()); + Metrics.globalRegistry.get("spring.batch.job").tag("spring.batch.job.name", "job") + .tag("spring.batch.job.status", "COMPLETED").timer(); + } + catch (Exception e) { + fail("There should be a meter of type TIMER named spring.batch.job " + "registered in the global registry: " + + e.getMessage()); } try { - Metrics.globalRegistry.get("spring.batch.job.active") - .tag("spring.batch.job.active.name", "job") + Metrics.globalRegistry.get("spring.batch.job.active").tag("spring.batch.job.active.name", "job") .longTaskTimer(); - } catch (Exception e) { - fail("There should be a meter of type LONG_TASK_TIMER named spring.batch.job.active" + - " registered in the global registry: " + e.getMessage()); } - + catch (Exception e) { + fail("There should be a meter of type LONG_TASK_TIMER named spring.batch.job.active" + + " registered in the global registry: " + e.getMessage()); + } + // Step 1 (tasklet) metrics try { - Metrics.globalRegistry.get("spring.batch.step") - .tag("spring.batch.step.name", "step1") - .tag("spring.batch.step.job.name", "job") - .tag("spring.batch.step.status", "COMPLETED") - .timer(); - } catch (Exception e) { - fail("There should be a meter of type TIMER named spring.batch.step" + - " registered in the global registry: " + e.getMessage()); + Metrics.globalRegistry.get("spring.batch.step").tag("spring.batch.step.name", "step1") + .tag("spring.batch.step.job.name", "job").tag("spring.batch.step.status", "COMPLETED").timer(); } - + catch (Exception e) { + fail("There should be a meter of type TIMER named spring.batch.step" + + " registered in the global registry: " + e.getMessage()); + } + // Step 2 (simple chunk-oriented) metrics try { - Metrics.globalRegistry.get("spring.batch.step") - .tag("spring.batch.step.name", "step2") - .tag("spring.batch.step.job.name", "job") - .tag("spring.batch.step.status", "COMPLETED") - .timer(); - } catch (Exception e) { - fail("There should be a meter of type TIMER named spring.batch.step" + - " registered in the global registry: " + e.getMessage()); + Metrics.globalRegistry.get("spring.batch.step").tag("spring.batch.step.name", "step2") + .tag("spring.batch.step.job.name", "job").tag("spring.batch.step.status", "COMPLETED").timer(); + } + catch (Exception e) { + fail("There should be a meter of type TIMER named spring.batch.step" + + " registered in the global registry: " + e.getMessage()); } try { - Metrics.globalRegistry.get("spring.batch.item.read") - .tag("spring.batch.item.read.job.name", "job") - .tag("spring.batch.item.read.step.name", "step2") - .tag("spring.batch.item.read.status", "SUCCESS") + Metrics.globalRegistry.get("spring.batch.item.read").tag("spring.batch.item.read.job.name", "job") + .tag("spring.batch.item.read.step.name", "step2").tag("spring.batch.item.read.status", "SUCCESS") .timer(); - } catch (Exception e) { - fail("There should be a meter of type TIMER named spring.batch.item.read" + - " registered in the global registry: " + e.getMessage()); + } + catch (Exception e) { + fail("There should be a meter of type TIMER named spring.batch.item.read" + + " registered in the global registry: " + e.getMessage()); } try { - Metrics.globalRegistry.get("spring.batch.item.process") - .tag("spring.batch.item.process.job.name", "job") + Metrics.globalRegistry.get("spring.batch.item.process").tag("spring.batch.item.process.job.name", "job") .tag("spring.batch.item.process.step.name", "step2") - .tag("spring.batch.item.process.status", "SUCCESS") - .timer(); - } catch (Exception e) { - fail("There should be a meter of type TIMER named spring.batch.item.process" + - " registered in the global registry: " + e.getMessage()); + .tag("spring.batch.item.process.status", "SUCCESS").timer(); + } + catch (Exception e) { + fail("There should be a meter of type TIMER named spring.batch.item.process" + + " registered in the global registry: " + e.getMessage()); } try { - Metrics.globalRegistry.get("spring.batch.chunk.write") - .tag("spring.batch.chunk.write.job.name", "job") + Metrics.globalRegistry.get("spring.batch.chunk.write").tag("spring.batch.chunk.write.job.name", "job") .tag("spring.batch.chunk.write.step.name", "step2") - .tag("spring.batch.chunk.write.status", "SUCCESS") - .timer(); - } catch (Exception e) { - fail("There should be a meter of type TIMER named spring.batch.chunk.write" + - " registered in the global registry: " + e.getMessage()); + .tag("spring.batch.chunk.write.status", "SUCCESS").timer(); } - + catch (Exception e) { + fail("There should be a meter of type TIMER named spring.batch.chunk.write" + + " registered in the global registry: " + e.getMessage()); + } + // Step 3 (fault-tolerant chunk-oriented) metrics try { - Metrics.globalRegistry.get("spring.batch.step") - .tag("spring.batch.step.name", "step3") - .tag("spring.batch.step.job.name", "job") - .tag("spring.batch.step.status", "COMPLETED") - .timer(); - } catch (Exception e) { - fail("There should be a meter of type TIMER named spring.batch.step" + - " registered in the global registry: " + e.getMessage()); + Metrics.globalRegistry.get("spring.batch.step").tag("spring.batch.step.name", "step3") + .tag("spring.batch.step.job.name", "job").tag("spring.batch.step.status", "COMPLETED").timer(); + } + catch (Exception e) { + fail("There should be a meter of type TIMER named spring.batch.step" + + " registered in the global registry: " + e.getMessage()); } try { - Metrics.globalRegistry.get("spring.batch.item.read") - .tag("spring.batch.item.read.job.name", "job") - .tag("spring.batch.item.read.step.name", "step3") - .tag("spring.batch.item.read.status", "SUCCESS") + Metrics.globalRegistry.get("spring.batch.item.read").tag("spring.batch.item.read.job.name", "job") + .tag("spring.batch.item.read.step.name", "step3").tag("spring.batch.item.read.status", "SUCCESS") .timer(); - } catch (Exception e) { - fail("There should be a meter of type TIMER named spring.batch.item.read" + - " registered in the global registry: " + e.getMessage()); + } + catch (Exception e) { + fail("There should be a meter of type TIMER named spring.batch.item.read" + + " registered in the global registry: " + e.getMessage()); } try { - Metrics.globalRegistry.get("spring.batch.item.process") - .tag("spring.batch.item.process.job.name", "job") + Metrics.globalRegistry.get("spring.batch.item.process").tag("spring.batch.item.process.job.name", "job") .tag("spring.batch.item.process.step.name", "step3") - .tag("spring.batch.item.process.status", "SUCCESS") - .timer(); - } catch (Exception e) { - fail("There should be a meter of type TIMER named spring.batch.item.process" + - " registered in the global registry: " + e.getMessage()); + .tag("spring.batch.item.process.status", "SUCCESS").timer(); + } + catch (Exception e) { + fail("There should be a meter of type TIMER named spring.batch.item.process" + + " registered in the global registry: " + e.getMessage()); } try { - Metrics.globalRegistry.get("spring.batch.chunk.write") - .tag("spring.batch.chunk.write.job.name", "job") + Metrics.globalRegistry.get("spring.batch.chunk.write").tag("spring.batch.chunk.write.job.name", "job") .tag("spring.batch.chunk.write.step.name", "step3") - .tag("spring.batch.chunk.write.status", "SUCCESS") - .timer(); - } catch (Exception e) { - fail("There should be a meter of type TIMER named spring.batch.chunk.write" + - " registered in the global registry: " + e.getMessage()); + .tag("spring.batch.chunk.write.status", "SUCCESS").timer(); + } + catch (Exception e) { + fail("There should be a meter of type TIMER named spring.batch.chunk.write" + + " registered in the global registry: " + e.getMessage()); } } @@ -284,6 +268,7 @@ public class BatchMetricsTests { static class MyJobConfiguration { private JobBuilderFactory jobBuilderFactory; + private StepBuilderFactory stepBuilderFactory; public MyJobConfiguration(JobBuilderFactory jobBuilderFactory, StepBuilderFactory stepBuilderFactory) { @@ -293,51 +278,41 @@ public class BatchMetricsTests { @Bean public Step step1() { - return stepBuilderFactory.get("step1") - .tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED) + return stepBuilderFactory.get("step1").tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED) .build(); } @Bean public Step step2() { - return stepBuilderFactory.get("step2") - .chunk(2) + return stepBuilderFactory.get("step2").chunk(2) .reader(new ListItemReader<>(Arrays.asList(1, 2, 3, 4, 5))) - .writer(items -> items.forEach(System.out::println)) - .build(); + .writer(items -> items.forEach(System.out::println)).build(); } @Bean public Step step3() { - return stepBuilderFactory.get("step3") - .chunk(2) + return stepBuilderFactory.get("step3").chunk(2) .reader(new ListItemReader<>(Arrays.asList(6, 7, 8, 9, 10))) - .writer(items -> items.forEach(System.out::println)) - .faultTolerant() - .skip(Exception.class) - .skipLimit(3) - .build(); + .writer(items -> items.forEach(System.out::println)).faultTolerant().skip(Exception.class) + .skipLimit(3).build(); } @Bean public Job job() { - return jobBuilderFactory.get("job") - .start(step1()) - .next(step2()) - .next(step3()) - .build(); + return jobBuilderFactory.get("job").start(step1()).next(step2()).next(step3()).build(); } + } @Configuration static class DataSoourceConfiguration { + @Bean public DataSource dataSource() { - return new EmbeddedDatabaseBuilder() - .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("/org/springframework/batch/core/schema-hsqldb.sql") - .generateUniqueName(true) - .build(); + return new EmbeddedDatabaseBuilder().addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") + .addScript("/org/springframework/batch/core/schema-hsqldb.sql").generateUniqueName(true).build(); } + } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/partition/ExampleItemReader.java b/spring-batch-core/src/test/java/org/springframework/batch/core/partition/ExampleItemReader.java index a2e071889..fcb020342 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/partition/ExampleItemReader.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/partition/ExampleItemReader.java @@ -1,99 +1,99 @@ -/* - * Copyright 2008-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.partition; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemStreamException; -import org.springframework.batch.item.ItemStreamReader; -import org.springframework.batch.item.support.AbstractItemStreamItemReader; -import org.springframework.lang.Nullable; -import org.springframework.util.ClassUtils; - -/** - * {@link ItemStreamReader} with hard-coded input data. - */ -public class ExampleItemReader extends AbstractItemStreamItemReader { - - private Log logger = LogFactory.getLog(getClass()); - - private String[] input = { "Hello", "world!", "Go", "on", "punk", "make", "my", "day!" }; - - private int index = 0; - - private int min = 0; - - private int max = Integer.MAX_VALUE; - - public static volatile boolean fail = false; - - public ExampleItemReader() { - this.setExecutionContextName(ClassUtils.getShortName(this.getClass())); - } - - /** - * @param min the min to set - */ - public void setMin(int min) { - this.min = min; - } - - /** - * @param max the max to set - */ - public void setMax(int max) { - this.max = max; - } - - /** - * Reads next record from input - */ - @Nullable - @Override - public String read() throws Exception { - if (index >= input.length || index >= max) { - return null; - } - logger.info(String.format("Processing input index=%s, item=%s, in (%s)", index, input[index], this)); - if (fail && index == 4) { - synchronized (ExampleItemReader.class) { - if (fail) { - // Only fail once per flag setting... - fail = false; - logger.info(String.format("Throwing exception index=%s, item=%s, in (%s)", index, input[index], - this)); - index++; - throw new RuntimeException("Planned failure"); - } - } - } - return input[index++]; - } - - @Override - public void open(ExecutionContext executionContext) throws ItemStreamException { - super.open(executionContext); - index = (int) executionContext.getLong(getExecutionContextKey("POSITION"), min); - } - - @Override - public void update(ExecutionContext executionContext) throws ItemStreamException { - super.update(executionContext); - executionContext.putLong(getExecutionContextKey("POSITION"), index); - } - -} +/* + * Copyright 2008-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.partition; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ItemStreamException; +import org.springframework.batch.item.ItemStreamReader; +import org.springframework.batch.item.support.AbstractItemStreamItemReader; +import org.springframework.lang.Nullable; +import org.springframework.util.ClassUtils; + +/** + * {@link ItemStreamReader} with hard-coded input data. + */ +public class ExampleItemReader extends AbstractItemStreamItemReader { + + private Log logger = LogFactory.getLog(getClass()); + + private String[] input = { "Hello", "world!", "Go", "on", "punk", "make", "my", "day!" }; + + private int index = 0; + + private int min = 0; + + private int max = Integer.MAX_VALUE; + + public static volatile boolean fail = false; + + public ExampleItemReader() { + this.setExecutionContextName(ClassUtils.getShortName(this.getClass())); + } + + /** + * @param min the min to set + */ + public void setMin(int min) { + this.min = min; + } + + /** + * @param max the max to set + */ + public void setMax(int max) { + this.max = max; + } + + /** + * Reads next record from input + */ + @Nullable + @Override + public String read() throws Exception { + if (index >= input.length || index >= max) { + return null; + } + logger.info(String.format("Processing input index=%s, item=%s, in (%s)", index, input[index], this)); + if (fail && index == 4) { + synchronized (ExampleItemReader.class) { + if (fail) { + // Only fail once per flag setting... + fail = false; + logger.info( + String.format("Throwing exception index=%s, item=%s, in (%s)", index, input[index], this)); + index++; + throw new RuntimeException("Planned failure"); + } + } + } + return input[index++]; + } + + @Override + public void open(ExecutionContext executionContext) throws ItemStreamException { + super.open(executionContext); + index = (int) executionContext.getLong(getExecutionContextKey("POSITION"), min); + } + + @Override + public void update(ExecutionContext executionContext) throws ItemStreamException { + super.update(executionContext); + executionContext.putLong(getExecutionContextKey("POSITION"), index); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/partition/ExampleItemReaderTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/partition/ExampleItemReaderTests.java index 0d2a0e539..afc2495e7 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/partition/ExampleItemReaderTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/partition/ExampleItemReaderTests.java @@ -1,85 +1,85 @@ -/* - * Copyright 2008 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.partition; - -import static org.junit.Assert.*; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.springframework.batch.item.ExecutionContext; - -public class ExampleItemReaderTests { - - private ExampleItemReader reader = new ExampleItemReader(); - - @Before - @After - public void ensureFailFlagUnset() { - ExampleItemReader.fail = false; - } - - @Test - public void testRead() throws Exception { - int count = 0; - while (reader.read()!=null) { - count++; - } - assertEquals(8, count); - } - - @Test - public void testOpen() throws Exception { - ExecutionContext context = new ExecutionContext(); - for (int i=0; i<4; i++) { - reader.read(); - } - reader.update(context); - reader.open(context); - int count = 0; - while (reader.read()!=null) { - count++; - } - assertEquals(4, count); - } - - @Test - public void testFailAndRestart() throws Exception { - ExecutionContext context = new ExecutionContext(); - ExampleItemReader.fail = true; - for (int i=0; i<4; i++) { - reader.read(); - reader.update(context); - } - try { - reader.read(); - reader.update(context); - fail("Expected Exception"); - } - catch (Exception e) { - // expected - assertEquals("Planned failure", e.getMessage()); - } - assertFalse(ExampleItemReader.fail); - reader.open(context); - int count = 0; - while (reader.read()!=null) { - count++; - } - assertEquals(4, count); - } - -} +/* + * Copyright 2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.partition; + +import static org.junit.Assert.*; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.springframework.batch.item.ExecutionContext; + +public class ExampleItemReaderTests { + + private ExampleItemReader reader = new ExampleItemReader(); + + @Before + @After + public void ensureFailFlagUnset() { + ExampleItemReader.fail = false; + } + + @Test + public void testRead() throws Exception { + int count = 0; + while (reader.read() != null) { + count++; + } + assertEquals(8, count); + } + + @Test + public void testOpen() throws Exception { + ExecutionContext context = new ExecutionContext(); + for (int i = 0; i < 4; i++) { + reader.read(); + } + reader.update(context); + reader.open(context); + int count = 0; + while (reader.read() != null) { + count++; + } + assertEquals(4, count); + } + + @Test + public void testFailAndRestart() throws Exception { + ExecutionContext context = new ExecutionContext(); + ExampleItemReader.fail = true; + for (int i = 0; i < 4; i++) { + reader.read(); + reader.update(context); + } + try { + reader.read(); + reader.update(context); + fail("Expected Exception"); + } + catch (Exception e) { + // expected + assertEquals("Planned failure", e.getMessage()); + } + assertFalse(ExampleItemReader.fail); + reader.open(context); + int count = 0; + while (reader.read() != null) { + count++; + } + assertEquals(4, count); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/partition/ExampleItemWriter.java b/spring-batch-core/src/test/java/org/springframework/batch/core/partition/ExampleItemWriter.java index 2f5df55c4..d142e3219 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/partition/ExampleItemWriter.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/partition/ExampleItemWriter.java @@ -1,51 +1,51 @@ -/* - * Copyright 2008-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.partition; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.batch.item.ItemWriter; - -/** - * Dummy {@link ItemWriter} which only logs data it receives. - */ -public class ExampleItemWriter implements ItemWriter { - - private static final Log log = LogFactory.getLog(ExampleItemWriter.class); - - private static List items = new ArrayList<>(); - - public static void clear() { - items.clear(); - } - - public static List getItems() { - return items; - } - - /** - * @see ItemWriter#write(List) - */ - @Override - public void write(List data) throws Exception { - log.info(data); - items.addAll(data); - } - -} +/* + * Copyright 2008-2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.partition; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.batch.item.ItemWriter; + +/** + * Dummy {@link ItemWriter} which only logs data it receives. + */ +public class ExampleItemWriter implements ItemWriter { + + private static final Log log = LogFactory.getLog(ExampleItemWriter.class); + + private static List items = new ArrayList<>(); + + public static void clear() { + items.clear(); + } + + public static List getItems() { + return items; + } + + /** + * @see ItemWriter#write(List) + */ + @Override + public void write(List data) throws Exception { + log.info(data); + items.addAll(data); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/partition/MinMaxPartitioner.java b/spring-batch-core/src/test/java/org/springframework/batch/core/partition/MinMaxPartitioner.java index 4aa8489f1..d46112f34 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/partition/MinMaxPartitioner.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/partition/MinMaxPartitioner.java @@ -1,45 +1,45 @@ -/* - * Copyright 2006-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.core.partition; - -import java.util.Map; - -import org.springframework.batch.core.partition.support.SimplePartitioner; -import org.springframework.batch.item.ExecutionContext; - -/** - * @author Dave Syer - * - */ -public class MinMaxPartitioner extends SimplePartitioner { - - @Override - public Map partition(int gridSize) { - Map partition = super.partition(gridSize); - int total = 8; // The number of items in the ExampleItemReader - int range = total/gridSize; - int i = 0; - for (ExecutionContext context : partition.values()) { - int min = (i++)*range; - int max = Math.min(total, i * range); - context.putInt("min", min); - context.putInt("max", max); - } - return partition; - } - -} +/* + * Copyright 2006-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.core.partition; + +import java.util.Map; + +import org.springframework.batch.core.partition.support.SimplePartitioner; +import org.springframework.batch.item.ExecutionContext; + +/** + * @author Dave Syer + * + */ +public class MinMaxPartitioner extends SimplePartitioner { + + @Override + public Map partition(int gridSize) { + Map partition = super.partition(gridSize); + int total = 8; // The number of items in the ExampleItemReader + int range = total / gridSize; + int i = 0; + for (ExecutionContext context : partition.values()) { + int min = (i++) * range; + int max = Math.min(total, i * range); + context.putInt("min", min); + context.putInt("max", max); + } + return partition; + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/partition/RestartIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/partition/RestartIntegrationTests.java index 4a51db655..95cbee187 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/partition/RestartIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/partition/RestartIntegrationTests.java @@ -39,7 +39,7 @@ import org.springframework.test.jdbc.JdbcTestUtils; /** * @author Dave Syer * @author Mahmoud Ben Hassine - * + * */ @ContextConfiguration(locations = "launch-context.xml") @RunWith(SpringJUnit4ClassRunner.class) @@ -52,7 +52,7 @@ public class RestartIntegrationTests { private Job job; private JdbcTemplate jdbcTemplate; - + @Autowired public void setDataSource(DataSource dataSource) { this.jdbcTemplate = new JdbcTemplate(dataSource); @@ -76,12 +76,14 @@ public class RestartIntegrationTests { ExampleItemReader.fail = true; JobParameters jobParameters = new JobParametersBuilder().addString("restart", "yes").toJobParameters(); - int beforeManager = JdbcTestUtils.countRowsInTableWhere(jdbcTemplate, "BATCH_STEP_EXECUTION", "STEP_NAME='step1:manager'"); - int beforePartition = JdbcTestUtils.countRowsInTableWhere(jdbcTemplate, "BATCH_STEP_EXECUTION", "STEP_NAME like 'step1:partition%'"); + int beforeManager = JdbcTestUtils.countRowsInTableWhere(jdbcTemplate, "BATCH_STEP_EXECUTION", + "STEP_NAME='step1:manager'"); + int beforePartition = JdbcTestUtils.countRowsInTableWhere(jdbcTemplate, "BATCH_STEP_EXECUTION", + "STEP_NAME like 'step1:partition%'"); ExampleItemWriter.clear(); JobExecution execution = jobLauncher.run(job, jobParameters); - assertEquals(BatchStatus.FAILED,execution.getStatus()); + assertEquals(BatchStatus.FAILED, execution.getStatus()); // Only 4 because the others were in the failed step execution assertEquals(4, ExampleItemWriter.getItems().size()); @@ -90,13 +92,15 @@ public class RestartIntegrationTests { // Only 4 because the others were processed in the first attempt assertEquals(4, ExampleItemWriter.getItems().size()); - int afterManager = JdbcTestUtils.countRowsInTableWhere(jdbcTemplate, "BATCH_STEP_EXECUTION", "STEP_NAME='step1:manager'"); - int afterPartition = JdbcTestUtils.countRowsInTableWhere(jdbcTemplate, "BATCH_STEP_EXECUTION", "STEP_NAME like 'step1:partition%'"); + int afterManager = JdbcTestUtils.countRowsInTableWhere(jdbcTemplate, "BATCH_STEP_EXECUTION", + "STEP_NAME='step1:manager'"); + int afterPartition = JdbcTestUtils.countRowsInTableWhere(jdbcTemplate, "BATCH_STEP_EXECUTION", + "STEP_NAME like 'step1:partition%'"); // Two attempts - assertEquals(2, afterManager-beforeManager); + assertEquals(2, afterManager - beforeManager); // One failure and two successes - assertEquals(3, afterPartition-beforePartition); + assertEquals(3, afterPartition - beforePartition); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/partition/VanillaIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/partition/VanillaIntegrationTests.java index 1b2c805a7..12cd966a9 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/partition/VanillaIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/partition/VanillaIntegrationTests.java @@ -34,9 +34,9 @@ import org.springframework.test.jdbc.JdbcTestUtils; /** * @author Dave Syer * @author Mahmoud Ben Hassine - * + * */ -@ContextConfiguration(locations="launch-context.xml") +@ContextConfiguration(locations = "launch-context.xml") @RunWith(SpringJUnit4ClassRunner.class) public class VanillaIntegrationTests { @@ -47,7 +47,7 @@ public class VanillaIntegrationTests { private Job job; private JdbcTemplate jdbcTemplate; - + @Autowired public void setDataSource(DataSource dataSource) { this.jdbcTemplate = new JdbcTemplate(dataSource); @@ -60,14 +60,18 @@ public class VanillaIntegrationTests { @Test public void testLaunchJob() throws Exception { - int beforeManager = JdbcTestUtils.countRowsInTableWhere(jdbcTemplate, "BATCH_STEP_EXECUTION", "STEP_NAME='step1:manager'"); - int beforePartition = JdbcTestUtils.countRowsInTableWhere(jdbcTemplate, "BATCH_STEP_EXECUTION", "STEP_NAME like 'step1:partition%'"); + int beforeManager = JdbcTestUtils.countRowsInTableWhere(jdbcTemplate, "BATCH_STEP_EXECUTION", + "STEP_NAME='step1:manager'"); + int beforePartition = JdbcTestUtils.countRowsInTableWhere(jdbcTemplate, "BATCH_STEP_EXECUTION", + "STEP_NAME like 'step1:partition%'"); assertNotNull(jobLauncher.run(job, new JobParameters())); - int afterManager = JdbcTestUtils.countRowsInTableWhere(jdbcTemplate, "BATCH_STEP_EXECUTION", "STEP_NAME='step1:manager'"); - int afterPartition = JdbcTestUtils.countRowsInTableWhere(jdbcTemplate, "BATCH_STEP_EXECUTION", "STEP_NAME like 'step1:partition%'"); - assertEquals(1, afterManager-beforeManager); + int afterManager = JdbcTestUtils.countRowsInTableWhere(jdbcTemplate, "BATCH_STEP_EXECUTION", + "STEP_NAME='step1:manager'"); + int afterPartition = JdbcTestUtils.countRowsInTableWhere(jdbcTemplate, "BATCH_STEP_EXECUTION", + "STEP_NAME like 'step1:partition%'"); + assertEquals(1, afterManager - beforeManager); // Should be same as grid size in step splitter - assertEquals(2, afterPartition-beforePartition); + assertEquals(2, afterPartition - beforePartition); } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/partition/support/DefaultStepExecutionAggregatorTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/partition/support/DefaultStepExecutionAggregatorTests.java index 8a9e6f6dc..d37be340c 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/partition/support/DefaultStepExecutionAggregatorTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/partition/support/DefaultStepExecutionAggregatorTests.java @@ -1,117 +1,118 @@ -/* - * Copyright 2009-2010 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.partition.support; - -import org.junit.Test; -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.StepExecution; - -import java.util.Arrays; -import java.util.Collections; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -public class DefaultStepExecutionAggregatorTests { - - private StepExecutionAggregator aggregator = new DefaultStepExecutionAggregator(); - - private JobExecution jobExecution = new JobExecution(11L); - - private StepExecution result = jobExecution.createStepExecution("aggregate"); - - private StepExecution stepExecution1 = jobExecution.createStepExecution("foo:1"); - - private StepExecution stepExecution2 = jobExecution.createStepExecution("foo:2"); - - @Test - public void testAggregateEmpty() { - aggregator.aggregate(result, Collections. emptySet()); - } - - @Test - public void testAggregateNull() { - aggregator.aggregate(result, null); - } - - @Test - public void testAggregateStatusSunnyDay() { - stepExecution1.setStatus(BatchStatus.COMPLETED); - stepExecution2.setStatus(BatchStatus.COMPLETED); - aggregator.aggregate(result, Arrays. asList(stepExecution1, stepExecution2)); - assertNotNull(result); - assertEquals(BatchStatus.STARTING, result.getStatus()); - } - - @Test - public void testAggregateStatusFromFailure() { - result.setStatus(BatchStatus.FAILED); - stepExecution1.setStatus(BatchStatus.COMPLETED); - stepExecution2.setStatus(BatchStatus.COMPLETED); - aggregator.aggregate(result, Arrays. asList(stepExecution1, stepExecution2)); - assertNotNull(result); - assertEquals(BatchStatus.FAILED, result.getStatus()); - } - - @Test - public void testAggregateStatusIncomplete() { - stepExecution1.setStatus(BatchStatus.COMPLETED); - stepExecution2.setStatus(BatchStatus.FAILED); - aggregator.aggregate(result, Arrays. asList(stepExecution1, stepExecution2)); - assertNotNull(result); - assertEquals(BatchStatus.FAILED, result.getStatus()); - } - - @Test - public void testAggregateExitStatusSunnyDay() { - stepExecution1.setExitStatus(ExitStatus.EXECUTING); - stepExecution2.setExitStatus(ExitStatus.FAILED); - aggregator.aggregate(result, Arrays. asList(stepExecution1, stepExecution2)); - assertNotNull(result); - assertEquals(ExitStatus.FAILED.and(ExitStatus.EXECUTING), result.getExitStatus()); - } - - @Test - public void testAggregateCountsSunnyDay() { - stepExecution1.setCommitCount(1); - stepExecution1.setFilterCount(2); - stepExecution1.setProcessSkipCount(3); - stepExecution1.setReadCount(4); - stepExecution1.setReadSkipCount(5); - stepExecution1.setRollbackCount(6); - stepExecution1.setWriteCount(7); - stepExecution1.setWriteSkipCount(8); - stepExecution2.setCommitCount(11); - stepExecution2.setFilterCount(12); - stepExecution2.setProcessSkipCount(13); - stepExecution2.setReadCount(14); - stepExecution2.setReadSkipCount(15); - stepExecution2.setRollbackCount(16); - stepExecution2.setWriteCount(17); - stepExecution2.setWriteSkipCount(18); - aggregator.aggregate(result, Arrays. asList(stepExecution1, stepExecution2)); - assertEquals(12, result.getCommitCount()); - assertEquals(14, result.getFilterCount()); - assertEquals(16, result.getProcessSkipCount()); - assertEquals(18, result.getReadCount()); - assertEquals(20, result.getReadSkipCount()); - assertEquals(22, result.getRollbackCount()); - assertEquals(24, result.getWriteCount()); - assertEquals(26, result.getWriteSkipCount()); - } -} +/* + * Copyright 2009-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.partition.support; + +import org.junit.Test; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.StepExecution; + +import java.util.Arrays; +import java.util.Collections; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +public class DefaultStepExecutionAggregatorTests { + + private StepExecutionAggregator aggregator = new DefaultStepExecutionAggregator(); + + private JobExecution jobExecution = new JobExecution(11L); + + private StepExecution result = jobExecution.createStepExecution("aggregate"); + + private StepExecution stepExecution1 = jobExecution.createStepExecution("foo:1"); + + private StepExecution stepExecution2 = jobExecution.createStepExecution("foo:2"); + + @Test + public void testAggregateEmpty() { + aggregator.aggregate(result, Collections.emptySet()); + } + + @Test + public void testAggregateNull() { + aggregator.aggregate(result, null); + } + + @Test + public void testAggregateStatusSunnyDay() { + stepExecution1.setStatus(BatchStatus.COMPLETED); + stepExecution2.setStatus(BatchStatus.COMPLETED); + aggregator.aggregate(result, Arrays.asList(stepExecution1, stepExecution2)); + assertNotNull(result); + assertEquals(BatchStatus.STARTING, result.getStatus()); + } + + @Test + public void testAggregateStatusFromFailure() { + result.setStatus(BatchStatus.FAILED); + stepExecution1.setStatus(BatchStatus.COMPLETED); + stepExecution2.setStatus(BatchStatus.COMPLETED); + aggregator.aggregate(result, Arrays.asList(stepExecution1, stepExecution2)); + assertNotNull(result); + assertEquals(BatchStatus.FAILED, result.getStatus()); + } + + @Test + public void testAggregateStatusIncomplete() { + stepExecution1.setStatus(BatchStatus.COMPLETED); + stepExecution2.setStatus(BatchStatus.FAILED); + aggregator.aggregate(result, Arrays.asList(stepExecution1, stepExecution2)); + assertNotNull(result); + assertEquals(BatchStatus.FAILED, result.getStatus()); + } + + @Test + public void testAggregateExitStatusSunnyDay() { + stepExecution1.setExitStatus(ExitStatus.EXECUTING); + stepExecution2.setExitStatus(ExitStatus.FAILED); + aggregator.aggregate(result, Arrays.asList(stepExecution1, stepExecution2)); + assertNotNull(result); + assertEquals(ExitStatus.FAILED.and(ExitStatus.EXECUTING), result.getExitStatus()); + } + + @Test + public void testAggregateCountsSunnyDay() { + stepExecution1.setCommitCount(1); + stepExecution1.setFilterCount(2); + stepExecution1.setProcessSkipCount(3); + stepExecution1.setReadCount(4); + stepExecution1.setReadSkipCount(5); + stepExecution1.setRollbackCount(6); + stepExecution1.setWriteCount(7); + stepExecution1.setWriteSkipCount(8); + stepExecution2.setCommitCount(11); + stepExecution2.setFilterCount(12); + stepExecution2.setProcessSkipCount(13); + stepExecution2.setReadCount(14); + stepExecution2.setReadSkipCount(15); + stepExecution2.setRollbackCount(16); + stepExecution2.setWriteCount(17); + stepExecution2.setWriteSkipCount(18); + aggregator.aggregate(result, Arrays.asList(stepExecution1, stepExecution2)); + assertEquals(12, result.getCommitCount()); + assertEquals(14, result.getFilterCount()); + assertEquals(16, result.getProcessSkipCount()); + assertEquals(18, result.getReadCount()); + assertEquals(20, result.getReadSkipCount()); + assertEquals(22, result.getRollbackCount()); + assertEquals(24, result.getWriteCount()); + assertEquals(26, result.getWriteSkipCount()); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/partition/support/PartitionStepTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/partition/support/PartitionStepTests.java index 116bc024b..054db83ff 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/partition/support/PartitionStepTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/partition/support/PartitionStepTests.java @@ -1,216 +1,220 @@ -/* - * Copyright 2006-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.partition.support; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Date; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; - -import org.junit.Before; -import org.junit.Test; - -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.partition.PartitionHandler; -import org.springframework.batch.core.partition.StepExecutionSplitter; -import org.springframework.batch.core.repository.JobRepository; -import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; -import org.springframework.jdbc.datasource.DataSourceTransactionManager; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; - -import static org.junit.Assert.assertEquals; - -/** - * @author Dave Syer - * @author Mahmoud Ben Hassine - * - */ -public class PartitionStepTests { - - private PartitionStep step = new PartitionStep(); - - private JobRepository jobRepository; - - @Before - public void setUp() throws Exception { - EmbeddedDatabase embeddedDatabase = new EmbeddedDatabaseBuilder() - .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("/org/springframework/batch/core/schema-hsqldb.sql") - .build(); - JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); - factory.setDataSource(embeddedDatabase); - factory.setTransactionManager(new DataSourceTransactionManager(embeddedDatabase)); - factory.afterPropertiesSet(); - jobRepository = factory.getObject(); - step.setJobRepository(jobRepository); - step.setName("partitioned"); - } - - @Test - public void testVanillaStepExecution() throws Exception { - step.setStepExecutionSplitter(new SimpleStepExecutionSplitter(jobRepository, true, step.getName(), new SimplePartitioner())); - step.setPartitionHandler(new PartitionHandler() { - @Override - public Collection handle(StepExecutionSplitter stepSplitter, StepExecution stepExecution) - throws Exception { - Set executions = stepSplitter.split(stepExecution, 2); - for (StepExecution execution : executions) { - execution.setStatus(BatchStatus.COMPLETED); - execution.setExitStatus(ExitStatus.COMPLETED); - } - return executions; - } - }); - step.afterPropertiesSet(); - JobExecution jobExecution = jobRepository.createJobExecution("vanillaJob", new JobParameters()); - StepExecution stepExecution = jobExecution.createStepExecution("foo"); - jobRepository.add(stepExecution); - step.execute(stepExecution); - // one manager and two workers - assertEquals(3, stepExecution.getJobExecution().getStepExecutions().size()); - assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - } - - @Test - public void testFailedStepExecution() throws Exception { - step.setStepExecutionSplitter(new SimpleStepExecutionSplitter(jobRepository, true, step.getName(), new SimplePartitioner())); - step.setPartitionHandler(new PartitionHandler() { - @Override - public Collection handle(StepExecutionSplitter stepSplitter, StepExecution stepExecution) - throws Exception { - Set executions = stepSplitter.split(stepExecution, 2); - for (StepExecution execution : executions) { - execution.setStatus(BatchStatus.FAILED); - execution.setExitStatus(ExitStatus.FAILED); - } - return executions; - } - }); - step.afterPropertiesSet(); - JobExecution jobExecution = jobRepository.createJobExecution("vanillaJob", new JobParameters()); - StepExecution stepExecution = jobExecution.createStepExecution("foo"); - jobRepository.add(stepExecution); - step.execute(stepExecution); - // one manager and two workers - assertEquals(3, stepExecution.getJobExecution().getStepExecutions().size()); - assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); - } - - @Test - public void testRestartStepExecution() throws Exception { - final AtomicBoolean started = new AtomicBoolean(false); - step.setStepExecutionSplitter(new SimpleStepExecutionSplitter(jobRepository, true, step.getName(), new SimplePartitioner())); - step.setPartitionHandler(new PartitionHandler() { - @Override - public Collection handle(StepExecutionSplitter stepSplitter, StepExecution stepExecution) - throws Exception { - Set executions = stepSplitter.split(stepExecution, 2); - if (!started.get()) { - started.set(true); - for (StepExecution execution : executions) { - execution.setStatus(BatchStatus.FAILED); - execution.setExitStatus(ExitStatus.FAILED); - execution.getExecutionContext().putString("foo", execution.getStepName()); - } - } - else { - for (StepExecution execution : executions) { - // On restart the execution context should have been restored - assertEquals(execution.getStepName(), execution.getExecutionContext().getString("foo")); - } - } - for (StepExecution execution : executions) { - jobRepository.update(execution); - jobRepository.updateExecutionContext(execution); - } - return executions; - } - }); - step.afterPropertiesSet(); - JobExecution jobExecution = jobRepository.createJobExecution("vanillaJob", new JobParameters()); - StepExecution stepExecution = jobExecution.createStepExecution("foo"); - jobRepository.add(stepExecution); - step.execute(stepExecution); - jobExecution.setStatus(BatchStatus.FAILED); - jobExecution.setEndTime(new Date()); - jobRepository.update(jobExecution); - // Now restart... - jobExecution = jobRepository.createJobExecution("vanillaJob", new JobParameters()); - stepExecution = jobExecution.createStepExecution("foo"); - jobRepository.add(stepExecution); - step.execute(stepExecution); - // one manager and two workers - assertEquals(3, stepExecution.getJobExecution().getStepExecutions().size()); - assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - } - - @Test - public void testStoppedStepExecution() throws Exception { - step.setStepExecutionSplitter(new SimpleStepExecutionSplitter(jobRepository, true, step.getName(), new SimplePartitioner())); - step.setPartitionHandler(new PartitionHandler() { - @Override - public Collection handle(StepExecutionSplitter stepSplitter, StepExecution stepExecution) - throws Exception { - Set executions = stepSplitter.split(stepExecution, 2); - for (StepExecution execution : executions) { - execution.setStatus(BatchStatus.STOPPED); - execution.setExitStatus(ExitStatus.STOPPED); - } - return executions; - } - }); - step.afterPropertiesSet(); - JobExecution jobExecution = jobRepository.createJobExecution("vanillaJob", new JobParameters()); - StepExecution stepExecution = jobExecution.createStepExecution("foo"); - jobRepository.add(stepExecution); - step.execute(stepExecution); - // one manager and two workers - assertEquals(3, stepExecution.getJobExecution().getStepExecutions().size()); - assertEquals(BatchStatus.STOPPED, stepExecution.getStatus()); - } - - @Test - public void testStepAggregator() throws Exception { - step.setStepExecutionAggregator(new DefaultStepExecutionAggregator() { - @Override - public void aggregate(StepExecution result, Collection executions) { - super.aggregate(result, executions); - result.getExecutionContext().put("aggregated", true); - } - }); - step.setStepExecutionSplitter(new SimpleStepExecutionSplitter(jobRepository, true, step.getName(), new SimplePartitioner())); - step.setPartitionHandler(new PartitionHandler() { - @Override - public Collection handle(StepExecutionSplitter stepSplitter, StepExecution stepExecution) - throws Exception { - return Arrays.asList(stepExecution); - } - }); - step.afterPropertiesSet(); - JobExecution jobExecution = jobRepository.createJobExecution("vanillaJob", new JobParameters()); - StepExecution stepExecution = jobExecution.createStepExecution("foo"); - jobRepository.add(stepExecution); - step.execute(stepExecution); - assertEquals(true, stepExecution.getExecutionContext().get("aggregated")); - } - -} +/* + * Copyright 2006-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.partition.support; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Date; +import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.junit.Before; +import org.junit.Test; + +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.partition.PartitionHandler; +import org.springframework.batch.core.partition.StepExecutionSplitter; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; + +import static org.junit.Assert.assertEquals; + +/** + * @author Dave Syer + * @author Mahmoud Ben Hassine + * + */ +public class PartitionStepTests { + + private PartitionStep step = new PartitionStep(); + + private JobRepository jobRepository; + + @Before + public void setUp() throws Exception { + EmbeddedDatabase embeddedDatabase = new EmbeddedDatabaseBuilder() + .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") + .addScript("/org/springframework/batch/core/schema-hsqldb.sql").build(); + JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); + factory.setDataSource(embeddedDatabase); + factory.setTransactionManager(new DataSourceTransactionManager(embeddedDatabase)); + factory.afterPropertiesSet(); + jobRepository = factory.getObject(); + step.setJobRepository(jobRepository); + step.setName("partitioned"); + } + + @Test + public void testVanillaStepExecution() throws Exception { + step.setStepExecutionSplitter( + new SimpleStepExecutionSplitter(jobRepository, true, step.getName(), new SimplePartitioner())); + step.setPartitionHandler(new PartitionHandler() { + @Override + public Collection handle(StepExecutionSplitter stepSplitter, StepExecution stepExecution) + throws Exception { + Set executions = stepSplitter.split(stepExecution, 2); + for (StepExecution execution : executions) { + execution.setStatus(BatchStatus.COMPLETED); + execution.setExitStatus(ExitStatus.COMPLETED); + } + return executions; + } + }); + step.afterPropertiesSet(); + JobExecution jobExecution = jobRepository.createJobExecution("vanillaJob", new JobParameters()); + StepExecution stepExecution = jobExecution.createStepExecution("foo"); + jobRepository.add(stepExecution); + step.execute(stepExecution); + // one manager and two workers + assertEquals(3, stepExecution.getJobExecution().getStepExecutions().size()); + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + } + + @Test + public void testFailedStepExecution() throws Exception { + step.setStepExecutionSplitter( + new SimpleStepExecutionSplitter(jobRepository, true, step.getName(), new SimplePartitioner())); + step.setPartitionHandler(new PartitionHandler() { + @Override + public Collection handle(StepExecutionSplitter stepSplitter, StepExecution stepExecution) + throws Exception { + Set executions = stepSplitter.split(stepExecution, 2); + for (StepExecution execution : executions) { + execution.setStatus(BatchStatus.FAILED); + execution.setExitStatus(ExitStatus.FAILED); + } + return executions; + } + }); + step.afterPropertiesSet(); + JobExecution jobExecution = jobRepository.createJobExecution("vanillaJob", new JobParameters()); + StepExecution stepExecution = jobExecution.createStepExecution("foo"); + jobRepository.add(stepExecution); + step.execute(stepExecution); + // one manager and two workers + assertEquals(3, stepExecution.getJobExecution().getStepExecutions().size()); + assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); + } + + @Test + public void testRestartStepExecution() throws Exception { + final AtomicBoolean started = new AtomicBoolean(false); + step.setStepExecutionSplitter( + new SimpleStepExecutionSplitter(jobRepository, true, step.getName(), new SimplePartitioner())); + step.setPartitionHandler(new PartitionHandler() { + @Override + public Collection handle(StepExecutionSplitter stepSplitter, StepExecution stepExecution) + throws Exception { + Set executions = stepSplitter.split(stepExecution, 2); + if (!started.get()) { + started.set(true); + for (StepExecution execution : executions) { + execution.setStatus(BatchStatus.FAILED); + execution.setExitStatus(ExitStatus.FAILED); + execution.getExecutionContext().putString("foo", execution.getStepName()); + } + } + else { + for (StepExecution execution : executions) { + // On restart the execution context should have been restored + assertEquals(execution.getStepName(), execution.getExecutionContext().getString("foo")); + } + } + for (StepExecution execution : executions) { + jobRepository.update(execution); + jobRepository.updateExecutionContext(execution); + } + return executions; + } + }); + step.afterPropertiesSet(); + JobExecution jobExecution = jobRepository.createJobExecution("vanillaJob", new JobParameters()); + StepExecution stepExecution = jobExecution.createStepExecution("foo"); + jobRepository.add(stepExecution); + step.execute(stepExecution); + jobExecution.setStatus(BatchStatus.FAILED); + jobExecution.setEndTime(new Date()); + jobRepository.update(jobExecution); + // Now restart... + jobExecution = jobRepository.createJobExecution("vanillaJob", new JobParameters()); + stepExecution = jobExecution.createStepExecution("foo"); + jobRepository.add(stepExecution); + step.execute(stepExecution); + // one manager and two workers + assertEquals(3, stepExecution.getJobExecution().getStepExecutions().size()); + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + } + + @Test + public void testStoppedStepExecution() throws Exception { + step.setStepExecutionSplitter( + new SimpleStepExecutionSplitter(jobRepository, true, step.getName(), new SimplePartitioner())); + step.setPartitionHandler(new PartitionHandler() { + @Override + public Collection handle(StepExecutionSplitter stepSplitter, StepExecution stepExecution) + throws Exception { + Set executions = stepSplitter.split(stepExecution, 2); + for (StepExecution execution : executions) { + execution.setStatus(BatchStatus.STOPPED); + execution.setExitStatus(ExitStatus.STOPPED); + } + return executions; + } + }); + step.afterPropertiesSet(); + JobExecution jobExecution = jobRepository.createJobExecution("vanillaJob", new JobParameters()); + StepExecution stepExecution = jobExecution.createStepExecution("foo"); + jobRepository.add(stepExecution); + step.execute(stepExecution); + // one manager and two workers + assertEquals(3, stepExecution.getJobExecution().getStepExecutions().size()); + assertEquals(BatchStatus.STOPPED, stepExecution.getStatus()); + } + + @Test + public void testStepAggregator() throws Exception { + step.setStepExecutionAggregator(new DefaultStepExecutionAggregator() { + @Override + public void aggregate(StepExecution result, Collection executions) { + super.aggregate(result, executions); + result.getExecutionContext().put("aggregated", true); + } + }); + step.setStepExecutionSplitter( + new SimpleStepExecutionSplitter(jobRepository, true, step.getName(), new SimplePartitioner())); + step.setPartitionHandler(new PartitionHandler() { + @Override + public Collection handle(StepExecutionSplitter stepSplitter, StepExecution stepExecution) + throws Exception { + return Arrays.asList(stepExecution); + } + }); + step.afterPropertiesSet(); + JobExecution jobExecution = jobRepository.createJobExecution("vanillaJob", new JobParameters()); + StepExecution stepExecution = jobExecution.createStepExecution("foo"); + jobRepository.add(stepExecution); + step.execute(stepExecution); + assertEquals(true, stepExecution.getExecutionContext().get("aggregated")); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/partition/support/RemoteStepExecutionAggregatorTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/partition/support/RemoteStepExecutionAggregatorTests.java index 447007a84..9fb1d3140 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/partition/support/RemoteStepExecutionAggregatorTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/partition/support/RemoteStepExecutionAggregatorTests.java @@ -1,101 +1,100 @@ -/* - * Copyright 2011-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.partition.support; - -import org.junit.Before; -import org.junit.Test; -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.explore.support.JobExplorerFactoryBean; -import org.springframework.batch.core.repository.JobRepository; -import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; -import org.springframework.jdbc.datasource.DataSourceTransactionManager; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; - -import java.util.Arrays; -import java.util.Collections; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -public class RemoteStepExecutionAggregatorTests { - - private RemoteStepExecutionAggregator aggregator = new RemoteStepExecutionAggregator(); - - private JobExecution jobExecution; - - private StepExecution result; - - private StepExecution stepExecution1; - - private StepExecution stepExecution2; - - @Before - public void init() throws Exception { - EmbeddedDatabase embeddedDatabase = new EmbeddedDatabaseBuilder() - .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("/org/springframework/batch/core/schema-hsqldb.sql") - .build(); - JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); - factory.setDataSource(embeddedDatabase); - factory.setTransactionManager(new DataSourceTransactionManager(embeddedDatabase)); - factory.afterPropertiesSet(); - JobRepository jobRepository = factory.getObject(); - JobExplorerFactoryBean explorerFactoryBean = new JobExplorerFactoryBean(); - explorerFactoryBean.setDataSource(embeddedDatabase); - explorerFactoryBean.afterPropertiesSet(); - aggregator.setJobExplorer(explorerFactoryBean.getObject()); - jobExecution = jobRepository.createJobExecution("job", new JobParameters()); - result = jobExecution.createStepExecution("aggregate"); - stepExecution1 = jobExecution.createStepExecution("foo:1"); - stepExecution2 = jobExecution.createStepExecution("foo:2"); - jobRepository.add(stepExecution1); - jobRepository.add(stepExecution2); - } - - @Test - public void testAggregateEmpty() { - aggregator.aggregate(result, Collections. emptySet()); - } - - @Test - public void testAggregateNull() { - aggregator.aggregate(result, null); - } - - @Test - public void testAggregateStatusSunnyDay() { - stepExecution1.setStatus(BatchStatus.COMPLETED); - stepExecution2.setStatus(BatchStatus.COMPLETED); - aggregator.aggregate(result, Arrays. asList(stepExecution1, stepExecution2)); - assertNotNull(result); - assertEquals(BatchStatus.STARTING, result.getStatus()); - } - - @Test(expected=IllegalStateException.class) - public void testAggregateStatusMissingExecution() { - stepExecution2 = jobExecution.createStepExecution("foo:3"); - stepExecution1.setStatus(BatchStatus.COMPLETED); - stepExecution2.setStatus(BatchStatus.COMPLETED); - aggregator.aggregate(result, Arrays. asList(stepExecution1, stepExecution2)); - assertNotNull(result); - assertEquals(BatchStatus.STARTING, result.getStatus()); - } - -} +/* + * Copyright 2011-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.partition.support; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.explore.support.JobExplorerFactoryBean; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; + +import java.util.Arrays; +import java.util.Collections; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +public class RemoteStepExecutionAggregatorTests { + + private RemoteStepExecutionAggregator aggregator = new RemoteStepExecutionAggregator(); + + private JobExecution jobExecution; + + private StepExecution result; + + private StepExecution stepExecution1; + + private StepExecution stepExecution2; + + @Before + public void init() throws Exception { + EmbeddedDatabase embeddedDatabase = new EmbeddedDatabaseBuilder() + .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") + .addScript("/org/springframework/batch/core/schema-hsqldb.sql").build(); + JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); + factory.setDataSource(embeddedDatabase); + factory.setTransactionManager(new DataSourceTransactionManager(embeddedDatabase)); + factory.afterPropertiesSet(); + JobRepository jobRepository = factory.getObject(); + JobExplorerFactoryBean explorerFactoryBean = new JobExplorerFactoryBean(); + explorerFactoryBean.setDataSource(embeddedDatabase); + explorerFactoryBean.afterPropertiesSet(); + aggregator.setJobExplorer(explorerFactoryBean.getObject()); + jobExecution = jobRepository.createJobExecution("job", new JobParameters()); + result = jobExecution.createStepExecution("aggregate"); + stepExecution1 = jobExecution.createStepExecution("foo:1"); + stepExecution2 = jobExecution.createStepExecution("foo:2"); + jobRepository.add(stepExecution1); + jobRepository.add(stepExecution2); + } + + @Test + public void testAggregateEmpty() { + aggregator.aggregate(result, Collections.emptySet()); + } + + @Test + public void testAggregateNull() { + aggregator.aggregate(result, null); + } + + @Test + public void testAggregateStatusSunnyDay() { + stepExecution1.setStatus(BatchStatus.COMPLETED); + stepExecution2.setStatus(BatchStatus.COMPLETED); + aggregator.aggregate(result, Arrays.asList(stepExecution1, stepExecution2)); + assertNotNull(result); + assertEquals(BatchStatus.STARTING, result.getStatus()); + } + + @Test(expected = IllegalStateException.class) + public void testAggregateStatusMissingExecution() { + stepExecution2 = jobExecution.createStepExecution("foo:3"); + stepExecution1.setStatus(BatchStatus.COMPLETED); + stepExecution2.setStatus(BatchStatus.COMPLETED); + aggregator.aggregate(result, Arrays.asList(stepExecution1, stepExecution2)); + assertNotNull(result); + assertEquals(BatchStatus.STARTING, result.getStatus()); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/partition/support/SimplePartitionerTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/partition/support/SimplePartitionerTests.java index 637f1d8dd..74c4389a6 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/partition/support/SimplePartitionerTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/partition/support/SimplePartitionerTests.java @@ -27,19 +27,20 @@ import org.springframework.batch.item.ExecutionContext; */ public class SimplePartitionerTests { - @Test - public void testPartition() { - // given - SimplePartitioner partitioner = new SimplePartitioner(); + @Test + public void testPartition() { + // given + SimplePartitioner partitioner = new SimplePartitioner(); - // when - Map partitions = partitioner.partition(3); + // when + Map partitions = partitioner.partition(3); + + // then + Assert.assertNotNull(partitions); + Assert.assertEquals(3, partitions.size()); + Assert.assertNotNull(partitions.get("partition0")); + Assert.assertNotNull(partitions.get("partition1")); + Assert.assertNotNull(partitions.get("partition2")); + } - // then - Assert.assertNotNull(partitions); - Assert.assertEquals(3, partitions.size()); - Assert.assertNotNull(partitions.get("partition0")); - Assert.assertNotNull(partitions.get("partition1")); - Assert.assertNotNull(partitions.get("partition2")); - } } \ No newline at end of file diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/partition/support/SimpleStepExecutionSplitterTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/partition/support/SimpleStepExecutionSplitterTests.java index e03b162e4..8a334f8c1 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/partition/support/SimpleStepExecutionSplitterTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/partition/support/SimpleStepExecutionSplitterTests.java @@ -1,261 +1,262 @@ -/* - * Copyright 2008-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.partition.support; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.Map; -import java.util.Set; - -import org.junit.Before; -import org.junit.Test; - -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobExecutionException; -import org.springframework.batch.core.JobInstance; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.Step; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.repository.JobRepository; -import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; -import org.springframework.batch.core.step.tasklet.TaskletStep; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.jdbc.datasource.DataSourceTransactionManager; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -public class SimpleStepExecutionSplitterTests { - - private Step step; - - private JobRepository jobRepository; - - private StepExecution stepExecution; - - @Before - public void setUp() throws Exception { - step = new TaskletStep("step"); - EmbeddedDatabase embeddedDatabase = new EmbeddedDatabaseBuilder() - .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("/org/springframework/batch/core/schema-hsqldb.sql") - .build(); - JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); - factory.setDataSource(embeddedDatabase); - factory.setTransactionManager(new DataSourceTransactionManager(embeddedDatabase)); - factory.afterPropertiesSet(); - jobRepository = factory.getObject(); - stepExecution = jobRepository.createJobExecution("job", new JobParameters()).createStepExecution("bar"); - jobRepository.add(stepExecution); - } - - @Test - public void testSimpleStepExecutionProviderJobRepositoryStep() throws Exception { - SimpleStepExecutionSplitter splitter = new SimpleStepExecutionSplitter(jobRepository, true, step.getName(), - new SimplePartitioner()); - Set execs = splitter.split(stepExecution, 2); - assertEquals(2, execs.size()); - - for (StepExecution execution : execs) { - assertNotNull("step execution partition is saved", execution.getId()); - } - } - - /** - * Tests the results of BATCH-2490 - * @throws Exception - */ - @Test - public void testAddressabilityOfSetResults() throws Exception { - SimpleStepExecutionSplitter splitter = new SimpleStepExecutionSplitter(jobRepository, true, step.getName(), - new SimplePartitioner()); - Set execs = splitter.split(stepExecution, 2); - assertEquals(2, execs.size()); - - StepExecution execution = execs.iterator().next(); - execs.remove(execution); - assertEquals(1, execs.size()); - } - - @Test - public void testSimpleStepExecutionProviderJobRepositoryStepPartitioner() throws Exception { - final Map map = Collections.singletonMap("foo", new ExecutionContext()); - SimpleStepExecutionSplitter splitter = new SimpleStepExecutionSplitter(jobRepository, true, step.getName(), - new Partitioner() { - @Override - public Map partition(int gridSize) { - return map; - } - }); - assertEquals(1, splitter.split(stepExecution, 2).size()); - } - - @Test - public void testRememberGridSize() throws Exception { - SimpleStepExecutionSplitter provider = new SimpleStepExecutionSplitter(jobRepository, true, step.getName(), - new SimplePartitioner()); - Set split = provider.split(stepExecution, 2); - assertEquals(2, split.size()); - stepExecution = update(split, stepExecution, BatchStatus.FAILED); - assertEquals(2, provider.split(stepExecution, 3).size()); - } - - @Test - public void testRememberPartitionNames() throws Exception { - class CustomPartitioner implements Partitioner, PartitionNameProvider { - @Override - public Map partition(int gridSize) { - return Collections.singletonMap("foo", new ExecutionContext()); - } - - @Override - public Collection getPartitionNames(int gridSize) { - return Arrays.asList("foo"); - } - } - SimpleStepExecutionSplitter provider = new SimpleStepExecutionSplitter(jobRepository, true, step.getName(), - new CustomPartitioner()); - Set split = provider.split(stepExecution, 2); - assertEquals(1, split.size()); - assertEquals("step:foo", split.iterator().next().getStepName()); - stepExecution = update(split, stepExecution, BatchStatus.FAILED); - split = provider.split(stepExecution, 2); - assertEquals("step:foo", split.iterator().next().getStepName()); - } - - @Test - public void testGetStepName() { - SimpleStepExecutionSplitter provider = new SimpleStepExecutionSplitter(jobRepository, true, step.getName(), - new SimplePartitioner()); - assertEquals("step", provider.getStepName()); - } - - @Test - public void testUnknownStatus() throws Exception { - SimpleStepExecutionSplitter provider = new SimpleStepExecutionSplitter(jobRepository, true, step.getName(), - new SimplePartitioner()); - Set split = provider.split(stepExecution, 2); - assertEquals(2, split.size()); - stepExecution = update(split, stepExecution, BatchStatus.UNKNOWN); - try { - provider.split(stepExecution, 2); - } - catch (JobExecutionException e) { - String message = e.getMessage(); - assertTrue("Wrong message: " + message, message.contains("UNKNOWN")); - } - } - - @Test - public void testCompleteStatusAfterFailure() throws Exception { - SimpleStepExecutionSplitter provider = new SimpleStepExecutionSplitter(jobRepository, false, step.getName(), - new SimplePartitioner()); - Set split = provider.split(stepExecution, 2); - assertEquals(2, split.size()); - StepExecution nextExecution = update(split, stepExecution, BatchStatus.COMPLETED, false); - // If already complete in another JobExecution we don't execute again - assertEquals(0, provider.split(nextExecution, 2).size()); - } - - @Test - public void testCompleteStatusSameJobExecution() throws Exception { - SimpleStepExecutionSplitter provider = new SimpleStepExecutionSplitter(jobRepository, false, step.getName(), - new SimplePartitioner()); - Set split = provider.split(stepExecution, 2); - assertEquals(2, split.size()); - stepExecution = update(split, stepExecution, BatchStatus.COMPLETED); - // If already complete in the same JobExecution we should execute again - assertEquals(2, provider.split(stepExecution, 2).size()); - } - - @Test - public void testIncompleteStatus() throws Exception { - SimpleStepExecutionSplitter provider = new SimpleStepExecutionSplitter(jobRepository, true, step.getName(), - new SimplePartitioner()); - Set split = provider.split(stepExecution, 2); - assertEquals(2, split.size()); - stepExecution = update(split, stepExecution, BatchStatus.STARTED); - // If not already complete we don't execute again - try { - provider.split(stepExecution, 2); - } - catch (JobExecutionException e) { - String message = e.getMessage(); - assertTrue("Wrong message: " + message, message.contains("STARTED")); - } - } - - @Test - public void testAbandonedStatus() throws Exception { - SimpleStepExecutionSplitter provider = new SimpleStepExecutionSplitter(jobRepository, true, step.getName(), - new SimplePartitioner()); - Set split = provider.split(stepExecution, 2); - assertEquals(2, split.size()); - stepExecution = update(split, stepExecution, BatchStatus.ABANDONED); - // If not already complete we don't execute again - try { - provider.split(stepExecution, 2); - } - catch (JobExecutionException e) { - String message = e.getMessage(); - assertTrue("Wrong message: " + message, message.contains("ABANDONED")); - } - } - - private StepExecution update(Set split, StepExecution stepExecution, BatchStatus status) - throws Exception { - return update(split, stepExecution, status, true); - } - - private StepExecution update(Set split, StepExecution stepExecution, BatchStatus status, - boolean sameJobExecution) throws Exception { - - ExecutionContext executionContext = stepExecution.getExecutionContext(); - - for (StepExecution child : split) { - child.setEndTime(new Date()); - child.setStatus(status); - jobRepository.update(child); - } - - stepExecution.setEndTime(new Date()); - stepExecution.setStatus(status); - jobRepository.update(stepExecution); - - JobExecution jobExecution = stepExecution.getJobExecution(); - if (!sameJobExecution) { - jobExecution.setStatus(BatchStatus.FAILED); - jobExecution.setEndTime(new Date()); - jobRepository.update(jobExecution); - JobInstance jobInstance = jobExecution.getJobInstance(); - jobExecution = jobRepository.createJobExecution(jobInstance.getJobName(), jobExecution.getJobParameters()); - } - - stepExecution = jobExecution.createStepExecution(stepExecution.getStepName()); - stepExecution.setExecutionContext(executionContext); - - jobRepository.add(stepExecution); - return stepExecution; - - } - -} +/* + * Copyright 2008-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.partition.support; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.Map; +import java.util.Set; + +import org.junit.Before; +import org.junit.Test; + +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobExecutionException; +import org.springframework.batch.core.JobInstance; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.Step; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; +import org.springframework.batch.core.step.tasklet.TaskletStep; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +public class SimpleStepExecutionSplitterTests { + + private Step step; + + private JobRepository jobRepository; + + private StepExecution stepExecution; + + @Before + public void setUp() throws Exception { + step = new TaskletStep("step"); + EmbeddedDatabase embeddedDatabase = new EmbeddedDatabaseBuilder() + .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") + .addScript("/org/springframework/batch/core/schema-hsqldb.sql").build(); + JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); + factory.setDataSource(embeddedDatabase); + factory.setTransactionManager(new DataSourceTransactionManager(embeddedDatabase)); + factory.afterPropertiesSet(); + jobRepository = factory.getObject(); + stepExecution = jobRepository.createJobExecution("job", new JobParameters()).createStepExecution("bar"); + jobRepository.add(stepExecution); + } + + @Test + public void testSimpleStepExecutionProviderJobRepositoryStep() throws Exception { + SimpleStepExecutionSplitter splitter = new SimpleStepExecutionSplitter(jobRepository, true, step.getName(), + new SimplePartitioner()); + Set execs = splitter.split(stepExecution, 2); + assertEquals(2, execs.size()); + + for (StepExecution execution : execs) { + assertNotNull("step execution partition is saved", execution.getId()); + } + } + + /** + * Tests the results of BATCH-2490 + * @throws Exception + */ + @Test + public void testAddressabilityOfSetResults() throws Exception { + SimpleStepExecutionSplitter splitter = new SimpleStepExecutionSplitter(jobRepository, true, step.getName(), + new SimplePartitioner()); + Set execs = splitter.split(stepExecution, 2); + assertEquals(2, execs.size()); + + StepExecution execution = execs.iterator().next(); + execs.remove(execution); + assertEquals(1, execs.size()); + } + + @Test + public void testSimpleStepExecutionProviderJobRepositoryStepPartitioner() throws Exception { + final Map map = Collections.singletonMap("foo", new ExecutionContext()); + SimpleStepExecutionSplitter splitter = new SimpleStepExecutionSplitter(jobRepository, true, step.getName(), + new Partitioner() { + @Override + public Map partition(int gridSize) { + return map; + } + }); + assertEquals(1, splitter.split(stepExecution, 2).size()); + } + + @Test + public void testRememberGridSize() throws Exception { + SimpleStepExecutionSplitter provider = new SimpleStepExecutionSplitter(jobRepository, true, step.getName(), + new SimplePartitioner()); + Set split = provider.split(stepExecution, 2); + assertEquals(2, split.size()); + stepExecution = update(split, stepExecution, BatchStatus.FAILED); + assertEquals(2, provider.split(stepExecution, 3).size()); + } + + @Test + public void testRememberPartitionNames() throws Exception { + class CustomPartitioner implements Partitioner, PartitionNameProvider { + + @Override + public Map partition(int gridSize) { + return Collections.singletonMap("foo", new ExecutionContext()); + } + + @Override + public Collection getPartitionNames(int gridSize) { + return Arrays.asList("foo"); + } + + } + SimpleStepExecutionSplitter provider = new SimpleStepExecutionSplitter(jobRepository, true, step.getName(), + new CustomPartitioner()); + Set split = provider.split(stepExecution, 2); + assertEquals(1, split.size()); + assertEquals("step:foo", split.iterator().next().getStepName()); + stepExecution = update(split, stepExecution, BatchStatus.FAILED); + split = provider.split(stepExecution, 2); + assertEquals("step:foo", split.iterator().next().getStepName()); + } + + @Test + public void testGetStepName() { + SimpleStepExecutionSplitter provider = new SimpleStepExecutionSplitter(jobRepository, true, step.getName(), + new SimplePartitioner()); + assertEquals("step", provider.getStepName()); + } + + @Test + public void testUnknownStatus() throws Exception { + SimpleStepExecutionSplitter provider = new SimpleStepExecutionSplitter(jobRepository, true, step.getName(), + new SimplePartitioner()); + Set split = provider.split(stepExecution, 2); + assertEquals(2, split.size()); + stepExecution = update(split, stepExecution, BatchStatus.UNKNOWN); + try { + provider.split(stepExecution, 2); + } + catch (JobExecutionException e) { + String message = e.getMessage(); + assertTrue("Wrong message: " + message, message.contains("UNKNOWN")); + } + } + + @Test + public void testCompleteStatusAfterFailure() throws Exception { + SimpleStepExecutionSplitter provider = new SimpleStepExecutionSplitter(jobRepository, false, step.getName(), + new SimplePartitioner()); + Set split = provider.split(stepExecution, 2); + assertEquals(2, split.size()); + StepExecution nextExecution = update(split, stepExecution, BatchStatus.COMPLETED, false); + // If already complete in another JobExecution we don't execute again + assertEquals(0, provider.split(nextExecution, 2).size()); + } + + @Test + public void testCompleteStatusSameJobExecution() throws Exception { + SimpleStepExecutionSplitter provider = new SimpleStepExecutionSplitter(jobRepository, false, step.getName(), + new SimplePartitioner()); + Set split = provider.split(stepExecution, 2); + assertEquals(2, split.size()); + stepExecution = update(split, stepExecution, BatchStatus.COMPLETED); + // If already complete in the same JobExecution we should execute again + assertEquals(2, provider.split(stepExecution, 2).size()); + } + + @Test + public void testIncompleteStatus() throws Exception { + SimpleStepExecutionSplitter provider = new SimpleStepExecutionSplitter(jobRepository, true, step.getName(), + new SimplePartitioner()); + Set split = provider.split(stepExecution, 2); + assertEquals(2, split.size()); + stepExecution = update(split, stepExecution, BatchStatus.STARTED); + // If not already complete we don't execute again + try { + provider.split(stepExecution, 2); + } + catch (JobExecutionException e) { + String message = e.getMessage(); + assertTrue("Wrong message: " + message, message.contains("STARTED")); + } + } + + @Test + public void testAbandonedStatus() throws Exception { + SimpleStepExecutionSplitter provider = new SimpleStepExecutionSplitter(jobRepository, true, step.getName(), + new SimplePartitioner()); + Set split = provider.split(stepExecution, 2); + assertEquals(2, split.size()); + stepExecution = update(split, stepExecution, BatchStatus.ABANDONED); + // If not already complete we don't execute again + try { + provider.split(stepExecution, 2); + } + catch (JobExecutionException e) { + String message = e.getMessage(); + assertTrue("Wrong message: " + message, message.contains("ABANDONED")); + } + } + + private StepExecution update(Set split, StepExecution stepExecution, BatchStatus status) + throws Exception { + return update(split, stepExecution, status, true); + } + + private StepExecution update(Set split, StepExecution stepExecution, BatchStatus status, + boolean sameJobExecution) throws Exception { + + ExecutionContext executionContext = stepExecution.getExecutionContext(); + + for (StepExecution child : split) { + child.setEndTime(new Date()); + child.setStatus(status); + jobRepository.update(child); + } + + stepExecution.setEndTime(new Date()); + stepExecution.setStatus(status); + jobRepository.update(stepExecution); + + JobExecution jobExecution = stepExecution.getJobExecution(); + if (!sameJobExecution) { + jobExecution.setStatus(BatchStatus.FAILED); + jobExecution.setEndTime(new Date()); + jobRepository.update(jobExecution); + JobInstance jobInstance = jobExecution.getJobInstance(); + jobExecution = jobRepository.createJobExecution(jobInstance.getJobName(), jobExecution.getJobParameters()); + } + + stepExecution = jobExecution.createStepExecution(stepExecution.getStepName()); + stepExecution.setExecutionContext(executionContext); + + jobRepository.add(stepExecution); + return stepExecution; + + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/partition/support/TaskExecutorPartitionHandlerTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/partition/support/TaskExecutorPartitionHandlerTests.java index aa25a7e34..eb94fba2e 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/partition/support/TaskExecutorPartitionHandlerTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/partition/support/TaskExecutorPartitionHandlerTests.java @@ -1,140 +1,140 @@ -/* - * Copyright 2008-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.partition.support; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; -import java.util.TreeSet; - -import org.junit.Before; -import org.junit.Test; -import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobExecutionException; -import org.springframework.batch.core.JobInterruptedException; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.partition.StepExecutionSplitter; -import org.springframework.batch.core.step.StepSupport; -import org.springframework.core.task.SimpleAsyncTaskExecutor; -import org.springframework.core.task.TaskExecutor; -import org.springframework.core.task.TaskRejectedException; - -public class TaskExecutorPartitionHandlerTests { - - private TaskExecutorPartitionHandler handler = new TaskExecutorPartitionHandler(); - - private int count = 0; - - private Collection stepExecutions = new TreeSet<>(); - - private StepExecution stepExecution = new StepExecution("step", new JobExecution(1L)); - - private StepExecutionSplitter stepExecutionSplitter = new StepExecutionSplitter() { - - @Override - public String getStepName() { - return stepExecution.getStepName(); - } - - @Override - public Set split(StepExecution stepExecution, int gridSize) throws JobExecutionException { - HashSet result = new HashSet<>(); - for (int i = gridSize; i-- > 0;) { - result.add(stepExecution.getJobExecution().createStepExecution("foo" + i)); - } - return result; - } - }; - - @Before - public void setUp() throws Exception { - handler.setStep(new StepSupport() { - @Override - public void execute(StepExecution stepExecution) throws JobInterruptedException { - count++; - stepExecutions.add(stepExecution.getStepName()); - } - }); - handler.afterPropertiesSet(); - } - - @Test - public void testConfiguration() throws Exception { - handler = new TaskExecutorPartitionHandler(); - try { - handler.afterPropertiesSet(); - fail("Expected IllegalStateException when no step is set"); - } - catch (IllegalStateException e) { - // expected - String message = e.getMessage(); - assertEquals("Wrong message: " + message, "A Step must be provided.", message); - } - } - - @Test - public void testNullStep() throws Exception { - handler = new TaskExecutorPartitionHandler(); - try { - handler.handle(stepExecutionSplitter, stepExecution); - fail("Expected IllegalArgumentException"); - } - catch (IllegalArgumentException e) { - // expected - String message = e.getMessage(); - assertTrue("Wrong message: " + message, message.contains("Step")); - } - } - - @Test - public void testSetGridSize() throws Exception { - handler.setGridSize(2); - handler.handle(stepExecutionSplitter, stepExecution); - assertEquals(2, count); - assertEquals("[foo0, foo1]", stepExecutions.toString()); - } - - @Test - public void testSetTaskExecutor() throws Exception { - handler.setTaskExecutor(new SimpleAsyncTaskExecutor()); - handler.handle(stepExecutionSplitter, stepExecution); - assertEquals(1, count); - } - - @Test - public void testTaskExecutorFailure() throws Exception { - handler.setGridSize(2); - handler.setTaskExecutor(new TaskExecutor() { - @Override - public void execute(Runnable task) { - if (count > 0) { - throw new TaskRejectedException("foo"); - } - task.run(); - } - }); - Collection executions = handler.handle(stepExecutionSplitter, stepExecution); - new DefaultStepExecutionAggregator().aggregate(stepExecution, executions); - assertEquals(1, count); - assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution.getExitStatus().getExitCode()); - } - -} +/* + * Copyright 2008-2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.partition.support; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; +import java.util.TreeSet; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobExecutionException; +import org.springframework.batch.core.JobInterruptedException; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.partition.StepExecutionSplitter; +import org.springframework.batch.core.step.StepSupport; +import org.springframework.core.task.SimpleAsyncTaskExecutor; +import org.springframework.core.task.TaskExecutor; +import org.springframework.core.task.TaskRejectedException; + +public class TaskExecutorPartitionHandlerTests { + + private TaskExecutorPartitionHandler handler = new TaskExecutorPartitionHandler(); + + private int count = 0; + + private Collection stepExecutions = new TreeSet<>(); + + private StepExecution stepExecution = new StepExecution("step", new JobExecution(1L)); + + private StepExecutionSplitter stepExecutionSplitter = new StepExecutionSplitter() { + + @Override + public String getStepName() { + return stepExecution.getStepName(); + } + + @Override + public Set split(StepExecution stepExecution, int gridSize) throws JobExecutionException { + HashSet result = new HashSet<>(); + for (int i = gridSize; i-- > 0;) { + result.add(stepExecution.getJobExecution().createStepExecution("foo" + i)); + } + return result; + } + }; + + @Before + public void setUp() throws Exception { + handler.setStep(new StepSupport() { + @Override + public void execute(StepExecution stepExecution) throws JobInterruptedException { + count++; + stepExecutions.add(stepExecution.getStepName()); + } + }); + handler.afterPropertiesSet(); + } + + @Test + public void testConfiguration() throws Exception { + handler = new TaskExecutorPartitionHandler(); + try { + handler.afterPropertiesSet(); + fail("Expected IllegalStateException when no step is set"); + } + catch (IllegalStateException e) { + // expected + String message = e.getMessage(); + assertEquals("Wrong message: " + message, "A Step must be provided.", message); + } + } + + @Test + public void testNullStep() throws Exception { + handler = new TaskExecutorPartitionHandler(); + try { + handler.handle(stepExecutionSplitter, stepExecution); + fail("Expected IllegalArgumentException"); + } + catch (IllegalArgumentException e) { + // expected + String message = e.getMessage(); + assertTrue("Wrong message: " + message, message.contains("Step")); + } + } + + @Test + public void testSetGridSize() throws Exception { + handler.setGridSize(2); + handler.handle(stepExecutionSplitter, stepExecution); + assertEquals(2, count); + assertEquals("[foo0, foo1]", stepExecutions.toString()); + } + + @Test + public void testSetTaskExecutor() throws Exception { + handler.setTaskExecutor(new SimpleAsyncTaskExecutor()); + handler.handle(stepExecutionSplitter, stepExecution); + assertEquals(1, count); + } + + @Test + public void testTaskExecutorFailure() throws Exception { + handler.setGridSize(2); + handler.setTaskExecutor(new TaskExecutor() { + @Override + public void execute(Runnable task) { + if (count > 0) { + throw new TaskRejectedException("foo"); + } + task.run(); + } + }); + Collection executions = handler.handle(stepExecutionSplitter, stepExecution); + new DefaultStepExecutionAggregator().aggregate(stepExecution, executions); + assertEquals(1, count); + assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution.getExitStatus().getExitCode()); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/JobExecutionAlreadyRunningExceptionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/JobExecutionAlreadyRunningExceptionTests.java index 77eceddd8..f02f66d05 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/JobExecutionAlreadyRunningExceptionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/JobExecutionAlreadyRunningExceptionTests.java @@ -23,16 +23,24 @@ import org.springframework.batch.core.AbstractExceptionTests; */ public class JobExecutionAlreadyRunningExceptionTests extends AbstractExceptionTests { - /* (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.io.exception.AbstractExceptionTests#getException(java. + * lang.String) */ @Override public Exception getException(String msg) throws Exception { return new JobExecutionAlreadyRunningException(msg); } - /* (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String, java.lang.Throwable) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.io.exception.AbstractExceptionTests#getException(java. + * lang.String, java.lang.Throwable) */ @Override public Exception getException(String msg, Throwable t) throws Exception { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/JobInstanceAlreadyCompleteExceptionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/JobInstanceAlreadyCompleteExceptionTests.java index 84fa41cfe..d550196ac 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/JobInstanceAlreadyCompleteExceptionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/JobInstanceAlreadyCompleteExceptionTests.java @@ -23,16 +23,24 @@ import org.springframework.batch.core.AbstractExceptionTests; */ public class JobInstanceAlreadyCompleteExceptionTests extends AbstractExceptionTests { - /* (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.io.exception.AbstractExceptionTests#getException(java. + * lang.String) */ @Override public Exception getException(String msg) throws Exception { return new JobInstanceAlreadyCompleteException(msg); } - /* (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String, java.lang.Throwable) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.io.exception.AbstractExceptionTests#getException(java. + * lang.String, java.lang.Throwable) */ @Override public Exception getException(String msg, Throwable t) throws Exception { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/JobRestartExceptionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/JobRestartExceptionTests.java index 54d835be3..926be5d4e 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/JobRestartExceptionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/JobRestartExceptionTests.java @@ -25,7 +25,10 @@ public class JobRestartExceptionTests extends AbstractExceptionTests { /* * (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String) + * + * @see + * org.springframework.batch.io.exception.AbstractExceptionTests#getException(java. + * lang.String) */ @Override public Exception getException(String msg) throws Exception { @@ -34,8 +37,10 @@ public class JobRestartExceptionTests extends AbstractExceptionTests { /* * (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String, - * java.lang.Throwable) + * + * @see + * org.springframework.batch.io.exception.AbstractExceptionTests#getException(java. + * lang.String, java.lang.Throwable) */ @Override public Exception getException(String msg, Throwable t) throws Exception { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/AbstractExecutionContextDaoTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/AbstractExecutionContextDaoTests.java index c46634291..3e71996ec 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/AbstractExecutionContextDaoTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/AbstractExecutionContextDaoTests.java @@ -1,228 +1,223 @@ -/* - * Copyright 2008-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.repository.dao; - -import static org.junit.Assert.assertEquals; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobInstance; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests; -import org.springframework.transaction.annotation.Transactional; - -/** - * Tests for {@link ExecutionContextDao} implementations. - */ -public abstract class AbstractExecutionContextDaoTests extends AbstractTransactionalJUnit4SpringContextTests { - - private JobInstanceDao jobInstanceDao; - - private JobExecutionDao jobExecutionDao; - - private StepExecutionDao stepExecutionDao; - - private ExecutionContextDao contextDao; - - private JobExecution jobExecution; - - private StepExecution stepExecution; - - @Before - public void setUp() { - jobInstanceDao = getJobInstanceDao(); - jobExecutionDao = getJobExecutionDao(); - stepExecutionDao = getStepExecutionDao(); - contextDao = getExecutionContextDao(); - - JobInstance ji = jobInstanceDao.createJobInstance("testJob", new JobParameters()); - jobExecution = new JobExecution(ji, new JobParameters()); - jobExecutionDao.saveJobExecution(jobExecution); - stepExecution = new StepExecution("stepName", jobExecution); - stepExecutionDao.saveStepExecution(stepExecution); - - } - - /** - * @return Configured {@link ExecutionContextDao} implementation ready for - * use. - */ - protected abstract JobExecutionDao getJobExecutionDao(); - - /** - * @return Configured {@link ExecutionContextDao} implementation ready for - * use. - */ - protected abstract JobInstanceDao getJobInstanceDao(); - - /** - * @return Configured {@link ExecutionContextDao} implementation ready for - * use. - */ - protected abstract StepExecutionDao getStepExecutionDao(); - - /** - * @return Configured {@link ExecutionContextDao} implementation ready for - * use. - */ - protected abstract ExecutionContextDao getExecutionContextDao(); - - @Transactional - @Test - public void testSaveAndFindJobContext() { - - ExecutionContext ctx = new ExecutionContext(Collections. singletonMap("key", "value")); - jobExecution.setExecutionContext(ctx); - contextDao.saveExecutionContext(jobExecution); - - ExecutionContext retrieved = contextDao.getExecutionContext(jobExecution); - assertEquals(ctx, retrieved); - } - - @Transactional - @Test - public void testSaveAndFindExecutionContexts() { - - List stepExecutions = new ArrayList<>(); - for (int i = 0; i < 3; i++) { - JobInstance ji = jobInstanceDao.createJobInstance("testJob" + i, new JobParameters()); - JobExecution je = new JobExecution(ji, new JobParameters()); - jobExecutionDao.saveJobExecution(je); - StepExecution se = new StepExecution("step" + i, je); - se.setStatus(BatchStatus.STARTED); - se.setReadSkipCount(i); - se.setProcessSkipCount(i); - se.setWriteSkipCount(i); - se.setProcessSkipCount(i); - se.setRollbackCount(i); - se.setLastUpdated(new Date(System.currentTimeMillis())); - se.setReadCount(i); - se.setFilterCount(i); - se.setWriteCount(i); - stepExecutions.add(se); - } - stepExecutionDao.saveStepExecutions(stepExecutions); - contextDao.saveExecutionContexts(stepExecutions); - - for (int i = 0; i < 3; i++) { - ExecutionContext retrieved = contextDao.getExecutionContext(stepExecutions.get(i).getJobExecution()); - assertEquals(stepExecutions.get(i).getExecutionContext(), retrieved); - } - } - - @Transactional - @Test(expected = IllegalArgumentException.class) - public void testSaveNullExecutionContexts() { - contextDao.saveExecutionContexts(null); - } - - @Transactional - @Test - public void testSaveEmptyExecutionContexts() { - contextDao.saveExecutionContexts(new ArrayList<>()); - } - - @Transactional - @Test - public void testSaveAndFindEmptyJobContext() { - - ExecutionContext ctx = new ExecutionContext(); - jobExecution.setExecutionContext(ctx); - contextDao.saveExecutionContext(jobExecution); - - ExecutionContext retrieved = contextDao.getExecutionContext(jobExecution); - assertEquals(ctx, retrieved); - } - - @Transactional - @Test - public void testUpdateContext() { - - ExecutionContext ctx = new ExecutionContext(Collections - . singletonMap("key", "value")); - jobExecution.setExecutionContext(ctx); - contextDao.saveExecutionContext(jobExecution); - - ctx.putLong("longKey", 7); - contextDao.updateExecutionContext(jobExecution); - - ExecutionContext retrieved = contextDao.getExecutionContext(jobExecution); - assertEquals(ctx, retrieved); - assertEquals(7, retrieved.getLong("longKey")); - } - - @Transactional - @Test - public void testSaveAndFindStepContext() { - - ExecutionContext ctx = new ExecutionContext(Collections. singletonMap("key", "value")); - stepExecution.setExecutionContext(ctx); - contextDao.saveExecutionContext(stepExecution); - - ExecutionContext retrieved = contextDao.getExecutionContext(stepExecution); - assertEquals(ctx, retrieved); - } - - @Transactional - @Test - public void testSaveAndFindEmptyStepContext() { - - ExecutionContext ctx = new ExecutionContext(); - stepExecution.setExecutionContext(ctx); - contextDao.saveExecutionContext(stepExecution); - - ExecutionContext retrieved = contextDao.getExecutionContext(stepExecution); - assertEquals(ctx, retrieved); - } - - @Transactional - @Test - public void testUpdateStepContext() { - - ExecutionContext ctx = new ExecutionContext(Collections. singletonMap("key", "value")); - stepExecution.setExecutionContext(ctx); - contextDao.saveExecutionContext(stepExecution); - - ctx.putLong("longKey", 7); - contextDao.updateExecutionContext(stepExecution); - - ExecutionContext retrieved = contextDao.getExecutionContext(stepExecution); - assertEquals(ctx, retrieved); - assertEquals(7, retrieved.getLong("longKey")); - } - - @Transactional - @Test - public void testStoreInteger() { - - ExecutionContext ec = new ExecutionContext(); - ec.put("intValue", 343232); - stepExecution.setExecutionContext(ec); - contextDao.saveExecutionContext(stepExecution); - ExecutionContext restoredEc = contextDao.getExecutionContext(stepExecution); - assertEquals(ec, restoredEc); - } - -} +/* + * Copyright 2008-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.repository.dao; + +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobInstance; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests; +import org.springframework.transaction.annotation.Transactional; + +/** + * Tests for {@link ExecutionContextDao} implementations. + */ +public abstract class AbstractExecutionContextDaoTests extends AbstractTransactionalJUnit4SpringContextTests { + + private JobInstanceDao jobInstanceDao; + + private JobExecutionDao jobExecutionDao; + + private StepExecutionDao stepExecutionDao; + + private ExecutionContextDao contextDao; + + private JobExecution jobExecution; + + private StepExecution stepExecution; + + @Before + public void setUp() { + jobInstanceDao = getJobInstanceDao(); + jobExecutionDao = getJobExecutionDao(); + stepExecutionDao = getStepExecutionDao(); + contextDao = getExecutionContextDao(); + + JobInstance ji = jobInstanceDao.createJobInstance("testJob", new JobParameters()); + jobExecution = new JobExecution(ji, new JobParameters()); + jobExecutionDao.saveJobExecution(jobExecution); + stepExecution = new StepExecution("stepName", jobExecution); + stepExecutionDao.saveStepExecution(stepExecution); + + } + + /** + * @return Configured {@link ExecutionContextDao} implementation ready for use. + */ + protected abstract JobExecutionDao getJobExecutionDao(); + + /** + * @return Configured {@link ExecutionContextDao} implementation ready for use. + */ + protected abstract JobInstanceDao getJobInstanceDao(); + + /** + * @return Configured {@link ExecutionContextDao} implementation ready for use. + */ + protected abstract StepExecutionDao getStepExecutionDao(); + + /** + * @return Configured {@link ExecutionContextDao} implementation ready for use. + */ + protected abstract ExecutionContextDao getExecutionContextDao(); + + @Transactional + @Test + public void testSaveAndFindJobContext() { + + ExecutionContext ctx = new ExecutionContext(Collections.singletonMap("key", "value")); + jobExecution.setExecutionContext(ctx); + contextDao.saveExecutionContext(jobExecution); + + ExecutionContext retrieved = contextDao.getExecutionContext(jobExecution); + assertEquals(ctx, retrieved); + } + + @Transactional + @Test + public void testSaveAndFindExecutionContexts() { + + List stepExecutions = new ArrayList<>(); + for (int i = 0; i < 3; i++) { + JobInstance ji = jobInstanceDao.createJobInstance("testJob" + i, new JobParameters()); + JobExecution je = new JobExecution(ji, new JobParameters()); + jobExecutionDao.saveJobExecution(je); + StepExecution se = new StepExecution("step" + i, je); + se.setStatus(BatchStatus.STARTED); + se.setReadSkipCount(i); + se.setProcessSkipCount(i); + se.setWriteSkipCount(i); + se.setProcessSkipCount(i); + se.setRollbackCount(i); + se.setLastUpdated(new Date(System.currentTimeMillis())); + se.setReadCount(i); + se.setFilterCount(i); + se.setWriteCount(i); + stepExecutions.add(se); + } + stepExecutionDao.saveStepExecutions(stepExecutions); + contextDao.saveExecutionContexts(stepExecutions); + + for (int i = 0; i < 3; i++) { + ExecutionContext retrieved = contextDao.getExecutionContext(stepExecutions.get(i).getJobExecution()); + assertEquals(stepExecutions.get(i).getExecutionContext(), retrieved); + } + } + + @Transactional + @Test(expected = IllegalArgumentException.class) + public void testSaveNullExecutionContexts() { + contextDao.saveExecutionContexts(null); + } + + @Transactional + @Test + public void testSaveEmptyExecutionContexts() { + contextDao.saveExecutionContexts(new ArrayList<>()); + } + + @Transactional + @Test + public void testSaveAndFindEmptyJobContext() { + + ExecutionContext ctx = new ExecutionContext(); + jobExecution.setExecutionContext(ctx); + contextDao.saveExecutionContext(jobExecution); + + ExecutionContext retrieved = contextDao.getExecutionContext(jobExecution); + assertEquals(ctx, retrieved); + } + + @Transactional + @Test + public void testUpdateContext() { + + ExecutionContext ctx = new ExecutionContext(Collections.singletonMap("key", "value")); + jobExecution.setExecutionContext(ctx); + contextDao.saveExecutionContext(jobExecution); + + ctx.putLong("longKey", 7); + contextDao.updateExecutionContext(jobExecution); + + ExecutionContext retrieved = contextDao.getExecutionContext(jobExecution); + assertEquals(ctx, retrieved); + assertEquals(7, retrieved.getLong("longKey")); + } + + @Transactional + @Test + public void testSaveAndFindStepContext() { + + ExecutionContext ctx = new ExecutionContext(Collections.singletonMap("key", "value")); + stepExecution.setExecutionContext(ctx); + contextDao.saveExecutionContext(stepExecution); + + ExecutionContext retrieved = contextDao.getExecutionContext(stepExecution); + assertEquals(ctx, retrieved); + } + + @Transactional + @Test + public void testSaveAndFindEmptyStepContext() { + + ExecutionContext ctx = new ExecutionContext(); + stepExecution.setExecutionContext(ctx); + contextDao.saveExecutionContext(stepExecution); + + ExecutionContext retrieved = contextDao.getExecutionContext(stepExecution); + assertEquals(ctx, retrieved); + } + + @Transactional + @Test + public void testUpdateStepContext() { + + ExecutionContext ctx = new ExecutionContext(Collections.singletonMap("key", "value")); + stepExecution.setExecutionContext(ctx); + contextDao.saveExecutionContext(stepExecution); + + ctx.putLong("longKey", 7); + contextDao.updateExecutionContext(stepExecution); + + ExecutionContext retrieved = contextDao.getExecutionContext(stepExecution); + assertEquals(ctx, retrieved); + assertEquals(7, retrieved.getLong("longKey")); + } + + @Transactional + @Test + public void testStoreInteger() { + + ExecutionContext ec = new ExecutionContext(); + ec.put("intValue", 343232); + stepExecution.setExecutionContext(ec); + contextDao.saveExecutionContext(stepExecution); + ExecutionContext restoredEc = contextDao.getExecutionContext(stepExecution); + assertEquals(ec, restoredEc); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/AbstractExecutionContextSerializerTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/AbstractExecutionContextSerializerTests.java index 871a7e20c..268374df7 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/AbstractExecutionContextSerializerTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/AbstractExecutionContextSerializerTests.java @@ -31,8 +31,9 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.hasEntry; /** - * Abstract test class for {@code ExecutionContextSerializer} implementations. Provides a minimum on test methods - * that should pass for each {@code ExecutionContextSerializer} implementation. + * Abstract test class for {@code ExecutionContextSerializer} implementations. Provides a + * minimum on test methods that should pass for each {@code ExecutionContextSerializer} + * implementation. * * @author Thomas Risberg * @author Michael Minella @@ -41,221 +42,225 @@ import static org.hamcrest.Matchers.hasEntry; */ public abstract class AbstractExecutionContextSerializerTests { - @Test - public void testSerializeAMap() throws Exception { - Map m1 = new HashMap<>(); - m1.put("object1", Long.valueOf(12345L)); - m1.put("object2", "OBJECT TWO"); - // Use a date after 1971 (otherwise daylight saving screws up)... - m1.put("object3", new Date(123456790123L)); - m1.put("object4", 1234567.1234D); + @Test + public void testSerializeAMap() throws Exception { + Map m1 = new HashMap<>(); + m1.put("object1", Long.valueOf(12345L)); + m1.put("object2", "OBJECT TWO"); + // Use a date after 1971 (otherwise daylight saving screws up)... + m1.put("object3", new Date(123456790123L)); + m1.put("object4", 1234567.1234D); - Map m2 = serializationRoundTrip(m1); + Map m2 = serializationRoundTrip(m1); - compareContexts(m1, m2); - } + compareContexts(m1, m2); + } - @Test - public void testSerializeStringJobParameter() throws Exception { - Map m1 = new HashMap<>(); - m1.put("name", new JobParameter("foo")); + @Test + public void testSerializeStringJobParameter() throws Exception { + Map m1 = new HashMap<>(); + m1.put("name", new JobParameter("foo")); - Map m2 = serializationRoundTrip(m1); + Map m2 = serializationRoundTrip(m1); - compareContexts(m1, m2); - } + compareContexts(m1, m2); + } - @Test - public void testSerializeDateJobParameter() throws Exception { - Map m1 = new HashMap<>(); - m1.put("birthDate", new JobParameter(new Date(123456790123L))); + @Test + public void testSerializeDateJobParameter() throws Exception { + Map m1 = new HashMap<>(); + m1.put("birthDate", new JobParameter(new Date(123456790123L))); - Map m2 = serializationRoundTrip(m1); + Map m2 = serializationRoundTrip(m1); - compareContexts(m1, m2); - } + compareContexts(m1, m2); + } - @Test - public void testSerializeDoubleJobParameter() throws Exception { - Map m1 = new HashMap<>(); - m1.put("weight", new JobParameter(80.5D)); + @Test + public void testSerializeDoubleJobParameter() throws Exception { + Map m1 = new HashMap<>(); + m1.put("weight", new JobParameter(80.5D)); - Map m2 = serializationRoundTrip(m1); + Map m2 = serializationRoundTrip(m1); - compareContexts(m1, m2); - } + compareContexts(m1, m2); + } - @Test - public void testSerializeLongJobParameter() throws Exception { - Map m1 = new HashMap<>(); - m1.put("age", new JobParameter(20L)); + @Test + public void testSerializeLongJobParameter() throws Exception { + Map m1 = new HashMap<>(); + m1.put("age", new JobParameter(20L)); - Map m2 = serializationRoundTrip(m1); + Map m2 = serializationRoundTrip(m1); - compareContexts(m1, m2); - } + compareContexts(m1, m2); + } - @Test - public void testSerializeNonIdentifyingJobParameter() throws Exception { - Map m1 = new HashMap<>(); - m1.put("name", new JobParameter("foo", false)); + @Test + public void testSerializeNonIdentifyingJobParameter() throws Exception { + Map m1 = new HashMap<>(); + m1.put("name", new JobParameter("foo", false)); - Map m2 = serializationRoundTrip(m1); + Map m2 = serializationRoundTrip(m1); - compareContexts(m1, m2); - } + compareContexts(m1, m2); + } - @Test - public void testSerializeJobParameters() throws Exception { - Map jobParametersMap = new HashMap<>(); - jobParametersMap.put("paramName", new JobParameter("paramValue")); + @Test + public void testSerializeJobParameters() throws Exception { + Map jobParametersMap = new HashMap<>(); + jobParametersMap.put("paramName", new JobParameter("paramValue")); - Map m1 = new HashMap<>(); - m1.put("params", new JobParameters(jobParametersMap)); + Map m1 = new HashMap<>(); + m1.put("params", new JobParameters(jobParametersMap)); - Map m2 = serializationRoundTrip(m1); + Map m2 = serializationRoundTrip(m1); - compareContexts(m1, m2); - } + compareContexts(m1, m2); + } - @Test - public void testSerializeEmptyJobParameters() throws IOException { - Map m1 = new HashMap<>(); - m1.put("params", new JobParameters()); + @Test + public void testSerializeEmptyJobParameters() throws IOException { + Map m1 = new HashMap<>(); + m1.put("params", new JobParameters()); - Map m2 = serializationRoundTrip(m1); + Map m2 = serializationRoundTrip(m1); - compareContexts(m1, m2); - } + compareContexts(m1, m2); + } - @Test - public void testComplexObject() throws Exception { - Map m1 = new HashMap<>(); - ComplexObject o1 = new ComplexObject(); - o1.setName("02345"); - Map m = new HashMap<>(); - m.put("object1", Long.valueOf(12345L)); - m.put("object2", "OBJECT TWO"); - o1.setMap(m); - o1.setNumber(new BigDecimal("12345.67")); - ComplexObject o2 = new ComplexObject(); - o2.setName("Inner Object"); - o2.setMap(m); - o2.setNumber(new BigDecimal("98765.43")); - o1.setObj(o2); - m1.put("co", o1); + @Test + public void testComplexObject() throws Exception { + Map m1 = new HashMap<>(); + ComplexObject o1 = new ComplexObject(); + o1.setName("02345"); + Map m = new HashMap<>(); + m.put("object1", Long.valueOf(12345L)); + m.put("object2", "OBJECT TWO"); + o1.setMap(m); + o1.setNumber(new BigDecimal("12345.67")); + ComplexObject o2 = new ComplexObject(); + o2.setName("Inner Object"); + o2.setMap(m); + o2.setNumber(new BigDecimal("98765.43")); + o1.setObj(o2); + m1.put("co", o1); - Map m2 = serializationRoundTrip(m1); + Map m2 = serializationRoundTrip(m1); - compareContexts(m1, m2); - } + compareContexts(m1, m2); + } - @Test (expected=IllegalArgumentException.class) - public void testNullSerialization() throws Exception { - getSerializer().serialize(null, null); - } + @Test(expected = IllegalArgumentException.class) + public void testNullSerialization() throws Exception { + getSerializer().serialize(null, null); + } - protected void compareContexts(Map m1, Map m2) { + protected void compareContexts(Map m1, Map m2) { - for (Map.Entry entry : m1.entrySet()) { - assertThat(m2, hasEntry(entry.getKey(), entry.getValue())); - } - } + for (Map.Entry entry : m1.entrySet()) { + assertThat(m2, hasEntry(entry.getKey(), entry.getValue())); + } + } - protected Map serializationRoundTrip(Map m1) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - getSerializer().serialize(m1, out); + protected Map serializationRoundTrip(Map m1) throws IOException { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + getSerializer().serialize(m1, out); - InputStream in = new ByteArrayInputStream(out.toByteArray()); - Map m2 = getSerializer().deserialize(in); - return m2; - } + InputStream in = new ByteArrayInputStream(out.toByteArray()); + Map m2 = getSerializer().deserialize(in); + return m2; + } + protected abstract ExecutionContextSerializer getSerializer(); - protected abstract ExecutionContextSerializer getSerializer(); + @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) + public static class ComplexObject implements Serializable { - @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) - public static class ComplexObject implements Serializable { - private static final long serialVersionUID = 1L; - private String name; - private BigDecimal number; - private ComplexObject obj; - private Map map; + private static final long serialVersionUID = 1L; - public String getName() { - return name; - } + private String name; - public void setName(String name) { - this.name = name; - } + private BigDecimal number; - public BigDecimal getNumber() { - return number; - } + private ComplexObject obj; - public void setNumber(BigDecimal number) { - this.number = number; - } + private Map map; - public ComplexObject getObj() { - return obj; - } + public String getName() { + return name; + } - public void setObj(ComplexObject obj) { - this.obj = obj; - } + public void setName(String name) { + this.name = name; + } - public Map getMap() { - return map; - } + public BigDecimal getNumber() { + return number; + } - public void setMap(Map map) { - this.map = map; - } + public void setNumber(BigDecimal number) { + this.number = number; + } + public ComplexObject getObj() { + return obj; + } - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } + public void setObj(ComplexObject obj) { + this.obj = obj; + } - ComplexObject that = (ComplexObject) o; + public Map getMap() { + return map; + } - if (map != null ? !map.equals(that.map) : that.map != null) { - return false; - } - if (name != null ? !name.equals(that.name) : that.name != null) { - return false; - } - if (number != null ? !number.equals(that.number) : that.number != null) { - return false; - } - if (obj != null ? !obj.equals(that.obj) : that.obj != null) { - return false; - } + public void setMap(Map map) { + this.map = map; + } - return true; - } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } - @Override - public int hashCode() { - int result; - result = (name != null ? name.hashCode() : 0); - result = 31 * result + (number != null ? number.hashCode() : 0); - result = 31 * result + (obj != null ? obj.hashCode() : 0); - result = 31 * result + (map != null ? map.hashCode() : 0); - return result; - } + ComplexObject that = (ComplexObject) o; - @Override - public String toString() { - return "ComplexObject [name=" + name + ", number=" + number + "]"; - } - } + if (map != null ? !map.equals(that.map) : that.map != null) { + return false; + } + if (name != null ? !name.equals(that.name) : that.name != null) { + return false; + } + if (number != null ? !number.equals(that.number) : that.number != null) { + return false; + } + if (obj != null ? !obj.equals(that.obj) : that.obj != null) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result; + result = (name != null ? name.hashCode() : 0); + result = 31 * result + (number != null ? number.hashCode() : 0); + result = 31 * result + (obj != null ? obj.hashCode() : 0); + result = 31 * result + (map != null ? map.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return "ComplexObject [name=" + name + ", number=" + number + "]"; + } + + } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/AbstractJobDaoTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/AbstractJobDaoTests.java index 6f6b66594..a18b171f0 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/AbstractJobDaoTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/AbstractJobDaoTests.java @@ -51,8 +51,8 @@ public abstract class AbstractJobDaoTests { protected JobExecutionDao jobExecutionDao; - protected JobParameters jobParameters = new JobParametersBuilder().addString("job.key", "jobKey").addLong("long", - (long) 1).addDate("date", new Date(7)).addDouble("double", 7.7).toJobParameters(); + protected JobParameters jobParameters = new JobParametersBuilder().addString("job.key", "jobKey") + .addLong("long", (long) 1).addDate("date", new Date(7)).addDouble("double", 7.7).toJobParameters(); protected JobInstance jobInstance; @@ -70,8 +70,8 @@ public abstract class AbstractJobDaoTests { } /* - * Because AbstractTransactionalSpringContextTests is used, this method will - * be called by Spring to set the JobRepository. + * Because AbstractTransactionalSpringContextTests is used, this method will be called + * by Spring to set the JobRepository. */ @Autowired public void setJobInstanceDao(JobInstanceDao jobInstanceDao) { @@ -96,35 +96,41 @@ public abstract class AbstractJobDaoTests { jobExecutionDao.saveJobExecution(jobExecution); } - @Transactional @Test + @Transactional + @Test public void testVersionIsNotNullForJob() throws Exception { - int version = jdbcTemplate.queryForObject("select version from BATCH_JOB_INSTANCE where JOB_INSTANCE_ID=" - + jobInstance.getId(), Integer.class); + int version = jdbcTemplate.queryForObject( + "select version from BATCH_JOB_INSTANCE where JOB_INSTANCE_ID=" + jobInstance.getId(), Integer.class); assertEquals(0, version); } - @Transactional @Test + @Transactional + @Test public void testVersionIsNotNullForJobExecution() throws Exception { - int version = jdbcTemplate.queryForObject("select version from BATCH_JOB_EXECUTION where JOB_EXECUTION_ID=" - + jobExecution.getId(), Integer.class); + int version = jdbcTemplate.queryForObject( + "select version from BATCH_JOB_EXECUTION where JOB_EXECUTION_ID=" + jobExecution.getId(), + Integer.class); assertEquals(0, version); } - @Transactional @Test + @Transactional + @Test public void testFindNonExistentJob() { // No job should be found since it hasn't been created. JobInstance jobInstance = jobInstanceDao.getJobInstance("nonexistentJob", jobParameters); assertNull(jobInstance); } - @Transactional @Test + @Transactional + @Test public void testFindJob() { JobInstance instance = jobInstanceDao.getJobInstance(jobName, jobParameters); assertNotNull(instance); assertTrue(jobInstance.equals(instance)); } - @Transactional @Test + @Transactional + @Test public void testFindJobWithNullRuntime() { try { @@ -137,11 +143,12 @@ public abstract class AbstractJobDaoTests { } /** - * Test that ensures that if you create a job with a given name, then find a - * job with the same name, but other pieces of the identifier different, you - * get no result, not the existing one. + * Test that ensures that if you create a job with a given name, then find a job with + * the same name, but other pieces of the identifier different, you get no result, not + * the existing one. */ - @Transactional @Test + @Transactional + @Test public void testCreateJobWithExistingName() { String scheduledJob = "ScheduledJob"; @@ -160,7 +167,8 @@ public abstract class AbstractJobDaoTests { } - @Transactional @Test + @Transactional + @Test public void testUpdateJobExecution() { jobExecution.setStatus(BatchStatus.COMPLETED); @@ -174,7 +182,8 @@ public abstract class AbstractJobDaoTests { } - @Transactional @Test + @Transactional + @Test public void testSaveJobExecution() { List executions = jobExecutionDao.findJobExecutions(jobInstance); @@ -182,7 +191,8 @@ public abstract class AbstractJobDaoTests { validateJobExecution(jobExecution, executions.get(0)); } - @Transactional @Test + @Transactional + @Test public void testUpdateInvalidJobExecution() { // id is invalid @@ -197,7 +207,8 @@ public abstract class AbstractJobDaoTests { } } - @Transactional @Test + @Transactional + @Test public void testUpdateNullIdJobExecution() { JobExecution execution = new JobExecution(jobInstance, jobParameters); @@ -210,23 +221,23 @@ public abstract class AbstractJobDaoTests { } } - - @Transactional @Test + @Transactional + @Test public void testJobWithSimpleJobIdentifier() throws Exception { String testJob = "test"; // Create job. jobInstance = jobInstanceDao.createJobInstance(testJob, jobParameters); - List> jobs = jdbcTemplate.queryForList( - "SELECT * FROM BATCH_JOB_INSTANCE where JOB_INSTANCE_ID=?", - jobInstance.getId()); + List> jobs = jdbcTemplate + .queryForList("SELECT * FROM BATCH_JOB_INSTANCE where JOB_INSTANCE_ID=?", jobInstance.getId()); assertEquals(1, jobs.size()); assertEquals("test", jobs.get(0).get("JOB_NAME")); } - @Transactional @Test + @Transactional + @Test public void testJobWithDefaultJobIdentifier() throws Exception { String testDefaultJob = "testDefault"; @@ -238,7 +249,8 @@ public abstract class AbstractJobDaoTests { assertNotNull(instance); } - @Transactional @Test + @Transactional + @Test public void testFindJobExecutions() { List results = jobExecutionDao.findJobExecutions(jobInstance); @@ -256,7 +268,8 @@ public abstract class AbstractJobDaoTests { assertEquals(lhs.getExitStatus(), rhs.getExitStatus()); } - @Transactional @Test + @Transactional + @Test public void testGetLastJobExecution() { JobExecution lastExecution = new JobExecution(jobInstance, jobParameters); lastExecution.setStatus(BatchStatus.STARTED); @@ -273,7 +286,8 @@ public abstract class AbstractJobDaoTests { /** * Trying to create instance twice for the same job+parameters causes error */ - @Transactional @Test + @Transactional + @Test public void testCreateDuplicateInstance() { jobParameters = new JobParameters(); @@ -289,7 +303,8 @@ public abstract class AbstractJobDaoTests { } } - @Transactional @Test + @Transactional + @Test public void testCreationAddsVersion() { jobInstance = jobInstanceDao.createJobInstance("testCreationAddsVersion", new JobParameters()); @@ -297,7 +312,8 @@ public abstract class AbstractJobDaoTests { assertNotNull(jobInstance.getVersion()); } - @Transactional @Test + @Transactional + @Test public void testSaveAddsVersionAndId() { JobExecution jobExecution = new JobExecution(jobInstance, jobParameters); @@ -311,7 +327,8 @@ public abstract class AbstractJobDaoTests { assertNotNull(jobExecution.getVersion()); } - @Transactional @Test + @Transactional + @Test public void testUpdateIncrementsVersion() { int version = jobExecution.getVersion(); @@ -319,4 +336,5 @@ public abstract class AbstractJobDaoTests { assertEquals(version + 1, jobExecution.getVersion().intValue()); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/AbstractJobExecutionDaoTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/AbstractJobExecutionDaoTests.java index 61b645458..752dfe230 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/AbstractJobExecutionDaoTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/AbstractJobExecutionDaoTests.java @@ -143,8 +143,7 @@ public abstract class AbstractJobExecutionDaoTests { } /** - * Update and retrieve job execution - check attributes have changed as - * expected. + * Update and retrieve job execution - check attributes have changed as expected. */ @Transactional @Test @@ -197,7 +196,7 @@ public abstract class AbstractJobExecutionDaoTests { @Transactional @Test public void testFindRunningExecutions() { - //Normally completed JobExecution as EndTime is populated + // Normally completed JobExecution as EndTime is populated JobExecution exec = new JobExecution(jobInstance, jobParameters); exec.setCreateTime(new Date(0)); exec.setStartTime(new Date(1L)); @@ -205,14 +204,15 @@ public abstract class AbstractJobExecutionDaoTests { exec.setLastUpdated(new Date(5L)); dao.saveJobExecution(exec); - //BATCH-2675 - //Abnormal JobExecution as both StartTime and EndTime are null - //This can occur when SimpleJobLauncher#run() submission to taskExecutor throws a TaskRejectedException + // BATCH-2675 + // Abnormal JobExecution as both StartTime and EndTime are null + // This can occur when SimpleJobLauncher#run() submission to taskExecutor throws a + // TaskRejectedException exec = new JobExecution(jobInstance, jobParameters); exec.setLastUpdated(new Date(5L)); dao.saveJobExecution(exec); - //Running JobExecution as StartTime is populated but EndTime is null + // Running JobExecution as StartTime is populated but EndTime is null exec = new JobExecution(jobInstance, jobParameters); exec.setStartTime(new Date(2L)); exec.setLastUpdated(new Date(5L)); @@ -279,8 +279,8 @@ public abstract class AbstractJobExecutionDaoTests { } /** - * Exception should be raised when the version of update argument doesn't - * match the version of persisted entity. + * Exception should be raised when the version of update argument doesn't match the + * version of persisted entity. */ @Transactional @Test @@ -336,8 +336,8 @@ public abstract class AbstractJobExecutionDaoTests { } /** - * UNKNOWN status won't be changed by synchronizeStatus, because it is the - * 'largest' BatchStatus (will not downgrade). + * UNKNOWN status won't be changed by synchronizeStatus, because it is the 'largest' + * BatchStatus (will not downgrade). */ @Transactional @Test @@ -363,9 +363,9 @@ public abstract class AbstractJobExecutionDaoTests { } /* - * Check to make sure the executions are equal. Normally, comparing the id's - * is sufficient. However, for testing purposes, especially of a DAO, we - * need to make sure all the fields are being stored/retrieved correctly. + * Check to make sure the executions are equal. Normally, comparing the id's is + * sufficient. However, for testing purposes, especially of a DAO, we need to make + * sure all the fields are being stored/retrieved correctly. */ private void assertExecutionsAreEqual(JobExecution lhs, JobExecution rhs) { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/AbstractJobInstanceDaoTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/AbstractJobInstanceDaoTests.java index 4c0759092..9cdbe0670 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/AbstractJobInstanceDaoTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/AbstractJobInstanceDaoTests.java @@ -131,8 +131,8 @@ public abstract class AbstractJobInstanceDaoTests { assertEquals(Integer.valueOf(0), jobInstances.get(0).getVersion()); assertEquals(Integer.valueOf(0), jobInstances.get(1).getVersion()); - assertTrue("Last instance should be first on the list", jobInstances.get(0).getId() > jobInstances.get(1) - .getId()); + assertTrue("Last instance should be first on the list", + jobInstances.get(0).getId() > jobInstances.get(1).getId()); } @@ -152,8 +152,7 @@ public abstract class AbstractJobInstanceDaoTests { JobInstance lastJobInstance = dao.getLastJobInstance(fooJob); assertNotNull(lastJobInstance); assertEquals(fooJob, lastJobInstance.getJobName()); - assertEquals("Last instance should be first on the list", - jobInstances.get(0), lastJobInstance); + assertEquals("Last instance should be first on the list", jobInstances.get(0), lastJobInstance); } @Transactional @@ -184,7 +183,6 @@ public abstract class AbstractJobInstanceDaoTests { dao.createJobInstance(multiInstanceJob, params); } - int startIndex = 3; int queryCount = 2; List jobInstances = dao.getJobInstances(multiInstanceJob, startIndex, queryCount); @@ -196,8 +194,9 @@ public abstract class AbstractJobInstanceDaoTests { assertEquals(multiInstanceJob, returnedInstance.getJobName()); assertEquals(Integer.valueOf(0), returnedInstance.getVersion()); - //checks the correct instances are returned and the order is descending - // assertEquals(instanceCount - startIndex - i , returnedInstance.getJobParameters().getLong(paramKey)); + // checks the correct instances are returned and the order is descending + // assertEquals(instanceCount - startIndex - i , + // returnedInstance.getJobParameters().getLong(paramKey)); } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/AbstractStepExecutionDaoTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/AbstractStepExecutionDaoTests.java index 67d826a2f..24184b980 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/AbstractStepExecutionDaoTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/AbstractStepExecutionDaoTests.java @@ -180,7 +180,8 @@ public abstract class AbstractStepExecutionDaoTests extends AbstractTransactiona stepExecution2.setStartTime(Date.from(now)); dao.saveStepExecutions(Arrays.asList(stepExecution1, stepExecution2)); - StepExecution lastStepExecution = stepExecution1.getId() > stepExecution2.getId() ? stepExecution1 : stepExecution2; + StepExecution lastStepExecution = stepExecution1.getId() > stepExecution2.getId() ? stepExecution1 + : stepExecution2; StepExecution retrieved = dao.getLastStepExecution(jobInstance, "step1"); assertNotNull(retrieved); assertEquals(lastStepExecution.getId(), retrieved.getId()); @@ -258,8 +259,8 @@ public abstract class AbstractStepExecutionDaoTests extends AbstractTransactiona } /** - * Update and retrieve updated StepExecution - make sure the update is - * reflected as expected and version number has been incremented + * Update and retrieve updated StepExecution - make sure the update is reflected as + * expected and version number has been incremented */ @Transactional @Test @@ -280,8 +281,8 @@ public abstract class AbstractStepExecutionDaoTests extends AbstractTransactiona } /** - * Exception should be raised when the version of update argument doesn't - * match the version of persisted entity. + * Exception should be raised when the version of update argument doesn't match the + * version of persisted entity. */ @Transactional @Test @@ -337,4 +338,5 @@ public abstract class AbstractStepExecutionDaoTests extends AbstractTransactiona assertEquals(expected.getJobExecutionId(), actual.getJobExecutionId()); assertEquals(expected.getCreateTime(), actual.getCreateTime()); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/DateFormatTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/DateFormatTests.java index 1348af337..d5d4cb870 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/DateFormatTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/DateFormatTests.java @@ -33,11 +33,11 @@ import org.junit.runners.Parameterized.Parameters; /** * Test case showing some weirdnesses in date formatting. Looks like a bug in - * SimpleDateFormat / GregorianCalendar, and it affects the JSON deserialization - * that we use in the ExecutionContext around daylight savings. - * + * SimpleDateFormat / GregorianCalendar, and it affects the JSON deserialization that we + * use in the ExecutionContext around daylight savings. + * * @author Dave Syer - * + * */ @RunWith(Parameterized.class) public class DateFormatTests { @@ -51,7 +51,7 @@ public class DateFormatTests { private final String output; /** - * + * */ public DateFormatTests(String pattern, String input, String output, int hour) { this.output = output; @@ -85,10 +85,10 @@ public class DateFormatTests { String format = "yyyy-MM-dd HH:mm:ss.S z"; /* - * When the date format has an explicit time zone these are OK. But on - * 2008/10/26 when the clocks went back to GMT these failed the hour - * assertion (with the hour coming back as 12). On 2008/10/27, the day - * after, they are fine, but the toString still didn't match. + * When the date format has an explicit time zone these are OK. But on 2008/10/26 + * when the clocks went back to GMT these failed the hour assertion (with the hour + * coming back as 12). On 2008/10/27, the day after, they are fine, but the + * toString still didn't match. */ params.add(new Object[] { format, "1970-01-01 11:20:34.0 GMT", "1970-01-01 11:20:34.0 GMT", 11 }); params.add(new Object[] { format, "1971-02-01 11:20:34.0 GMT", "1971-02-01 11:20:34.0 GMT", 11 }); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/DefaultExecutionContextSerializerTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/DefaultExecutionContextSerializerTests.java index 2d3214562..94381b585 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/DefaultExecutionContextSerializerTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/DefaultExecutionContextSerializerTests.java @@ -39,7 +39,6 @@ public class DefaultExecutionContextSerializerTests extends AbstractExecutionCon serializer = new DefaultExecutionContextSerializer(); } - @Test(expected = IllegalArgumentException.class) public void testSerializeNonSerializable() throws Exception { Map m1 = new HashMap<>(); @@ -52,4 +51,5 @@ public class DefaultExecutionContextSerializerTests extends AbstractExecutionCon protected ExecutionContextSerializer getSerializer() { return this.serializer; } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/Jackson2ExecutionContextStringSerializerTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/Jackson2ExecutionContextStringSerializerTests.java index 066a91b19..6263008e6 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/Jackson2ExecutionContextStringSerializerTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/Jackson2ExecutionContextStringSerializerTests.java @@ -83,8 +83,8 @@ public class Jackson2ExecutionContextStringSerializerTests extends AbstractExecu @Test public void testAdditionalTrustedClass() throws IOException { // given - Jackson2ExecutionContextStringSerializer serializer = - new Jackson2ExecutionContextStringSerializer("java.util.Locale"); + Jackson2ExecutionContextStringSerializer serializer = new Jackson2ExecutionContextStringSerializer( + "java.util.Locale"); Map context = new HashMap<>(1); context.put("locale", Locale.getDefault()); @@ -106,21 +106,31 @@ public class Jackson2ExecutionContextStringSerializerTests extends AbstractExecu @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) public static class Person { + public String name; + public int age; + @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) public PhoneNumber phone; + } public static abstract class PhoneNumber { + public int areaCode, local; + } public static class InternationalNumber extends PhoneNumber { + public int countryCode; + } - public static class DomesticNumber extends PhoneNumber{} + public static class DomesticNumber extends PhoneNumber { + + } @Test public void unmappedTypeTest() throws IOException { @@ -152,24 +162,34 @@ public class Jackson2ExecutionContextStringSerializerTests extends AbstractExecu } public static class UnmappedPerson { + public String name; + public int age; + public UnmappedPhoneNumber phone; + } public static abstract class UnmappedPhoneNumber { + public int areaCode, local; + } public static class UnmappedInternationalNumber extends UnmappedPhoneNumber { + public int countryCode; + } - public static class UnmappedDomesticNumber extends UnmappedPhoneNumber{} + public static class UnmappedDomesticNumber extends UnmappedPhoneNumber { + + } @Test public void arrayAsListSerializationTest() throws IOException { - //given + // given List list = Arrays.asList("foo", "bar"); String key = "Arrays.asList"; Jackson2ExecutionContextStringSerializer serializer = new Jackson2ExecutionContextStringSerializer(); @@ -185,12 +205,12 @@ public class Jackson2ExecutionContextStringSerializerTests extends AbstractExecu // then Object deserializedValue = deserializedContext.get(key); Assert.assertTrue(List.class.isAssignableFrom(deserializedValue.getClass())); - Assert.assertTrue(((List)deserializedValue).containsAll(list)); + Assert.assertTrue(((List) deserializedValue).containsAll(list)); } @Test public void testSqlTimestampSerialization() throws IOException { - //given + // given Jackson2ExecutionContextStringSerializer serializer = new Jackson2ExecutionContextStringSerializer(); Map context = new HashMap<>(1); Timestamp timestamp = new Timestamp(Instant.now().toEpochMilli()); @@ -206,4 +226,5 @@ public class Jackson2ExecutionContextStringSerializerTests extends AbstractExecu Timestamp deserializedTimestamp = (Timestamp) deserializedContext.get("timestamp"); Assert.assertEquals(timestamp, deserializedTimestamp); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcExecutionContextDaoTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcExecutionContextDaoTests.java index 5868ef36d..f6b7f180c 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcExecutionContextDaoTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcExecutionContextDaoTests.java @@ -1,77 +1,79 @@ -/* - * Copyright 2008-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.repository.dao; - -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.springframework.jdbc.core.JdbcOperations; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -import static org.mockito.Mockito.mock; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = {"sql-dao-test.xml"}) -public class JdbcExecutionContextDaoTests extends AbstractExecutionContextDaoTests { - - @Test - public void testNoSerializer() { - try { - JdbcExecutionContextDao jdbcExecutionContextDao = new JdbcExecutionContextDao(); - jdbcExecutionContextDao.setJdbcTemplate(mock(JdbcOperations.class)); - jdbcExecutionContextDao.afterPropertiesSet(); - } catch (Exception e) { - Assert.assertTrue(e instanceof IllegalStateException); - Assert.assertEquals("ExecutionContextSerializer is required", e.getMessage()); - } - } - - @Test - public void testNullSerializer() { - try { - JdbcExecutionContextDao jdbcExecutionContextDao = new JdbcExecutionContextDao(); - jdbcExecutionContextDao.setJdbcTemplate(mock(JdbcOperations.class)); - jdbcExecutionContextDao.setSerializer(null); - jdbcExecutionContextDao.afterPropertiesSet(); - } catch (Exception e) { - Assert.assertTrue(e instanceof IllegalArgumentException); - Assert.assertEquals("Serializer must not be null", e.getMessage()); - } - } - - @Override - protected JobInstanceDao getJobInstanceDao() { - return applicationContext.getBean("jobInstanceDao", JobInstanceDao.class); - } - - @Override - protected JobExecutionDao getJobExecutionDao() { - return applicationContext.getBean("jobExecutionDao", JdbcJobExecutionDao.class); - } - - @Override - protected StepExecutionDao getStepExecutionDao() { - return applicationContext.getBean("stepExecutionDao", StepExecutionDao.class); - } - - @Override - protected ExecutionContextDao getExecutionContextDao() { - return applicationContext.getBean("executionContextDao", JdbcExecutionContextDao.class); - } - -} +/* + * Copyright 2008-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.repository.dao; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.jdbc.core.JdbcOperations; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import static org.mockito.Mockito.mock; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = { "sql-dao-test.xml" }) +public class JdbcExecutionContextDaoTests extends AbstractExecutionContextDaoTests { + + @Test + public void testNoSerializer() { + try { + JdbcExecutionContextDao jdbcExecutionContextDao = new JdbcExecutionContextDao(); + jdbcExecutionContextDao.setJdbcTemplate(mock(JdbcOperations.class)); + jdbcExecutionContextDao.afterPropertiesSet(); + } + catch (Exception e) { + Assert.assertTrue(e instanceof IllegalStateException); + Assert.assertEquals("ExecutionContextSerializer is required", e.getMessage()); + } + } + + @Test + public void testNullSerializer() { + try { + JdbcExecutionContextDao jdbcExecutionContextDao = new JdbcExecutionContextDao(); + jdbcExecutionContextDao.setJdbcTemplate(mock(JdbcOperations.class)); + jdbcExecutionContextDao.setSerializer(null); + jdbcExecutionContextDao.afterPropertiesSet(); + } + catch (Exception e) { + Assert.assertTrue(e instanceof IllegalArgumentException); + Assert.assertEquals("Serializer must not be null", e.getMessage()); + } + } + + @Override + protected JobInstanceDao getJobInstanceDao() { + return applicationContext.getBean("jobInstanceDao", JobInstanceDao.class); + } + + @Override + protected JobExecutionDao getJobExecutionDao() { + return applicationContext.getBean("jobExecutionDao", JdbcJobExecutionDao.class); + } + + @Override + protected StepExecutionDao getStepExecutionDao() { + return applicationContext.getBean("stepExecutionDao", StepExecutionDao.class); + } + + @Override + protected ExecutionContextDao getExecutionContextDao() { + return applicationContext.getBean("executionContextDao", JdbcExecutionContextDao.class); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcJobDaoQueryTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcJobDaoQueryTests.java index 0a95dd4cc..efbdfa184 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcJobDaoQueryTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcJobDaoQueryTests.java @@ -39,6 +39,7 @@ public class JdbcJobDaoQueryTests extends TestCase { /* * (non-Javadoc) + * * @see junit.framework.TestCase#setUp() */ @Override diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcJobDaoTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcJobDaoTests.java index 3bf89ddc0..810c781f6 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcJobDaoTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcJobDaoTests.java @@ -30,7 +30,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.transaction.annotation.Transactional; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = {"sql-dao-test.xml"}) +@ContextConfiguration(locations = { "sql-dao-test.xml" }) public class JdbcJobDaoTests extends AbstractJobDaoTests { public static final String LONG_STRING = "A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String "; @@ -41,21 +41,19 @@ public class JdbcJobDaoTests extends AbstractJobDaoTests { ((JdbcJobExecutionDao) jobExecutionDao).setTablePrefix(AbstractJdbcBatchMetadataDao.DEFAULT_TABLE_PREFIX); } - @Transactional @Test + @Transactional + @Test public void testUpdateJobExecutionWithLongExitCode() { assertTrue(LONG_STRING.length() > 250); ((JdbcJobExecutionDao) jobExecutionDao).setExitMessageLength(250); - jobExecution.setExitStatus(ExitStatus.COMPLETED - .addExitDescription(LONG_STRING)); + jobExecution.setExitStatus(ExitStatus.COMPLETED.addExitDescription(LONG_STRING)); jobExecutionDao.updateJobExecution(jobExecution); - List> executions = jdbcTemplate.queryForList( - "SELECT * FROM BATCH_JOB_EXECUTION where JOB_INSTANCE_ID=?", - jobInstance.getId()); + List> executions = jdbcTemplate + .queryForList("SELECT * FROM BATCH_JOB_EXECUTION where JOB_INSTANCE_ID=?", jobInstance.getId()); assertEquals(1, executions.size()); - assertEquals(LONG_STRING.substring(0, 250), executions.get(0) - .get("EXIT_MESSAGE")); + assertEquals(LONG_STRING.substring(0, 250), executions.get(0).get("EXIT_MESSAGE")); } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcJobExecutionDaoTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcJobExecutionDaoTests.java index c2a1c688a..5807cf101 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcJobExecutionDaoTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcJobExecutionDaoTests.java @@ -1,114 +1,114 @@ -/* - * Copyright 2008-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.repository.dao; - -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.sql.DataSource; - -import static org.junit.Assert.assertNull; -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameter; -import org.springframework.batch.core.JobParameters; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; -import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; -import org.springframework.jdbc.core.namedparam.SqlParameterSource; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.jdbc.JdbcTestUtils; -import org.springframework.transaction.annotation.Transactional; - -/** - * @author Parikshit Dutta - */ -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = { "sql-dao-test.xml" }) -public class JdbcJobExecutionDaoTests extends AbstractJobExecutionDaoTests { - - @Autowired - private StepExecutionDao stepExecutionDao; - - @Autowired - private JobExecutionDao jobExecutionDao; - - @Autowired - private JobInstanceDao jobInstanceDao; - - private JdbcTemplate jdbcTemplate; - - @Autowired - public void setDataSource(DataSource dataSource) { - jdbcTemplate = new JdbcTemplate(dataSource); - } - - @Override - protected JobInstanceDao getJobInstanceDao() { - return jobInstanceDao; - } - - @Override - protected JobExecutionDao getJobExecutionDao() { - JdbcTestUtils.deleteFromTables(jdbcTemplate, "BATCH_JOB_EXECUTION_CONTEXT", - "BATCH_STEP_EXECUTION_CONTEXT", "BATCH_STEP_EXECUTION", "BATCH_JOB_EXECUTION", "BATCH_JOB_EXECUTION_PARAMS", - "BATCH_JOB_INSTANCE"); - return jobExecutionDao; - } - - @Override - protected StepExecutionDao getStepExecutionDao() { - return stepExecutionDao; - } - - @Transactional - @Test - public void testSavedDateIsNullForNonDateTypeJobParams() { - final String FIND_DATE_PARAM_FROM_ID = "SELECT DATE_VAL " + - "from %PREFIX%JOB_EXECUTION_PARAMS where JOB_EXECUTION_ID = :JOB_EXECUTION_ID"; - - Map parameters = new HashMap<>(); - parameters.put("string-param", new JobParameter("value")); - parameters.put("long-param", new JobParameter(1L)); - parameters.put("double-param", new JobParameter(1D)); - - JobExecution execution = new JobExecution(jobInstance, new JobParameters(parameters)); - dao.saveJobExecution(execution); - - List executions = dao.findJobExecutions(jobInstance); - JobExecution savedJobExecution = executions.get(0); - - NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate( - jdbcTemplate.getDataSource()); - - JdbcJobExecutionDao jdbcJobExecutionDao = (JdbcJobExecutionDao) jobExecutionDao; - String query = jdbcJobExecutionDao.getQuery(FIND_DATE_PARAM_FROM_ID); - - SqlParameterSource namedParameters = new MapSqlParameterSource() - .addValue("JOB_EXECUTION_ID", savedJobExecution.getJobId()); - - List paramValues = namedParameterJdbcTemplate.queryForList(query, namedParameters, Date.class); - for (Date paramValue: paramValues) { - assertNull(paramValue); - } - } -} +/* + * Copyright 2008-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.repository.dao; + +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.sql.DataSource; + +import static org.junit.Assert.assertNull; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobParameter; +import org.springframework.batch.core.JobParameters; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.jdbc.core.namedparam.SqlParameterSource; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.jdbc.JdbcTestUtils; +import org.springframework.transaction.annotation.Transactional; + +/** + * @author Parikshit Dutta + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = { "sql-dao-test.xml" }) +public class JdbcJobExecutionDaoTests extends AbstractJobExecutionDaoTests { + + @Autowired + private StepExecutionDao stepExecutionDao; + + @Autowired + private JobExecutionDao jobExecutionDao; + + @Autowired + private JobInstanceDao jobInstanceDao; + + private JdbcTemplate jdbcTemplate; + + @Autowired + public void setDataSource(DataSource dataSource) { + jdbcTemplate = new JdbcTemplate(dataSource); + } + + @Override + protected JobInstanceDao getJobInstanceDao() { + return jobInstanceDao; + } + + @Override + protected JobExecutionDao getJobExecutionDao() { + JdbcTestUtils.deleteFromTables(jdbcTemplate, "BATCH_JOB_EXECUTION_CONTEXT", "BATCH_STEP_EXECUTION_CONTEXT", + "BATCH_STEP_EXECUTION", "BATCH_JOB_EXECUTION", "BATCH_JOB_EXECUTION_PARAMS", "BATCH_JOB_INSTANCE"); + return jobExecutionDao; + } + + @Override + protected StepExecutionDao getStepExecutionDao() { + return stepExecutionDao; + } + + @Transactional + @Test + public void testSavedDateIsNullForNonDateTypeJobParams() { + final String FIND_DATE_PARAM_FROM_ID = "SELECT DATE_VAL " + + "from %PREFIX%JOB_EXECUTION_PARAMS where JOB_EXECUTION_ID = :JOB_EXECUTION_ID"; + + Map parameters = new HashMap<>(); + parameters.put("string-param", new JobParameter("value")); + parameters.put("long-param", new JobParameter(1L)); + parameters.put("double-param", new JobParameter(1D)); + + JobExecution execution = new JobExecution(jobInstance, new JobParameters(parameters)); + dao.saveJobExecution(execution); + + List executions = dao.findJobExecutions(jobInstance); + JobExecution savedJobExecution = executions.get(0); + + NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate( + jdbcTemplate.getDataSource()); + + JdbcJobExecutionDao jdbcJobExecutionDao = (JdbcJobExecutionDao) jobExecutionDao; + String query = jdbcJobExecutionDao.getQuery(FIND_DATE_PARAM_FROM_ID); + + SqlParameterSource namedParameters = new MapSqlParameterSource().addValue("JOB_EXECUTION_ID", + savedJobExecution.getJobId()); + + List paramValues = namedParameterJdbcTemplate.queryForList(query, namedParameters, Date.class); + for (Date paramValue : paramValues) { + assertNull(paramValue); + } + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcJobInstanceDaoTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcJobInstanceDaoTests.java index 31061ff95..d692788e3 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcJobInstanceDaoTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcJobInstanceDaoTests.java @@ -1,107 +1,106 @@ -/* - * Copyright 2008-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.repository.dao; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.math.BigInteger; -import java.security.MessageDigest; -import java.util.List; - -import javax.sql.DataSource; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobInstance; -import org.springframework.batch.core.JobParameters; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.jdbc.JdbcTestUtils; -import org.springframework.transaction.annotation.Transactional; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = "sql-dao-test.xml") -public class JdbcJobInstanceDaoTests extends AbstractJobInstanceDaoTests { - - private JdbcTemplate jdbcTemplate; - - @Autowired - public void setDataSource(DataSource dataSource) { - this.jdbcTemplate = new JdbcTemplate(dataSource); - } - - @Autowired - private JobInstanceDao jobInstanceDao; - - @Autowired - private JobExecutionDao jobExecutionDao; - - @Override - protected JobInstanceDao getJobInstanceDao() { - JdbcTestUtils.deleteFromTables(jdbcTemplate, "BATCH_JOB_EXECUTION_CONTEXT", - "BATCH_STEP_EXECUTION_CONTEXT", "BATCH_STEP_EXECUTION", "BATCH_JOB_EXECUTION_PARAMS", - "BATCH_JOB_EXECUTION", "BATCH_JOB_INSTANCE"); - return jobInstanceDao; - } - - @Transactional - @Test - public void testFindJobInstanceByExecution() { - - JobParameters jobParameters = new JobParameters(); - JobInstance jobInstance = dao.createJobInstance("testInstance", - jobParameters); - JobExecution jobExecution = new JobExecution(jobInstance, 2L, jobParameters); - jobExecutionDao.saveJobExecution(jobExecution); - - JobInstance returnedInstance = dao.getJobInstance(jobExecution); - assertEquals(jobInstance, returnedInstance); - } - - @Test - public void testHexing() throws Exception { - MessageDigest digest = MessageDigest.getInstance("MD5"); - byte[] bytes = digest.digest("f78spx".getBytes("UTF-8")); - StringBuilder output = new StringBuilder(); - for (byte bite : bytes) { - output.append(String.format("%02x", bite)); - } - assertEquals("Wrong hash: " + output, 32, output.length()); - String value = String.format("%032x", new BigInteger(1, bytes)); - assertEquals("Wrong hash: " + value, 32, value.length()); - assertEquals(value, output.toString()); - } - - @Test - public void testJobInstanceWildcard() { - dao.createJobInstance("anotherJob", new JobParameters()); - dao.createJobInstance("someJob", new JobParameters()); - - List jobInstances = dao.findJobInstancesByName("*Job", 0, 2); - assertEquals(2, jobInstances.size()); - - for (JobInstance instance : jobInstances) { - assertTrue(instance.getJobName().contains("Job")); - } - - jobInstances = dao.getJobInstances("Job*", 0, 2); - assertTrue(jobInstances.isEmpty()); - } -} +/* + * Copyright 2008-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.repository.dao; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.math.BigInteger; +import java.security.MessageDigest; +import java.util.List; + +import javax.sql.DataSource; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobInstance; +import org.springframework.batch.core.JobParameters; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.jdbc.JdbcTestUtils; +import org.springframework.transaction.annotation.Transactional; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = "sql-dao-test.xml") +public class JdbcJobInstanceDaoTests extends AbstractJobInstanceDaoTests { + + private JdbcTemplate jdbcTemplate; + + @Autowired + public void setDataSource(DataSource dataSource) { + this.jdbcTemplate = new JdbcTemplate(dataSource); + } + + @Autowired + private JobInstanceDao jobInstanceDao; + + @Autowired + private JobExecutionDao jobExecutionDao; + + @Override + protected JobInstanceDao getJobInstanceDao() { + JdbcTestUtils.deleteFromTables(jdbcTemplate, "BATCH_JOB_EXECUTION_CONTEXT", "BATCH_STEP_EXECUTION_CONTEXT", + "BATCH_STEP_EXECUTION", "BATCH_JOB_EXECUTION_PARAMS", "BATCH_JOB_EXECUTION", "BATCH_JOB_INSTANCE"); + return jobInstanceDao; + } + + @Transactional + @Test + public void testFindJobInstanceByExecution() { + + JobParameters jobParameters = new JobParameters(); + JobInstance jobInstance = dao.createJobInstance("testInstance", jobParameters); + JobExecution jobExecution = new JobExecution(jobInstance, 2L, jobParameters); + jobExecutionDao.saveJobExecution(jobExecution); + + JobInstance returnedInstance = dao.getJobInstance(jobExecution); + assertEquals(jobInstance, returnedInstance); + } + + @Test + public void testHexing() throws Exception { + MessageDigest digest = MessageDigest.getInstance("MD5"); + byte[] bytes = digest.digest("f78spx".getBytes("UTF-8")); + StringBuilder output = new StringBuilder(); + for (byte bite : bytes) { + output.append(String.format("%02x", bite)); + } + assertEquals("Wrong hash: " + output, 32, output.length()); + String value = String.format("%032x", new BigInteger(1, bytes)); + assertEquals("Wrong hash: " + value, 32, value.length()); + assertEquals(value, output.toString()); + } + + @Test + public void testJobInstanceWildcard() { + dao.createJobInstance("anotherJob", new JobParameters()); + dao.createJobInstance("someJob", new JobParameters()); + + List jobInstances = dao.findJobInstancesByName("*Job", 0, 2); + assertEquals(2, jobInstances.size()); + + for (JobInstance instance : jobInstances) { + assertTrue(instance.getJobName().contains("Job")); + } + + jobInstances = dao.getJobInstances("Job*", 0, 2); + assertTrue(jobInstances.isEmpty()); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcStepExecutionDaoTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcStepExecutionDaoTests.java index c4938819a..e42374e90 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcStepExecutionDaoTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcStepExecutionDaoTests.java @@ -1,91 +1,92 @@ -/* - * Copyright 2008-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.repository.dao; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.repository.JobRepository; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.transaction.annotation.Transactional; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = "sql-dao-test.xml") -public class JdbcStepExecutionDaoTests extends AbstractStepExecutionDaoTests { - - @Override - protected StepExecutionDao getStepExecutionDao() { - return (StepExecutionDao) applicationContext.getBean("stepExecutionDao"); - } - - @Override - protected JobRepository getJobRepository() { - deleteFromTables("BATCH_JOB_EXECUTION_CONTEXT", "BATCH_STEP_EXECUTION_CONTEXT", "BATCH_STEP_EXECUTION", - "BATCH_JOB_EXECUTION_PARAMS", "BATCH_JOB_EXECUTION", "BATCH_JOB_INSTANCE"); - return (JobRepository) applicationContext.getBean("jobRepository"); - } - - /** - * Long exit descriptions are truncated on both save and update. - */ - @Transactional - @Test - public void testTruncateExitDescription() { - - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < 100; i++) { - sb.append("too long exit description"); - } - String longDescription = sb.toString(); - - ExitStatus exitStatus = ExitStatus.FAILED.addExitDescription(longDescription); - - stepExecution.setExitStatus(exitStatus); - - ((JdbcStepExecutionDao) dao).setExitMessageLength(250); - dao.saveStepExecution(stepExecution); - - StepExecution retrievedAfterSave = dao.getStepExecution(jobExecution, stepExecution.getId()); - - assertTrue("Exit description should be truncated", retrievedAfterSave.getExitStatus().getExitDescription() - .length() < stepExecution.getExitStatus().getExitDescription().length()); - - dao.updateStepExecution(stepExecution); - - StepExecution retrievedAfterUpdate = dao.getStepExecution(jobExecution, stepExecution.getId()); - - assertTrue("Exit description should be truncated", retrievedAfterUpdate.getExitStatus().getExitDescription() - .length() < stepExecution.getExitStatus().getExitDescription().length()); - } - - @Transactional - @Test - public void testCountStepExecutions() { - // Given - dao.saveStepExecution(stepExecution); - - // When - int result = dao.countStepExecutions(jobInstance, stepExecution.getStepName()); - - // Then - assertEquals(1, result); - } -} +/* + * Copyright 2008-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.repository.dao; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.transaction.annotation.Transactional; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = "sql-dao-test.xml") +public class JdbcStepExecutionDaoTests extends AbstractStepExecutionDaoTests { + + @Override + protected StepExecutionDao getStepExecutionDao() { + return (StepExecutionDao) applicationContext.getBean("stepExecutionDao"); + } + + @Override + protected JobRepository getJobRepository() { + deleteFromTables("BATCH_JOB_EXECUTION_CONTEXT", "BATCH_STEP_EXECUTION_CONTEXT", "BATCH_STEP_EXECUTION", + "BATCH_JOB_EXECUTION_PARAMS", "BATCH_JOB_EXECUTION", "BATCH_JOB_INSTANCE"); + return (JobRepository) applicationContext.getBean("jobRepository"); + } + + /** + * Long exit descriptions are truncated on both save and update. + */ + @Transactional + @Test + public void testTruncateExitDescription() { + + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < 100; i++) { + sb.append("too long exit description"); + } + String longDescription = sb.toString(); + + ExitStatus exitStatus = ExitStatus.FAILED.addExitDescription(longDescription); + + stepExecution.setExitStatus(exitStatus); + + ((JdbcStepExecutionDao) dao).setExitMessageLength(250); + dao.saveStepExecution(stepExecution); + + StepExecution retrievedAfterSave = dao.getStepExecution(jobExecution, stepExecution.getId()); + + assertTrue("Exit description should be truncated", retrievedAfterSave.getExitStatus().getExitDescription() + .length() < stepExecution.getExitStatus().getExitDescription().length()); + + dao.updateStepExecution(stepExecution); + + StepExecution retrievedAfterUpdate = dao.getStepExecution(jobExecution, stepExecution.getId()); + + assertTrue("Exit description should be truncated", retrievedAfterUpdate.getExitStatus().getExitDescription() + .length() < stepExecution.getExitStatus().getExitDescription().length()); + } + + @Transactional + @Test + public void testCountStepExecutions() { + // Given + dao.saveStepExecution(stepExecution); + + // When + int result = dao.countStepExecutions(jobInstance, stepExecution.getStepName()); + + // Then + assertEquals(1, result); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/NoSuchBatchDomainObjectExceptionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/NoSuchBatchDomainObjectExceptionTests.java index 21a0753b9..7527d4ee6 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/NoSuchBatchDomainObjectExceptionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/NoSuchBatchDomainObjectExceptionTests.java @@ -21,7 +21,7 @@ import org.junit.Test; /** * @author Dave Syer - * + * */ public class NoSuchBatchDomainObjectExceptionTests { @@ -30,4 +30,5 @@ public class NoSuchBatchDomainObjectExceptionTests { NoSuchObjectException e = new NoSuchObjectException("Foo"); assertEquals("Foo", e.getMessage()); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/OptimisticLockingFailureTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/OptimisticLockingFailureTests.java index 8b81b32bf..4434f2392 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/OptimisticLockingFailureTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/OptimisticLockingFailureTests.java @@ -44,21 +44,19 @@ import org.springframework.lang.Nullable; public class OptimisticLockingFailureTests { - private static final Set END_STATUSES = - EnumSet.of(BatchStatus.COMPLETED, BatchStatus.FAILED, BatchStatus.STOPPED); + private static final Set END_STATUSES = EnumSet.of(BatchStatus.COMPLETED, BatchStatus.FAILED, + BatchStatus.STOPPED); @Test public void testAsyncStopOfStartingJob() throws Exception { - ApplicationContext applicationContext = - new ClassPathXmlApplicationContext("org/springframework/batch/core/repository/dao/OptimisticLockingFailureTests-context.xml"); + ApplicationContext applicationContext = new ClassPathXmlApplicationContext( + "org/springframework/batch/core/repository/dao/OptimisticLockingFailureTests-context.xml"); Job job = applicationContext.getBean(Job.class); JobLauncher jobLauncher = applicationContext.getBean(JobLauncher.class); JobOperator jobOperator = applicationContext.getBean(JobOperator.class); JobRepository jobRepository = applicationContext.getBean(JobRepository.class); - JobParameters jobParameters = new JobParametersBuilder() - .addLong("test", 1L) - .toJobParameters(); + JobParameters jobParameters = new JobParametersBuilder().addLong("test", 1L).toJobParameters(); JobExecution jobExecution = jobLauncher.run(job, jobParameters); Thread.sleep(1000); @@ -78,8 +76,10 @@ public class OptimisticLockingFailureTests { assertTrue("Should only be one StepExecution but got: " + numStepExecutions, numStepExecutions == 1); assertTrue("Step name for execution should be step1 but got: " + stepName, "step1".equals(stepName)); - assertTrue("Step execution status should be STOPPED but got: " + stepExecutionStatus, stepExecutionStatus.equals(BatchStatus.STOPPED)); - assertTrue("Job execution status should be STOPPED but got:" + jobExecutionStatus, jobExecutionStatus.equals(BatchStatus.STOPPED)); + assertTrue("Step execution status should be STOPPED but got: " + stepExecutionStatus, + stepExecutionStatus.equals(BatchStatus.STOPPED)); + assertTrue("Job execution status should be STOPPED but got:" + jobExecutionStatus, + jobExecutionStatus.equals(BatchStatus.STOPPED)); JobExecution restartJobExecution = jobLauncher.run(job, jobParameters); @@ -91,9 +91,10 @@ public class OptimisticLockingFailureTests { } int restartNumStepExecutions = restartJobExecution.getStepExecutions().size(); - assertTrue("Should be two StepExecution's on restart but got: " + restartNumStepExecutions, restartNumStepExecutions == 2); + assertTrue("Should be two StepExecution's on restart but got: " + restartNumStepExecutions, + restartNumStepExecutions == 2); - for(StepExecution restartStepExecution : restartJobExecution.getStepExecutions()) { + for (StepExecution restartStepExecution : restartJobExecution.getStepExecutions()) { BatchStatus restartStepExecutionStatus = restartStepExecution.getStatus(); assertTrue("Step execution status should be COMPLETED but got: " + restartStepExecutionStatus, @@ -106,20 +107,25 @@ public class OptimisticLockingFailureTests { } public static class Writer implements ItemWriter { + @Override public void write(List items) throws Exception { - for(String item : items) { + for (String item : items) { System.out.println(item); } } + } public static class SleepingTasklet implements Tasklet { + @Nullable @Override public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { Thread.sleep(2000L); return RepeatStatus.FINISHED; } + } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/JobRepositoryFactoryBeanTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/JobRepositoryFactoryBeanTests.java index 974b48cb8..e019a1671 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/JobRepositoryFactoryBeanTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/JobRepositoryFactoryBeanTests.java @@ -94,8 +94,10 @@ public class JobRepositoryFactoryBeanTests { when(incrementerFactory.isSupportedIncrementerType("ORACLE")).thenReturn(true); when(incrementerFactory.getSupportedIncrementerTypes()).thenReturn(new String[0]); when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_SEQ")).thenReturn(new StubIncrementer()); - when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_EXECUTION_SEQ")).thenReturn(new StubIncrementer()); - when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "STEP_EXECUTION_SEQ")).thenReturn(new StubIncrementer()); + when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_EXECUTION_SEQ")) + .thenReturn(new StubIncrementer()); + when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "STEP_EXECUTION_SEQ")) + .thenReturn(new StubIncrementer()); factory.afterPropertiesSet(); factory.getObject(); @@ -110,8 +112,10 @@ public class JobRepositoryFactoryBeanTests { incrementerFactory = mock(DataFieldMaxValueIncrementerFactory.class); when(incrementerFactory.isSupportedIncrementerType("ORACLE")).thenReturn(true); when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_SEQ")).thenReturn(new StubIncrementer()); - when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_EXECUTION_SEQ")).thenReturn(new StubIncrementer()); - when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "STEP_EXECUTION_SEQ")).thenReturn(new StubIncrementer()); + when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_EXECUTION_SEQ")) + .thenReturn(new StubIncrementer()); + when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "STEP_EXECUTION_SEQ")) + .thenReturn(new StubIncrementer()); factory.setIncrementerFactory(incrementerFactory); factory.afterPropertiesSet(); @@ -128,8 +132,10 @@ public class JobRepositoryFactoryBeanTests { incrementerFactory = mock(DataFieldMaxValueIncrementerFactory.class); when(incrementerFactory.isSupportedIncrementerType("ORACLE")).thenReturn(true); when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_SEQ")).thenReturn(new StubIncrementer()); - when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_EXECUTION_SEQ")).thenReturn(new StubIncrementer()); - when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "STEP_EXECUTION_SEQ")).thenReturn(new StubIncrementer()); + when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_EXECUTION_SEQ")) + .thenReturn(new StubIncrementer()); + when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "STEP_EXECUTION_SEQ")) + .thenReturn(new StubIncrementer()); factory.setIncrementerFactory(incrementerFactory); LobHandler lobHandler = new DefaultLobHandler(); @@ -149,12 +155,15 @@ public class JobRepositoryFactoryBeanTests { incrementerFactory = mock(DataFieldMaxValueIncrementerFactory.class); when(incrementerFactory.isSupportedIncrementerType("ORACLE")).thenReturn(true); when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_SEQ")).thenReturn(new StubIncrementer()); - when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_EXECUTION_SEQ")).thenReturn(new StubIncrementer()); - when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "STEP_EXECUTION_SEQ")).thenReturn(new StubIncrementer()); + when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_EXECUTION_SEQ")) + .thenReturn(new StubIncrementer()); + when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "STEP_EXECUTION_SEQ")) + .thenReturn(new StubIncrementer()); factory.setIncrementerFactory(incrementerFactory); factory.afterPropertiesSet(); - Serializer> serializer = (Serializer>) ReflectionTestUtils.getField(factory, "serializer"); + Serializer> serializer = (Serializer>) ReflectionTestUtils + .getField(factory, "serializer"); assertTrue(serializer instanceof Jackson2ExecutionContextStringSerializer); } @@ -166,8 +175,10 @@ public class JobRepositoryFactoryBeanTests { incrementerFactory = mock(DataFieldMaxValueIncrementerFactory.class); when(incrementerFactory.isSupportedIncrementerType("ORACLE")).thenReturn(true); when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_SEQ")).thenReturn(new StubIncrementer()); - when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_EXECUTION_SEQ")).thenReturn(new StubIncrementer()); - when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "STEP_EXECUTION_SEQ")).thenReturn(new StubIncrementer()); + when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_EXECUTION_SEQ")) + .thenReturn(new StubIncrementer()); + when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "STEP_EXECUTION_SEQ")) + .thenReturn(new StubIncrementer()); factory.setIncrementerFactory(incrementerFactory); ExecutionContextSerializer customSerializer = new DefaultExecutionContextSerializer(); @@ -176,7 +187,7 @@ public class JobRepositoryFactoryBeanTests { factory.afterPropertiesSet(); assertEquals(customSerializer, ReflectionTestUtils.getField(factory, "serializer")); } - + @Test public void testDefaultJdbcOperations() throws Exception { @@ -185,15 +196,17 @@ public class JobRepositoryFactoryBeanTests { incrementerFactory = mock(DataFieldMaxValueIncrementerFactory.class); when(incrementerFactory.isSupportedIncrementerType("ORACLE")).thenReturn(true); when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_SEQ")).thenReturn(new StubIncrementer()); - when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_EXECUTION_SEQ")).thenReturn(new StubIncrementer()); - when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "STEP_EXECUTION_SEQ")).thenReturn(new StubIncrementer()); + when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_EXECUTION_SEQ")) + .thenReturn(new StubIncrementer()); + when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "STEP_EXECUTION_SEQ")) + .thenReturn(new StubIncrementer()); factory.setIncrementerFactory(incrementerFactory); factory.afterPropertiesSet(); - + JdbcOperations jdbcOperations = (JdbcOperations) ReflectionTestUtils.getField(factory, "jdbcOperations"); assertTrue(jdbcOperations instanceof JdbcTemplate); - } + } @Test public void testCustomJdbcOperations() throws Exception { @@ -203,18 +216,20 @@ public class JobRepositoryFactoryBeanTests { incrementerFactory = mock(DataFieldMaxValueIncrementerFactory.class); when(incrementerFactory.isSupportedIncrementerType("ORACLE")).thenReturn(true); when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_SEQ")).thenReturn(new StubIncrementer()); - when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_EXECUTION_SEQ")).thenReturn(new StubIncrementer()); - when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "STEP_EXECUTION_SEQ")).thenReturn(new StubIncrementer()); + when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_EXECUTION_SEQ")) + .thenReturn(new StubIncrementer()); + when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "STEP_EXECUTION_SEQ")) + .thenReturn(new StubIncrementer()); factory.setIncrementerFactory(incrementerFactory); - + JdbcOperations customJdbcOperations = mock(JdbcOperations.class); factory.setJdbcOperations(customJdbcOperations); - + factory.afterPropertiesSet(); - + assertEquals(customJdbcOperations, ReflectionTestUtils.getField(factory, "jdbcOperations")); - } - + } + @Test public void testMissingDataSource() throws Exception { @@ -276,9 +291,12 @@ public class JobRepositoryFactoryBeanTests { when(incrementerFactory.isSupportedIncrementerType("HSQL")).thenReturn(true); when(incrementerFactory.getSupportedIncrementerTypes()).thenReturn(new String[0]); - when(incrementerFactory.getIncrementer(databaseType, tablePrefix + "JOB_SEQ")).thenReturn(new StubIncrementer()); - when(incrementerFactory.getIncrementer(databaseType, tablePrefix + "JOB_EXECUTION_SEQ")).thenReturn(new StubIncrementer()); - when(incrementerFactory.getIncrementer(databaseType, tablePrefix + "STEP_EXECUTION_SEQ")).thenReturn(new StubIncrementer()); + when(incrementerFactory.getIncrementer(databaseType, tablePrefix + "JOB_SEQ")) + .thenReturn(new StubIncrementer()); + when(incrementerFactory.getIncrementer(databaseType, tablePrefix + "JOB_EXECUTION_SEQ")) + .thenReturn(new StubIncrementer()); + when(incrementerFactory.getIncrementer(databaseType, tablePrefix + "STEP_EXECUTION_SEQ")) + .thenReturn(new StubIncrementer()); factory.afterPropertiesSet(); factory.getObject(); @@ -354,7 +372,7 @@ public class JobRepositoryFactoryBeanTests { } } - @Test(expected=IllegalArgumentException.class) + @Test(expected = IllegalArgumentException.class) public void testInvalidCustomLobType() throws Exception { factory.setClobType(Integer.MAX_VALUE); testCreateRepository(); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/SimpleJobRepositoryIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/SimpleJobRepositoryIntegrationTests.java index e2204bcd8..683259b0f 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/SimpleJobRepositoryIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/SimpleJobRepositoryIntegrationTests.java @@ -58,8 +58,8 @@ public class SimpleJobRepositoryIntegrationTests { private JobParameters jobParameters = new JobParameters(); /* - * Create two job executions for same job+parameters tuple. Check both - * executions belong to the same job instance and job. + * Create two job executions for same job+parameters tuple. Check both executions + * belong to the same job instance and job. */ @Transactional @Test @@ -68,8 +68,8 @@ public class SimpleJobRepositoryIntegrationTests { job.setRestartable(true); JobParametersBuilder builder = new JobParametersBuilder(); - builder.addString("stringKey", "stringValue").addLong("longKey", 1L).addDouble("doubleKey", 1.1).addDate( - "dateKey", new Date(1L)); + builder.addString("stringKey", "stringValue").addLong("longKey", 1L).addDouble("doubleKey", 1.1) + .addDate("dateKey", new Date(1L)); JobParameters jobParams = builder.toJobParameters(); JobExecution firstExecution = jobRepository.createJobExecution(job.getName(), jobParams); @@ -88,8 +88,8 @@ public class SimpleJobRepositoryIntegrationTests { } /* - * Create two job executions for same job+parameters tuple. Check both - * executions belong to the same job instance and job. + * Create two job executions for same job+parameters tuple. Check both executions + * belong to the same job instance and job. */ @Transactional @Test @@ -107,8 +107,8 @@ public class SimpleJobRepositoryIntegrationTests { } /* - * Save multiple StepExecutions for the same step and check the returned - * count and last execution are correct. + * Save multiple StepExecutions for the same step and check the returned count and + * last execution are correct. */ @Transactional @Test @@ -140,7 +140,8 @@ public class SimpleJobRepositoryIntegrationTests { jobRepository.add(secondStepExec); assertEquals(2, jobRepository.getStepExecutionCount(secondJobExec.getJobInstance(), step.getName())); - assertEquals(secondStepExec, jobRepository.getLastStepExecution(secondJobExec.getJobInstance(), step.getName())); + assertEquals(secondStepExec, + jobRepository.getLastStepExecution(secondJobExec.getJobInstance(), step.getName())); } /* @@ -175,8 +176,8 @@ public class SimpleJobRepositoryIntegrationTests { } /* - * If JobExecution is already running, exception will be thrown in attempt - * to create new execution. + * If JobExecution is already running, exception will be thrown in attempt to create + * new execution. */ @Transactional @Test @@ -184,7 +185,7 @@ public class SimpleJobRepositoryIntegrationTests { job.setRestartable(true); JobExecution jobExecution = jobRepository.createJobExecution(job.getName(), jobParameters); - //simulating a running job execution + // simulating a running job execution jobExecution.setStartTime(new Date()); jobRepository.update(jobExecution); @@ -220,9 +221,7 @@ public class SimpleJobRepositoryIntegrationTests { @Transactional @Test public void testReExecuteWithSameJobParameters() throws Exception { - JobParameters jobParameters = new JobParametersBuilder() - .addString("name", "foo", false) - .toJobParameters(); + JobParameters jobParameters = new JobParametersBuilder().addString("name", "foo", false).toJobParameters(); JobExecution jobExecution1 = jobRepository.createJobExecution(job.getName(), jobParameters); jobExecution1.setStatus(BatchStatus.COMPLETED); jobExecution1.setEndTime(new Date()); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/SimpleJobRepositoryProxyTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/SimpleJobRepositoryProxyTests.java index b7c4d78d8..9f853770c 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/SimpleJobRepositoryProxyTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/SimpleJobRepositoryProxyTests.java @@ -41,7 +41,7 @@ import org.springframework.transaction.annotation.Transactional; */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration -@DirtiesContext(classMode=ClassMode.AFTER_EACH_TEST_METHOD) +@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD) public class SimpleJobRepositoryProxyTests { @Autowired @@ -53,7 +53,7 @@ public class SimpleJobRepositoryProxyTests { private JobSupport job = new JobSupport("SimpleJobRepositoryProxyTestsJob"); @Transactional - @Test(expected=IllegalStateException.class) + @Test(expected = IllegalStateException.class) public void testCreateAndFindWithExistingTransaction() throws Exception { assertFalse(advice.invoked); JobExecution jobExecution = jobRepository.createJobExecution(job.getName(), new JobParameters()); @@ -78,6 +78,7 @@ public class SimpleJobRepositoryProxyTests { invoked = true; return invocation.proceed(); } + } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/SimpleJobRepositoryTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/SimpleJobRepositoryTests.java index 327bf1e36..aa28437d3 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/SimpleJobRepositoryTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/SimpleJobRepositoryTests.java @@ -51,9 +51,9 @@ import org.springframework.batch.core.repository.dao.StepExecutionDao; import org.springframework.batch.core.step.StepSupport; /** - * Test SimpleJobRepository. The majority of test cases are tested using - * EasyMock, however, there were some issues with using it for the stepExecutionDao when - * testing finding or creating steps, so an actual mock class had to be written. + * Test SimpleJobRepository. The majority of test cases are tested using EasyMock, + * however, there were some issues with using it for the stepExecutionDao when testing + * finding or creating steps, so an actual mock class had to be written. * * @author Lucas Ward * @author Will Schipp @@ -170,7 +170,7 @@ public class SimpleJobRepositoryTests { } @Test - public void testSaveStepExecutionSetsLastUpdated(){ + public void testSaveStepExecutionSetsLastUpdated() { StepExecution stepExecution = new StepExecution("stepName", jobExecution); @@ -203,7 +203,7 @@ public class SimpleJobRepositoryTests { } @Test - public void testUpdateStepExecutionSetsLastUpdated(){ + public void testUpdateStepExecutionSetsLastUpdated() { StepExecution stepExecution = new StepExecution("stepName", jobExecution); stepExecution.setId(2343L); @@ -219,7 +219,7 @@ public class SimpleJobRepositoryTests { } @Test - public void testInterrupted(){ + public void testInterrupted() { jobExecution.setStatus(BatchStatus.STOPPING); StepExecution stepExecution = new StepExecution("stepName", jobExecution); @@ -296,4 +296,5 @@ public class SimpleJobRepositoryTests { // Then assertEquals(expectedResult, actualResult); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/resource/Foo.java b/spring-batch-core/src/test/java/org/springframework/batch/core/resource/Foo.java index 17ced1aea..c0764beee 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/resource/Foo.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/resource/Foo.java @@ -15,17 +15,19 @@ */ package org.springframework.batch.core.resource; - /** * Simple domain object for testing purposes. */ public class Foo { private int id; + private String name; + private int value; - public Foo(){} + public Foo() { + } public Foo(int id, String name, int value) { this.id = id; @@ -36,25 +38,30 @@ public class Foo { public String getName() { return name; } + public void setName(String name) { this.name = name; } + public int getValue() { return value; } + public void setValue(int value) { this.value = value; } + public int getId() { return id; } + public void setId(int id) { this.id = id; } @Override public String toString() { - return "Foo[id=" +id +",name=" + name + ",value=" + value + "]"; + return "Foo[id=" + id + ",name=" + name + ",value=" + value + "]"; } @Override diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/resource/FooRowMapper.java b/spring-batch-core/src/test/java/org/springframework/batch/core/resource/FooRowMapper.java index 85e309f04..5b8f0659e 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/resource/FooRowMapper.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/resource/FooRowMapper.java @@ -20,7 +20,6 @@ import java.sql.SQLException; import org.springframework.jdbc.core.RowMapper; - public class FooRowMapper implements RowMapper { @Override @@ -33,4 +32,5 @@ public class FooRowMapper implements RowMapper { return foo; } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/resource/JdbcCursorItemReaderPreparedStatementIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/resource/JdbcCursorItemReaderPreparedStatementIntegrationTests.java index ae26762b7..21d5d2356 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/resource/JdbcCursorItemReaderPreparedStatementIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/resource/JdbcCursorItemReaderPreparedStatementIntegrationTests.java @@ -46,16 +46,16 @@ public class JdbcCursorItemReaderPreparedStatementIntegrationTests { public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } - + @Before public void onSetUpInTransaction() throws Exception { - + itemReader = new JdbcCursorItemReader<>(); itemReader.setDataSource(dataSource); itemReader.setSql("select ID, NAME, VALUE from T_FOOS where ID > ? and ID < ?"); itemReader.setIgnoreWarnings(true); itemReader.setVerifyCursorPosition(true); - + itemReader.setRowMapper(new FooRowMapper()); itemReader.setFetchSize(10); itemReader.setMaxRows(100); @@ -68,9 +68,10 @@ public class JdbcCursorItemReaderPreparedStatementIntegrationTests { itemReader.setPreparedStatementSetter(pss); } - - @Transactional @Test - public void testRead() throws Exception{ + + @Transactional + @Test + public void testRead() throws Exception { itemReader.open(new ExecutionContext()); Foo foo = itemReader.read(); assertEquals(2, foo.getId()); @@ -78,5 +79,5 @@ public class JdbcCursorItemReaderPreparedStatementIntegrationTests { assertEquals(3, foo.getId()); assertNull(itemReader.read()); } - + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/resource/StepExecutionSimpleCompletionPolicyTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/resource/StepExecutionSimpleCompletionPolicyTests.java index a9273f017..0ec458503 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/resource/StepExecutionSimpleCompletionPolicyTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/resource/StepExecutionSimpleCompletionPolicyTests.java @@ -63,7 +63,7 @@ public class StepExecutionSimpleCompletionPolicyTests extends TestCase { public void testToString() throws Exception { String msg = policy.toString(); - assertTrue("String does not contain chunk size", msg.indexOf("chunkSize=2")>=0); + assertTrue("String does not contain chunk size", msg.indexOf("chunkSize=2") >= 0); } public void testKeyName() throws Exception, IOException { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/AsyncJobScopeIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/AsyncJobScopeIntegrationTests.java index ad344a505..78b484899 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/AsyncJobScopeIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/AsyncJobScopeIntegrationTests.java @@ -1,166 +1,166 @@ -/* - * Copyright 2013-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope; - -import static org.junit.Assert.assertEquals; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.FutureTask; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.scope.context.JobContext; -import org.springframework.batch.core.scope.context.JobSynchronizationManager; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.BeanFactoryAware; -import org.springframework.beans.factory.ListableBeanFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.core.task.SimpleAsyncTaskExecutor; -import org.springframework.core.task.TaskExecutor; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -public class AsyncJobScopeIntegrationTests implements BeanFactoryAware { - - private Log logger = LogFactory.getLog(getClass()); - - @Autowired - @Qualifier("simple") - private Collaborator simple; - - private TaskExecutor taskExecutor = new SimpleAsyncTaskExecutor(); - - private ListableBeanFactory beanFactory; - - private int beanCount; - - @Override - public void setBeanFactory(BeanFactory beanFactory) throws BeansException { - this.beanFactory = (ListableBeanFactory) beanFactory; - } - - @Before - public void countBeans() { - JobSynchronizationManager.release(); - beanCount = beanFactory.getBeanDefinitionCount(); - } - - @After - public void cleanUp() { - JobSynchronizationManager.close(); - // Check that all temporary bean definitions are cleaned up - assertEquals(beanCount, beanFactory.getBeanDefinitionCount()); - } - - @Test - public void testSimpleProperty() throws Exception { - JobExecution jobExecution = new JobExecution(11L); - ExecutionContext executionContext = jobExecution.getExecutionContext(); - executionContext.put("foo", "bar"); - JobSynchronizationManager.register(jobExecution); - assertEquals("bar", simple.getName()); - } - - @Test - public void testGetMultipleInMultipleThreads() throws Exception { - - List> tasks = new ArrayList<>(); - - for (int i = 0; i < 12; i++) { - final String value = "foo" + i; - final Long id = 123L + i; - FutureTask task = new FutureTask<>(new Callable() { - @Override - public String call() throws Exception { - JobExecution jobExecution = new JobExecution(id); - ExecutionContext executionContext = jobExecution.getExecutionContext(); - executionContext.put("foo", value); - JobContext context = JobSynchronizationManager.register(jobExecution); - logger.debug("Registered: " + context.getJobExecutionContext()); - try { - return simple.getName(); - } - finally { - JobSynchronizationManager.close(); - } - } - }); - tasks.add(task); - taskExecutor.execute(task); - } - - int i = 0; - for (FutureTask task : tasks) { - assertEquals("foo" + i, task.get()); - i++; - } - - } - - @Test - public void testGetSameInMultipleThreads() throws Exception { - - List> tasks = new ArrayList<>(); - final JobExecution jobExecution = new JobExecution(11L); - ExecutionContext executionContext = jobExecution.getExecutionContext(); - executionContext.put("foo", "foo"); - JobSynchronizationManager.register(jobExecution); - assertEquals("foo", simple.getName()); - - for (int i = 0; i < 12; i++) { - final String value = "foo" + i; - FutureTask task = new FutureTask<>(new Callable() { - @Override - public String call() throws Exception { - ExecutionContext executionContext = jobExecution.getExecutionContext(); - executionContext.put("foo", value); - JobContext context = JobSynchronizationManager.register(jobExecution); - logger.debug("Registered: " + context.getJobExecutionContext()); - try { - return simple.getName(); - } - finally { - JobSynchronizationManager.close(); - } - } - }); - tasks.add(task); - taskExecutor.execute(task); - } - - for (FutureTask task : tasks) { - assertEquals("foo", task.get()); - } - - // Don't close the outer scope until all tasks are finished. This should - // always be the case if using an AbstractJob - JobSynchronizationManager.close(); - - } - -} +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope; + +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.FutureTask; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.scope.context.JobContext; +import org.springframework.batch.core.scope.context.JobSynchronizationManager; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.beans.factory.ListableBeanFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.core.task.SimpleAsyncTaskExecutor; +import org.springframework.core.task.TaskExecutor; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class AsyncJobScopeIntegrationTests implements BeanFactoryAware { + + private Log logger = LogFactory.getLog(getClass()); + + @Autowired + @Qualifier("simple") + private Collaborator simple; + + private TaskExecutor taskExecutor = new SimpleAsyncTaskExecutor(); + + private ListableBeanFactory beanFactory; + + private int beanCount; + + @Override + public void setBeanFactory(BeanFactory beanFactory) throws BeansException { + this.beanFactory = (ListableBeanFactory) beanFactory; + } + + @Before + public void countBeans() { + JobSynchronizationManager.release(); + beanCount = beanFactory.getBeanDefinitionCount(); + } + + @After + public void cleanUp() { + JobSynchronizationManager.close(); + // Check that all temporary bean definitions are cleaned up + assertEquals(beanCount, beanFactory.getBeanDefinitionCount()); + } + + @Test + public void testSimpleProperty() throws Exception { + JobExecution jobExecution = new JobExecution(11L); + ExecutionContext executionContext = jobExecution.getExecutionContext(); + executionContext.put("foo", "bar"); + JobSynchronizationManager.register(jobExecution); + assertEquals("bar", simple.getName()); + } + + @Test + public void testGetMultipleInMultipleThreads() throws Exception { + + List> tasks = new ArrayList<>(); + + for (int i = 0; i < 12; i++) { + final String value = "foo" + i; + final Long id = 123L + i; + FutureTask task = new FutureTask<>(new Callable() { + @Override + public String call() throws Exception { + JobExecution jobExecution = new JobExecution(id); + ExecutionContext executionContext = jobExecution.getExecutionContext(); + executionContext.put("foo", value); + JobContext context = JobSynchronizationManager.register(jobExecution); + logger.debug("Registered: " + context.getJobExecutionContext()); + try { + return simple.getName(); + } + finally { + JobSynchronizationManager.close(); + } + } + }); + tasks.add(task); + taskExecutor.execute(task); + } + + int i = 0; + for (FutureTask task : tasks) { + assertEquals("foo" + i, task.get()); + i++; + } + + } + + @Test + public void testGetSameInMultipleThreads() throws Exception { + + List> tasks = new ArrayList<>(); + final JobExecution jobExecution = new JobExecution(11L); + ExecutionContext executionContext = jobExecution.getExecutionContext(); + executionContext.put("foo", "foo"); + JobSynchronizationManager.register(jobExecution); + assertEquals("foo", simple.getName()); + + for (int i = 0; i < 12; i++) { + final String value = "foo" + i; + FutureTask task = new FutureTask<>(new Callable() { + @Override + public String call() throws Exception { + ExecutionContext executionContext = jobExecution.getExecutionContext(); + executionContext.put("foo", value); + JobContext context = JobSynchronizationManager.register(jobExecution); + logger.debug("Registered: " + context.getJobExecutionContext()); + try { + return simple.getName(); + } + finally { + JobSynchronizationManager.close(); + } + } + }); + tasks.add(task); + taskExecutor.execute(task); + } + + for (FutureTask task : tasks) { + assertEquals("foo", task.get()); + } + + // Don't close the outer scope until all tasks are finished. This should + // always be the case if using an AbstractJob + JobSynchronizationManager.close(); + + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/AsyncStepScopeIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/AsyncStepScopeIntegrationTests.java index 2e08dab1e..053386e15 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/AsyncStepScopeIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/AsyncStepScopeIntegrationTests.java @@ -1,166 +1,167 @@ -/* - * Copyright 2008-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope; - -import static org.junit.Assert.assertEquals; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.FutureTask; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.scope.context.StepContext; -import org.springframework.batch.core.scope.context.StepSynchronizationManager; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.BeanFactoryAware; -import org.springframework.beans.factory.ListableBeanFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.core.task.SimpleAsyncTaskExecutor; -import org.springframework.core.task.TaskExecutor; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -public class AsyncStepScopeIntegrationTests implements BeanFactoryAware { - - private Log logger = LogFactory.getLog(getClass()); - - @Autowired - @Qualifier("simple") - private Collaborator simple; - - private TaskExecutor taskExecutor = new SimpleAsyncTaskExecutor(); - - private ListableBeanFactory beanFactory; - - private int beanCount; - - @Override - public void setBeanFactory(BeanFactory beanFactory) throws BeansException { - this.beanFactory = (ListableBeanFactory) beanFactory; - } - - @Before - public void countBeans() { - StepSynchronizationManager.release(); - beanCount = beanFactory.getBeanDefinitionCount(); - } - - @After - public void cleanUp() { - StepSynchronizationManager.close(); - // Check that all temporary bean definitions are cleaned up - assertEquals(beanCount, beanFactory.getBeanDefinitionCount()); - } - - @Test - public void testSimpleProperty() throws Exception { - StepExecution stepExecution = new StepExecution("step", new JobExecution(0L), 123L); - ExecutionContext executionContext = stepExecution.getExecutionContext(); - executionContext.put("foo", "bar"); - StepSynchronizationManager.register(stepExecution); - assertEquals("bar", simple.getName()); - } - - @Test - public void testGetMultipleInMultipleThreads() throws Exception { - - List> tasks = new ArrayList<>(); - - for (int i = 0; i < 12; i++) { - final String value = "foo" + i; - final Long id = 123L + i; - FutureTask task = new FutureTask<>(new Callable() { - @Override - public String call() throws Exception { - StepExecution stepExecution = new StepExecution(value, new JobExecution(0L), id); - ExecutionContext executionContext = stepExecution.getExecutionContext(); - executionContext.put("foo", value); - StepContext context = StepSynchronizationManager.register(stepExecution); - logger.debug("Registered: " + context.getStepExecutionContext()); - try { - return simple.getName(); - } finally { - StepSynchronizationManager.close(); - } - } - }); - tasks.add(task); - taskExecutor.execute(task); - } - - int i = 0; - for (FutureTask task : tasks) { - assertEquals("foo" + i, task.get()); - i++; - } - - } - - @Test - public void testGetSameInMultipleThreads() throws Exception { - - List> tasks = new ArrayList<>(); - final StepExecution stepExecution = new StepExecution("foo", new JobExecution(0L), 123L); - ExecutionContext executionContext = stepExecution.getExecutionContext(); - executionContext.put("foo", "foo"); - StepSynchronizationManager.register(stepExecution); - assertEquals("foo", simple.getName()); - - for (int i = 0; i < 12; i++) { - final String value = "foo" + i; - FutureTask task = new FutureTask<>(new Callable() { - @Override - public String call() throws Exception { - ExecutionContext executionContext = stepExecution.getExecutionContext(); - executionContext.put("foo", value); - StepContext context = StepSynchronizationManager.register(stepExecution); - logger.debug("Registered: " + context.getStepExecutionContext()); - try { - return simple.getName(); - } - finally { - StepSynchronizationManager.close(); - } - } - }); - tasks.add(task); - taskExecutor.execute(task); - } - - for (FutureTask task : tasks) { - assertEquals("foo", task.get()); - } - - // Don't close the outer scope until all tasks are finished. This should - // always be the case if using an AbstractStep - StepSynchronizationManager.close(); - - } - -} +/* + * Copyright 2008-2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope; + +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.FutureTask; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.scope.context.StepContext; +import org.springframework.batch.core.scope.context.StepSynchronizationManager; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.beans.factory.ListableBeanFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.core.task.SimpleAsyncTaskExecutor; +import org.springframework.core.task.TaskExecutor; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class AsyncStepScopeIntegrationTests implements BeanFactoryAware { + + private Log logger = LogFactory.getLog(getClass()); + + @Autowired + @Qualifier("simple") + private Collaborator simple; + + private TaskExecutor taskExecutor = new SimpleAsyncTaskExecutor(); + + private ListableBeanFactory beanFactory; + + private int beanCount; + + @Override + public void setBeanFactory(BeanFactory beanFactory) throws BeansException { + this.beanFactory = (ListableBeanFactory) beanFactory; + } + + @Before + public void countBeans() { + StepSynchronizationManager.release(); + beanCount = beanFactory.getBeanDefinitionCount(); + } + + @After + public void cleanUp() { + StepSynchronizationManager.close(); + // Check that all temporary bean definitions are cleaned up + assertEquals(beanCount, beanFactory.getBeanDefinitionCount()); + } + + @Test + public void testSimpleProperty() throws Exception { + StepExecution stepExecution = new StepExecution("step", new JobExecution(0L), 123L); + ExecutionContext executionContext = stepExecution.getExecutionContext(); + executionContext.put("foo", "bar"); + StepSynchronizationManager.register(stepExecution); + assertEquals("bar", simple.getName()); + } + + @Test + public void testGetMultipleInMultipleThreads() throws Exception { + + List> tasks = new ArrayList<>(); + + for (int i = 0; i < 12; i++) { + final String value = "foo" + i; + final Long id = 123L + i; + FutureTask task = new FutureTask<>(new Callable() { + @Override + public String call() throws Exception { + StepExecution stepExecution = new StepExecution(value, new JobExecution(0L), id); + ExecutionContext executionContext = stepExecution.getExecutionContext(); + executionContext.put("foo", value); + StepContext context = StepSynchronizationManager.register(stepExecution); + logger.debug("Registered: " + context.getStepExecutionContext()); + try { + return simple.getName(); + } + finally { + StepSynchronizationManager.close(); + } + } + }); + tasks.add(task); + taskExecutor.execute(task); + } + + int i = 0; + for (FutureTask task : tasks) { + assertEquals("foo" + i, task.get()); + i++; + } + + } + + @Test + public void testGetSameInMultipleThreads() throws Exception { + + List> tasks = new ArrayList<>(); + final StepExecution stepExecution = new StepExecution("foo", new JobExecution(0L), 123L); + ExecutionContext executionContext = stepExecution.getExecutionContext(); + executionContext.put("foo", "foo"); + StepSynchronizationManager.register(stepExecution); + assertEquals("foo", simple.getName()); + + for (int i = 0; i < 12; i++) { + final String value = "foo" + i; + FutureTask task = new FutureTask<>(new Callable() { + @Override + public String call() throws Exception { + ExecutionContext executionContext = stepExecution.getExecutionContext(); + executionContext.put("foo", value); + StepContext context = StepSynchronizationManager.register(stepExecution); + logger.debug("Registered: " + context.getStepExecutionContext()); + try { + return simple.getName(); + } + finally { + StepSynchronizationManager.close(); + } + } + }); + tasks.add(task); + taskExecutor.execute(task); + } + + for (FutureTask task : tasks) { + assertEquals("foo", task.get()); + } + + // Don't close the outer scope until all tasks are finished. This should + // always be the case if using an AbstractStep + StepSynchronizationManager.close(); + + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/Collaborator.java b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/Collaborator.java index 4e9d4c396..e8c822829 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/Collaborator.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/Collaborator.java @@ -1,28 +1,28 @@ -/* - * Copyright 2008-2009 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope; - -import java.util.List; - -public interface Collaborator { - - String getName(); - - Collaborator getParent(); - - List getList(); - +/* + * Copyright 2008-2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope; + +import java.util.List; + +public interface Collaborator { + + String getName(); + + Collaborator getParent(); + + List getList(); + } \ No newline at end of file diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/JobScopeDestructionCallbackIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/JobScopeDestructionCallbackIntegrationTests.java index 5b0508bb9..cf598aca7 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/JobScopeDestructionCallbackIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/JobScopeDestructionCallbackIntegrationTests.java @@ -1,102 +1,102 @@ -/* - * Copyright 2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.util.StringUtils; - -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -public class JobScopeDestructionCallbackIntegrationTests { - - @Autowired - @Qualifier("proxied") - private Job proxied; - - @Autowired - @Qualifier("nested") - private Job nested; - - @Autowired - @Qualifier("ref") - private Job ref; - - @Autowired - @Qualifier("foo") - private Collaborator foo; - - @Before - @After - public void resetMessage() throws Exception { - TestDisposableCollaborator.message = "none"; - TestAdvice.names.clear(); - } - - @Test - public void testDisposableScopedProxy() throws Exception { - assertNotNull(proxied); - proxied.execute(new JobExecution(1L)); - assertEquals(1, StringUtils.countOccurrencesOf(TestDisposableCollaborator.message, "destroyed")); - } - - @Test - public void testDisposableInnerScopedProxy() throws Exception { - assertNotNull(nested); - nested.execute(new JobExecution(1L)); - assertEquals(1, StringUtils.countOccurrencesOf(TestDisposableCollaborator.message, "destroyed")); - } - - @Test - public void testProxiedScopedProxy() throws Exception { - assertNotNull(nested); - nested.execute(new JobExecution(1L)); - assertEquals(4, TestAdvice.names.size()); - assertEquals("bar", TestAdvice.names.get(0)); - assertEquals(1, StringUtils.countOccurrencesOf(TestDisposableCollaborator.message, "destroyed")); - } - - @Test - public void testRefScopedProxy() throws Exception { - assertNotNull(ref); - ref.execute(new JobExecution(1L)); - assertEquals(4, TestAdvice.names.size()); - assertEquals("spam", TestAdvice.names.get(0)); - assertEquals(2, StringUtils.countOccurrencesOf(TestDisposableCollaborator.message, "destroyed")); - assertEquals(1, StringUtils.countOccurrencesOf(TestDisposableCollaborator.message, "bar:destroyed")); - assertEquals(1, StringUtils.countOccurrencesOf(TestDisposableCollaborator.message, "spam:destroyed")); - } - - @Test - public void testProxiedNormalBean() throws Exception { - assertNotNull(nested); - String name = foo.getName(); - assertEquals(1, TestAdvice.names.size()); - assertEquals(name, TestAdvice.names.get(0)); - } - -} +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.Job; +import org.springframework.batch.core.JobExecution; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.util.StringUtils; + +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class JobScopeDestructionCallbackIntegrationTests { + + @Autowired + @Qualifier("proxied") + private Job proxied; + + @Autowired + @Qualifier("nested") + private Job nested; + + @Autowired + @Qualifier("ref") + private Job ref; + + @Autowired + @Qualifier("foo") + private Collaborator foo; + + @Before + @After + public void resetMessage() throws Exception { + TestDisposableCollaborator.message = "none"; + TestAdvice.names.clear(); + } + + @Test + public void testDisposableScopedProxy() throws Exception { + assertNotNull(proxied); + proxied.execute(new JobExecution(1L)); + assertEquals(1, StringUtils.countOccurrencesOf(TestDisposableCollaborator.message, "destroyed")); + } + + @Test + public void testDisposableInnerScopedProxy() throws Exception { + assertNotNull(nested); + nested.execute(new JobExecution(1L)); + assertEquals(1, StringUtils.countOccurrencesOf(TestDisposableCollaborator.message, "destroyed")); + } + + @Test + public void testProxiedScopedProxy() throws Exception { + assertNotNull(nested); + nested.execute(new JobExecution(1L)); + assertEquals(4, TestAdvice.names.size()); + assertEquals("bar", TestAdvice.names.get(0)); + assertEquals(1, StringUtils.countOccurrencesOf(TestDisposableCollaborator.message, "destroyed")); + } + + @Test + public void testRefScopedProxy() throws Exception { + assertNotNull(ref); + ref.execute(new JobExecution(1L)); + assertEquals(4, TestAdvice.names.size()); + assertEquals("spam", TestAdvice.names.get(0)); + assertEquals(2, StringUtils.countOccurrencesOf(TestDisposableCollaborator.message, "destroyed")); + assertEquals(1, StringUtils.countOccurrencesOf(TestDisposableCollaborator.message, "bar:destroyed")); + assertEquals(1, StringUtils.countOccurrencesOf(TestDisposableCollaborator.message, "spam:destroyed")); + } + + @Test + public void testProxiedNormalBean() throws Exception { + assertNotNull(nested); + String name = foo.getName(); + assertEquals(1, TestAdvice.names.size()); + assertEquals(name, TestAdvice.names.get(0)); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/JobScopeIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/JobScopeIntegrationTests.java index 8dd863a29..2d5075b9d 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/JobScopeIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/JobScopeIntegrationTests.java @@ -1,132 +1,132 @@ -/* - * Copyright 2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.scope.context.JobSynchronizationManager; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -public class JobScopeIntegrationTests { - - private static final String PROXY_TO_STRING_REGEX = "class .*\\$Proxy\\d+"; - - @Autowired - @Qualifier("vanilla") - private Job vanilla; - - @Autowired - @Qualifier("proxied") - private Job proxied; - - @Autowired - @Qualifier("nested") - private Job nested; - - @Autowired - @Qualifier("enhanced") - private Job enhanced; - - @Autowired - @Qualifier("double") - private Job doubleEnhanced; - - @Before - @After - public void start() { - JobSynchronizationManager.close(); - TestJob.reset(); - } - - @Test - public void testScopeCreation() throws Exception { - vanilla.execute(new JobExecution(11L)); - assertNotNull(TestJob.getContext()); - assertNull(JobSynchronizationManager.getContext()); - } - - @Test - public void testScopedProxy() throws Exception { - proxied.execute(new JobExecution(11L)); - assertTrue(TestJob.getContext().attributeNames().length > 0); - String collaborator = (String) TestJob.getContext().getAttribute("collaborator"); - assertNotNull(collaborator); - assertEquals("bar", collaborator); - assertTrue("Scoped proxy not created", ((String) TestJob.getContext().getAttribute("collaborator.class")) - .matches(PROXY_TO_STRING_REGEX)); - } - - @Test - public void testNestedScopedProxy() throws Exception { - nested.execute(new JobExecution(11L)); - assertTrue(TestJob.getContext().attributeNames().length > 0); - String collaborator = (String) TestJob.getContext().getAttribute("collaborator"); - assertNotNull(collaborator); - assertEquals("foo", collaborator); - String parent = (String) TestJob.getContext().getAttribute("parent"); - assertNotNull(parent); - assertEquals("bar", parent); - assertTrue("Scoped proxy not created", ((String) TestJob.getContext().getAttribute("parent.class")) - .matches(PROXY_TO_STRING_REGEX)); - } - - @Test - public void testExecutionContext() throws Exception { - JobExecution stepExecution = new JobExecution(11L); - ExecutionContext executionContext = new ExecutionContext(); - executionContext.put("name", "spam"); - stepExecution.setExecutionContext(executionContext); - proxied.execute(stepExecution); - assertTrue(TestJob.getContext().attributeNames().length > 0); - String collaborator = (String) TestJob.getContext().getAttribute("collaborator"); - assertNotNull(collaborator); - assertEquals("bar", collaborator); - } - - @Test - public void testScopedProxyForReference() throws Exception { - enhanced.execute(new JobExecution(11L)); - assertTrue(TestJob.getContext().attributeNames().length > 0); - String collaborator = (String) TestJob.getContext().getAttribute("collaborator"); - assertNotNull(collaborator); - assertEquals("bar", collaborator); - } - - @Test - public void testScopedProxyForSecondReference() throws Exception { - doubleEnhanced.execute(new JobExecution(11L)); - assertTrue(TestJob.getContext().attributeNames().length > 0); - String collaborator = (String) TestJob.getContext().getAttribute("collaborator"); - assertNotNull(collaborator); - assertEquals("bar", collaborator); - } - -} +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.Job; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.scope.context.JobSynchronizationManager; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class JobScopeIntegrationTests { + + private static final String PROXY_TO_STRING_REGEX = "class .*\\$Proxy\\d+"; + + @Autowired + @Qualifier("vanilla") + private Job vanilla; + + @Autowired + @Qualifier("proxied") + private Job proxied; + + @Autowired + @Qualifier("nested") + private Job nested; + + @Autowired + @Qualifier("enhanced") + private Job enhanced; + + @Autowired + @Qualifier("double") + private Job doubleEnhanced; + + @Before + @After + public void start() { + JobSynchronizationManager.close(); + TestJob.reset(); + } + + @Test + public void testScopeCreation() throws Exception { + vanilla.execute(new JobExecution(11L)); + assertNotNull(TestJob.getContext()); + assertNull(JobSynchronizationManager.getContext()); + } + + @Test + public void testScopedProxy() throws Exception { + proxied.execute(new JobExecution(11L)); + assertTrue(TestJob.getContext().attributeNames().length > 0); + String collaborator = (String) TestJob.getContext().getAttribute("collaborator"); + assertNotNull(collaborator); + assertEquals("bar", collaborator); + assertTrue("Scoped proxy not created", + ((String) TestJob.getContext().getAttribute("collaborator.class")).matches(PROXY_TO_STRING_REGEX)); + } + + @Test + public void testNestedScopedProxy() throws Exception { + nested.execute(new JobExecution(11L)); + assertTrue(TestJob.getContext().attributeNames().length > 0); + String collaborator = (String) TestJob.getContext().getAttribute("collaborator"); + assertNotNull(collaborator); + assertEquals("foo", collaborator); + String parent = (String) TestJob.getContext().getAttribute("parent"); + assertNotNull(parent); + assertEquals("bar", parent); + assertTrue("Scoped proxy not created", + ((String) TestJob.getContext().getAttribute("parent.class")).matches(PROXY_TO_STRING_REGEX)); + } + + @Test + public void testExecutionContext() throws Exception { + JobExecution stepExecution = new JobExecution(11L); + ExecutionContext executionContext = new ExecutionContext(); + executionContext.put("name", "spam"); + stepExecution.setExecutionContext(executionContext); + proxied.execute(stepExecution); + assertTrue(TestJob.getContext().attributeNames().length > 0); + String collaborator = (String) TestJob.getContext().getAttribute("collaborator"); + assertNotNull(collaborator); + assertEquals("bar", collaborator); + } + + @Test + public void testScopedProxyForReference() throws Exception { + enhanced.execute(new JobExecution(11L)); + assertTrue(TestJob.getContext().attributeNames().length > 0); + String collaborator = (String) TestJob.getContext().getAttribute("collaborator"); + assertNotNull(collaborator); + assertEquals("bar", collaborator); + } + + @Test + public void testScopedProxyForSecondReference() throws Exception { + doubleEnhanced.execute(new JobExecution(11L)); + assertTrue(TestJob.getContext().attributeNames().length > 0); + String collaborator = (String) TestJob.getContext().getAttribute("collaborator"); + assertNotNull(collaborator); + assertEquals("bar", collaborator); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/JobScopeNestedIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/JobScopeNestedIntegrationTests.java index f82fafb83..f60571b51 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/JobScopeNestedIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/JobScopeNestedIntegrationTests.java @@ -1,48 +1,47 @@ -/* - * Copyright 2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.Job; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - - -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -public class JobScopeNestedIntegrationTests { - - @Autowired - @Qualifier("proxied") - private Job proxied; - - @Autowired - @Qualifier("parent") - private Collaborator parent; - - @Test - public void testNestedScopedProxy() throws Exception { - assertNotNull(proxied); - assertEquals("foo", parent.getName()); - } - -} +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.Job; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class JobScopeNestedIntegrationTests { + + @Autowired + @Qualifier("proxied") + private Job proxied; + + @Autowired + @Qualifier("parent") + private Collaborator parent; + + @Test + public void testNestedScopedProxy() throws Exception { + assertNotNull(proxied); + assertEquals("foo", parent.getName()); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/JobScopePlaceholderIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/JobScopePlaceholderIntegrationTests.java index dab3bc90b..a58e4c338 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/JobScopePlaceholderIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/JobScopePlaceholderIntegrationTests.java @@ -1,171 +1,171 @@ -/* - * Copyright 2013-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope; - -import static org.junit.Assert.assertEquals; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.scope.context.JobSynchronizationManager; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.BeanFactoryAware; -import org.springframework.beans.factory.ListableBeanFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -public class JobScopePlaceholderIntegrationTests implements BeanFactoryAware { - - @Autowired - @Qualifier("simple") - private Collaborator simple; - - @Autowired - @Qualifier("compound") - private Collaborator compound; - - @Autowired - @Qualifier("value") - private Collaborator value; - - @Autowired - @Qualifier("ref") - private Collaborator ref; - - @Autowired - @Qualifier("scopedRef") - private Collaborator scopedRef; - - @Autowired - @Qualifier("list") - private Collaborator list; - - @Autowired - @Qualifier("bar") - private Collaborator bar; - - @Autowired - @Qualifier("nested") - private Collaborator nested; - - private JobExecution jobExecution; - - private ListableBeanFactory beanFactory; - - private int beanCount; - - @Override - public void setBeanFactory(BeanFactory beanFactory) throws BeansException { - this.beanFactory = (ListableBeanFactory) beanFactory; - } - - @Before - public void start() { - start("bar"); - } - - private void start(String foo) { - - JobSynchronizationManager.close(); - jobExecution = new JobExecution(123L); - - ExecutionContext executionContext = new ExecutionContext(); - executionContext.put("foo", foo); - executionContext.put("parent", bar); - - jobExecution.setExecutionContext(executionContext); - JobSynchronizationManager.register(jobExecution); - - beanCount = beanFactory.getBeanDefinitionCount(); - - } - - @After - public void stop() { - JobSynchronizationManager.close(); - // Check that all temporary bean definitions are cleaned up - assertEquals(beanCount, beanFactory.getBeanDefinitionCount()); - } - - @Test - public void testSimpleProperty() throws Exception { - assertEquals("bar", simple.getName()); - // Once the job context is set up it should be baked into the proxies - // so changing it now should have no effect - jobExecution.getExecutionContext().put("foo", "wrong!"); - assertEquals("bar", simple.getName()); - } - - @Test - public void testCompoundProperty() throws Exception { - assertEquals("bar-bar", compound.getName()); - } - - @Test - public void testCompoundPropertyTwice() throws Exception { - - assertEquals("bar-bar", compound.getName()); - - JobSynchronizationManager.close(); - jobExecution = new JobExecution(123L); - - ExecutionContext executionContext = new ExecutionContext(); - executionContext.put("foo", "spam"); - - jobExecution.setExecutionContext(executionContext); - JobSynchronizationManager.register(jobExecution); - - assertEquals("spam-bar", compound.getName()); - - } - - @Test - public void testParentByRef() throws Exception { - assertEquals("bar", ref.getParent().getName()); - } - - @Test - public void testParentByValue() throws Exception { - assertEquals("bar", value.getParent().getName()); - } - - @Test - public void testList() throws Exception { - assertEquals("[bar]", list.getList().toString()); - } - - @Test - public void testNested() throws Exception { - assertEquals("bar", nested.getParent().getName()); - } - - @Test - public void testScopedRef() throws Exception { - assertEquals("bar", scopedRef.getParent().getName()); - stop(); - start("spam"); - assertEquals("spam", scopedRef.getParent().getName()); - } - -} +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope; + +import static org.junit.Assert.assertEquals; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.scope.context.JobSynchronizationManager; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.beans.factory.ListableBeanFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class JobScopePlaceholderIntegrationTests implements BeanFactoryAware { + + @Autowired + @Qualifier("simple") + private Collaborator simple; + + @Autowired + @Qualifier("compound") + private Collaborator compound; + + @Autowired + @Qualifier("value") + private Collaborator value; + + @Autowired + @Qualifier("ref") + private Collaborator ref; + + @Autowired + @Qualifier("scopedRef") + private Collaborator scopedRef; + + @Autowired + @Qualifier("list") + private Collaborator list; + + @Autowired + @Qualifier("bar") + private Collaborator bar; + + @Autowired + @Qualifier("nested") + private Collaborator nested; + + private JobExecution jobExecution; + + private ListableBeanFactory beanFactory; + + private int beanCount; + + @Override + public void setBeanFactory(BeanFactory beanFactory) throws BeansException { + this.beanFactory = (ListableBeanFactory) beanFactory; + } + + @Before + public void start() { + start("bar"); + } + + private void start(String foo) { + + JobSynchronizationManager.close(); + jobExecution = new JobExecution(123L); + + ExecutionContext executionContext = new ExecutionContext(); + executionContext.put("foo", foo); + executionContext.put("parent", bar); + + jobExecution.setExecutionContext(executionContext); + JobSynchronizationManager.register(jobExecution); + + beanCount = beanFactory.getBeanDefinitionCount(); + + } + + @After + public void stop() { + JobSynchronizationManager.close(); + // Check that all temporary bean definitions are cleaned up + assertEquals(beanCount, beanFactory.getBeanDefinitionCount()); + } + + @Test + public void testSimpleProperty() throws Exception { + assertEquals("bar", simple.getName()); + // Once the job context is set up it should be baked into the proxies + // so changing it now should have no effect + jobExecution.getExecutionContext().put("foo", "wrong!"); + assertEquals("bar", simple.getName()); + } + + @Test + public void testCompoundProperty() throws Exception { + assertEquals("bar-bar", compound.getName()); + } + + @Test + public void testCompoundPropertyTwice() throws Exception { + + assertEquals("bar-bar", compound.getName()); + + JobSynchronizationManager.close(); + jobExecution = new JobExecution(123L); + + ExecutionContext executionContext = new ExecutionContext(); + executionContext.put("foo", "spam"); + + jobExecution.setExecutionContext(executionContext); + JobSynchronizationManager.register(jobExecution); + + assertEquals("spam-bar", compound.getName()); + + } + + @Test + public void testParentByRef() throws Exception { + assertEquals("bar", ref.getParent().getName()); + } + + @Test + public void testParentByValue() throws Exception { + assertEquals("bar", value.getParent().getName()); + } + + @Test + public void testList() throws Exception { + assertEquals("[bar]", list.getList().toString()); + } + + @Test + public void testNested() throws Exception { + assertEquals("bar", nested.getParent().getName()); + } + + @Test + public void testScopedRef() throws Exception { + assertEquals("bar", scopedRef.getParent().getName()); + stop(); + start("spam"); + assertEquals("spam", scopedRef.getParent().getName()); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/JobScopeProxyTargetClassIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/JobScopeProxyTargetClassIntegrationTests.java index 9005273e3..082b2f4ca 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/JobScopeProxyTargetClassIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/JobScopeProxyTargetClassIntegrationTests.java @@ -1,87 +1,87 @@ -/* - * Copyright 2013-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope; - -import static org.junit.Assert.assertEquals; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.scope.context.JobSynchronizationManager; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.BeanFactoryAware; -import org.springframework.beans.factory.ListableBeanFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -public class JobScopeProxyTargetClassIntegrationTests implements BeanFactoryAware { - - @Autowired - @Qualifier("simple") - private TestCollaborator simple; - - private JobExecution jobExecution; - - private ListableBeanFactory beanFactory; - - private int beanCount; - - @Override - public void setBeanFactory(BeanFactory beanFactory) throws BeansException { - this.beanFactory = (ListableBeanFactory) beanFactory; - } - - @Before - public void start() { - - JobSynchronizationManager.close(); - jobExecution = new JobExecution(123L); - - ExecutionContext executionContext = new ExecutionContext(); - executionContext.put("foo", "bar"); - - jobExecution.setExecutionContext(executionContext); - JobSynchronizationManager.register(jobExecution); - - beanCount = beanFactory.getBeanDefinitionCount(); - - } - - @After - public void cleanUp() { - JobSynchronizationManager.close(); - // Check that all temporary bean definitions are cleaned up - assertEquals(beanCount, beanFactory.getBeanDefinitionCount()); - } - - @Test - public void testSimpleProperty() throws Exception { - assertEquals("bar", simple.getName()); - // Once the job context is set up it should be baked into the proxies - // so changing it now should have no effect - jobExecution.getExecutionContext().put("foo", "wrong!"); - assertEquals("bar", simple.getName()); - } - -} +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope; + +import static org.junit.Assert.assertEquals; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.scope.context.JobSynchronizationManager; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.beans.factory.ListableBeanFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class JobScopeProxyTargetClassIntegrationTests implements BeanFactoryAware { + + @Autowired + @Qualifier("simple") + private TestCollaborator simple; + + private JobExecution jobExecution; + + private ListableBeanFactory beanFactory; + + private int beanCount; + + @Override + public void setBeanFactory(BeanFactory beanFactory) throws BeansException { + this.beanFactory = (ListableBeanFactory) beanFactory; + } + + @Before + public void start() { + + JobSynchronizationManager.close(); + jobExecution = new JobExecution(123L); + + ExecutionContext executionContext = new ExecutionContext(); + executionContext.put("foo", "bar"); + + jobExecution.setExecutionContext(executionContext); + JobSynchronizationManager.register(jobExecution); + + beanCount = beanFactory.getBeanDefinitionCount(); + + } + + @After + public void cleanUp() { + JobSynchronizationManager.close(); + // Check that all temporary bean definitions are cleaned up + assertEquals(beanCount, beanFactory.getBeanDefinitionCount()); + } + + @Test + public void testSimpleProperty() throws Exception { + assertEquals("bar", simple.getName()); + // Once the job context is set up it should be baked into the proxies + // so changing it now should have no effect + jobExecution.getExecutionContext().put("foo", "wrong!"); + assertEquals("bar", simple.getName()); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/JobScopeStartupIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/JobScopeStartupIntegrationTests.java index 6119d8c35..7ba25f7ec 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/JobScopeStartupIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/JobScopeStartupIntegrationTests.java @@ -1,32 +1,31 @@ -/* - * Copyright 2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - - -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -public class JobScopeStartupIntegrationTests { - - @Test - public void testScopedProxyDuringStartup() throws Exception { - } - -} +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class JobScopeStartupIntegrationTests { + + @Test + public void testScopedProxyDuringStartup() throws Exception { + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/JobScopeTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/JobScopeTests.java index 49fd282c4..b45c0d4b9 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/JobScopeTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/JobScopeTests.java @@ -1,175 +1,175 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.scope.context.JobContext; -import org.springframework.batch.core.scope.context.JobSynchronizationManager; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.ObjectFactory; -import org.springframework.context.support.StaticApplicationContext; - -/** - * @author Dave Syer - * @author Jimmy Praet - */ -public class JobScopeTests { - - private JobScope scope = new JobScope(); - - private JobExecution jobExecution = new JobExecution(0L); - - private JobContext context; - - @Before - public void setUp() throws Exception { - context = JobSynchronizationManager.register(jobExecution); - } - - @After - public void tearDown() throws Exception { - JobSynchronizationManager.release(); - } - - @Test - public void testGetWithNoContext() throws Exception { - final String foo = "bar"; - JobSynchronizationManager.release(); - try { - scope.get("foo", new ObjectFactory() { - @Override - public String getObject() throws BeansException { - return foo; - } - }); - fail("Expected IllegalStateException"); - } - catch (IllegalStateException e) { - // expected - } - - } - - @Test - public void testGetWithNothingAlreadyThere() { - final String foo = "bar"; - Object value = scope.get("foo", new ObjectFactory() { - @Override - public String getObject() throws BeansException { - return foo; - } - }); - assertEquals(foo, value); - assertTrue(context.hasAttribute("foo")); - } - - @Test - public void testGetWithSomethingAlreadyThere() { - context.setAttribute("foo", "bar"); - Object value = scope.get("foo", new ObjectFactory() { - @Override - public String getObject() throws BeansException { - return null; - } - }); - assertEquals("bar", value); - assertTrue(context.hasAttribute("foo")); - } - - @Test - public void testGetConversationId() { - String id = scope.getConversationId(); - assertNotNull(id); - } - - @Test - public void testRegisterDestructionCallback() { - final List list = new ArrayList<>(); - context.setAttribute("foo", "bar"); - scope.registerDestructionCallback("foo", new Runnable() { - @Override - public void run() { - list.add("foo"); - } - }); - assertEquals(0, list.size()); - // When the context is closed, provided the attribute exists the - // callback is called... - context.close(); - assertEquals(1, list.size()); - } - - @Test - public void testRegisterAnotherDestructionCallback() { - final List list = new ArrayList<>(); - context.setAttribute("foo", "bar"); - scope.registerDestructionCallback("foo", new Runnable() { - @Override - public void run() { - list.add("foo"); - } - }); - scope.registerDestructionCallback("foo", new Runnable() { - @Override - public void run() { - list.add("bar"); - } - }); - assertEquals(0, list.size()); - // When the context is closed, provided the attribute exists the - // callback is called... - context.close(); - assertEquals(2, list.size()); - } - - @Test - public void testRemove() { - context.setAttribute("foo", "bar"); - scope.remove("foo"); - assertFalse(context.hasAttribute("foo")); - } - - @Test - public void testOrder() throws Exception { - assertEquals(Integer.MAX_VALUE, scope.getOrder()); - scope.setOrder(11); - assertEquals(11, scope.getOrder()); - } - - @Test - @SuppressWarnings("resource") - public void testName() throws Exception { - scope.setName("foo"); - StaticApplicationContext beanFactory = new StaticApplicationContext(); - scope.postProcessBeanFactory(beanFactory.getDefaultListableBeanFactory()); - String[] scopes = beanFactory.getDefaultListableBeanFactory().getRegisteredScopeNames(); - assertEquals(1, scopes.length); - assertEquals("foo", scopes[0]); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.scope.context.JobContext; +import org.springframework.batch.core.scope.context.JobSynchronizationManager; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.ObjectFactory; +import org.springframework.context.support.StaticApplicationContext; + +/** + * @author Dave Syer + * @author Jimmy Praet + */ +public class JobScopeTests { + + private JobScope scope = new JobScope(); + + private JobExecution jobExecution = new JobExecution(0L); + + private JobContext context; + + @Before + public void setUp() throws Exception { + context = JobSynchronizationManager.register(jobExecution); + } + + @After + public void tearDown() throws Exception { + JobSynchronizationManager.release(); + } + + @Test + public void testGetWithNoContext() throws Exception { + final String foo = "bar"; + JobSynchronizationManager.release(); + try { + scope.get("foo", new ObjectFactory() { + @Override + public String getObject() throws BeansException { + return foo; + } + }); + fail("Expected IllegalStateException"); + } + catch (IllegalStateException e) { + // expected + } + + } + + @Test + public void testGetWithNothingAlreadyThere() { + final String foo = "bar"; + Object value = scope.get("foo", new ObjectFactory() { + @Override + public String getObject() throws BeansException { + return foo; + } + }); + assertEquals(foo, value); + assertTrue(context.hasAttribute("foo")); + } + + @Test + public void testGetWithSomethingAlreadyThere() { + context.setAttribute("foo", "bar"); + Object value = scope.get("foo", new ObjectFactory() { + @Override + public String getObject() throws BeansException { + return null; + } + }); + assertEquals("bar", value); + assertTrue(context.hasAttribute("foo")); + } + + @Test + public void testGetConversationId() { + String id = scope.getConversationId(); + assertNotNull(id); + } + + @Test + public void testRegisterDestructionCallback() { + final List list = new ArrayList<>(); + context.setAttribute("foo", "bar"); + scope.registerDestructionCallback("foo", new Runnable() { + @Override + public void run() { + list.add("foo"); + } + }); + assertEquals(0, list.size()); + // When the context is closed, provided the attribute exists the + // callback is called... + context.close(); + assertEquals(1, list.size()); + } + + @Test + public void testRegisterAnotherDestructionCallback() { + final List list = new ArrayList<>(); + context.setAttribute("foo", "bar"); + scope.registerDestructionCallback("foo", new Runnable() { + @Override + public void run() { + list.add("foo"); + } + }); + scope.registerDestructionCallback("foo", new Runnable() { + @Override + public void run() { + list.add("bar"); + } + }); + assertEquals(0, list.size()); + // When the context is closed, provided the attribute exists the + // callback is called... + context.close(); + assertEquals(2, list.size()); + } + + @Test + public void testRemove() { + context.setAttribute("foo", "bar"); + scope.remove("foo"); + assertFalse(context.hasAttribute("foo")); + } + + @Test + public void testOrder() throws Exception { + assertEquals(Integer.MAX_VALUE, scope.getOrder()); + scope.setOrder(11); + assertEquals(11, scope.getOrder()); + } + + @Test + @SuppressWarnings("resource") + public void testName() throws Exception { + scope.setName("foo"); + StaticApplicationContext beanFactory = new StaticApplicationContext(); + scope.postProcessBeanFactory(beanFactory.getDefaultListableBeanFactory()); + String[] scopes = beanFactory.getDefaultListableBeanFactory().getRegisteredScopeNames(); + assertEquals(1, scopes.length); + assertEquals("foo", scopes[0]); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/JobStartupRunner.java b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/JobStartupRunner.java index 903899b43..fd9162271 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/JobStartupRunner.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/JobStartupRunner.java @@ -1,37 +1,37 @@ -/* - * Copyright 2008-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope; - -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.beans.factory.InitializingBean; - -public class JobStartupRunner implements InitializingBean { - - private Job job; - - public void setJob(Job job) { - this.job = job; - } - - @Override - public void afterPropertiesSet() throws Exception { - JobExecution jobExecution = new JobExecution(11L); - job.execute(jobExecution); - // expect no errors - } - -} +/* + * Copyright 2008-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope; + +import org.springframework.batch.core.Job; +import org.springframework.batch.core.JobExecution; +import org.springframework.beans.factory.InitializingBean; + +public class JobStartupRunner implements InitializingBean { + + private Job job; + + public void setJob(Job job) { + this.job = job; + } + + @Override + public void afterPropertiesSet() throws Exception { + JobExecution jobExecution = new JobExecution(11L); + job.execute(jobExecution); + // expect no errors + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopeClassIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopeClassIntegrationTests.java index 0bdbd7529..ce053d333 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopeClassIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopeClassIntegrationTests.java @@ -1,101 +1,100 @@ -/* - * Copyright 2010-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope; - -import static org.junit.Assert.assertEquals; - -import org.junit.After; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.scope.context.StepSynchronizationManager; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.BeanFactoryAware; -import org.springframework.beans.factory.ListableBeanFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -@Ignore // Maybe one day support class replacement? -public class StepScopeClassIntegrationTests implements BeanFactoryAware { - - - @Autowired - @Qualifier("value") - private Collaborator value; - - @Autowired - @Qualifier("nested") - private Collaborator nested; - - private StepExecution stepExecution; - - private ListableBeanFactory beanFactory; - - private int beanCount; - - @Override - public void setBeanFactory(BeanFactory beanFactory) throws BeansException { - this.beanFactory = (ListableBeanFactory) beanFactory; - } - - @Before - public void start() { - start("bar"); - } - - private void start(String foo) { - - StepSynchronizationManager.close(); - stepExecution = new StepExecution("foo", new JobExecution(11L), 123L); - - ExecutionContext executionContext = new ExecutionContext(); - executionContext.put("foo", foo); - executionContext.put("type", TestCollaborator.class.getName()); - - stepExecution.setExecutionContext(executionContext); - StepSynchronizationManager.register(stepExecution); - - beanCount = beanFactory.getBeanDefinitionCount(); - - } - - @After - public void stop() { - StepSynchronizationManager.close(); - // Check that all temporary bean definitions are cleaned up - assertEquals(beanCount, beanFactory.getBeanDefinitionCount()); - } - - @Test - public void testSimpleValue() throws Exception { - assertEquals("foo", value.getName()); - } - - @Test - public void testNested() throws Exception { - assertEquals("bar", nested.getParent().getName()); - } - -} +/* + * Copyright 2010-2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope; + +import static org.junit.Assert.assertEquals; + +import org.junit.After; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.scope.context.StepSynchronizationManager; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.beans.factory.ListableBeanFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +@Ignore // Maybe one day support class replacement? +public class StepScopeClassIntegrationTests implements BeanFactoryAware { + + @Autowired + @Qualifier("value") + private Collaborator value; + + @Autowired + @Qualifier("nested") + private Collaborator nested; + + private StepExecution stepExecution; + + private ListableBeanFactory beanFactory; + + private int beanCount; + + @Override + public void setBeanFactory(BeanFactory beanFactory) throws BeansException { + this.beanFactory = (ListableBeanFactory) beanFactory; + } + + @Before + public void start() { + start("bar"); + } + + private void start(String foo) { + + StepSynchronizationManager.close(); + stepExecution = new StepExecution("foo", new JobExecution(11L), 123L); + + ExecutionContext executionContext = new ExecutionContext(); + executionContext.put("foo", foo); + executionContext.put("type", TestCollaborator.class.getName()); + + stepExecution.setExecutionContext(executionContext); + StepSynchronizationManager.register(stepExecution); + + beanCount = beanFactory.getBeanDefinitionCount(); + + } + + @After + public void stop() { + StepSynchronizationManager.close(); + // Check that all temporary bean definitions are cleaned up + assertEquals(beanCount, beanFactory.getBeanDefinitionCount()); + } + + @Test + public void testSimpleValue() throws Exception { + assertEquals("foo", value.getName()); + } + + @Test + public void testNested() throws Exception { + assertEquals("bar", nested.getParent().getName()); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopeDestructionCallbackIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopeDestructionCallbackIntegrationTests.java index b6c03de6f..58e261027 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopeDestructionCallbackIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopeDestructionCallbackIntegrationTests.java @@ -1,103 +1,103 @@ -/* - * Copyright 2008-2010 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.Step; -import org.springframework.batch.core.StepExecution; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.util.StringUtils; - -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -public class StepScopeDestructionCallbackIntegrationTests { - - @Autowired - @Qualifier("proxied") - private Step proxied; - - @Autowired - @Qualifier("nested") - private Step nested; - - @Autowired - @Qualifier("ref") - private Step ref; - - @Autowired - @Qualifier("foo") - private Collaborator foo; - - @Before - @After - public void resetMessage() throws Exception { - TestDisposableCollaborator.message = "none"; - TestAdvice.names.clear(); - } - - @Test - public void testDisposableScopedProxy() throws Exception { - assertNotNull(proxied); - proxied.execute(new StepExecution("step", new JobExecution(0L), 1L)); - assertEquals(1, StringUtils.countOccurrencesOf(TestDisposableCollaborator.message, "destroyed")); - } - - @Test - public void testDisposableInnerScopedProxy() throws Exception { - assertNotNull(nested); - nested.execute(new StepExecution("step", new JobExecution(0L), 1L)); - assertEquals(1, StringUtils.countOccurrencesOf(TestDisposableCollaborator.message, "destroyed")); - } - - @Test - public void testProxiedScopedProxy() throws Exception { - assertNotNull(nested); - nested.execute(new StepExecution("step", new JobExecution(0L), 1L)); - assertEquals(4, TestAdvice.names.size()); - assertEquals("bar", TestAdvice.names.get(0)); - assertEquals(1, StringUtils.countOccurrencesOf(TestDisposableCollaborator.message, "destroyed")); - } - - @Test - public void testRefScopedProxy() throws Exception { - assertNotNull(ref); - ref.execute(new StepExecution("step", new JobExecution(0L), 1L)); - assertEquals(4, TestAdvice.names.size()); - assertEquals("spam", TestAdvice.names.get(0)); - assertEquals(2, StringUtils.countOccurrencesOf(TestDisposableCollaborator.message, "destroyed")); - assertEquals(1, StringUtils.countOccurrencesOf(TestDisposableCollaborator.message, "bar:destroyed")); - assertEquals(1, StringUtils.countOccurrencesOf(TestDisposableCollaborator.message, "spam:destroyed")); - } - - @Test - public void testProxiedNormalBean() throws Exception { - assertNotNull(nested); - String name = foo.getName(); - assertEquals(1, TestAdvice.names.size()); - assertEquals(name, TestAdvice.names.get(0)); - } - -} +/* + * Copyright 2008-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.Step; +import org.springframework.batch.core.StepExecution; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.util.StringUtils; + +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class StepScopeDestructionCallbackIntegrationTests { + + @Autowired + @Qualifier("proxied") + private Step proxied; + + @Autowired + @Qualifier("nested") + private Step nested; + + @Autowired + @Qualifier("ref") + private Step ref; + + @Autowired + @Qualifier("foo") + private Collaborator foo; + + @Before + @After + public void resetMessage() throws Exception { + TestDisposableCollaborator.message = "none"; + TestAdvice.names.clear(); + } + + @Test + public void testDisposableScopedProxy() throws Exception { + assertNotNull(proxied); + proxied.execute(new StepExecution("step", new JobExecution(0L), 1L)); + assertEquals(1, StringUtils.countOccurrencesOf(TestDisposableCollaborator.message, "destroyed")); + } + + @Test + public void testDisposableInnerScopedProxy() throws Exception { + assertNotNull(nested); + nested.execute(new StepExecution("step", new JobExecution(0L), 1L)); + assertEquals(1, StringUtils.countOccurrencesOf(TestDisposableCollaborator.message, "destroyed")); + } + + @Test + public void testProxiedScopedProxy() throws Exception { + assertNotNull(nested); + nested.execute(new StepExecution("step", new JobExecution(0L), 1L)); + assertEquals(4, TestAdvice.names.size()); + assertEquals("bar", TestAdvice.names.get(0)); + assertEquals(1, StringUtils.countOccurrencesOf(TestDisposableCollaborator.message, "destroyed")); + } + + @Test + public void testRefScopedProxy() throws Exception { + assertNotNull(ref); + ref.execute(new StepExecution("step", new JobExecution(0L), 1L)); + assertEquals(4, TestAdvice.names.size()); + assertEquals("spam", TestAdvice.names.get(0)); + assertEquals(2, StringUtils.countOccurrencesOf(TestDisposableCollaborator.message, "destroyed")); + assertEquals(1, StringUtils.countOccurrencesOf(TestDisposableCollaborator.message, "bar:destroyed")); + assertEquals(1, StringUtils.countOccurrencesOf(TestDisposableCollaborator.message, "spam:destroyed")); + } + + @Test + public void testProxiedNormalBean() throws Exception { + assertNotNull(nested); + String name = foo.getName(); + assertEquals(1, TestAdvice.names.size()); + assertEquals(name, TestAdvice.names.get(0)); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopeIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopeIntegrationTests.java index 585ea0232..a0ea85f02 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopeIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopeIntegrationTests.java @@ -1,133 +1,133 @@ -/* - * Copyright 2008-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.Step; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.scope.context.StepSynchronizationManager; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -public class StepScopeIntegrationTests { - - private static final String PROXY_TO_STRING_REGEX = "class .*\\$Proxy\\d+"; - - @Autowired - @Qualifier("vanilla") - private Step vanilla; - - @Autowired - @Qualifier("proxied") - private Step proxied; - - @Autowired - @Qualifier("nested") - private Step nested; - - @Autowired - @Qualifier("enhanced") - private Step enhanced; - - @Autowired - @Qualifier("double") - private Step doubleEnhanced; - - @Before - @After - public void start() { - StepSynchronizationManager.close(); - TestStep.reset(); - } - - @Test - public void testScopeCreation() throws Exception { - vanilla.execute(new StepExecution("foo", new JobExecution(11L), 12L)); - assertNotNull(TestStep.getContext()); - assertNull(StepSynchronizationManager.getContext()); - } - - @Test - public void testScopedProxy() throws Exception { - proxied.execute(new StepExecution("foo", new JobExecution(11L), 31L)); - assertTrue(TestStep.getContext().attributeNames().length > 0); - String collaborator = (String) TestStep.getContext().getAttribute("collaborator"); - assertNotNull(collaborator); - assertEquals("bar", collaborator); - assertTrue("Scoped proxy not created", ((String) TestStep.getContext().getAttribute("collaborator.class")) - .matches(PROXY_TO_STRING_REGEX)); - } - - @Test - public void testNestedScopedProxy() throws Exception { - nested.execute(new StepExecution("foo", new JobExecution(11L), 31L)); - assertTrue(TestStep.getContext().attributeNames().length > 0); - String collaborator = (String) TestStep.getContext().getAttribute("collaborator"); - assertNotNull(collaborator); - assertEquals("foo", collaborator); - String parent = (String) TestStep.getContext().getAttribute("parent"); - assertNotNull(parent); - assertEquals("bar", parent); - assertTrue("Scoped proxy not created", ((String) TestStep.getContext().getAttribute("parent.class")) - .matches(PROXY_TO_STRING_REGEX)); - } - - @Test - public void testExecutionContext() throws Exception { - StepExecution stepExecution = new StepExecution("foo", new JobExecution(11L), 1L); - ExecutionContext executionContext = new ExecutionContext(); - executionContext.put("name", "spam"); - stepExecution.setExecutionContext(executionContext); - proxied.execute(stepExecution); - assertTrue(TestStep.getContext().attributeNames().length > 0); - String collaborator = (String) TestStep.getContext().getAttribute("collaborator"); - assertNotNull(collaborator); - assertEquals("bar", collaborator); - } - - @Test - public void testScopedProxyForReference() throws Exception { - enhanced.execute(new StepExecution("foo", new JobExecution(11L), 123L)); - assertTrue(TestStep.getContext().attributeNames().length > 0); - String collaborator = (String) TestStep.getContext().getAttribute("collaborator"); - assertNotNull(collaborator); - assertEquals("bar", collaborator); - } - - @Test - public void testScopedProxyForSecondReference() throws Exception { - doubleEnhanced.execute(new StepExecution("foo", new JobExecution(11L), 321L)); - assertTrue(TestStep.getContext().attributeNames().length > 0); - String collaborator = (String) TestStep.getContext().getAttribute("collaborator"); - assertNotNull(collaborator); - assertEquals("bar", collaborator); - } - -} +/* + * Copyright 2008-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.Step; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.scope.context.StepSynchronizationManager; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class StepScopeIntegrationTests { + + private static final String PROXY_TO_STRING_REGEX = "class .*\\$Proxy\\d+"; + + @Autowired + @Qualifier("vanilla") + private Step vanilla; + + @Autowired + @Qualifier("proxied") + private Step proxied; + + @Autowired + @Qualifier("nested") + private Step nested; + + @Autowired + @Qualifier("enhanced") + private Step enhanced; + + @Autowired + @Qualifier("double") + private Step doubleEnhanced; + + @Before + @After + public void start() { + StepSynchronizationManager.close(); + TestStep.reset(); + } + + @Test + public void testScopeCreation() throws Exception { + vanilla.execute(new StepExecution("foo", new JobExecution(11L), 12L)); + assertNotNull(TestStep.getContext()); + assertNull(StepSynchronizationManager.getContext()); + } + + @Test + public void testScopedProxy() throws Exception { + proxied.execute(new StepExecution("foo", new JobExecution(11L), 31L)); + assertTrue(TestStep.getContext().attributeNames().length > 0); + String collaborator = (String) TestStep.getContext().getAttribute("collaborator"); + assertNotNull(collaborator); + assertEquals("bar", collaborator); + assertTrue("Scoped proxy not created", + ((String) TestStep.getContext().getAttribute("collaborator.class")).matches(PROXY_TO_STRING_REGEX)); + } + + @Test + public void testNestedScopedProxy() throws Exception { + nested.execute(new StepExecution("foo", new JobExecution(11L), 31L)); + assertTrue(TestStep.getContext().attributeNames().length > 0); + String collaborator = (String) TestStep.getContext().getAttribute("collaborator"); + assertNotNull(collaborator); + assertEquals("foo", collaborator); + String parent = (String) TestStep.getContext().getAttribute("parent"); + assertNotNull(parent); + assertEquals("bar", parent); + assertTrue("Scoped proxy not created", + ((String) TestStep.getContext().getAttribute("parent.class")).matches(PROXY_TO_STRING_REGEX)); + } + + @Test + public void testExecutionContext() throws Exception { + StepExecution stepExecution = new StepExecution("foo", new JobExecution(11L), 1L); + ExecutionContext executionContext = new ExecutionContext(); + executionContext.put("name", "spam"); + stepExecution.setExecutionContext(executionContext); + proxied.execute(stepExecution); + assertTrue(TestStep.getContext().attributeNames().length > 0); + String collaborator = (String) TestStep.getContext().getAttribute("collaborator"); + assertNotNull(collaborator); + assertEquals("bar", collaborator); + } + + @Test + public void testScopedProxyForReference() throws Exception { + enhanced.execute(new StepExecution("foo", new JobExecution(11L), 123L)); + assertTrue(TestStep.getContext().attributeNames().length > 0); + String collaborator = (String) TestStep.getContext().getAttribute("collaborator"); + assertNotNull(collaborator); + assertEquals("bar", collaborator); + } + + @Test + public void testScopedProxyForSecondReference() throws Exception { + doubleEnhanced.execute(new StepExecution("foo", new JobExecution(11L), 321L)); + assertTrue(TestStep.getContext().attributeNames().length > 0); + String collaborator = (String) TestStep.getContext().getAttribute("collaborator"); + assertNotNull(collaborator); + assertEquals("bar", collaborator); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopeNestedIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopeNestedIntegrationTests.java index d44cf0a73..333c8188d 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopeNestedIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopeNestedIntegrationTests.java @@ -1,48 +1,47 @@ -/* - * Copyright 2008 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.Step; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - - -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -public class StepScopeNestedIntegrationTests { - - @Autowired - @Qualifier("proxied") - private Step proxied; - - @Autowired - @Qualifier("parent") - private Collaborator parent; - - @Test - public void testNestedScopedProxy() throws Exception { - assertNotNull(proxied); - assertEquals("foo", parent.getName()); - } - -} +/* + * Copyright 2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.Step; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class StepScopeNestedIntegrationTests { + + @Autowired + @Qualifier("proxied") + private Step proxied; + + @Autowired + @Qualifier("parent") + private Collaborator parent; + + @Test + public void testNestedScopedProxy() throws Exception { + assertNotNull(proxied); + assertEquals("foo", parent.getName()); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopePerformanceTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopePerformanceTests.java index d624cf6e7..18b3a8283 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopePerformanceTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopePerformanceTests.java @@ -1,93 +1,92 @@ -/* - * Copyright 2009-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.scope.context.StepSynchronizationManager; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemStreamReader; -import org.springframework.beans.BeansException; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.util.StopWatch; - -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -public class StepScopePerformanceTests implements ApplicationContextAware { - - private Log logger = LogFactory.getLog(getClass()); - - private ApplicationContext applicationContext; - - @Override - public void setApplicationContext(ApplicationContext applicationContext) - throws BeansException { - this.applicationContext = applicationContext; - - } - - @Before - public void start() throws Exception { - int count = doTest("vanilla", "warmup"); - logger.info("Item count: "+count); - StepSynchronizationManager.close(); - StepSynchronizationManager.register(new StepExecution("step", new JobExecution(0L),1L)); - } - - @After - public void cleanup() { - StepSynchronizationManager.close(); - } - - @Test - public void testVanilla() throws Exception { - int count = doTest("vanilla", "vanilla"); - logger.info("Item count: "+count); - } - - @Test - public void testProxied() throws Exception { - int count = doTest("proxied", "proxied"); - logger.info("Item count: "+count); - } - - private int doTest(String name, String test) throws Exception { - @SuppressWarnings("unchecked") - ItemStreamReader reader = (ItemStreamReader) applicationContext.getBean(name); - reader.open(new ExecutionContext()); - StopWatch stopWatch = new StopWatch(test); - stopWatch.start(); - int count = 0; - while (reader.read() != null) { - // do nothing - count++; - } - stopWatch.stop(); - reader.close(); - logger.info(stopWatch.shortSummary()); - return count; - } - -} +/* + * Copyright 2009-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.scope.context.StepSynchronizationManager; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ItemStreamReader; +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.util.StopWatch; + +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class StepScopePerformanceTests implements ApplicationContextAware { + + private Log logger = LogFactory.getLog(getClass()); + + private ApplicationContext applicationContext; + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext = applicationContext; + + } + + @Before + public void start() throws Exception { + int count = doTest("vanilla", "warmup"); + logger.info("Item count: " + count); + StepSynchronizationManager.close(); + StepSynchronizationManager.register(new StepExecution("step", new JobExecution(0L), 1L)); + } + + @After + public void cleanup() { + StepSynchronizationManager.close(); + } + + @Test + public void testVanilla() throws Exception { + int count = doTest("vanilla", "vanilla"); + logger.info("Item count: " + count); + } + + @Test + public void testProxied() throws Exception { + int count = doTest("proxied", "proxied"); + logger.info("Item count: " + count); + } + + private int doTest(String name, String test) throws Exception { + @SuppressWarnings("unchecked") + ItemStreamReader reader = (ItemStreamReader) applicationContext.getBean(name); + reader.open(new ExecutionContext()); + StopWatch stopWatch = new StopWatch(test); + stopWatch.start(); + int count = 0; + while (reader.read() != null) { + // do nothing + count++; + } + stopWatch.stop(); + reader.close(); + logger.info(stopWatch.shortSummary()); + return count; + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopePlaceholderIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopePlaceholderIntegrationTests.java index 2744cb4a9..ffc9458d1 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopePlaceholderIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopePlaceholderIntegrationTests.java @@ -1,172 +1,172 @@ -/* - * Copyright 2008-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope; - -import static org.junit.Assert.assertEquals; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.scope.context.StepSynchronizationManager; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.BeanFactoryAware; -import org.springframework.beans.factory.ListableBeanFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -public class StepScopePlaceholderIntegrationTests implements BeanFactoryAware { - - @Autowired - @Qualifier("simple") - private Collaborator simple; - - @Autowired - @Qualifier("compound") - private Collaborator compound; - - @Autowired - @Qualifier("value") - private Collaborator value; - - @Autowired - @Qualifier("ref") - private Collaborator ref; - - @Autowired - @Qualifier("scopedRef") - private Collaborator scopedRef; - - @Autowired - @Qualifier("list") - private Collaborator list; - - @Autowired - @Qualifier("bar") - private Collaborator bar; - - @Autowired - @Qualifier("nested") - private Collaborator nested; - - private StepExecution stepExecution; - - private ListableBeanFactory beanFactory; - - private int beanCount; - - @Override - public void setBeanFactory(BeanFactory beanFactory) throws BeansException { - this.beanFactory = (ListableBeanFactory) beanFactory; - } - - @Before - public void start() { - start("bar"); - } - - private void start(String foo) { - - StepSynchronizationManager.close(); - stepExecution = new StepExecution("foo", new JobExecution(11L), 123L); - - ExecutionContext executionContext = new ExecutionContext(); - executionContext.put("foo", foo); - executionContext.put("parent", bar); - - stepExecution.setExecutionContext(executionContext); - StepSynchronizationManager.register(stepExecution); - - beanCount = beanFactory.getBeanDefinitionCount(); - - } - - @After - public void stop() { - StepSynchronizationManager.close(); - // Check that all temporary bean definitions are cleaned up - assertEquals(beanCount, beanFactory.getBeanDefinitionCount()); - } - - @Test - public void testSimpleProperty() throws Exception { - assertEquals("bar", simple.getName()); - // Once the step context is set up it should be baked into the proxies - // so changing it now should have no effect - stepExecution.getExecutionContext().put("foo", "wrong!"); - assertEquals("bar", simple.getName()); - } - - @Test - public void testCompoundProperty() throws Exception { - assertEquals("bar-bar", compound.getName()); - } - - @Test - public void testCompoundPropertyTwice() throws Exception { - - assertEquals("bar-bar", compound.getName()); - - StepSynchronizationManager.close(); - stepExecution = new StepExecution("foo", new JobExecution(11L), 123L); - - ExecutionContext executionContext = new ExecutionContext(); - executionContext.put("foo", "spam"); - - stepExecution.setExecutionContext(executionContext); - StepSynchronizationManager.register(stepExecution); - - assertEquals("spam-bar", compound.getName()); - - } - - @Test - public void testParentByRef() throws Exception { - assertEquals("bar", ref.getParent().getName()); - } - - @Test - public void testParentByValue() throws Exception { - assertEquals("bar", value.getParent().getName()); - } - - @Test - public void testList() throws Exception { - assertEquals("[bar]", list.getList().toString()); - } - - @Test - public void testNested() throws Exception { - assertEquals("bar", nested.getParent().getName()); - } - - @Test - public void testScopedRef() throws Exception { - assertEquals("bar", scopedRef.getParent().getName()); - stop(); - start("spam"); - assertEquals("spam", scopedRef.getParent().getName()); - } - -} +/* + * Copyright 2008-2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope; + +import static org.junit.Assert.assertEquals; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.scope.context.StepSynchronizationManager; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.beans.factory.ListableBeanFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class StepScopePlaceholderIntegrationTests implements BeanFactoryAware { + + @Autowired + @Qualifier("simple") + private Collaborator simple; + + @Autowired + @Qualifier("compound") + private Collaborator compound; + + @Autowired + @Qualifier("value") + private Collaborator value; + + @Autowired + @Qualifier("ref") + private Collaborator ref; + + @Autowired + @Qualifier("scopedRef") + private Collaborator scopedRef; + + @Autowired + @Qualifier("list") + private Collaborator list; + + @Autowired + @Qualifier("bar") + private Collaborator bar; + + @Autowired + @Qualifier("nested") + private Collaborator nested; + + private StepExecution stepExecution; + + private ListableBeanFactory beanFactory; + + private int beanCount; + + @Override + public void setBeanFactory(BeanFactory beanFactory) throws BeansException { + this.beanFactory = (ListableBeanFactory) beanFactory; + } + + @Before + public void start() { + start("bar"); + } + + private void start(String foo) { + + StepSynchronizationManager.close(); + stepExecution = new StepExecution("foo", new JobExecution(11L), 123L); + + ExecutionContext executionContext = new ExecutionContext(); + executionContext.put("foo", foo); + executionContext.put("parent", bar); + + stepExecution.setExecutionContext(executionContext); + StepSynchronizationManager.register(stepExecution); + + beanCount = beanFactory.getBeanDefinitionCount(); + + } + + @After + public void stop() { + StepSynchronizationManager.close(); + // Check that all temporary bean definitions are cleaned up + assertEquals(beanCount, beanFactory.getBeanDefinitionCount()); + } + + @Test + public void testSimpleProperty() throws Exception { + assertEquals("bar", simple.getName()); + // Once the step context is set up it should be baked into the proxies + // so changing it now should have no effect + stepExecution.getExecutionContext().put("foo", "wrong!"); + assertEquals("bar", simple.getName()); + } + + @Test + public void testCompoundProperty() throws Exception { + assertEquals("bar-bar", compound.getName()); + } + + @Test + public void testCompoundPropertyTwice() throws Exception { + + assertEquals("bar-bar", compound.getName()); + + StepSynchronizationManager.close(); + stepExecution = new StepExecution("foo", new JobExecution(11L), 123L); + + ExecutionContext executionContext = new ExecutionContext(); + executionContext.put("foo", "spam"); + + stepExecution.setExecutionContext(executionContext); + StepSynchronizationManager.register(stepExecution); + + assertEquals("spam-bar", compound.getName()); + + } + + @Test + public void testParentByRef() throws Exception { + assertEquals("bar", ref.getParent().getName()); + } + + @Test + public void testParentByValue() throws Exception { + assertEquals("bar", value.getParent().getName()); + } + + @Test + public void testList() throws Exception { + assertEquals("[bar]", list.getList().toString()); + } + + @Test + public void testNested() throws Exception { + assertEquals("bar", nested.getParent().getName()); + } + + @Test + public void testScopedRef() throws Exception { + assertEquals("bar", scopedRef.getParent().getName()); + stop(); + start("spam"); + assertEquals("spam", scopedRef.getParent().getName()); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopeProxyTargetClassIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopeProxyTargetClassIntegrationTests.java index 2440eb2df..defa91584 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopeProxyTargetClassIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopeProxyTargetClassIntegrationTests.java @@ -1,88 +1,88 @@ -/* - * Copyright 2009-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope; - -import static org.junit.Assert.assertEquals; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.scope.context.StepSynchronizationManager; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.BeanFactoryAware; -import org.springframework.beans.factory.ListableBeanFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -public class StepScopeProxyTargetClassIntegrationTests implements BeanFactoryAware { - - @Autowired - @Qualifier("simple") - private TestCollaborator simple; - - private StepExecution stepExecution; - - private ListableBeanFactory beanFactory; - - private int beanCount; - - @Override - public void setBeanFactory(BeanFactory beanFactory) throws BeansException { - this.beanFactory = (ListableBeanFactory) beanFactory; - } - - @Before - public void start() { - - StepSynchronizationManager.close(); - stepExecution = new StepExecution("foo", new JobExecution(11L), 123L); - - ExecutionContext executionContext = new ExecutionContext(); - executionContext.put("foo", "bar"); - - stepExecution.setExecutionContext(executionContext); - StepSynchronizationManager.register(stepExecution); - - beanCount = beanFactory.getBeanDefinitionCount(); - - } - - @After - public void cleanUp() { - StepSynchronizationManager.close(); - // Check that all temporary bean definitions are cleaned up - assertEquals(beanCount, beanFactory.getBeanDefinitionCount()); - } - - @Test - public void testSimpleProperty() throws Exception { - assertEquals("bar", simple.getName()); - // Once the step context is set up it should be baked into the proxies - // so changing it now should have no effect - stepExecution.getExecutionContext().put("foo", "wrong!"); - assertEquals("bar", simple.getName()); - } - -} +/* + * Copyright 2009-2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope; + +import static org.junit.Assert.assertEquals; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.scope.context.StepSynchronizationManager; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.beans.factory.ListableBeanFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class StepScopeProxyTargetClassIntegrationTests implements BeanFactoryAware { + + @Autowired + @Qualifier("simple") + private TestCollaborator simple; + + private StepExecution stepExecution; + + private ListableBeanFactory beanFactory; + + private int beanCount; + + @Override + public void setBeanFactory(BeanFactory beanFactory) throws BeansException { + this.beanFactory = (ListableBeanFactory) beanFactory; + } + + @Before + public void start() { + + StepSynchronizationManager.close(); + stepExecution = new StepExecution("foo", new JobExecution(11L), 123L); + + ExecutionContext executionContext = new ExecutionContext(); + executionContext.put("foo", "bar"); + + stepExecution.setExecutionContext(executionContext); + StepSynchronizationManager.register(stepExecution); + + beanCount = beanFactory.getBeanDefinitionCount(); + + } + + @After + public void cleanUp() { + StepSynchronizationManager.close(); + // Check that all temporary bean definitions are cleaned up + assertEquals(beanCount, beanFactory.getBeanDefinitionCount()); + } + + @Test + public void testSimpleProperty() throws Exception { + assertEquals("bar", simple.getName()); + // Once the step context is set up it should be baked into the proxies + // so changing it now should have no effect + stepExecution.getExecutionContext().put("foo", "wrong!"); + assertEquals("bar", simple.getName()); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopeProxyTargetClassOverrideIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopeProxyTargetClassOverrideIntegrationTests.java index 4129ab108..bd588f9c0 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopeProxyTargetClassOverrideIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopeProxyTargetClassOverrideIntegrationTests.java @@ -1,158 +1,158 @@ -/* - * Copyright 2013-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.aop.support.AopUtils; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.Step; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.scope.context.StepSynchronizationManager; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.BeanFactoryAware; -import org.springframework.beans.factory.ListableBeanFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -public class StepScopeProxyTargetClassOverrideIntegrationTests implements BeanFactoryAware { - - private static final String JDK_PROXY_TO_STRING_REGEX = "class .*\\$Proxy\\d+"; - - private static final String CGLIB_PROXY_TO_STRING_REGEX = "class .*\\$EnhancerBySpringCGLIB.*"; - - @Autowired - @Qualifier("simple") - private TestCollaborator simple; - - @Autowired - @Qualifier("simpleProxyTargetClassTrue") - private TestCollaborator simpleProxyTargetClassTrue; - - @Autowired - @Qualifier("simpleProxyTargetClassFalse") - private Collaborator simpleProxyTargetClassFalse; - - @Autowired - @Qualifier("nested") - private Step nested; - - @Autowired - @Qualifier("nestedProxyTargetClassTrue") - private Step nestedProxyTargetClassTrue; - - @Autowired - @Qualifier("nestedProxyTargetClassFalse") - private Step nestedProxyTargetClassFalse; - - private StepExecution stepExecution; - - private ListableBeanFactory beanFactory; - - private int beanCount; - - @Override - public void setBeanFactory(BeanFactory beanFactory) throws BeansException { - this.beanFactory = (ListableBeanFactory) beanFactory; - } - - @Before - public void start() { - - StepSynchronizationManager.close(); - TestStep.reset(); - stepExecution = new StepExecution("foo", new JobExecution(11L), 123L); - - ExecutionContext executionContext = new ExecutionContext(); - executionContext.put("foo", "bar"); - - stepExecution.setExecutionContext(executionContext); - StepSynchronizationManager.register(stepExecution); - - beanCount = beanFactory.getBeanDefinitionCount(); - - } - - @After - public void cleanUp() { - StepSynchronizationManager.close(); - // Check that all temporary bean definitions are cleaned up - assertEquals(beanCount, beanFactory.getBeanDefinitionCount()); - } - - @Test - public void testSimple() throws Exception { - assertTrue(AopUtils.isCglibProxy(simple)); - assertEquals("bar", simple.getName()); - } - - @Test - public void testSimpleProxyTargetClassTrue() throws Exception { - assertTrue(AopUtils.isCglibProxy(simpleProxyTargetClassTrue)); - assertEquals("bar", simpleProxyTargetClassTrue.getName()); - } - - @Test - public void testSimpleProxyTargetClassFalse() throws Exception { - assertTrue(AopUtils.isJdkDynamicProxy(simpleProxyTargetClassFalse)); - assertEquals("bar", simpleProxyTargetClassFalse.getName()); - } - - @Test - public void testNested() throws Exception { - nested.execute(new StepExecution("foo", new JobExecution(11L), 31L)); - assertTrue(TestStep.getContext().attributeNames().length > 0); - String collaborator = (String) TestStep.getContext().getAttribute("collaborator"); - assertNotNull(collaborator); - assertEquals("foo", collaborator); - String parent = (String) TestStep.getContext().getAttribute("parent"); - assertNotNull(parent); - assertEquals("bar", parent); - assertTrue("Scoped proxy not created", ((String) TestStep.getContext().getAttribute("parent.class")) - .matches(CGLIB_PROXY_TO_STRING_REGEX)); - } - - @Test - public void testNestedProxyTargetClassTrue() throws Exception { - nestedProxyTargetClassTrue.execute(new StepExecution("foo", new JobExecution(11L), 31L)); - String parent = (String) TestStep.getContext().getAttribute("parent"); - assertEquals("bar", parent); - assertTrue("Scoped proxy not created", ((String) TestStep.getContext().getAttribute("parent.class")) - .matches(CGLIB_PROXY_TO_STRING_REGEX)); - } - - @Test - public void testNestedProxyTargetClassFalse() throws Exception { - nestedProxyTargetClassFalse.execute(new StepExecution("foo", new JobExecution(11L), 31L)); - String parent = (String) TestStep.getContext().getAttribute("parent"); - assertEquals("bar", parent); - assertTrue("Scoped proxy not created", ((String) TestStep.getContext().getAttribute("parent.class")) - .matches(JDK_PROXY_TO_STRING_REGEX)); - } - -} +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.aop.support.AopUtils; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.Step; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.scope.context.StepSynchronizationManager; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.beans.factory.ListableBeanFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class StepScopeProxyTargetClassOverrideIntegrationTests implements BeanFactoryAware { + + private static final String JDK_PROXY_TO_STRING_REGEX = "class .*\\$Proxy\\d+"; + + private static final String CGLIB_PROXY_TO_STRING_REGEX = "class .*\\$EnhancerBySpringCGLIB.*"; + + @Autowired + @Qualifier("simple") + private TestCollaborator simple; + + @Autowired + @Qualifier("simpleProxyTargetClassTrue") + private TestCollaborator simpleProxyTargetClassTrue; + + @Autowired + @Qualifier("simpleProxyTargetClassFalse") + private Collaborator simpleProxyTargetClassFalse; + + @Autowired + @Qualifier("nested") + private Step nested; + + @Autowired + @Qualifier("nestedProxyTargetClassTrue") + private Step nestedProxyTargetClassTrue; + + @Autowired + @Qualifier("nestedProxyTargetClassFalse") + private Step nestedProxyTargetClassFalse; + + private StepExecution stepExecution; + + private ListableBeanFactory beanFactory; + + private int beanCount; + + @Override + public void setBeanFactory(BeanFactory beanFactory) throws BeansException { + this.beanFactory = (ListableBeanFactory) beanFactory; + } + + @Before + public void start() { + + StepSynchronizationManager.close(); + TestStep.reset(); + stepExecution = new StepExecution("foo", new JobExecution(11L), 123L); + + ExecutionContext executionContext = new ExecutionContext(); + executionContext.put("foo", "bar"); + + stepExecution.setExecutionContext(executionContext); + StepSynchronizationManager.register(stepExecution); + + beanCount = beanFactory.getBeanDefinitionCount(); + + } + + @After + public void cleanUp() { + StepSynchronizationManager.close(); + // Check that all temporary bean definitions are cleaned up + assertEquals(beanCount, beanFactory.getBeanDefinitionCount()); + } + + @Test + public void testSimple() throws Exception { + assertTrue(AopUtils.isCglibProxy(simple)); + assertEquals("bar", simple.getName()); + } + + @Test + public void testSimpleProxyTargetClassTrue() throws Exception { + assertTrue(AopUtils.isCglibProxy(simpleProxyTargetClassTrue)); + assertEquals("bar", simpleProxyTargetClassTrue.getName()); + } + + @Test + public void testSimpleProxyTargetClassFalse() throws Exception { + assertTrue(AopUtils.isJdkDynamicProxy(simpleProxyTargetClassFalse)); + assertEquals("bar", simpleProxyTargetClassFalse.getName()); + } + + @Test + public void testNested() throws Exception { + nested.execute(new StepExecution("foo", new JobExecution(11L), 31L)); + assertTrue(TestStep.getContext().attributeNames().length > 0); + String collaborator = (String) TestStep.getContext().getAttribute("collaborator"); + assertNotNull(collaborator); + assertEquals("foo", collaborator); + String parent = (String) TestStep.getContext().getAttribute("parent"); + assertNotNull(parent); + assertEquals("bar", parent); + assertTrue("Scoped proxy not created", + ((String) TestStep.getContext().getAttribute("parent.class")).matches(CGLIB_PROXY_TO_STRING_REGEX)); + } + + @Test + public void testNestedProxyTargetClassTrue() throws Exception { + nestedProxyTargetClassTrue.execute(new StepExecution("foo", new JobExecution(11L), 31L)); + String parent = (String) TestStep.getContext().getAttribute("parent"); + assertEquals("bar", parent); + assertTrue("Scoped proxy not created", + ((String) TestStep.getContext().getAttribute("parent.class")).matches(CGLIB_PROXY_TO_STRING_REGEX)); + } + + @Test + public void testNestedProxyTargetClassFalse() throws Exception { + nestedProxyTargetClassFalse.execute(new StepExecution("foo", new JobExecution(11L), 31L)); + String parent = (String) TestStep.getContext().getAttribute("parent"); + assertEquals("bar", parent); + assertTrue("Scoped proxy not created", + ((String) TestStep.getContext().getAttribute("parent.class")).matches(JDK_PROXY_TO_STRING_REGEX)); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopeStartupIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopeStartupIntegrationTests.java index 781564181..a03e334c9 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopeStartupIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopeStartupIntegrationTests.java @@ -1,32 +1,31 @@ -/* - * Copyright 2008 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - - -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -public class StepScopeStartupIntegrationTests { - - @Test - public void testScopedProxyDuringStartup() throws Exception { - } - -} +/* + * Copyright 2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class StepScopeStartupIntegrationTests { + + @Test + public void testScopedProxyDuringStartup() throws Exception { + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopeTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopeTests.java index 252c6728f..b4cbfecf7 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopeTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopeTests.java @@ -1,201 +1,201 @@ -/* - * Copyright 2006-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.scope.context.StepContext; -import org.springframework.batch.core.scope.context.StepSynchronizationManager; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.ObjectFactory; -import org.springframework.context.support.StaticApplicationContext; - -/** - * @author Dave Syer - * - */ -public class StepScopeTests { - - private StepScope scope = new StepScope(); - - private StepExecution stepExecution = new StepExecution("foo", new JobExecution(0L), 123L); - - private StepContext context; - - @Before - public void setUp() throws Exception { - StepSynchronizationManager.release(); - context = StepSynchronizationManager.register(stepExecution); - } - - @After - public void tearDown() throws Exception { - StepSynchronizationManager.close(); - } - - @Test - public void testGetWithNoContext() throws Exception { - final String foo = "bar"; - StepSynchronizationManager.close(); - try { - scope.get("foo", new ObjectFactory() { - @Override - public Object getObject() throws BeansException { - return foo; - } - }); - fail("Expected IllegalStateException"); - } - catch (IllegalStateException e) { - // expected - } - - } - - @Test - public void testGetWithNothingAlreadyThere() { - final String foo = "bar"; - Object value = scope.get("foo", new ObjectFactory() { - @Override - public Object getObject() throws BeansException { - return foo; - } - }); - assertEquals(foo, value); - assertTrue(context.hasAttribute("foo")); - } - - @Test - public void testGetWithSomethingAlreadyThere() { - context.setAttribute("foo", "bar"); - Object value = scope.get("foo", new ObjectFactory() { - @Override - public Object getObject() throws BeansException { - return null; - } - }); - assertEquals("bar", value); - assertTrue(context.hasAttribute("foo")); - } - - @Test - public void testGetWithSomethingAlreadyInParentContext() { - context.setAttribute("foo", "bar"); - StepContext context = StepSynchronizationManager.register(new StepExecution("bar", new JobExecution(0L))); - Object value = scope.get("foo", new ObjectFactory() { - @Override - public Object getObject() throws BeansException { - return "spam"; - } - }); - assertEquals("spam", value); - assertTrue(context.hasAttribute("foo")); - StepSynchronizationManager.close(); - assertEquals("bar", scope.get("foo", null)); - } - - @Test - public void testParentContextWithSameStepExecution() { - context.setAttribute("foo", "bar"); - StepContext other = StepSynchronizationManager.register(stepExecution); - assertSame(other, context); - } - - @Test - public void testGetConversationId() { - String id = scope.getConversationId(); - assertNotNull(id); - } - - @Test - public void testRegisterDestructionCallback() { - final List list = new ArrayList<>(); - context.setAttribute("foo", "bar"); - scope.registerDestructionCallback("foo", new Runnable() { - @Override - public void run() { - list.add("foo"); - } - }); - assertEquals(0, list.size()); - // When the context is closed, provided the attribute exists the - // callback is called... - context.close(); - assertEquals(1, list.size()); - } - - @Test - public void testRegisterAnotherDestructionCallback() { - final List list = new ArrayList<>(); - context.setAttribute("foo", "bar"); - scope.registerDestructionCallback("foo", new Runnable() { - @Override - public void run() { - list.add("foo"); - } - }); - scope.registerDestructionCallback("foo", new Runnable() { - @Override - public void run() { - list.add("bar"); - } - }); - assertEquals(0, list.size()); - // When the context is closed, provided the attribute exists the - // callback is called... - context.close(); - assertEquals(2, list.size()); - } - - @Test - public void testRemove() { - context.setAttribute("foo", "bar"); - scope.remove("foo"); - assertFalse(context.hasAttribute("foo")); - } - - @Test - public void testOrder() throws Exception { - assertEquals(Integer.MAX_VALUE, scope.getOrder()); - scope.setOrder(11); - assertEquals(11, scope.getOrder()); - } - - @SuppressWarnings("resource") - @Test - public void testName() throws Exception { - scope.setName("foo"); - StaticApplicationContext beanFactory = new StaticApplicationContext(); - scope.postProcessBeanFactory(beanFactory.getDefaultListableBeanFactory()); - String[] scopes = beanFactory.getDefaultListableBeanFactory().getRegisteredScopeNames(); - assertEquals(1, scopes.length); - assertEquals("foo", scopes[0]); - } - -} +/* + * Copyright 2006-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.scope.context.StepContext; +import org.springframework.batch.core.scope.context.StepSynchronizationManager; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.ObjectFactory; +import org.springframework.context.support.StaticApplicationContext; + +/** + * @author Dave Syer + * + */ +public class StepScopeTests { + + private StepScope scope = new StepScope(); + + private StepExecution stepExecution = new StepExecution("foo", new JobExecution(0L), 123L); + + private StepContext context; + + @Before + public void setUp() throws Exception { + StepSynchronizationManager.release(); + context = StepSynchronizationManager.register(stepExecution); + } + + @After + public void tearDown() throws Exception { + StepSynchronizationManager.close(); + } + + @Test + public void testGetWithNoContext() throws Exception { + final String foo = "bar"; + StepSynchronizationManager.close(); + try { + scope.get("foo", new ObjectFactory() { + @Override + public Object getObject() throws BeansException { + return foo; + } + }); + fail("Expected IllegalStateException"); + } + catch (IllegalStateException e) { + // expected + } + + } + + @Test + public void testGetWithNothingAlreadyThere() { + final String foo = "bar"; + Object value = scope.get("foo", new ObjectFactory() { + @Override + public Object getObject() throws BeansException { + return foo; + } + }); + assertEquals(foo, value); + assertTrue(context.hasAttribute("foo")); + } + + @Test + public void testGetWithSomethingAlreadyThere() { + context.setAttribute("foo", "bar"); + Object value = scope.get("foo", new ObjectFactory() { + @Override + public Object getObject() throws BeansException { + return null; + } + }); + assertEquals("bar", value); + assertTrue(context.hasAttribute("foo")); + } + + @Test + public void testGetWithSomethingAlreadyInParentContext() { + context.setAttribute("foo", "bar"); + StepContext context = StepSynchronizationManager.register(new StepExecution("bar", new JobExecution(0L))); + Object value = scope.get("foo", new ObjectFactory() { + @Override + public Object getObject() throws BeansException { + return "spam"; + } + }); + assertEquals("spam", value); + assertTrue(context.hasAttribute("foo")); + StepSynchronizationManager.close(); + assertEquals("bar", scope.get("foo", null)); + } + + @Test + public void testParentContextWithSameStepExecution() { + context.setAttribute("foo", "bar"); + StepContext other = StepSynchronizationManager.register(stepExecution); + assertSame(other, context); + } + + @Test + public void testGetConversationId() { + String id = scope.getConversationId(); + assertNotNull(id); + } + + @Test + public void testRegisterDestructionCallback() { + final List list = new ArrayList<>(); + context.setAttribute("foo", "bar"); + scope.registerDestructionCallback("foo", new Runnable() { + @Override + public void run() { + list.add("foo"); + } + }); + assertEquals(0, list.size()); + // When the context is closed, provided the attribute exists the + // callback is called... + context.close(); + assertEquals(1, list.size()); + } + + @Test + public void testRegisterAnotherDestructionCallback() { + final List list = new ArrayList<>(); + context.setAttribute("foo", "bar"); + scope.registerDestructionCallback("foo", new Runnable() { + @Override + public void run() { + list.add("foo"); + } + }); + scope.registerDestructionCallback("foo", new Runnable() { + @Override + public void run() { + list.add("bar"); + } + }); + assertEquals(0, list.size()); + // When the context is closed, provided the attribute exists the + // callback is called... + context.close(); + assertEquals(2, list.size()); + } + + @Test + public void testRemove() { + context.setAttribute("foo", "bar"); + scope.remove("foo"); + assertFalse(context.hasAttribute("foo")); + } + + @Test + public void testOrder() throws Exception { + assertEquals(Integer.MAX_VALUE, scope.getOrder()); + scope.setOrder(11); + assertEquals(11, scope.getOrder()); + } + + @SuppressWarnings("resource") + @Test + public void testName() throws Exception { + scope.setName("foo"); + StaticApplicationContext beanFactory = new StaticApplicationContext(); + scope.postProcessBeanFactory(beanFactory.getDefaultListableBeanFactory()); + String[] scopes = beanFactory.getDefaultListableBeanFactory().getRegisteredScopeNames(); + assertEquals(1, scopes.length); + assertEquals("foo", scopes[0]); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepStartupRunner.java b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepStartupRunner.java index 09c392325..058ec0848 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepStartupRunner.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepStartupRunner.java @@ -1,38 +1,38 @@ -/* - * Copyright 2013-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope; - -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.Step; -import org.springframework.batch.core.StepExecution; -import org.springframework.beans.factory.InitializingBean; - -public class StepStartupRunner implements InitializingBean { - - private Step step; - - public void setStep(Step step) { - this.step = step; - } - - @Override - public void afterPropertiesSet() throws Exception { - StepExecution stepExecution = new StepExecution("step", new JobExecution(1L), 0L); - step.execute(stepExecution); - // expect no errors - } - -} +/* + * Copyright 2013-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope; + +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.Step; +import org.springframework.batch.core.StepExecution; +import org.springframework.beans.factory.InitializingBean; + +public class StepStartupRunner implements InitializingBean { + + private Step step; + + public void setStep(Step step) { + this.step = step; + } + + @Override + public void afterPropertiesSet() throws Exception { + StepExecution stepExecution = new StepExecution("step", new JobExecution(1L), 0L); + step.execute(stepExecution); + // expect no errors + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/TestAdvice.java b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/TestAdvice.java index bd5c9e060..7b8e561c9 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/TestAdvice.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/TestAdvice.java @@ -1,35 +1,35 @@ -/* - * Copyright 2008 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope; - -import java.util.ArrayList; -import java.util.List; - -import org.aspectj.lang.annotation.AfterReturning; -import org.aspectj.lang.annotation.Aspect; - -@Aspect -public class TestAdvice { - - public static final List names = new ArrayList<>(); - - @AfterReturning(pointcut="execution(String org.springframework.batch.core.scope.Collaborator+.getName(..))", returning="name") - public void registerCollaborator(String name) { - names.add(name); - } - - -} +/* + * Copyright 2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope; + +import java.util.ArrayList; +import java.util.List; + +import org.aspectj.lang.annotation.AfterReturning; +import org.aspectj.lang.annotation.Aspect; + +@Aspect +public class TestAdvice { + + public static final List names = new ArrayList<>(); + + @AfterReturning(pointcut = "execution(String org.springframework.batch.core.scope.Collaborator+.getName(..))", + returning = "name") + public void registerCollaborator(String name) { + names.add(name); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/TestCollaborator.java b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/TestCollaborator.java index f00b6e3e1..5b8ee24ad 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/TestCollaborator.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/TestCollaborator.java @@ -1,58 +1,57 @@ -/* - * Copyright 2008-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope; - -import java.io.Serializable; -import java.util.List; - - -@SuppressWarnings("serial") -public class TestCollaborator implements Collaborator, Serializable { - - private String name; - - private Collaborator parent; - - private List list; - - @Override - public List getList() { - return list; - } - - public void setList(List list) { - this.list = list; - } - - @Override - public Collaborator getParent() { - return parent; - } - - public void setParent(Collaborator parent) { - this.parent = parent; - } - - @Override - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - -} +/* + * Copyright 2008-2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope; + +import java.io.Serializable; +import java.util.List; + +@SuppressWarnings("serial") +public class TestCollaborator implements Collaborator, Serializable { + + private String name; + + private Collaborator parent; + + private List list; + + @Override + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } + + @Override + public Collaborator getParent() { + return parent; + } + + public void setParent(Collaborator parent) { + this.parent = parent; + } + + @Override + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/TestDisposableCollaborator.java b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/TestDisposableCollaborator.java index 43d64e333..29656aa20 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/TestDisposableCollaborator.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/TestDisposableCollaborator.java @@ -1,30 +1,30 @@ -/* - * Copyright 2008-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope; - -import org.springframework.beans.factory.DisposableBean; - -@SuppressWarnings("serial") -public class TestDisposableCollaborator extends TestCollaborator implements DisposableBean { - - public static volatile String message = "none"; - - @Override - public void destroy() throws Exception { - message = (message.equals("none") ? "" : message + ",") + getName() + ":destroyed"; - } - -} +/* + * Copyright 2008-2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope; + +import org.springframework.beans.factory.DisposableBean; + +@SuppressWarnings("serial") +public class TestDisposableCollaborator extends TestCollaborator implements DisposableBean { + + public static volatile String message = "none"; + + @Override + public void destroy() throws Exception { + message = (message.equals("none") ? "" : message + ",") + getName() + ":destroyed"; + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/TestJob.java b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/TestJob.java index 1cb4cbb0d..8639add60 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/TestJob.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/TestJob.java @@ -1,83 +1,84 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope; - -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParametersIncrementer; -import org.springframework.batch.core.JobParametersValidator; -import org.springframework.batch.core.scope.context.JobContext; -import org.springframework.batch.core.scope.context.JobSynchronizationManager; -import org.springframework.lang.Nullable; - -public class TestJob implements Job { - - private static JobContext context; - - private Collaborator collaborator; - - public void setCollaborator(Collaborator collaborator) { - this.collaborator = collaborator; - } - - public static JobContext getContext() { - return context; - } - - public static void reset() { - context = null; - } - - @Override - public void execute(JobExecution stepExecution) { - context = JobSynchronizationManager.getContext(); - setContextFromCollaborator(); - stepExecution.getExecutionContext().put("foo", "changed but it shouldn't affect the collaborator"); - setContextFromCollaborator(); - } - - private void setContextFromCollaborator() { - if (context != null) { - context.setAttribute("collaborator", collaborator.getName()); - context.setAttribute("collaborator.class", collaborator.getClass().toString()); - if (collaborator.getParent()!=null) { - context.setAttribute("parent", collaborator.getParent().getName()); - context.setAttribute("parent.class", collaborator.getParent().getClass().toString()); - } - } - } - - @Override - public String getName() { - return "foo"; - } - - @Override - public boolean isRestartable() { - return false; - } - - @Nullable - @Override - public JobParametersIncrementer getJobParametersIncrementer() { - return null; - } - - @Override - public JobParametersValidator getJobParametersValidator() { - return null; - } -} +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope; + +import org.springframework.batch.core.Job; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobParametersIncrementer; +import org.springframework.batch.core.JobParametersValidator; +import org.springframework.batch.core.scope.context.JobContext; +import org.springframework.batch.core.scope.context.JobSynchronizationManager; +import org.springframework.lang.Nullable; + +public class TestJob implements Job { + + private static JobContext context; + + private Collaborator collaborator; + + public void setCollaborator(Collaborator collaborator) { + this.collaborator = collaborator; + } + + public static JobContext getContext() { + return context; + } + + public static void reset() { + context = null; + } + + @Override + public void execute(JobExecution stepExecution) { + context = JobSynchronizationManager.getContext(); + setContextFromCollaborator(); + stepExecution.getExecutionContext().put("foo", "changed but it shouldn't affect the collaborator"); + setContextFromCollaborator(); + } + + private void setContextFromCollaborator() { + if (context != null) { + context.setAttribute("collaborator", collaborator.getName()); + context.setAttribute("collaborator.class", collaborator.getClass().toString()); + if (collaborator.getParent() != null) { + context.setAttribute("parent", collaborator.getParent().getName()); + context.setAttribute("parent.class", collaborator.getParent().getClass().toString()); + } + } + } + + @Override + public String getName() { + return "foo"; + } + + @Override + public boolean isRestartable() { + return false; + } + + @Nullable + @Override + public JobParametersIncrementer getJobParametersIncrementer() { + return null; + } + + @Override + public JobParametersValidator getJobParametersValidator() { + return null; + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/TestStep.java b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/TestStep.java index f69a6700a..eed227ffc 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/TestStep.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/TestStep.java @@ -1,76 +1,76 @@ -/* - * Copyright 2008-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope; - -import org.springframework.batch.core.JobInterruptedException; -import org.springframework.batch.core.Step; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.scope.context.StepContext; -import org.springframework.batch.core.scope.context.StepSynchronizationManager; - -public class TestStep implements Step { - - private static StepContext context; - - private Collaborator collaborator; - - public void setCollaborator(Collaborator collaborator) { - this.collaborator = collaborator; - } - - public static StepContext getContext() { - return context; - } - - public static void reset() { - context = null; - } - - @Override - public void execute(StepExecution stepExecution) throws JobInterruptedException { - context = StepSynchronizationManager.getContext(); - setContextFromCollaborator(); - stepExecution.getExecutionContext().put("foo", "changed but it shouldn't affect the collaborator"); - setContextFromCollaborator(); - } - - private void setContextFromCollaborator() { - if (context != null) { - context.setAttribute("collaborator", collaborator.getName()); - context.setAttribute("collaborator.class", collaborator.getClass().toString()); - if (collaborator.getParent()!=null) { - context.setAttribute("parent", collaborator.getParent().getName()); - context.setAttribute("parent.class", collaborator.getParent().getClass().toString()); - } - } - } - - @Override - public String getName() { - return "foo"; - } - - @Override - public int getStartLimit() { - return Integer.MAX_VALUE; - } - - @Override - public boolean isAllowStartIfComplete() { - return false; - } - -} +/* + * Copyright 2008-2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope; + +import org.springframework.batch.core.JobInterruptedException; +import org.springframework.batch.core.Step; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.scope.context.StepContext; +import org.springframework.batch.core.scope.context.StepSynchronizationManager; + +public class TestStep implements Step { + + private static StepContext context; + + private Collaborator collaborator; + + public void setCollaborator(Collaborator collaborator) { + this.collaborator = collaborator; + } + + public static StepContext getContext() { + return context; + } + + public static void reset() { + context = null; + } + + @Override + public void execute(StepExecution stepExecution) throws JobInterruptedException { + context = StepSynchronizationManager.getContext(); + setContextFromCollaborator(); + stepExecution.getExecutionContext().put("foo", "changed but it shouldn't affect the collaborator"); + setContextFromCollaborator(); + } + + private void setContextFromCollaborator() { + if (context != null) { + context.setAttribute("collaborator", collaborator.getName()); + context.setAttribute("collaborator.class", collaborator.getClass().toString()); + if (collaborator.getParent() != null) { + context.setAttribute("parent", collaborator.getParent().getName()); + context.setAttribute("parent.class", collaborator.getParent().getClass().toString()); + } + } + } + + @Override + public String getName() { + return "foo"; + } + + @Override + public int getStartLimit() { + return Integer.MAX_VALUE; + } + + @Override + public boolean isAllowStartIfComplete() { + return false; + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/context/ChunkContextTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/context/ChunkContextTests.java index 6d833ad06..c1edcc22d 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/context/ChunkContextTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/context/ChunkContextTests.java @@ -1,64 +1,63 @@ -/* - * Copyright 2006-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope.context; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.util.Collections; - -import org.junit.Test; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobInstance; -import org.springframework.batch.core.JobParameter; -import org.springframework.batch.core.JobParameters; - -/** - * @author Dave Syer - * @author Mahmoud Ben Hassine - * - */ -public class ChunkContextTests { - - private ChunkContext context = new ChunkContext(new StepContext(new JobExecution(new JobInstance(0L, - "job"), 1L, new JobParameters(Collections.singletonMap("foo", new JobParameter("bar")))) - .createStepExecution("foo"))); - - @Test - public void testGetStepContext() { - StepContext stepContext = context.getStepContext(); - assertNotNull(stepContext); - assertEquals("bar", context.getStepContext().getJobParameters().get("foo")); - } - - @Test - public void testIsComplete() { - assertFalse(context.isComplete()); - context.setComplete(); - assertTrue(context.isComplete()); - } - - @Test - public void testToString() { - String value = context.toString(); - assertTrue("Wrong toString: "+value, value.contains("stepContext=")); - assertTrue("Wrong toString: "+value, value.contains("complete=false")); - assertTrue("Wrong toString: "+value, value.contains("attributes=[]")); - } - -} +/* + * Copyright 2006-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope.context; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.Collections; + +import org.junit.Test; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobInstance; +import org.springframework.batch.core.JobParameter; +import org.springframework.batch.core.JobParameters; + +/** + * @author Dave Syer + * @author Mahmoud Ben Hassine + * + */ +public class ChunkContextTests { + + private ChunkContext context = new ChunkContext(new StepContext(new JobExecution(new JobInstance(0L, "job"), 1L, + new JobParameters(Collections.singletonMap("foo", new JobParameter("bar")))).createStepExecution("foo"))); + + @Test + public void testGetStepContext() { + StepContext stepContext = context.getStepContext(); + assertNotNull(stepContext); + assertEquals("bar", context.getStepContext().getJobParameters().get("foo")); + } + + @Test + public void testIsComplete() { + assertFalse(context.isComplete()); + context.setComplete(); + assertTrue(context.isComplete()); + } + + @Test + public void testToString() { + String value = context.toString(); + assertTrue("Wrong toString: " + value, value.contains("stepContext=")); + assertTrue("Wrong toString: " + value, value.contains("complete=false")); + assertTrue("Wrong toString: " + value, value.contains("attributes=[]")); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/context/InternalBeanStepScopeIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/context/InternalBeanStepScopeIntegrationTests.java index 3b899cb37..82761453a 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/context/InternalBeanStepScopeIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/context/InternalBeanStepScopeIntegrationTests.java @@ -33,11 +33,13 @@ public class InternalBeanStepScopeIntegrationTests { @Test public void testCommitIntervalJobParameter() throws Exception { - ApplicationContext context = new ClassPathXmlApplicationContext("/org/springframework/batch/core/scope/context/CommitIntervalJobParameter-context.xml"); + ApplicationContext context = new ClassPathXmlApplicationContext( + "/org/springframework/batch/core/scope/context/CommitIntervalJobParameter-context.xml"); Job job = context.getBean(Job.class); JobLauncher launcher = context.getBean(JobLauncher.class); - JobExecution execution = launcher.run(job, new JobParametersBuilder().addLong("commit.interval", 1l).toJobParameters()); + JobExecution execution = launcher.run(job, + new JobParametersBuilder().addLong("commit.interval", 1l).toJobParameters()); assertEquals(BatchStatus.COMPLETED, execution.getStatus()); assertEquals(2, execution.getStepExecutions().iterator().next().getReadCount()); @@ -46,12 +48,15 @@ public class InternalBeanStepScopeIntegrationTests { @Test public void testInvalidCommitIntervalJobParameter() throws Exception { - ApplicationContext context = new ClassPathXmlApplicationContext("/org/springframework/batch/core/scope/context/CommitIntervalJobParameter-context.xml"); + ApplicationContext context = new ClassPathXmlApplicationContext( + "/org/springframework/batch/core/scope/context/CommitIntervalJobParameter-context.xml"); Job job = context.getBean(Job.class); JobLauncher launcher = context.getBean(JobLauncher.class); - JobExecution execution = launcher.run(job, new JobParametersBuilder().addLong("commit.intervall", 1l).toJobParameters()); + JobExecution execution = launcher.run(job, + new JobParametersBuilder().addLong("commit.intervall", 1l).toJobParameters()); assertEquals(BatchStatus.FAILED, execution.getStatus()); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/context/JobContextTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/context/JobContextTests.java index 005a8dbb4..51bc75699 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/context/JobContextTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/context/JobContextTests.java @@ -1,187 +1,187 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope.context; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobInstance; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.item.ExecutionContext; - -/** - * @author Dave Syer - * @author Jimmy Praet - */ -public class JobContextTests { - - private List list; - - private JobExecution jobExecution; - - private JobContext context; - - @Before - public void setUp() { - jobExecution = new JobExecution(1L); - JobInstance jobInstance = new JobInstance(2L, "job"); - jobExecution.setJobInstance(jobInstance); - context = new JobContext(jobExecution); - list = new ArrayList<>(); - } - - @Test - public void testGetJobExecution() { - context = new JobContext(jobExecution); - assertNotNull(context.getJobExecution()); - } - - @Test - public void testNullJobExecution() { - try { - context = new JobContext(null); - fail("Expected IllegalArgumentException"); - } - catch (IllegalArgumentException e) { - // expected - } - } - - @Test - public void testEqualsSelf() { - assertEquals(context, context); - } - - @Test - public void testNotEqualsNull() { - assertFalse(context.equals(null)); - } - - @Test - public void testEqualsContextWithSameJobExecution() { - assertEquals(new JobContext(jobExecution), context); - } - - @Test - public void testDestructionCallbackSunnyDay() throws Exception { - context.setAttribute("foo", "FOO"); - context.registerDestructionCallback("foo", new Runnable() { - @Override - public void run() { - list.add("bar"); - } - }); - context.close(); - assertEquals(1, list.size()); - assertEquals("bar", list.get(0)); - } - - @Test - public void testDestructionCallbackMissingAttribute() throws Exception { - context.registerDestructionCallback("foo", new Runnable() { - @Override - public void run() { - list.add("bar"); - } - }); - context.close(); - // Yes the callback should be called even if the attribute is missing - - // for inner beans - assertEquals(1, list.size()); - } - - @Test - public void testDestructionCallbackWithException() throws Exception { - context.setAttribute("foo", "FOO"); - context.setAttribute("bar", "BAR"); - context.registerDestructionCallback("bar", new Runnable() { - @Override - public void run() { - list.add("spam"); - throw new RuntimeException("fail!"); - } - }); - context.registerDestructionCallback("foo", new Runnable() { - @Override - public void run() { - list.add("bar"); - throw new RuntimeException("fail!"); - } - }); - try { - context.close(); - fail("Expected RuntimeException"); - } - catch (RuntimeException e) { - // We don't care which one was thrown... - assertEquals("fail!", e.getMessage()); - } - // ...but we do care that both were executed: - assertEquals(2, list.size()); - assertTrue(list.contains("bar")); - assertTrue(list.contains("spam")); - } - - @Test - public void testJobName() throws Exception { - assertEquals("job", context.getJobName()); - } - - @Test - public void testJobExecutionContext() throws Exception { - ExecutionContext executionContext = jobExecution.getExecutionContext(); - executionContext.put("foo", "bar"); - assertEquals("bar", context.getJobExecutionContext().get("foo")); - } - - @Test - public void testSystemProperties() throws Exception { - System.setProperty("foo", "bar"); - assertEquals("bar", context.getSystemProperties().getProperty("foo")); - } - - @Test - public void testJobParameters() throws Exception { - JobParameters jobParameters = new JobParametersBuilder().addString("foo", "bar").toJobParameters(); - JobInstance jobInstance = new JobInstance(0L, "foo"); - jobExecution = new JobExecution(5L, jobParameters); - jobExecution.setJobInstance(jobInstance); - context = new JobContext(jobExecution); - assertEquals("bar", context.getJobParameters().get("foo")); - } - - @Test - public void testContextId() throws Exception { - assertEquals("jobExecution#1", context.getId()); - } - - @Test(expected = IllegalStateException.class) - public void testIllegalContextId() throws Exception { - context = new JobContext(new JobExecution((Long) null)); - context.getId(); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope.context; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobInstance; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.JobParametersBuilder; +import org.springframework.batch.item.ExecutionContext; + +/** + * @author Dave Syer + * @author Jimmy Praet + */ +public class JobContextTests { + + private List list; + + private JobExecution jobExecution; + + private JobContext context; + + @Before + public void setUp() { + jobExecution = new JobExecution(1L); + JobInstance jobInstance = new JobInstance(2L, "job"); + jobExecution.setJobInstance(jobInstance); + context = new JobContext(jobExecution); + list = new ArrayList<>(); + } + + @Test + public void testGetJobExecution() { + context = new JobContext(jobExecution); + assertNotNull(context.getJobExecution()); + } + + @Test + public void testNullJobExecution() { + try { + context = new JobContext(null); + fail("Expected IllegalArgumentException"); + } + catch (IllegalArgumentException e) { + // expected + } + } + + @Test + public void testEqualsSelf() { + assertEquals(context, context); + } + + @Test + public void testNotEqualsNull() { + assertFalse(context.equals(null)); + } + + @Test + public void testEqualsContextWithSameJobExecution() { + assertEquals(new JobContext(jobExecution), context); + } + + @Test + public void testDestructionCallbackSunnyDay() throws Exception { + context.setAttribute("foo", "FOO"); + context.registerDestructionCallback("foo", new Runnable() { + @Override + public void run() { + list.add("bar"); + } + }); + context.close(); + assertEquals(1, list.size()); + assertEquals("bar", list.get(0)); + } + + @Test + public void testDestructionCallbackMissingAttribute() throws Exception { + context.registerDestructionCallback("foo", new Runnable() { + @Override + public void run() { + list.add("bar"); + } + }); + context.close(); + // Yes the callback should be called even if the attribute is missing - + // for inner beans + assertEquals(1, list.size()); + } + + @Test + public void testDestructionCallbackWithException() throws Exception { + context.setAttribute("foo", "FOO"); + context.setAttribute("bar", "BAR"); + context.registerDestructionCallback("bar", new Runnable() { + @Override + public void run() { + list.add("spam"); + throw new RuntimeException("fail!"); + } + }); + context.registerDestructionCallback("foo", new Runnable() { + @Override + public void run() { + list.add("bar"); + throw new RuntimeException("fail!"); + } + }); + try { + context.close(); + fail("Expected RuntimeException"); + } + catch (RuntimeException e) { + // We don't care which one was thrown... + assertEquals("fail!", e.getMessage()); + } + // ...but we do care that both were executed: + assertEquals(2, list.size()); + assertTrue(list.contains("bar")); + assertTrue(list.contains("spam")); + } + + @Test + public void testJobName() throws Exception { + assertEquals("job", context.getJobName()); + } + + @Test + public void testJobExecutionContext() throws Exception { + ExecutionContext executionContext = jobExecution.getExecutionContext(); + executionContext.put("foo", "bar"); + assertEquals("bar", context.getJobExecutionContext().get("foo")); + } + + @Test + public void testSystemProperties() throws Exception { + System.setProperty("foo", "bar"); + assertEquals("bar", context.getSystemProperties().getProperty("foo")); + } + + @Test + public void testJobParameters() throws Exception { + JobParameters jobParameters = new JobParametersBuilder().addString("foo", "bar").toJobParameters(); + JobInstance jobInstance = new JobInstance(0L, "foo"); + jobExecution = new JobExecution(5L, jobParameters); + jobExecution.setJobInstance(jobInstance); + context = new JobContext(jobExecution); + assertEquals("bar", context.getJobParameters().get("foo")); + } + + @Test + public void testContextId() throws Exception { + assertEquals("jobExecution#1", context.getId()); + } + + @Test(expected = IllegalStateException.class) + public void testIllegalContextId() throws Exception { + context = new JobContext(new JobExecution((Long) null)); + context.getId(); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/context/JobSynchronizationManagerTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/context/JobSynchronizationManagerTests.java index 74fb81725..90c0a2a56 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/context/JobSynchronizationManagerTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/context/JobSynchronizationManagerTests.java @@ -1,135 +1,135 @@ -/* - * Copyright 2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope.context; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.FutureTask; -import java.util.concurrent.TimeUnit; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.springframework.batch.core.JobExecution; - -/** - * JobSynchronizationManagerTests. - * - * @author Jimmy Praet - */ -public class JobSynchronizationManagerTests { - - private JobExecution jobExecution = new JobExecution(0L); - - @Before - @After - public void start() { - while (JobSynchronizationManager.getContext() != null) { - JobSynchronizationManager.close(); - } - } - - @Test - public void testGetContext() { - assertNull(JobSynchronizationManager.getContext()); - JobSynchronizationManager.register(jobExecution); - assertNotNull(JobSynchronizationManager.getContext()); - } - - @Test - public void testClose() throws Exception { - final List list = new ArrayList<>(); - JobContext context = JobSynchronizationManager.register(jobExecution); - context.registerDestructionCallback("foo", new Runnable() { - @Override - public void run() { - list.add("foo"); - } - }); - JobSynchronizationManager.close(); - assertNull(JobSynchronizationManager.getContext()); - assertEquals(0, list.size()); - } - - @Test - public void testMultithreaded() throws Exception { - JobContext context = JobSynchronizationManager.register(jobExecution); - ExecutorService executorService = Executors.newFixedThreadPool(2); - FutureTask task = new FutureTask<>(new Callable() { - @Override - public JobContext call() throws Exception { - try { - JobSynchronizationManager.register(jobExecution); - JobContext context = JobSynchronizationManager.getContext(); - context.setAttribute("foo", "bar"); - return context; - } - finally { - JobSynchronizationManager.close(); - } - } - }); - executorService.execute(task); - executorService.awaitTermination(1, TimeUnit.SECONDS); - assertEquals(context.attributeNames().length, task.get().attributeNames().length); - JobSynchronizationManager.close(); - assertNull(JobSynchronizationManager.getContext()); - } - - @Test - public void testRelease() { - JobContext context = JobSynchronizationManager.register(jobExecution); - final List list = new ArrayList<>(); - context.registerDestructionCallback("foo", new Runnable() { - @Override - public void run() { - list.add("foo"); - } - }); - // On release we expect the destruction callbacks to be called - JobSynchronizationManager.release(); - assertNull(JobSynchronizationManager.getContext()); - assertEquals(1, list.size()); - } - - @Test - public void testRegisterNull() { - assertNull(JobSynchronizationManager.getContext()); - JobSynchronizationManager.register(null); - assertNull(JobSynchronizationManager.getContext()); - } - - @Test - public void testRegisterTwice() { - JobSynchronizationManager.register(jobExecution); - JobSynchronizationManager.register(jobExecution); - JobSynchronizationManager.close(); - // if someone registers you have to assume they are going to close, so - // the last thing you want is for the close to remove another context - // that someone else has registered - assertNotNull(JobSynchronizationManager.getContext()); - JobSynchronizationManager.close(); - assertNull(JobSynchronizationManager.getContext()); - } - -} +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope.context; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.FutureTask; +import java.util.concurrent.TimeUnit; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.springframework.batch.core.JobExecution; + +/** + * JobSynchronizationManagerTests. + * + * @author Jimmy Praet + */ +public class JobSynchronizationManagerTests { + + private JobExecution jobExecution = new JobExecution(0L); + + @Before + @After + public void start() { + while (JobSynchronizationManager.getContext() != null) { + JobSynchronizationManager.close(); + } + } + + @Test + public void testGetContext() { + assertNull(JobSynchronizationManager.getContext()); + JobSynchronizationManager.register(jobExecution); + assertNotNull(JobSynchronizationManager.getContext()); + } + + @Test + public void testClose() throws Exception { + final List list = new ArrayList<>(); + JobContext context = JobSynchronizationManager.register(jobExecution); + context.registerDestructionCallback("foo", new Runnable() { + @Override + public void run() { + list.add("foo"); + } + }); + JobSynchronizationManager.close(); + assertNull(JobSynchronizationManager.getContext()); + assertEquals(0, list.size()); + } + + @Test + public void testMultithreaded() throws Exception { + JobContext context = JobSynchronizationManager.register(jobExecution); + ExecutorService executorService = Executors.newFixedThreadPool(2); + FutureTask task = new FutureTask<>(new Callable() { + @Override + public JobContext call() throws Exception { + try { + JobSynchronizationManager.register(jobExecution); + JobContext context = JobSynchronizationManager.getContext(); + context.setAttribute("foo", "bar"); + return context; + } + finally { + JobSynchronizationManager.close(); + } + } + }); + executorService.execute(task); + executorService.awaitTermination(1, TimeUnit.SECONDS); + assertEquals(context.attributeNames().length, task.get().attributeNames().length); + JobSynchronizationManager.close(); + assertNull(JobSynchronizationManager.getContext()); + } + + @Test + public void testRelease() { + JobContext context = JobSynchronizationManager.register(jobExecution); + final List list = new ArrayList<>(); + context.registerDestructionCallback("foo", new Runnable() { + @Override + public void run() { + list.add("foo"); + } + }); + // On release we expect the destruction callbacks to be called + JobSynchronizationManager.release(); + assertNull(JobSynchronizationManager.getContext()); + assertEquals(1, list.size()); + } + + @Test + public void testRegisterNull() { + assertNull(JobSynchronizationManager.getContext()); + JobSynchronizationManager.register(null); + assertNull(JobSynchronizationManager.getContext()); + } + + @Test + public void testRegisterTwice() { + JobSynchronizationManager.register(jobExecution); + JobSynchronizationManager.register(jobExecution); + JobSynchronizationManager.close(); + // if someone registers you have to assume they are going to close, so + // the last thing you want is for the close to remove another context + // that someone else has registered + assertNotNull(JobSynchronizationManager.getContext()); + JobSynchronizationManager.close(); + assertNull(JobSynchronizationManager.getContext()); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/context/StepContextRepeatCallbackTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/context/StepContextRepeatCallbackTests.java index 5f190e4cb..1cf3a01ee 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/context/StepContextRepeatCallbackTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/context/StepContextRepeatCallbackTests.java @@ -29,14 +29,16 @@ import org.springframework.batch.repeat.RepeatStatus; /** * @author Dave Syer - * + * */ public class StepContextRepeatCallbackTests { - + private StepExecution stepExecution = new StepExecution("foo", new JobExecution(0L), 123L); + private boolean addedAttribute = false; + private boolean removedAttribute = false; - + @After public void cleanUpStepContext() { StepSynchronizationManager.close(); @@ -51,7 +53,7 @@ public class StepContextRepeatCallbackTests { return RepeatStatus.FINISHED; } }; - assertEquals(RepeatStatus.FINISHED, callback.doInIteration(null)); + assertEquals(RepeatStatus.FINISHED, callback.doInIteration(null)); assertEquals(ExitStatus.EXECUTING, stepExecution.getExitStatus()); } @@ -64,14 +66,15 @@ public class StepContextRepeatCallbackTests { if (addedAttribute) { removedAttribute = chunkContext.hasAttribute("foo"); chunkContext.removeAttribute("foo"); - } else { + } + else { addedAttribute = true; chunkContext.setAttribute("foo", "bar"); } return RepeatStatus.FINISHED; } }; - assertEquals(RepeatStatus.FINISHED, callback.doInIteration(null)); + assertEquals(RepeatStatus.FINISHED, callback.doInIteration(null)); assertTrue(addedAttribute); callback.doInIteration(null); assertTrue(removedAttribute); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/context/StepContextTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/context/StepContextTests.java index 4c795d1ab..02a2587b7 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/context/StepContextTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/context/StepContextTests.java @@ -44,7 +44,8 @@ public class StepContextTests { private List list = new ArrayList<>(); - private StepExecution stepExecution = new StepExecution("step", new JobExecution(new JobInstance(2L, "job"), 0L, null), 1L); + private StepExecution stepExecution = new StepExecution("step", + new JobExecution(new JobInstance(2L, "job"), 0L, null), 1L); private StepContext context = new StepContext(stepExecution); @@ -152,7 +153,7 @@ public class StepContextTests { @Test public void testJobInstanceId() throws Exception { - assertEquals(2L, (long)context.getJobInstanceId()); + assertEquals(2L, (long) context.getJobInstanceId()); } @Test diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/context/StepSynchronizationManagerTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/context/StepSynchronizationManagerTests.java index 215501bd4..39d529179 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/context/StepSynchronizationManagerTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/context/StepSynchronizationManagerTests.java @@ -1,131 +1,131 @@ -/* - * Copyright 2013-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.scope.context; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.FutureTask; -import java.util.concurrent.TimeUnit; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.StepExecution; - -public class StepSynchronizationManagerTests { - - private StepExecution stepExecution = new StepExecution("step", new JobExecution(0L)); - - @Before - @After - public void start() { - while (StepSynchronizationManager.getContext() != null) { - StepSynchronizationManager.close(); - } - } - - @Test - public void testGetContext() { - assertNull(StepSynchronizationManager.getContext()); - StepSynchronizationManager.register(stepExecution); - assertNotNull(StepSynchronizationManager.getContext()); - } - - @Test - public void testClose() throws Exception { - final List list = new ArrayList<>(); - StepContext context = StepSynchronizationManager.register(stepExecution); - context.registerDestructionCallback("foo", new Runnable() { - @Override - public void run() { - list.add("foo"); - } - }); - StepSynchronizationManager.close(); - assertNull(StepSynchronizationManager.getContext()); - assertEquals(0, list.size()); - } - - @Test - public void testMultithreaded() throws Exception { - StepContext context = StepSynchronizationManager.register(stepExecution); - ExecutorService executorService = Executors.newFixedThreadPool(2); - FutureTask task = new FutureTask<>(new Callable() { - @Override - public StepContext call() throws Exception { - try { - StepSynchronizationManager.register(stepExecution); - StepContext context = StepSynchronizationManager.getContext(); - context.setAttribute("foo", "bar"); - return context; - } - finally { - StepSynchronizationManager.close(); - } - } - }); - executorService.execute(task); - executorService.awaitTermination(1, TimeUnit.SECONDS); - assertEquals(context.attributeNames().length, task.get().attributeNames().length); - StepSynchronizationManager.close(); - assertNull(StepSynchronizationManager.getContext()); - } - - @Test - public void testRelease() { - StepContext context = StepSynchronizationManager.register(stepExecution); - final List list = new ArrayList<>(); - context.registerDestructionCallback("foo", new Runnable() { - @Override - public void run() { - list.add("foo"); - } - }); - // On release we expect the destruction callbacks to be called - StepSynchronizationManager.release(); - assertNull(StepSynchronizationManager.getContext()); - assertEquals(1, list.size()); - } - - @Test - public void testRegisterNull() { - assertNull(StepSynchronizationManager.getContext()); - StepSynchronizationManager.register(null); - assertNull(StepSynchronizationManager.getContext()); - } - - @Test - public void testRegisterTwice() { - StepSynchronizationManager.register(stepExecution); - StepSynchronizationManager.register(stepExecution); - StepSynchronizationManager.close(); - // if someone registers you have to assume they are going to close, so - // the last thing you want is for the close to remove another context - // that someone else has registered - assertNotNull(StepSynchronizationManager.getContext()); - StepSynchronizationManager.close(); - assertNull(StepSynchronizationManager.getContext()); - } - -} +/* + * Copyright 2013-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.scope.context; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.FutureTask; +import java.util.concurrent.TimeUnit; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.StepExecution; + +public class StepSynchronizationManagerTests { + + private StepExecution stepExecution = new StepExecution("step", new JobExecution(0L)); + + @Before + @After + public void start() { + while (StepSynchronizationManager.getContext() != null) { + StepSynchronizationManager.close(); + } + } + + @Test + public void testGetContext() { + assertNull(StepSynchronizationManager.getContext()); + StepSynchronizationManager.register(stepExecution); + assertNotNull(StepSynchronizationManager.getContext()); + } + + @Test + public void testClose() throws Exception { + final List list = new ArrayList<>(); + StepContext context = StepSynchronizationManager.register(stepExecution); + context.registerDestructionCallback("foo", new Runnable() { + @Override + public void run() { + list.add("foo"); + } + }); + StepSynchronizationManager.close(); + assertNull(StepSynchronizationManager.getContext()); + assertEquals(0, list.size()); + } + + @Test + public void testMultithreaded() throws Exception { + StepContext context = StepSynchronizationManager.register(stepExecution); + ExecutorService executorService = Executors.newFixedThreadPool(2); + FutureTask task = new FutureTask<>(new Callable() { + @Override + public StepContext call() throws Exception { + try { + StepSynchronizationManager.register(stepExecution); + StepContext context = StepSynchronizationManager.getContext(); + context.setAttribute("foo", "bar"); + return context; + } + finally { + StepSynchronizationManager.close(); + } + } + }); + executorService.execute(task); + executorService.awaitTermination(1, TimeUnit.SECONDS); + assertEquals(context.attributeNames().length, task.get().attributeNames().length); + StepSynchronizationManager.close(); + assertNull(StepSynchronizationManager.getContext()); + } + + @Test + public void testRelease() { + StepContext context = StepSynchronizationManager.register(stepExecution); + final List list = new ArrayList<>(); + context.registerDestructionCallback("foo", new Runnable() { + @Override + public void run() { + list.add("foo"); + } + }); + // On release we expect the destruction callbacks to be called + StepSynchronizationManager.release(); + assertNull(StepSynchronizationManager.getContext()); + assertEquals(1, list.size()); + } + + @Test + public void testRegisterNull() { + assertNull(StepSynchronizationManager.getContext()); + StepSynchronizationManager.register(null); + assertNull(StepSynchronizationManager.getContext()); + } + + @Test + public void testRegisterTwice() { + StepSynchronizationManager.register(stepExecution); + StepSynchronizationManager.register(stepExecution); + StepSynchronizationManager.close(); + // if someone registers you have to assume they are going to close, so + // the last thing you want is for the close to remove another context + // that someone else has registered + assertNotNull(StepSynchronizationManager.getContext()); + StepSynchronizationManager.close(); + assertNull(StepSynchronizationManager.getContext()); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/JobRepositorySupport.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/JobRepositorySupport.java index a190681c1..a2c6bbcea 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/JobRepositorySupport.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/JobRepositorySupport.java @@ -32,8 +32,12 @@ import org.springframework.lang.Nullable; */ public class JobRepositorySupport implements JobRepository { - /* (non-Javadoc) - * @see org.springframework.batch.container.common.repository.JobRepository#findOrCreateJob(org.springframework.batch.container.common.domain.JobConfiguration) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.container.common.repository.JobRepository#findOrCreateJob + * (org.springframework.batch.container.common.domain.JobConfiguration) */ @Override public JobExecution createJobExecution(String jobName, JobParameters jobParameters) { @@ -41,15 +45,23 @@ public class JobRepositorySupport implements JobRepository { return new JobExecution(jobInstance, 11L, jobParameters); } - /* (non-Javadoc) - * @see org.springframework.batch.container.common.repository.JobRepository#saveOrUpdate(org.springframework.batch.container.common.domain.JobExecution) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.container.common.repository.JobRepository#saveOrUpdate( + * org.springframework.batch.container.common.domain.JobExecution) */ @Override public void update(JobExecution jobExecution) { } - /* (non-Javadoc) - * @see org.springframework.batch.container.common.repository.JobRepository#update(org.springframework.batch.container.common.domain.Job) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.container.common.repository.JobRepository#update(org. + * springframework.batch.container.common.domain.Job) */ public void update(JobInstance job) { } @@ -85,8 +97,12 @@ public class JobRepositorySupport implements JobRepository { public void updateExecutionContext(StepExecution stepExecution) { } - /* (non-Javadoc) - * @see org.springframework.batch.core.repository.JobRepository#isJobInstanceExists(java.lang.String, org.springframework.batch.core.JobParameters) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.core.repository.JobRepository#isJobInstanceExists(java. + * lang.String, org.springframework.batch.core.JobParameters) */ @Override public boolean isJobInstanceExists(String jobName, JobParameters jobParameters) { @@ -108,8 +124,7 @@ public class JobRepositorySupport implements JobRepository { } @Override - public JobInstance createJobInstance(String jobName, - JobParameters jobParameters) { + public JobInstance createJobInstance(String jobName, JobParameters jobParameters) { return null; } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/NoSuchStepExceptionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/NoSuchStepExceptionTests.java index 47c272cbb..41fe26fb7 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/NoSuchStepExceptionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/NoSuchStepExceptionTests.java @@ -19,7 +19,6 @@ import static org.junit.Assert.assertEquals; import org.junit.Test; - public class NoSuchStepExceptionTests { @Test diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/NoWorkFoundStepExecutionListenerTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/NoWorkFoundStepExecutionListenerTests.java index 85f456feb..e0e342a2b 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/NoWorkFoundStepExecutionListenerTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/NoWorkFoundStepExecutionListenerTests.java @@ -34,7 +34,8 @@ public class NoWorkFoundStepExecutionListenerTests { @Test public void noWork() { - StepExecution stepExecution = new StepExecution("NoProcessingStep", new JobExecution(new JobInstance(1L, "NoProcessingJob"), new JobParameters())); + StepExecution stepExecution = new StepExecution("NoProcessingStep", + new JobExecution(new JobInstance(1L, "NoProcessingJob"), new JobParameters())); stepExecution.setExitStatus(ExitStatus.COMPLETED); stepExecution.setReadCount(0); @@ -45,12 +46,13 @@ public class NoWorkFoundStepExecutionListenerTests { @Test public void workDone() { - StepExecution stepExecution = new StepExecution("NoProcessingStep", new JobExecution(new JobInstance(1L, - "NoProcessingJob"), new JobParameters())); + StepExecution stepExecution = new StepExecution("NoProcessingStep", + new JobExecution(new JobInstance(1L, "NoProcessingJob"), new JobParameters())); stepExecution.setReadCount(1); ExitStatus exitStatus = tested.afterStep(stepExecution); assertNull(exitStatus); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/NonAbstractStepTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/NonAbstractStepTests.java index 450cd3826..bdf1b145b 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/NonAbstractStepTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/NonAbstractStepTests.java @@ -1,356 +1,361 @@ -/* - * Copyright 2009-2022 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.step; - -import java.util.ArrayList; -import java.util.List; - -import io.micrometer.core.instrument.Metrics; -import io.micrometer.core.instrument.Tag; -import io.micrometer.core.instrument.Tags; -import io.micrometer.core.tck.MeterRegistryAssert; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobInstance; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.StepExecutionListener; -import org.springframework.batch.core.observability.BatchStepObservation; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.lang.Nullable; -import org.springframework.util.Assert; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; - -/** - * Tests for {@link AbstractStep}. - */ -public class NonAbstractStepTests { - - AbstractStep tested = new EventTrackingStep(); - - StepExecutionListener listener1 = new EventTrackingListener("listener1"); - - StepExecutionListener listener2 = new EventTrackingListener("listener2"); - - JobRepositoryStub repository = new JobRepositoryStub(); - - /** - * Sequence of events encountered during step execution. - */ - final List events = new ArrayList<>(); - - final StepExecution execution = new StepExecution(tested.getName(), new JobExecution(new JobInstance(1L, - "jobName"), new JobParameters())); - - /** - * Fills the events list when abstract methods are called. - */ - private class EventTrackingStep extends AbstractStep { - - public EventTrackingStep() { - setBeanName("eventTrackingStep"); - } - - @Override - protected void open(ExecutionContext ctx) throws Exception { - events.add("open"); - } - - @Override - protected void doExecute(StepExecution context) throws Exception { - assertSame(execution, context); - events.add("doExecute"); - context.setExitStatus(ExitStatus.COMPLETED); - } - - @Override - protected void close(ExecutionContext ctx) throws Exception { - events.add("close"); - } - } - - /** - * Fills the events list when listener methods are called, prefixed with the name of the listener. - */ - private class EventTrackingListener implements StepExecutionListener { - - private String name; - - public EventTrackingListener(String name) { - this.name = name; - } - - private String getEvent(String event) { - return name + "#" + event; - } - - @Nullable - @Override - public ExitStatus afterStep(StepExecution stepExecution) { - assertSame(execution, stepExecution); - events.add(getEvent("afterStep(" + stepExecution.getExitStatus().getExitCode() + ")")); - stepExecution.getExecutionContext().putString("afterStep", "afterStep"); - return stepExecution.getExitStatus(); - } - - @Override - public void beforeStep(StepExecution stepExecution) { - assertSame(execution, stepExecution); - events.add(getEvent("beforeStep")); - stepExecution.getExecutionContext().putString("beforeStep", "beforeStep"); - } - - } - - /** - * Remembers the last saved values of execution context. - */ - private static class JobRepositoryStub extends JobRepositorySupport { - - ExecutionContext saved = new ExecutionContext(); - - static long counter = 0; - - @Override - public void updateExecutionContext(StepExecution stepExecution) { - Assert.state(stepExecution.getId() != null, "StepExecution must already be saved"); - saved = stepExecution.getExecutionContext(); - } - - @Override - public void add(StepExecution stepExecution) { - if (stepExecution.getId() == null) { - stepExecution.setId(counter); - counter++; - } - } - - } - - @Before - public void setUp() throws Exception { - tested.setJobRepository(repository); - repository.add(execution); - } - - @Test - public void testBeanName() throws Exception { - AbstractStep step = new AbstractStep() { - @Override - protected void doExecute(StepExecution stepExecution) throws Exception { - } - }; - assertNull(step.getName()); - step.setBeanName("foo"); - assertEquals("foo", step.getName()); - } - - @Test - public void testName() throws Exception { - AbstractStep step = new AbstractStep() { - @Override - protected void doExecute(StepExecution stepExecution) throws Exception { - } - }; - assertNull(step.getName()); - step.setName("foo"); - assertEquals("foo", step.getName()); - step.setBeanName("bar"); - assertEquals("foo", step.getName()); - } - - /** - * Typical step execution scenario. - */ - @Test - public void testExecute() throws Exception { - tested.setStepExecutionListeners(new StepExecutionListener[] { listener1, listener2 }); - tested.execute(execution); - - int i = 0; - assertEquals("listener1#beforeStep", events.get(i++)); - assertEquals("listener2#beforeStep", events.get(i++)); - assertEquals("open", events.get(i++)); - assertEquals("doExecute", events.get(i++)); - assertEquals("listener2#afterStep(COMPLETED)", events.get(i++)); - assertEquals("listener1#afterStep(COMPLETED)", events.get(i++)); - assertEquals("close", events.get(i++)); - assertEquals(7, events.size()); - - assertEquals(ExitStatus.COMPLETED, execution.getExitStatus()); - - assertTrue("Execution context modifications made by listener should be persisted", - repository.saved.containsKey("beforeStep")); - assertTrue("Execution context modifications made by listener should be persisted", - repository.saved.containsKey("afterStep")); - - // Observability - MeterRegistryAssert.assertThat(Metrics.globalRegistry) - .hasTimerWithNameAndTags(BatchStepObservation.BATCH_STEP_OBSERVATION.getName(), Tags.of(Tag.of("error", "none"), Tag.of("spring.batch.step.job.name", "jobName"), Tag.of("spring.batch.step.name", "eventTrackingStep"), Tag.of("spring.batch.step.status", "COMPLETED"))); - } - - @After - public void cleanup() { - Metrics.globalRegistry.clear(); - } - - @Test - public void testFailure() throws Exception { - tested = new EventTrackingStep() { - @Override - protected void doExecute(StepExecution context) throws Exception { - super.doExecute(context); - throw new RuntimeException("crash!"); - } - }; - tested.setJobRepository(repository); - tested.setStepExecutionListeners(new StepExecutionListener[] { listener1, listener2 }); - - tested.execute(execution); - assertEquals(BatchStatus.FAILED, execution.getStatus()); - Throwable expected = execution.getFailureExceptions().get(0); - assertEquals("crash!", expected.getMessage()); - - int i = 0; - assertEquals("listener1#beforeStep", events.get(i++)); - assertEquals("listener2#beforeStep", events.get(i++)); - assertEquals("open", events.get(i++)); - assertEquals("doExecute", events.get(i++)); - assertEquals("listener2#afterStep(FAILED)", events.get(i++)); - assertEquals("listener1#afterStep(FAILED)", events.get(i++)); - assertEquals("close", events.get(i++)); - assertEquals(7, events.size()); - - assertEquals(ExitStatus.FAILED.getExitCode(), execution.getExitStatus().getExitCode()); - String exitDescription = execution.getExitStatus().getExitDescription(); - assertTrue("Wrong message: " + exitDescription, exitDescription.contains("crash")); - - assertTrue("Execution context modifications made by listener should be persisted", - repository.saved.containsKey("afterStep")); - } - - /** - * Exception during business processing. - */ - @Test - public void testStoppedStep() throws Exception { - tested = new EventTrackingStep() { - @Override - protected void doExecute(StepExecution context) throws Exception { - context.setTerminateOnly(); - super.doExecute(context); - } - }; - tested.setJobRepository(repository); - tested.setStepExecutionListeners(new StepExecutionListener[] { listener1, listener2 }); - - tested.execute(execution); - assertEquals(BatchStatus.STOPPED, execution.getStatus()); - Throwable expected = execution.getFailureExceptions().get(0); - assertEquals("JobExecution interrupted.", expected.getMessage()); - - int i = 0; - assertEquals("listener1#beforeStep", events.get(i++)); - assertEquals("listener2#beforeStep", events.get(i++)); - assertEquals("open", events.get(i++)); - assertEquals("doExecute", events.get(i++)); - assertEquals("listener2#afterStep(STOPPED)", events.get(i++)); - assertEquals("listener1#afterStep(STOPPED)", events.get(i++)); - assertEquals("close", events.get(i++)); - assertEquals(7, events.size()); - - assertEquals("STOPPED", execution.getExitStatus().getExitCode()); - - assertTrue("Execution context modifications made by listener should be persisted", - repository.saved.containsKey("afterStep")); - } - - @Test - public void testStoppedStepWithCustomStatus() throws Exception { - tested = new EventTrackingStep() { - @Override - protected void doExecute(StepExecution context) throws Exception { - super.doExecute(context); - context.setTerminateOnly(); - context.setExitStatus(new ExitStatus("FUNNY")); - } - }; - tested.setJobRepository(repository); - tested.setStepExecutionListeners(new StepExecutionListener[] { listener1, listener2 }); - - tested.execute(execution); - assertEquals(BatchStatus.STOPPED, execution.getStatus()); - Throwable expected = execution.getFailureExceptions().get(0); - assertEquals("JobExecution interrupted.", expected.getMessage()); - - assertEquals("FUNNY", execution.getExitStatus().getExitCode()); - - assertTrue("Execution context modifications made by listener should be persisted", - repository.saved.containsKey("afterStep")); - } - - /** - * Exception during business processing. - */ - @Test - public void testFailureInSavingExecutionContext() throws Exception { - tested = new EventTrackingStep() { - @Override - protected void doExecute(StepExecution context) throws Exception { - super.doExecute(context); - } - }; - repository = new JobRepositoryStub() { - @Override - public void updateExecutionContext(StepExecution stepExecution) { - throw new RuntimeException("Bad context!"); - } - }; - tested.setJobRepository(repository); - - tested.execute(execution); - assertEquals(BatchStatus.UNKNOWN, execution.getStatus()); - Throwable expected = execution.getFailureExceptions().get(0); - assertEquals("Bad context!", expected.getMessage()); - - int i = 0; - assertEquals("open", events.get(i++)); - assertEquals("doExecute", events.get(i++)); - assertEquals("close", events.get(i++)); - assertEquals(3, events.size()); - - assertEquals(ExitStatus.UNKNOWN, execution.getExitStatus()); - } - - /** - * JobRepository is a required property. - */ - @Test(expected = IllegalStateException.class) - public void testAfterPropertiesSet() throws Exception { - tested.setJobRepository(null); - tested.afterPropertiesSet(); - } - -} +/* + * Copyright 2009-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.step; + +import java.util.ArrayList; +import java.util.List; + +import io.micrometer.core.instrument.Metrics; +import io.micrometer.core.instrument.Tag; +import io.micrometer.core.instrument.Tags; +import io.micrometer.core.tck.MeterRegistryAssert; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobInstance; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.StepExecutionListener; +import org.springframework.batch.core.observability.BatchStepObservation; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +/** + * Tests for {@link AbstractStep}. + */ +public class NonAbstractStepTests { + + AbstractStep tested = new EventTrackingStep(); + + StepExecutionListener listener1 = new EventTrackingListener("listener1"); + + StepExecutionListener listener2 = new EventTrackingListener("listener2"); + + JobRepositoryStub repository = new JobRepositoryStub(); + + /** + * Sequence of events encountered during step execution. + */ + final List events = new ArrayList<>(); + + final StepExecution execution = new StepExecution(tested.getName(), + new JobExecution(new JobInstance(1L, "jobName"), new JobParameters())); + + /** + * Fills the events list when abstract methods are called. + */ + private class EventTrackingStep extends AbstractStep { + + public EventTrackingStep() { + setBeanName("eventTrackingStep"); + } + + @Override + protected void open(ExecutionContext ctx) throws Exception { + events.add("open"); + } + + @Override + protected void doExecute(StepExecution context) throws Exception { + assertSame(execution, context); + events.add("doExecute"); + context.setExitStatus(ExitStatus.COMPLETED); + } + + @Override + protected void close(ExecutionContext ctx) throws Exception { + events.add("close"); + } + + } + + /** + * Fills the events list when listener methods are called, prefixed with the name of + * the listener. + */ + private class EventTrackingListener implements StepExecutionListener { + + private String name; + + public EventTrackingListener(String name) { + this.name = name; + } + + private String getEvent(String event) { + return name + "#" + event; + } + + @Nullable + @Override + public ExitStatus afterStep(StepExecution stepExecution) { + assertSame(execution, stepExecution); + events.add(getEvent("afterStep(" + stepExecution.getExitStatus().getExitCode() + ")")); + stepExecution.getExecutionContext().putString("afterStep", "afterStep"); + return stepExecution.getExitStatus(); + } + + @Override + public void beforeStep(StepExecution stepExecution) { + assertSame(execution, stepExecution); + events.add(getEvent("beforeStep")); + stepExecution.getExecutionContext().putString("beforeStep", "beforeStep"); + } + + } + + /** + * Remembers the last saved values of execution context. + */ + private static class JobRepositoryStub extends JobRepositorySupport { + + ExecutionContext saved = new ExecutionContext(); + + static long counter = 0; + + @Override + public void updateExecutionContext(StepExecution stepExecution) { + Assert.state(stepExecution.getId() != null, "StepExecution must already be saved"); + saved = stepExecution.getExecutionContext(); + } + + @Override + public void add(StepExecution stepExecution) { + if (stepExecution.getId() == null) { + stepExecution.setId(counter); + counter++; + } + } + + } + + @Before + public void setUp() throws Exception { + tested.setJobRepository(repository); + repository.add(execution); + } + + @Test + public void testBeanName() throws Exception { + AbstractStep step = new AbstractStep() { + @Override + protected void doExecute(StepExecution stepExecution) throws Exception { + } + }; + assertNull(step.getName()); + step.setBeanName("foo"); + assertEquals("foo", step.getName()); + } + + @Test + public void testName() throws Exception { + AbstractStep step = new AbstractStep() { + @Override + protected void doExecute(StepExecution stepExecution) throws Exception { + } + }; + assertNull(step.getName()); + step.setName("foo"); + assertEquals("foo", step.getName()); + step.setBeanName("bar"); + assertEquals("foo", step.getName()); + } + + /** + * Typical step execution scenario. + */ + @Test + public void testExecute() throws Exception { + tested.setStepExecutionListeners(new StepExecutionListener[] { listener1, listener2 }); + tested.execute(execution); + + int i = 0; + assertEquals("listener1#beforeStep", events.get(i++)); + assertEquals("listener2#beforeStep", events.get(i++)); + assertEquals("open", events.get(i++)); + assertEquals("doExecute", events.get(i++)); + assertEquals("listener2#afterStep(COMPLETED)", events.get(i++)); + assertEquals("listener1#afterStep(COMPLETED)", events.get(i++)); + assertEquals("close", events.get(i++)); + assertEquals(7, events.size()); + + assertEquals(ExitStatus.COMPLETED, execution.getExitStatus()); + + assertTrue("Execution context modifications made by listener should be persisted", + repository.saved.containsKey("beforeStep")); + assertTrue("Execution context modifications made by listener should be persisted", + repository.saved.containsKey("afterStep")); + + // Observability + MeterRegistryAssert.assertThat(Metrics.globalRegistry).hasTimerWithNameAndTags( + BatchStepObservation.BATCH_STEP_OBSERVATION.getName(), + Tags.of(Tag.of("error", "none"), Tag.of("spring.batch.step.job.name", "jobName"), + Tag.of("spring.batch.step.name", "eventTrackingStep"), + Tag.of("spring.batch.step.status", "COMPLETED"))); + } + + @After + public void cleanup() { + Metrics.globalRegistry.clear(); + } + + @Test + public void testFailure() throws Exception { + tested = new EventTrackingStep() { + @Override + protected void doExecute(StepExecution context) throws Exception { + super.doExecute(context); + throw new RuntimeException("crash!"); + } + }; + tested.setJobRepository(repository); + tested.setStepExecutionListeners(new StepExecutionListener[] { listener1, listener2 }); + + tested.execute(execution); + assertEquals(BatchStatus.FAILED, execution.getStatus()); + Throwable expected = execution.getFailureExceptions().get(0); + assertEquals("crash!", expected.getMessage()); + + int i = 0; + assertEquals("listener1#beforeStep", events.get(i++)); + assertEquals("listener2#beforeStep", events.get(i++)); + assertEquals("open", events.get(i++)); + assertEquals("doExecute", events.get(i++)); + assertEquals("listener2#afterStep(FAILED)", events.get(i++)); + assertEquals("listener1#afterStep(FAILED)", events.get(i++)); + assertEquals("close", events.get(i++)); + assertEquals(7, events.size()); + + assertEquals(ExitStatus.FAILED.getExitCode(), execution.getExitStatus().getExitCode()); + String exitDescription = execution.getExitStatus().getExitDescription(); + assertTrue("Wrong message: " + exitDescription, exitDescription.contains("crash")); + + assertTrue("Execution context modifications made by listener should be persisted", + repository.saved.containsKey("afterStep")); + } + + /** + * Exception during business processing. + */ + @Test + public void testStoppedStep() throws Exception { + tested = new EventTrackingStep() { + @Override + protected void doExecute(StepExecution context) throws Exception { + context.setTerminateOnly(); + super.doExecute(context); + } + }; + tested.setJobRepository(repository); + tested.setStepExecutionListeners(new StepExecutionListener[] { listener1, listener2 }); + + tested.execute(execution); + assertEquals(BatchStatus.STOPPED, execution.getStatus()); + Throwable expected = execution.getFailureExceptions().get(0); + assertEquals("JobExecution interrupted.", expected.getMessage()); + + int i = 0; + assertEquals("listener1#beforeStep", events.get(i++)); + assertEquals("listener2#beforeStep", events.get(i++)); + assertEquals("open", events.get(i++)); + assertEquals("doExecute", events.get(i++)); + assertEquals("listener2#afterStep(STOPPED)", events.get(i++)); + assertEquals("listener1#afterStep(STOPPED)", events.get(i++)); + assertEquals("close", events.get(i++)); + assertEquals(7, events.size()); + + assertEquals("STOPPED", execution.getExitStatus().getExitCode()); + + assertTrue("Execution context modifications made by listener should be persisted", + repository.saved.containsKey("afterStep")); + } + + @Test + public void testStoppedStepWithCustomStatus() throws Exception { + tested = new EventTrackingStep() { + @Override + protected void doExecute(StepExecution context) throws Exception { + super.doExecute(context); + context.setTerminateOnly(); + context.setExitStatus(new ExitStatus("FUNNY")); + } + }; + tested.setJobRepository(repository); + tested.setStepExecutionListeners(new StepExecutionListener[] { listener1, listener2 }); + + tested.execute(execution); + assertEquals(BatchStatus.STOPPED, execution.getStatus()); + Throwable expected = execution.getFailureExceptions().get(0); + assertEquals("JobExecution interrupted.", expected.getMessage()); + + assertEquals("FUNNY", execution.getExitStatus().getExitCode()); + + assertTrue("Execution context modifications made by listener should be persisted", + repository.saved.containsKey("afterStep")); + } + + /** + * Exception during business processing. + */ + @Test + public void testFailureInSavingExecutionContext() throws Exception { + tested = new EventTrackingStep() { + @Override + protected void doExecute(StepExecution context) throws Exception { + super.doExecute(context); + } + }; + repository = new JobRepositoryStub() { + @Override + public void updateExecutionContext(StepExecution stepExecution) { + throw new RuntimeException("Bad context!"); + } + }; + tested.setJobRepository(repository); + + tested.execute(execution); + assertEquals(BatchStatus.UNKNOWN, execution.getStatus()); + Throwable expected = execution.getFailureExceptions().get(0); + assertEquals("Bad context!", expected.getMessage()); + + int i = 0; + assertEquals("open", events.get(i++)); + assertEquals("doExecute", events.get(i++)); + assertEquals("close", events.get(i++)); + assertEquals(3, events.size()); + + assertEquals(ExitStatus.UNKNOWN, execution.getExitStatus()); + } + + /** + * JobRepository is a required property. + */ + @Test(expected = IllegalStateException.class) + public void testAfterPropertiesSet() throws Exception { + tested.setJobRepository(null); + tested.afterPropertiesSet(); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/RestartInPriorStepTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/RestartInPriorStepTests.java index 0cdef27b8..dc03023f6 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/RestartInPriorStepTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/RestartInPriorStepTests.java @@ -47,7 +47,8 @@ import static org.junit.Assert.assertEquals; */ @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) -// FIXME this test fails when upgrading the batch xsd from 2.2 to 3.0: https://github.com/spring-projects/spring-batch/issues/1287 +// FIXME this test fails when upgrading the batch xsd from 2.2 to 3.0: +// https://github.com/spring-projects/spring-batch/issues/1287 public class RestartInPriorStepTests { @Autowired @@ -76,19 +77,20 @@ public class RestartInPriorStepTests { @Nullable @Override - public RepeatStatus execute(StepContribution contribution, - ChunkContext chunkContext) throws Exception { + public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { Map context = chunkContext.getStepContext().getJobExecutionContext(); - if(context.get("restart") != null) { + if (context.get("restart") != null) { contribution.setExitStatus(new ExitStatus("ES3")); - } else { + } + else { chunkContext.getStepContext().setAttribute("restart", true); contribution.setExitStatus(new ExitStatus("ES4")); } return RepeatStatus.FINISHED; } + } public static class CompletionDecider implements JobExecutionDecider { @@ -96,16 +98,17 @@ public class RestartInPriorStepTests { private int count = 0; @Override - public FlowExecutionStatus decide(JobExecution jobExecution, - @Nullable StepExecution stepExecution) { + public FlowExecutionStatus decide(JobExecution jobExecution, @Nullable StepExecution stepExecution) { count++; - if(count > 2) { + if (count > 2) { return new FlowExecutionStatus("END"); } else { return new FlowExecutionStatus("CONTINUE"); } } + } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/RestartLoopTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/RestartLoopTests.java index 6c497ec7b..d1af78d0e 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/RestartLoopTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/RestartLoopTests.java @@ -60,10 +60,13 @@ public class RestartLoopTests { } public static class DefaultTasklet implements Tasklet { + @Nullable @Override public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { return RepeatStatus.FINISHED; } + } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/StepLocatorStepFactoryBeanTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/StepLocatorStepFactoryBeanTests.java index 1989990aa..b43e2caaa 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/StepLocatorStepFactoryBeanTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/StepLocatorStepFactoryBeanTests.java @@ -37,7 +37,7 @@ public class StepLocatorStepFactoryBeanTests { Step testStep2 = buildTestStep("bar"); Step testStep3 = buildTestStep("baz"); - SimpleJob simpleJob = new SimpleJob(); // is a StepLocator + SimpleJob simpleJob = new SimpleJob(); // is a StepLocator simpleJob.addStep(testStep1); simpleJob.addStep(testStep2); simpleJob.addStep(testStep3); @@ -76,4 +76,5 @@ public class StepLocatorStepFactoryBeanTests { public void testGetObjectType() { assertTrue((new StepLocatorStepFactoryBean()).getObjectType().isAssignableFrom(Step.class)); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/StepSupport.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/StepSupport.java index d235745d1..057c07d87 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/StepSupport.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/StepSupport.java @@ -22,8 +22,9 @@ import org.springframework.batch.core.UnexpectedJobExecutionException; import org.springframework.beans.factory.BeanNameAware; /** - * Basic no-op support implementation for use as base class for {@link Step}. Implements {@link BeanNameAware} so that - * if no name is provided explicitly it will be inferred from the bean definition in Spring configuration. + * Basic no-op support implementation for use as base class for {@link Step}. Implements + * {@link BeanNameAware} so that if no name is provided explicitly it will be inferred + * from the bean definition in Spring configuration. * * @author Dave Syer * @@ -57,9 +58,11 @@ public class StepSupport implements Step, BeanNameAware { } /** - * Set the name property if it is not already set. Because of the order of the callbacks in a Spring container the - * name property will be set first if it is present. Care is needed with bean definition inheritance - if a parent - * bean has a name, then its children need an explicit name as well, otherwise they will not be unique. + * Set the name property if it is not already set. Because of the order of the + * callbacks in a Spring container the name property will be set first if it is + * present. Care is needed with bean definition inheritance - if a parent bean has a + * name, then its children need an explicit name as well, otherwise they will not be + * unique. * * @see org.springframework.beans.factory.BeanNameAware#setBeanName(java.lang.String) */ @@ -71,7 +74,8 @@ public class StepSupport implements Step, BeanNameAware { } /** - * Set the name property. Always overrides the default value if this object is a Spring bean. + * Set the name property. Always overrides the default value if this object is a + * Spring bean. * * @see #setBeanName(java.lang.String) */ @@ -86,7 +90,6 @@ public class StepSupport implements Step, BeanNameAware { /** * Public setter for the startLimit. - * * @param startLimit the startLimit to set */ public void setStartLimit(int startLimit) { @@ -100,7 +103,6 @@ public class StepSupport implements Step, BeanNameAware { /** * Public setter for the shouldAllowStartIfComplete. - * * @param allowStartIfComplete the shouldAllowStartIfComplete to set */ public void setAllowStartIfComplete(boolean allowStartIfComplete) { @@ -109,7 +111,6 @@ public class StepSupport implements Step, BeanNameAware { /** * Not supported but provided so that tests can easily create a step. - * * @throws UnsupportedOperationException always * * @see org.springframework.batch.core.Step#execute(org.springframework.batch.core.StepExecution) @@ -119,4 +120,5 @@ public class StepSupport implements Step, BeanNameAware { throw new UnsupportedOperationException( "Cannot process a StepExecution. Use a smarter subclass of StepSupport."); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/ThreadStepInterruptionPolicyTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/ThreadStepInterruptionPolicyTests.java index e31b7b776..f2dd035f4 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/ThreadStepInterruptionPolicyTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/ThreadStepInterruptionPolicyTests.java @@ -27,11 +27,13 @@ import org.springframework.batch.core.StepExecution; public class ThreadStepInterruptionPolicyTests extends TestCase { ThreadStepInterruptionPolicy policy = new ThreadStepInterruptionPolicy(); + private StepExecution context = new StepExecution("stepSupport", null); - + /** - * Test method for {@link org.springframework.batch.core.step.ThreadStepInterruptionPolicy#checkInterrupted(StepExecution)}. - * @throws Exception + * Test method for + * {@link org.springframework.batch.core.step.ThreadStepInterruptionPolicy#checkInterrupted(StepExecution)}. + * @throws Exception */ public void testCheckInterruptedNotComplete() throws Exception { policy.checkInterrupted(context); @@ -39,17 +41,19 @@ public class ThreadStepInterruptionPolicyTests extends TestCase { } /** - * Test method for {@link org.springframework.batch.core.step.ThreadStepInterruptionPolicy#checkInterrupted(StepExecution)}. - * @throws Exception + * Test method for + * {@link org.springframework.batch.core.step.ThreadStepInterruptionPolicy#checkInterrupted(StepExecution)}. + * @throws Exception */ public void testCheckInterruptedComplete() throws Exception { context.setTerminateOnly(); try { policy.checkInterrupted(context); fail("Expected StepInterruptedException"); - } catch (JobInterruptedException e) { + } + catch (JobInterruptedException e) { // expected - assertTrue(e.getMessage().indexOf("interrupt")>=0); + assertTrue(e.getMessage().indexOf("interrupt") >= 0); } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/builder/FaultTolerantStepBuilderTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/builder/FaultTolerantStepBuilderTests.java index b9f5bf331..017ea30b1 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/builder/FaultTolerantStepBuilderTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/builder/FaultTolerantStepBuilderTests.java @@ -21,9 +21,10 @@ import static org.junit.Assert.assertEquals; public class FaultTolerantStepBuilderTests { - @Test - public void faultTolerantReturnsSameInstance() { - FaultTolerantStepBuilder builder = new FaultTolerantStepBuilder<>(new StepBuilder("test")); - assertEquals(builder, builder.faultTolerant()); - } + @Test + public void faultTolerantReturnsSameInstance() { + FaultTolerantStepBuilder builder = new FaultTolerantStepBuilder<>(new StepBuilder("test")); + assertEquals(builder, builder.faultTolerant()); + } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/builder/RegisterMultiListenerTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/builder/RegisterMultiListenerTests.java index 262253c29..12c51eb11 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/builder/RegisterMultiListenerTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/builder/RegisterMultiListenerTests.java @@ -81,20 +81,16 @@ public class RegisterMultiListenerTests { job = null; callChecker = null; - if(context != null) { + if (context != null) { context.close(); } } /** - * The times the beforeChunkCalled occurs are: - * - Before chunk 1 (item1, item2) - * - Before the re-attempt of item1 (scanning) - * - Before the re-attempt of item2 (scanning) - * - Before the checking that scanning is complete - * - Before chunk 2 (item3, item4) - * - Before chunk 3 (null) - * + * The times the beforeChunkCalled occurs are: - Before chunk 1 (item1, item2) - + * Before the re-attempt of item1 (scanning) - Before the re-attempt of item2 + * (scanning) - Before the checking that scanning is complete - Before chunk 2 (item3, + * item4) - Before chunk 3 (null) * @throws Exception */ @Test @@ -123,7 +119,8 @@ public class RegisterMultiListenerTests { private void bootstrap(Class configurationClass) { context = new AnnotationConfigApplicationContext(configurationClass); - context.getAutowireCapableBeanFactory().autowireBeanProperties(this, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, false); + context.getAutowireCapableBeanFactory().autowireBeanProperties(this, + AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, false); } public static abstract class MultiListenerTestConfigurationSupport { @@ -135,38 +132,36 @@ public class RegisterMultiListenerTests { protected StepBuilderFactory stepBuilders; @Bean - public Job testJob(){ - return jobBuilders.get("testJob") - .start(step()) - .build(); + public Job testJob() { + return jobBuilders.get("testJob").start(step()).build(); } @Bean - public CallChecker callChecker(){ + public CallChecker callChecker() { return new CallChecker(); } @Bean - public MultiListener listener(){ + public MultiListener listener() { return new MultiListener(callChecker()); } @Bean - public ItemReader reader(){ - return new ItemReader(){ + public ItemReader reader() { + return new ItemReader() { private int count = 0; @Nullable @Override - public String read() throws Exception, - UnexpectedInputException, ParseException, - NonTransientResourceException { + public String read() + throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException { count++; - if(count < 5) { + if (count < 5) { return "item" + count; - } else { + } + else { return null; } } @@ -175,13 +170,12 @@ public class RegisterMultiListenerTests { } @Bean - public ItemWriter writer(){ - return new ItemWriter(){ + public ItemWriter writer() { + return new ItemWriter() { @Override - public void write(List items) - throws Exception { - if(items.contains("item2")) { + public void write(List items) throws Exception { + if (items.contains("item2")) { throw new MySkippableException(); } } @@ -190,73 +184,67 @@ public class RegisterMultiListenerTests { } public abstract Step step(); + } @Configuration @EnableBatchProcessing - public static class MultiListenerFaultTolerantTestConfiguration extends MultiListenerTestConfigurationSupport{ + public static class MultiListenerFaultTolerantTestConfiguration extends MultiListenerTestConfigurationSupport { @Bean - public DataSource dataSource(){ + public DataSource dataSource() { return new PooledEmbeddedDataSource(new EmbeddedDatabaseBuilder() - .addScript("classpath:org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("classpath:org/springframework/batch/core/schema-hsqldb.sql") - .setType(EmbeddedDatabaseType.HSQL) - .generateUniqueName(true) - .build()); + .addScript("classpath:org/springframework/batch/core/schema-drop-hsqldb.sql") + .addScript("classpath:org/springframework/batch/core/schema-hsqldb.sql") + .setType(EmbeddedDatabaseType.HSQL).generateUniqueName(true).build()); } @Override @Bean - public Step step(){ - return stepBuilders.get("step") - .listener(listener()) - .chunk(2) - .reader(reader()) - .writer(writer()) - .faultTolerant() - .skipLimit(1) - .skip(MySkippableException.class) + public Step step() { + return stepBuilders.get("step").listener(listener()).chunk(2).reader(reader()) + .writer(writer()).faultTolerant().skipLimit(1).skip(MySkippableException.class) // ChunkListener registered twice for checking BATCH-2149 - .listener((ChunkListener) listener()) - .build(); + .listener((ChunkListener) listener()).build(); } + } @Configuration @EnableBatchProcessing - public static class MultiListenerTestConfiguration extends MultiListenerTestConfigurationSupport{ + public static class MultiListenerTestConfiguration extends MultiListenerTestConfigurationSupport { @Bean - public DataSource dataSource(){ + public DataSource dataSource() { return new PooledEmbeddedDataSource(new EmbeddedDatabaseBuilder() - .addScript("classpath:org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("classpath:org/springframework/batch/core/schema-hsqldb.sql") - .setType(EmbeddedDatabaseType.HSQL) - .generateUniqueName(true) - .build()); + .addScript("classpath:org/springframework/batch/core/schema-drop-hsqldb.sql") + .addScript("classpath:org/springframework/batch/core/schema-hsqldb.sql") + .setType(EmbeddedDatabaseType.HSQL).generateUniqueName(true).build()); } @Override @Bean - public Step step(){ - return stepBuilders.get("step") - .listener(listener()) - .chunk(2) - .reader(reader()) - .writer(writer()) - .build(); + public Step step() { + return stepBuilders.get("step").listener(listener()).chunk(2).reader(reader()) + .writer(writer()).build(); } + } private static class CallChecker { + int beforeStepCalled = 0; + int beforeChunkCalled = 0; + int beforeWriteCalled = 0; + int skipInWriteCalled = 0; + } - private static class MultiListener implements StepExecutionListener, ChunkListener, ItemWriteListener, SkipListener{ + private static class MultiListener + implements StepExecutionListener, ChunkListener, ItemWriteListener, SkipListener { private CallChecker callChecker; @@ -288,8 +276,7 @@ public class RegisterMultiListenerTests { } @Override - public void onWriteError(Exception exception, - List items) { + public void onWriteError(Exception exception, List items) { } @Override @@ -318,7 +305,7 @@ public class RegisterMultiListenerTests { } - private static class MySkippableException extends RuntimeException{ + private static class MySkippableException extends RuntimeException { private static final long serialVersionUID = 1L; diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/builder/StepBuilderTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/builder/StepBuilderTests.java index f80dd2a02..8509fb408 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/builder/StepBuilderTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/builder/StepBuilderTests.java @@ -70,8 +70,7 @@ public class StepBuilderTests { public void setUp() throws Exception { EmbeddedDatabase embeddedDatabase = new EmbeddedDatabaseBuilder() .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("/org/springframework/batch/core/schema-hsqldb.sql") - .build(); + .addScript("/org/springframework/batch/core/schema-hsqldb.sql").build(); DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(embeddedDatabase); JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); factory.setDataSource(embeddedDatabase); @@ -82,8 +81,8 @@ public class StepBuilderTests { @Test public void test() throws Exception { - StepExecution execution = jobRepository.createJobExecution("foo", new JobParameters()).createStepExecution( - "step"); + StepExecution execution = jobRepository.createJobExecution("foo", new JobParameters()) + .createStepExecution("step"); jobRepository.add(execution); PlatformTransactionManager transactionManager = new ResourcelessTransactionManager(); TaskletStepBuilder builder = new StepBuilder("step").repository(jobRepository) @@ -94,15 +93,13 @@ public class StepBuilderTests { @Test public void testListeners() throws Exception { - StepExecution execution = jobRepository.createJobExecution("foo", new JobParameters()).createStepExecution("step"); + StepExecution execution = jobRepository.createJobExecution("foo", new JobParameters()) + .createStepExecution("step"); jobRepository.add(execution); PlatformTransactionManager transactionManager = new ResourcelessTransactionManager(); - TaskletStepBuilder builder = new StepBuilder("step") - .repository(jobRepository) - .transactionManager(transactionManager) - .listener(new InterfaceBasedStepExecutionListener()) - .listener(new AnnotationBasedStepExecutionListener()) - .tasklet((contribution, chunkContext) -> null); + TaskletStepBuilder builder = new StepBuilder("step").repository(jobRepository) + .transactionManager(transactionManager).listener(new InterfaceBasedStepExecutionListener()) + .listener(new AnnotationBasedStepExecutionListener()).tasklet((contribution, chunkContext) -> null); builder.build().execute(execution); assertEquals(BatchStatus.COMPLETED, execution.getStatus()); assertEquals(1, InterfaceBasedStepExecutionListener.beforeStepCount); @@ -115,13 +112,12 @@ public class StepBuilderTests { @Test public void testAnnotationBasedChunkListenerForTaskletStep() throws Exception { - StepExecution execution = jobRepository.createJobExecution("foo", new JobParameters()).createStepExecution("step"); + StepExecution execution = jobRepository.createJobExecution("foo", new JobParameters()) + .createStepExecution("step"); jobRepository.add(execution); PlatformTransactionManager transactionManager = new ResourcelessTransactionManager(); - TaskletStepBuilder builder = new StepBuilder("step") - .repository(jobRepository) - .transactionManager(transactionManager) - .tasklet((contribution, chunkContext) -> null) + TaskletStepBuilder builder = new StepBuilder("step").repository(jobRepository) + .transactionManager(transactionManager).tasklet((contribution, chunkContext) -> null) .listener(new AnnotationBasedChunkListener()); builder.build().execute(execution); assertEquals(BatchStatus.COMPLETED, execution.getStatus()); @@ -131,16 +127,13 @@ public class StepBuilderTests { @Test public void testAnnotationBasedChunkListenerForSimpleTaskletStep() throws Exception { - StepExecution execution = jobRepository.createJobExecution("foo", new JobParameters()).createStepExecution("step"); + StepExecution execution = jobRepository.createJobExecution("foo", new JobParameters()) + .createStepExecution("step"); jobRepository.add(execution); PlatformTransactionManager transactionManager = new ResourcelessTransactionManager(); - SimpleStepBuilder builder = new StepBuilder("step") - .repository(jobRepository) - .transactionManager(transactionManager) - .chunk(5) - .reader(new DummyItemReader()) - .writer(new DummyItemWriter()) - .listener(new AnnotationBasedChunkListener()); + SimpleStepBuilder builder = new StepBuilder("step").repository(jobRepository) + .transactionManager(transactionManager).chunk(5).reader(new DummyItemReader()) + .writer(new DummyItemWriter()).listener(new AnnotationBasedChunkListener()); builder.build().execute(execution); assertEquals(BatchStatus.COMPLETED, execution.getStatus()); assertEquals(1, AnnotationBasedChunkListener.beforeChunkCount); @@ -149,17 +142,17 @@ public class StepBuilderTests { @Test public void testAnnotationBasedChunkListenerForFaultTolerantTaskletStep() throws Exception { - StepExecution execution = jobRepository.createJobExecution("foo", new JobParameters()).createStepExecution("step"); + StepExecution execution = jobRepository.createJobExecution("foo", new JobParameters()) + .createStepExecution("step"); jobRepository.add(execution); PlatformTransactionManager transactionManager = new ResourcelessTransactionManager(); - SimpleStepBuilder builder = new StepBuilder("step") - .repository(jobRepository) - .transactionManager(transactionManager) - .chunk(5) - .reader(new DummyItemReader()) - .writer(new DummyItemWriter()) - .faultTolerant() - .listener(new AnnotationBasedChunkListener()); // TODO should this return FaultTolerantStepBuilder? + SimpleStepBuilder builder = new StepBuilder("step").repository(jobRepository) + .transactionManager(transactionManager).chunk(5).reader(new DummyItemReader()) + .writer(new DummyItemWriter()).faultTolerant().listener(new AnnotationBasedChunkListener()); // TODO + // should + // this + // return + // FaultTolerantStepBuilder? builder.build().execute(execution); assertEquals(BatchStatus.COMPLETED, execution.getStatus()); assertEquals(1, AnnotationBasedChunkListener.beforeChunkCount); @@ -168,27 +161,27 @@ public class StepBuilderTests { @Test public void testAnnotationBasedChunkListenerForJobStepBuilder() throws Exception { - StepExecution execution = jobRepository.createJobExecution("foo", new JobParameters()).createStepExecution("step"); + StepExecution execution = jobRepository.createJobExecution("foo", new JobParameters()) + .createStepExecution("step"); jobRepository.add(execution); PlatformTransactionManager transactionManager = new ResourcelessTransactionManager(); SimpleJob job = new SimpleJob("job"); job.setJobRepository(jobRepository); - JobStepBuilder builder = new StepBuilder("step") - .repository(jobRepository) - .transactionManager(transactionManager) - .job(job) - .listener(new AnnotationBasedChunkListener()); + JobStepBuilder builder = new StepBuilder("step").repository(jobRepository) + .transactionManager(transactionManager).job(job).listener(new AnnotationBasedChunkListener()); builder.build().execute(execution); assertEquals(BatchStatus.COMPLETED, execution.getStatus()); - // it makes no sense to register a ChunkListener on a step which is not of type tasklet, so it should not be invoked + // it makes no sense to register a ChunkListener on a step which is not of type + // tasklet, so it should not be invoked assertEquals(0, AnnotationBasedChunkListener.beforeChunkCount); assertEquals(0, AnnotationBasedChunkListener.afterChunkCount); } @Test public void testItemListeners() throws Exception { - StepExecution execution = jobRepository.createJobExecution("foo", new JobParameters()).createStepExecution("step"); + StepExecution execution = jobRepository.createJobExecution("foo", new JobParameters()) + .createStepExecution("step"); jobRepository.add(execution); PlatformTransactionManager transactionManager = new ResourcelessTransactionManager(); @@ -196,14 +189,10 @@ public class StepBuilderTests { ItemReader reader = new ListItemReader<>(items); - SimpleStepBuilder builder = new StepBuilder("step") - .repository(jobRepository) - .transactionManager(transactionManager) - .chunk(3) - .reader(reader) - .processor(new PassThroughItemProcessor<>()) - .writer(new DummyItemWriter()) - .listener(new AnnotationBasedStepExecutionListener()); + SimpleStepBuilder builder = new StepBuilder("step").repository(jobRepository) + .transactionManager(transactionManager).chunk(3).reader(reader) + .processor(new PassThroughItemProcessor<>()).writer(new DummyItemWriter()) + .listener(new AnnotationBasedStepExecutionListener()); builder.build().execute(execution); assertEquals(BatchStatus.COMPLETED, execution.getStatus()); @@ -230,7 +219,8 @@ public class StepBuilderTests { } private void assertStepFunctions(boolean faultTolerantStep) throws Exception { - StepExecution execution = jobRepository.createJobExecution("foo", new JobParameters()).createStepExecution("step"); + StepExecution execution = jobRepository.createJobExecution("foo", new JobParameters()) + .createStepExecution("step"); jobRepository.add(execution); PlatformTransactionManager transactionManager = new ResourcelessTransactionManager(); @@ -239,14 +229,9 @@ public class StepBuilderTests { ItemReader reader = new ListItemReader<>(items); ListItemWriter itemWriter = new ListItemWriter<>(); - SimpleStepBuilder builder = new StepBuilder("step") - .repository(jobRepository) - .transactionManager(transactionManager) - .chunk(3) - .reader(reader) - .processor(Object::toString) - .writer(itemWriter) - .listener(new AnnotationBasedStepExecutionListener()); + SimpleStepBuilder builder = new StepBuilder("step").repository(jobRepository) + .transactionManager(transactionManager).chunk(3).reader(reader) + .processor(Object::toString).writer(itemWriter).listener(new AnnotationBasedStepExecutionListener()); if (faultTolerantStep) { builder = builder.faultTolerant(); @@ -277,6 +262,7 @@ public class StepBuilderTests { afterStepCount++; return stepExecution.getExitStatus(); } + } @SuppressWarnings("unused") @@ -356,6 +342,7 @@ public class StepBuilderTests { public void afterChunk() { afterChunkCount++; } + } public static class AnnotationBasedChunkListener { @@ -384,5 +371,7 @@ public class StepBuilderTests { public void afterChunkError() { afterChunkErrorCount++; } + } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/AbstractExceptionThrowingItemHandlerStub.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/AbstractExceptionThrowingItemHandlerStub.java index 7c70f9114..f7bdfaeaf 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/AbstractExceptionThrowingItemHandlerStub.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/AbstractExceptionThrowingItemHandlerStub.java @@ -1,89 +1,90 @@ -/* - * Copyright 2006-2009 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.step.item; - -import java.lang.reflect.Constructor; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * @author Dan Garrette - * @since 2.0.1 - */ -public abstract class AbstractExceptionThrowingItemHandlerStub { - - protected Log logger = LogFactory.getLog(getClass()); - - private Collection failures = Collections.emptyList(); - - private Constructor exception; - - public AbstractExceptionThrowingItemHandlerStub() throws Exception { - exception = SkippableRuntimeException.class.getConstructor(String.class); - } - - @SuppressWarnings("unchecked") - public void setFailures(T... failures) { - this.failures = new ArrayList<>(Arrays.asList(failures)); - } - - public void setExceptionType(Class exceptionType) throws Exception { - try { - exception = exceptionType.getConstructor(String.class); - } - catch (NoSuchMethodException e) { - try { - exception = exceptionType.getConstructor(String.class, Throwable.class); - } - catch (NoSuchMethodException ex) { - exception = exceptionType.getConstructor(Object.class); - } - } - } - - public void clearFailures() { - failures.clear(); - } - - protected void checkFailure(T item) throws Exception { - if (isFailure(item)) { - Throwable t = getException("Intended Failure: " + item); - if (t instanceof Exception) { - throw (Exception) t; - } - if (t instanceof Error) { - throw (Error) t; - } - throw new IllegalStateException("Unexpected non-Error Throwable"); - } - } - - private Throwable getException(String string) throws Exception { - if (exception.getParameterTypes().length==1) { - return exception.newInstance(string); - } - return exception.newInstance(string, new RuntimeException("Planned")); - } - - protected boolean isFailure(T item) { - return this.failures.contains(item); - } -} +/* + * Copyright 2006-2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.step.item; + +import java.lang.reflect.Constructor; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * @author Dan Garrette + * @since 2.0.1 + */ +public abstract class AbstractExceptionThrowingItemHandlerStub { + + protected Log logger = LogFactory.getLog(getClass()); + + private Collection failures = Collections.emptyList(); + + private Constructor exception; + + public AbstractExceptionThrowingItemHandlerStub() throws Exception { + exception = SkippableRuntimeException.class.getConstructor(String.class); + } + + @SuppressWarnings("unchecked") + public void setFailures(T... failures) { + this.failures = new ArrayList<>(Arrays.asList(failures)); + } + + public void setExceptionType(Class exceptionType) throws Exception { + try { + exception = exceptionType.getConstructor(String.class); + } + catch (NoSuchMethodException e) { + try { + exception = exceptionType.getConstructor(String.class, Throwable.class); + } + catch (NoSuchMethodException ex) { + exception = exceptionType.getConstructor(Object.class); + } + } + } + + public void clearFailures() { + failures.clear(); + } + + protected void checkFailure(T item) throws Exception { + if (isFailure(item)) { + Throwable t = getException("Intended Failure: " + item); + if (t instanceof Exception) { + throw (Exception) t; + } + if (t instanceof Error) { + throw (Error) t; + } + throw new IllegalStateException("Unexpected non-Error Throwable"); + } + } + + private Throwable getException(String string) throws Exception { + if (exception.getParameterTypes().length == 1) { + return exception.newInstance(string); + } + return exception.newInstance(string, new RuntimeException("Planned")); + } + + protected boolean isFailure(T item) { + return this.failures.contains(item); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/AlmostStatefulRetryChunkTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/AlmostStatefulRetryChunkTests.java index aa55f2009..947ec4cce 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/AlmostStatefulRetryChunkTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/AlmostStatefulRetryChunkTests.java @@ -32,7 +32,7 @@ import static org.junit.Assert.assertTrue; /** * @author Dave Syer - * + * */ @RunWith(Parameterized.class) public class AlmostStatefulRetryChunkTests { @@ -77,11 +77,11 @@ public class AlmostStatefulRetryChunkTests { assertTrue("Backstop reached. Probably an infinite loop...", count < BACKSTOP_LIMIT); assertFalse(chunk.getItems().contains("fail")); assertEquals(items, chunk.getItems()); - assertEquals(before-chunk.getItems().size(), chunk.getSkips().size()); + assertEquals(before - chunk.getItems().size(), chunk.getSkips().size()); } /** - * @param chunk Chunk to retry + * @param chunk Chunk to retry */ private void statefulRetry(Chunk chunk) throws Exception { if (retryAttempts <= retryLimit) { @@ -119,7 +119,8 @@ public class AlmostStatefulRetryChunkTests { String string = iterator.next(); try { doWrite(Collections.singletonList(string)); - } catch (Exception e) { + } + catch (Exception e) { iterator.remove(e); throw e; } @@ -156,4 +157,5 @@ public class AlmostStatefulRetryChunkTests { params.add(new Object[] { new String[] { "foo", "fail", "fail", "fail", "rab", "oof" }, 4 }); return params; } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/BatchRetryTemplateTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/BatchRetryTemplateTests.java index 0550061a3..10eb6e167 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/BatchRetryTemplateTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/BatchRetryTemplateTests.java @@ -1,227 +1,227 @@ -/* - * Copyright 2008-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.step.item; - -import org.junit.Test; -import org.springframework.retry.ExhaustedRetryException; -import org.springframework.retry.RecoveryCallback; -import org.springframework.retry.RetryCallback; -import org.springframework.retry.RetryContext; -import org.springframework.retry.RetryState; -import org.springframework.retry.policy.SimpleRetryPolicy; -import org.springframework.retry.support.DefaultRetryState; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -public class BatchRetryTemplateTests { - - @SuppressWarnings("serial") - private static class RecoverableException extends Exception { - - public RecoverableException(String message) { - super(message); - } - - } - - private int count = 0; - - private List outputs = new ArrayList<>(); - - @Test - public void testSuccessfulAttempt() throws Exception { - - BatchRetryTemplate template = new BatchRetryTemplate(); - - String result = template.execute(new RetryCallback() { - @Override - public String doWithRetry(RetryContext context) throws Exception { - assertTrue("Wrong context type: " + context.getClass().getSimpleName(), context.getClass() - .getSimpleName().contains("Batch")); - return "2"; - } - }, Arrays. asList(new DefaultRetryState("1"))); - - assertEquals("2", result); - - } - - @Test - public void testUnSuccessfulAttemptAndRetry() throws Exception { - - BatchRetryTemplate template = new BatchRetryTemplate(); - - RetryCallback retryCallback = new RetryCallback() { - @Override - public String[] doWithRetry(RetryContext context) throws Exception { - assertEquals(count, context.getRetryCount()); - if (count++ == 0) { - throw new RecoverableException("Recoverable"); - } - return new String[] { "a", "b" }; - } - }; - - List states = Arrays. asList(new DefaultRetryState("1"), new DefaultRetryState("2")); - try { - template.execute(retryCallback, states); - fail("Expected RecoverableException"); - } - catch (RecoverableException e) { - assertEquals("Recoverable", e.getMessage()); - } - String[] result = template.execute(retryCallback, states); - - assertEquals("[a, b]", Arrays.toString(result)); - - } - - @Test(expected = ExhaustedRetryException.class) - public void testExhaustedRetry() throws Exception { - - BatchRetryTemplate template = new BatchRetryTemplate(); - template.setRetryPolicy(new SimpleRetryPolicy(1, Collections - ., Boolean> singletonMap(Exception.class, true))); - - RetryCallback retryCallback = new RetryCallback() { - @Override - public String[] doWithRetry(RetryContext context) throws Exception { - if (count++ < 2) { - throw new RecoverableException("Recoverable"); - } - return outputs.toArray(new String[0]); - } - }; - - outputs = Arrays.asList("a", "b"); - try { - template.execute(retryCallback, BatchRetryTemplate.createState(outputs)); - fail("Expected RecoverableException"); - } - catch (RecoverableException e) { - assertEquals("Recoverable", e.getMessage()); - } - outputs = Arrays.asList("a", "c"); - template.execute(retryCallback, BatchRetryTemplate.createState(outputs)); - - } - - @Test - public void testExhaustedRetryAfterShuffle() throws Exception { - - BatchRetryTemplate template = new BatchRetryTemplate(); - template.setRetryPolicy(new SimpleRetryPolicy(1, Collections - ., Boolean> singletonMap(Exception.class, true))); - - RetryCallback retryCallback = new RetryCallback() { - @Override - public String[] doWithRetry(RetryContext context) throws Exception { - if (count++ < 1) { - throw new RecoverableException("Recoverable"); - } - return outputs.toArray(new String[0]); - } - }; - - outputs = Arrays.asList("a", "b"); - try { - template.execute(retryCallback, BatchRetryTemplate.createState(outputs)); - fail("Expected RecoverableException"); - } - catch (RecoverableException e) { - assertEquals("Recoverable", e.getMessage()); - } - - outputs = Arrays.asList("b", "c"); - try { - template.execute(retryCallback, BatchRetryTemplate.createState(outputs)); - fail("Expected ExhaustedRetryException"); - } - catch (ExhaustedRetryException e) { - } - - // "c" is not tarred with same brush as "b" because it was never - // processed on account of the exhausted retry - outputs = Arrays.asList("d", "c"); - String[] result = template.execute(retryCallback, BatchRetryTemplate.createState(outputs)); - assertEquals("[d, c]", Arrays.toString(result)); - - // "a" is still marked as a failure from the first chunk - outputs = Arrays.asList("a", "e"); - try { - template.execute(retryCallback, BatchRetryTemplate.createState(outputs)); - fail("Expected ExhaustedRetryException"); - } - catch (ExhaustedRetryException e) { - } - - outputs = Arrays.asList("e", "f"); - result = template.execute(retryCallback, BatchRetryTemplate.createState(outputs)); - assertEquals("[e, f]", Arrays.toString(result)); - - } - - @Test - public void testExhaustedRetryWithRecovery() throws Exception { - - BatchRetryTemplate template = new BatchRetryTemplate(); - template.setRetryPolicy(new SimpleRetryPolicy(1, Collections - ., Boolean> singletonMap(Exception.class, true))); - - RetryCallback retryCallback = new RetryCallback() { - @Override - public String[] doWithRetry(RetryContext context) throws Exception { - if (count++ < 2) { - throw new RecoverableException("Recoverable"); - } - return outputs.toArray(new String[0]); - } - }; - - RecoveryCallback recoveryCallback = new RecoveryCallback() { - @Override - public String[] recover(RetryContext context) throws Exception { - List recovered = new ArrayList<>(); - for (String item : outputs) { - recovered.add("r:" + item); - } - return recovered.toArray(new String[0]); - } - }; - - outputs = Arrays.asList("a", "b"); - try { - template.execute(retryCallback, recoveryCallback, BatchRetryTemplate.createState(outputs)); - fail("Expected RecoverableException"); - } - catch (RecoverableException e) { - assertEquals("Recoverable", e.getMessage()); - } - - outputs = Arrays.asList("b", "c"); - String[] result = template.execute(retryCallback, recoveryCallback, BatchRetryTemplate.createState(outputs)); - assertEquals("[r:b, r:c]", Arrays.toString(result)); - - } - -} +/* + * Copyright 2008-2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.step.item; + +import org.junit.Test; +import org.springframework.retry.ExhaustedRetryException; +import org.springframework.retry.RecoveryCallback; +import org.springframework.retry.RetryCallback; +import org.springframework.retry.RetryContext; +import org.springframework.retry.RetryState; +import org.springframework.retry.policy.SimpleRetryPolicy; +import org.springframework.retry.support.DefaultRetryState; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +public class BatchRetryTemplateTests { + + @SuppressWarnings("serial") + private static class RecoverableException extends Exception { + + public RecoverableException(String message) { + super(message); + } + + } + + private int count = 0; + + private List outputs = new ArrayList<>(); + + @Test + public void testSuccessfulAttempt() throws Exception { + + BatchRetryTemplate template = new BatchRetryTemplate(); + + String result = template.execute(new RetryCallback() { + @Override + public String doWithRetry(RetryContext context) throws Exception { + assertTrue("Wrong context type: " + context.getClass().getSimpleName(), + context.getClass().getSimpleName().contains("Batch")); + return "2"; + } + }, Arrays.asList(new DefaultRetryState("1"))); + + assertEquals("2", result); + + } + + @Test + public void testUnSuccessfulAttemptAndRetry() throws Exception { + + BatchRetryTemplate template = new BatchRetryTemplate(); + + RetryCallback retryCallback = new RetryCallback() { + @Override + public String[] doWithRetry(RetryContext context) throws Exception { + assertEquals(count, context.getRetryCount()); + if (count++ == 0) { + throw new RecoverableException("Recoverable"); + } + return new String[] { "a", "b" }; + } + }; + + List states = Arrays.asList(new DefaultRetryState("1"), new DefaultRetryState("2")); + try { + template.execute(retryCallback, states); + fail("Expected RecoverableException"); + } + catch (RecoverableException e) { + assertEquals("Recoverable", e.getMessage()); + } + String[] result = template.execute(retryCallback, states); + + assertEquals("[a, b]", Arrays.toString(result)); + + } + + @Test(expected = ExhaustedRetryException.class) + public void testExhaustedRetry() throws Exception { + + BatchRetryTemplate template = new BatchRetryTemplate(); + template.setRetryPolicy(new SimpleRetryPolicy(1, + Collections., Boolean>singletonMap(Exception.class, true))); + + RetryCallback retryCallback = new RetryCallback() { + @Override + public String[] doWithRetry(RetryContext context) throws Exception { + if (count++ < 2) { + throw new RecoverableException("Recoverable"); + } + return outputs.toArray(new String[0]); + } + }; + + outputs = Arrays.asList("a", "b"); + try { + template.execute(retryCallback, BatchRetryTemplate.createState(outputs)); + fail("Expected RecoverableException"); + } + catch (RecoverableException e) { + assertEquals("Recoverable", e.getMessage()); + } + outputs = Arrays.asList("a", "c"); + template.execute(retryCallback, BatchRetryTemplate.createState(outputs)); + + } + + @Test + public void testExhaustedRetryAfterShuffle() throws Exception { + + BatchRetryTemplate template = new BatchRetryTemplate(); + template.setRetryPolicy(new SimpleRetryPolicy(1, + Collections., Boolean>singletonMap(Exception.class, true))); + + RetryCallback retryCallback = new RetryCallback() { + @Override + public String[] doWithRetry(RetryContext context) throws Exception { + if (count++ < 1) { + throw new RecoverableException("Recoverable"); + } + return outputs.toArray(new String[0]); + } + }; + + outputs = Arrays.asList("a", "b"); + try { + template.execute(retryCallback, BatchRetryTemplate.createState(outputs)); + fail("Expected RecoverableException"); + } + catch (RecoverableException e) { + assertEquals("Recoverable", e.getMessage()); + } + + outputs = Arrays.asList("b", "c"); + try { + template.execute(retryCallback, BatchRetryTemplate.createState(outputs)); + fail("Expected ExhaustedRetryException"); + } + catch (ExhaustedRetryException e) { + } + + // "c" is not tarred with same brush as "b" because it was never + // processed on account of the exhausted retry + outputs = Arrays.asList("d", "c"); + String[] result = template.execute(retryCallback, BatchRetryTemplate.createState(outputs)); + assertEquals("[d, c]", Arrays.toString(result)); + + // "a" is still marked as a failure from the first chunk + outputs = Arrays.asList("a", "e"); + try { + template.execute(retryCallback, BatchRetryTemplate.createState(outputs)); + fail("Expected ExhaustedRetryException"); + } + catch (ExhaustedRetryException e) { + } + + outputs = Arrays.asList("e", "f"); + result = template.execute(retryCallback, BatchRetryTemplate.createState(outputs)); + assertEquals("[e, f]", Arrays.toString(result)); + + } + + @Test + public void testExhaustedRetryWithRecovery() throws Exception { + + BatchRetryTemplate template = new BatchRetryTemplate(); + template.setRetryPolicy(new SimpleRetryPolicy(1, + Collections., Boolean>singletonMap(Exception.class, true))); + + RetryCallback retryCallback = new RetryCallback() { + @Override + public String[] doWithRetry(RetryContext context) throws Exception { + if (count++ < 2) { + throw new RecoverableException("Recoverable"); + } + return outputs.toArray(new String[0]); + } + }; + + RecoveryCallback recoveryCallback = new RecoveryCallback() { + @Override + public String[] recover(RetryContext context) throws Exception { + List recovered = new ArrayList<>(); + for (String item : outputs) { + recovered.add("r:" + item); + } + return recovered.toArray(new String[0]); + } + }; + + outputs = Arrays.asList("a", "b"); + try { + template.execute(retryCallback, recoveryCallback, BatchRetryTemplate.createState(outputs)); + fail("Expected RecoverableException"); + } + catch (RecoverableException e) { + assertEquals("Recoverable", e.getMessage()); + } + + outputs = Arrays.asList("b", "c"); + String[] result = template.execute(retryCallback, recoveryCallback, BatchRetryTemplate.createState(outputs)); + assertEquals("[r:b, r:c]", Arrays.toString(result)); + + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/ChunkMonitorTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/ChunkMonitorTests.java index bf9ed43ab..992c8e0b7 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/ChunkMonitorTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/ChunkMonitorTests.java @@ -1,161 +1,162 @@ -/* - * Copyright 2006-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.step.item; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import org.junit.Before; -import org.junit.Test; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.ItemStreamException; -import org.springframework.batch.item.ItemStreamSupport; -import org.springframework.batch.item.ParseException; -import org.springframework.batch.item.UnexpectedInputException; -import org.springframework.lang.Nullable; - -/** - * @author Dave Syer - * - */ -public class ChunkMonitorTests { - - private static final int CHUNK_SIZE = 5; - - private ChunkMonitor monitor = new ChunkMonitor(); - - private int count = 0; - - private boolean closed = false; - - @Before - public void setUp() { - monitor.setItemReader(new ItemReader() { - @Nullable - @Override - public String read() throws Exception, UnexpectedInputException, ParseException { - return "" + (count++); - } - }); - monitor.registerItemStream(new ItemStreamSupport() { - @Override - public void close() { - super.close(); - closed = true; - } - }); - monitor.setChunkSize(CHUNK_SIZE); - } - - @Test - public void testIncrementOffset() { - assertEquals(0, monitor.getOffset()); - monitor.incrementOffset(); - assertEquals(1, monitor.getOffset()); - } - - @Test - public void testResetOffsetManually() { - monitor.incrementOffset(); - monitor.resetOffset(); - assertEquals(0, monitor.getOffset()); - } - - @Test - public void testResetOffsetAutomatically() { - for (int i = 0; i < CHUNK_SIZE; i++) { - monitor.incrementOffset(); - } - assertEquals(0, monitor.getOffset()); - } - - @Test - public void testClose() { - monitor.incrementOffset(); - monitor.close(); - assertTrue(closed); - assertEquals(0, monitor.getOffset()); - } - - @Test - public void testOpen() { - ExecutionContext executionContext = new ExecutionContext(); - executionContext.putInt(ChunkMonitor.class.getName() + ".OFFSET", 2); - monitor.open(executionContext); - assertEquals(2, count); - assertEquals(0, monitor.getOffset()); - } - - @Test - public void testOpenWithNullReader() { - monitor.setItemReader(null); - ExecutionContext executionContext = new ExecutionContext(); - monitor.open(executionContext); - assertEquals(0, monitor.getOffset()); - } - - @Test(expected = ItemStreamException.class) - public void testOpenWithErrorInReader() { - monitor.setItemReader(new ItemReader() { - @Nullable - @Override - public String read() throws Exception, UnexpectedInputException, ParseException { - throw new IllegalStateException("Expected"); - } - }); - ExecutionContext executionContext = new ExecutionContext(); - executionContext.putInt(ChunkMonitor.class.getName() + ".OFFSET", 2); - monitor.open(executionContext); - } - - @Test - public void testUpdateOnBoundary() { - monitor.resetOffset(); - ExecutionContext executionContext = new ExecutionContext(); - monitor.update(executionContext); - assertEquals(0, executionContext.size()); - - executionContext.put(ChunkMonitor.class.getName() + ".OFFSET", 3); - monitor.update(executionContext); - assertEquals(0, executionContext.size()); - } - - @Test - public void testUpdateVanilla() { - monitor.incrementOffset(); - ExecutionContext executionContext = new ExecutionContext(); - monitor.update(executionContext); - assertEquals(1, executionContext.size()); - } - - @Test - public void testUpdateWithNoStream() throws Exception { - monitor = new ChunkMonitor(); - monitor.setItemReader(new ItemReader() { - @Nullable - @Override - public String read() throws Exception, UnexpectedInputException, ParseException { - return "" + (count++); - } - }); - monitor.setChunkSize(CHUNK_SIZE); - monitor.incrementOffset(); - ExecutionContext executionContext = new ExecutionContext(); - monitor.update(executionContext); - assertEquals(0, executionContext.size()); - } -} +/* + * Copyright 2006-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.step.item; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemStreamException; +import org.springframework.batch.item.ItemStreamSupport; +import org.springframework.batch.item.ParseException; +import org.springframework.batch.item.UnexpectedInputException; +import org.springframework.lang.Nullable; + +/** + * @author Dave Syer + * + */ +public class ChunkMonitorTests { + + private static final int CHUNK_SIZE = 5; + + private ChunkMonitor monitor = new ChunkMonitor(); + + private int count = 0; + + private boolean closed = false; + + @Before + public void setUp() { + monitor.setItemReader(new ItemReader() { + @Nullable + @Override + public String read() throws Exception, UnexpectedInputException, ParseException { + return "" + (count++); + } + }); + monitor.registerItemStream(new ItemStreamSupport() { + @Override + public void close() { + super.close(); + closed = true; + } + }); + monitor.setChunkSize(CHUNK_SIZE); + } + + @Test + public void testIncrementOffset() { + assertEquals(0, monitor.getOffset()); + monitor.incrementOffset(); + assertEquals(1, monitor.getOffset()); + } + + @Test + public void testResetOffsetManually() { + monitor.incrementOffset(); + monitor.resetOffset(); + assertEquals(0, monitor.getOffset()); + } + + @Test + public void testResetOffsetAutomatically() { + for (int i = 0; i < CHUNK_SIZE; i++) { + monitor.incrementOffset(); + } + assertEquals(0, monitor.getOffset()); + } + + @Test + public void testClose() { + monitor.incrementOffset(); + monitor.close(); + assertTrue(closed); + assertEquals(0, monitor.getOffset()); + } + + @Test + public void testOpen() { + ExecutionContext executionContext = new ExecutionContext(); + executionContext.putInt(ChunkMonitor.class.getName() + ".OFFSET", 2); + monitor.open(executionContext); + assertEquals(2, count); + assertEquals(0, monitor.getOffset()); + } + + @Test + public void testOpenWithNullReader() { + monitor.setItemReader(null); + ExecutionContext executionContext = new ExecutionContext(); + monitor.open(executionContext); + assertEquals(0, monitor.getOffset()); + } + + @Test(expected = ItemStreamException.class) + public void testOpenWithErrorInReader() { + monitor.setItemReader(new ItemReader() { + @Nullable + @Override + public String read() throws Exception, UnexpectedInputException, ParseException { + throw new IllegalStateException("Expected"); + } + }); + ExecutionContext executionContext = new ExecutionContext(); + executionContext.putInt(ChunkMonitor.class.getName() + ".OFFSET", 2); + monitor.open(executionContext); + } + + @Test + public void testUpdateOnBoundary() { + monitor.resetOffset(); + ExecutionContext executionContext = new ExecutionContext(); + monitor.update(executionContext); + assertEquals(0, executionContext.size()); + + executionContext.put(ChunkMonitor.class.getName() + ".OFFSET", 3); + monitor.update(executionContext); + assertEquals(0, executionContext.size()); + } + + @Test + public void testUpdateVanilla() { + monitor.incrementOffset(); + ExecutionContext executionContext = new ExecutionContext(); + monitor.update(executionContext); + assertEquals(1, executionContext.size()); + } + + @Test + public void testUpdateWithNoStream() throws Exception { + monitor = new ChunkMonitor(); + monitor.setItemReader(new ItemReader() { + @Nullable + @Override + public String read() throws Exception, UnexpectedInputException, ParseException { + return "" + (count++); + } + }); + monitor.setChunkSize(CHUNK_SIZE); + monitor.incrementOffset(); + ExecutionContext executionContext = new ExecutionContext(); + monitor.update(executionContext); + assertEquals(0, executionContext.size()); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/ChunkOrientedTaskletTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/ChunkOrientedTaskletTests.java index e20958759..56c1f7ef9 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/ChunkOrientedTaskletTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/ChunkOrientedTaskletTests.java @@ -1,118 +1,124 @@ -/* - * Copyright 2006-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.step.item; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -import org.junit.Test; -import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobInstance; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.StepContribution; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.scope.context.ChunkContext; - -/** - * @author Dave Syer - * - */ -public class ChunkOrientedTaskletTests { - - private ChunkContext context = new ChunkContext(null); - - @Test - public void testHandle() throws Exception { - ChunkOrientedTasklet handler = new ChunkOrientedTasklet<>(new ChunkProvider() { - @Override - public Chunk provide(StepContribution contribution) throws Exception { - contribution.incrementReadCount(); - Chunk chunk = new Chunk<>(); - chunk.add("foo"); - return chunk; - } - @Override - public void postProcess(StepContribution contribution, Chunk chunk) {} - }, new ChunkProcessor() { - @Override - public void process(StepContribution contribution, Chunk chunk) { - contribution.incrementWriteCount(1); - } - }); - StepContribution contribution = new StepContribution(new StepExecution("foo", new JobExecution(new JobInstance( - 123L, "job"),new JobParameters()))); - handler.execute(contribution, context); - assertEquals(1, contribution.getReadCount()); - assertEquals(1, contribution.getWriteCount()); - assertEquals(0, context.attributeNames().length); - } - - @Test - public void testFail() throws Exception { - ChunkOrientedTasklet handler = new ChunkOrientedTasklet<>(new ChunkProvider() { - @Override - public Chunk provide(StepContribution contribution) throws Exception { - throw new RuntimeException("Foo!"); - } - @Override - public void postProcess(StepContribution contribution, Chunk chunk) {} - }, new ChunkProcessor() { - @Override - public void process(StepContribution contribution, Chunk chunk) { - fail("Not expecting to get this far"); - } - }); - StepContribution contribution = new StepContribution(new StepExecution("foo", new JobExecution(new JobInstance( - 123L, "job"), new JobParameters()))); - try { - handler.execute(contribution, context); - fail("Expected RuntimeException"); - } - catch (RuntimeException e) { - assertEquals("Foo!", e.getMessage()); - } - assertEquals(0, contribution.getReadCount()); - } - - @Test - public void testExitCode() throws Exception { - ChunkOrientedTasklet handler = new ChunkOrientedTasklet<>(new ChunkProvider() { - @Override - public Chunk provide(StepContribution contribution) throws Exception { - contribution.incrementReadCount(); - Chunk chunk = new Chunk<>(); - chunk.add("foo"); - chunk.setEnd(); - return chunk; - } - @Override - public void postProcess(StepContribution contribution, Chunk chunk) {} - }, new ChunkProcessor() { - @Override - public void process(StepContribution contribution, Chunk chunk) { - contribution.incrementWriteCount(1); - } - }); - StepContribution contribution = new StepContribution(new StepExecution("foo", new JobExecution(new JobInstance( - 123L, "job"), new JobParameters()))); - ExitStatus expected = contribution.getExitStatus(); - handler.execute(contribution, context); - // The tasklet does not change the exit code - assertEquals(expected, contribution.getExitStatus()); - } - -} +/* + * Copyright 2006-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.step.item; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import org.junit.Test; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobInstance; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.StepContribution; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.scope.context.ChunkContext; + +/** + * @author Dave Syer + * + */ +public class ChunkOrientedTaskletTests { + + private ChunkContext context = new ChunkContext(null); + + @Test + public void testHandle() throws Exception { + ChunkOrientedTasklet handler = new ChunkOrientedTasklet<>(new ChunkProvider() { + @Override + public Chunk provide(StepContribution contribution) throws Exception { + contribution.incrementReadCount(); + Chunk chunk = new Chunk<>(); + chunk.add("foo"); + return chunk; + } + + @Override + public void postProcess(StepContribution contribution, Chunk chunk) { + } + }, new ChunkProcessor() { + @Override + public void process(StepContribution contribution, Chunk chunk) { + contribution.incrementWriteCount(1); + } + }); + StepContribution contribution = new StepContribution( + new StepExecution("foo", new JobExecution(new JobInstance(123L, "job"), new JobParameters()))); + handler.execute(contribution, context); + assertEquals(1, contribution.getReadCount()); + assertEquals(1, contribution.getWriteCount()); + assertEquals(0, context.attributeNames().length); + } + + @Test + public void testFail() throws Exception { + ChunkOrientedTasklet handler = new ChunkOrientedTasklet<>(new ChunkProvider() { + @Override + public Chunk provide(StepContribution contribution) throws Exception { + throw new RuntimeException("Foo!"); + } + + @Override + public void postProcess(StepContribution contribution, Chunk chunk) { + } + }, new ChunkProcessor() { + @Override + public void process(StepContribution contribution, Chunk chunk) { + fail("Not expecting to get this far"); + } + }); + StepContribution contribution = new StepContribution( + new StepExecution("foo", new JobExecution(new JobInstance(123L, "job"), new JobParameters()))); + try { + handler.execute(contribution, context); + fail("Expected RuntimeException"); + } + catch (RuntimeException e) { + assertEquals("Foo!", e.getMessage()); + } + assertEquals(0, contribution.getReadCount()); + } + + @Test + public void testExitCode() throws Exception { + ChunkOrientedTasklet handler = new ChunkOrientedTasklet<>(new ChunkProvider() { + @Override + public Chunk provide(StepContribution contribution) throws Exception { + contribution.incrementReadCount(); + Chunk chunk = new Chunk<>(); + chunk.add("foo"); + chunk.setEnd(); + return chunk; + } + + @Override + public void postProcess(StepContribution contribution, Chunk chunk) { + } + }, new ChunkProcessor() { + @Override + public void process(StepContribution contribution, Chunk chunk) { + contribution.incrementWriteCount(1); + } + }); + StepContribution contribution = new StepContribution( + new StepExecution("foo", new JobExecution(new JobInstance(123L, "job"), new JobParameters()))); + ExitStatus expected = contribution.getExitStatus(); + handler.execute(contribution, context); + // The tasklet does not change the exit code + assertEquals(expected, contribution.getExitStatus()); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/ExceptionThrowingTaskletStub.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/ExceptionThrowingTaskletStub.java index 89bdfbb3d..40be641d2 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/ExceptionThrowingTaskletStub.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/ExceptionThrowingTaskletStub.java @@ -1,69 +1,70 @@ -/* - * Copyright 2006-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.step.item; - -import java.lang.reflect.Constructor; -import java.util.List; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.batch.core.StepContribution; -import org.springframework.batch.core.scope.context.ChunkContext; -import org.springframework.batch.core.step.tasklet.Tasklet; -import org.springframework.batch.repeat.RepeatStatus; -import org.springframework.batch.support.transaction.TransactionAwareProxyFactory; -import org.springframework.lang.Nullable; - -/** - * @author Dan Garrette - * @since 2.0.2 - */ -public class ExceptionThrowingTaskletStub implements Tasklet { - - private int maxTries = 4; - - protected Log logger = LogFactory.getLog(getClass()); - - private List committed = TransactionAwareProxyFactory.createTransactionalList(); - - private Constructor exception; - - public ExceptionThrowingTaskletStub() throws Exception { - exception = SkippableRuntimeException.class.getConstructor(String.class); - } - - public void setExceptionType(Class exceptionType) throws Exception { - exception = exceptionType.getConstructor(String.class); - } - - public List getCommitted() { - return committed; - } - - public void clear() { - committed.clear(); - } - - @Nullable - @Override - public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { - committed.add(1); - if (committed.size()>=maxTries) { - return RepeatStatus.FINISHED; - } - throw exception.newInstance("Expected exception"); - } -} +/* + * Copyright 2006-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.step.item; + +import java.lang.reflect.Constructor; +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.batch.core.StepContribution; +import org.springframework.batch.core.scope.context.ChunkContext; +import org.springframework.batch.core.step.tasklet.Tasklet; +import org.springframework.batch.repeat.RepeatStatus; +import org.springframework.batch.support.transaction.TransactionAwareProxyFactory; +import org.springframework.lang.Nullable; + +/** + * @author Dan Garrette + * @since 2.0.2 + */ +public class ExceptionThrowingTaskletStub implements Tasklet { + + private int maxTries = 4; + + protected Log logger = LogFactory.getLog(getClass()); + + private List committed = TransactionAwareProxyFactory.createTransactionalList(); + + private Constructor exception; + + public ExceptionThrowingTaskletStub() throws Exception { + exception = SkippableRuntimeException.class.getConstructor(String.class); + } + + public void setExceptionType(Class exceptionType) throws Exception { + exception = exceptionType.getConstructor(String.class); + } + + public List getCommitted() { + return committed; + } + + public void clear() { + committed.clear(); + } + + @Nullable + @Override + public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { + committed.add(1); + if (committed.size() >= maxTries) { + return RepeatStatus.FINISHED; + } + throw exception.newInstance("Expected exception"); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FatalRuntimeException.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FatalRuntimeException.java index 6bb16646b..9a0c67305 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FatalRuntimeException.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FatalRuntimeException.java @@ -1,27 +1,29 @@ -/* - * Copyright 2009-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.step.item; - -/** - * @author Dan Garrette - * @since 2.0.2 - */ -@SuppressWarnings("serial") -public class FatalRuntimeException extends SkippableRuntimeException { - public FatalRuntimeException(String message) { - super(message); - } -} +/* + * Copyright 2009-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.step.item; + +/** + * @author Dan Garrette + * @since 2.0.2 + */ +@SuppressWarnings("serial") +public class FatalRuntimeException extends SkippableRuntimeException { + + public FatalRuntimeException(String message) { + super(message); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FatalSkippableException.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FatalSkippableException.java index 7eea1d7cd..9762a510a 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FatalSkippableException.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FatalSkippableException.java @@ -1,27 +1,29 @@ -/* - * Copyright 2009-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.step.item; - -/** - * @author Dan Garrette - * @since 2.0.2 - */ -@SuppressWarnings("serial") -public class FatalSkippableException extends SkippableException { - public FatalSkippableException(String message) { - super(message); - } -} +/* + * Copyright 2009-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.step.item; + +/** + * @author Dan Garrette + * @since 2.0.2 + */ +@SuppressWarnings("serial") +public class FatalSkippableException extends SkippableException { + + public FatalSkippableException(String message) { + super(message); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantChunkProcessorTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantChunkProcessorTests.java index ec854c422..8517b08af 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantChunkProcessorTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantChunkProcessorTests.java @@ -62,18 +62,15 @@ public class FaultTolerantChunkProcessorTests { @Before public void setUp() { batchRetryTemplate = new BatchRetryTemplate(); - processor = new FaultTolerantChunkProcessor<>( - new PassThroughItemProcessor<>(), - new ItemWriter() { - @Override - public void write(List items) - throws Exception { - if (items.contains("fail")) { - throw new RuntimeException("Planned failure!"); - } - list.addAll(items); - } - }, batchRetryTemplate); + processor = new FaultTolerantChunkProcessor<>(new PassThroughItemProcessor<>(), new ItemWriter() { + @Override + public void write(List items) throws Exception { + if (items.contains("fail")) { + throw new RuntimeException("Planned failure!"); + } + list.addAll(items); + } + }, batchRetryTemplate); batchRetryTemplate.setRetryPolicy(new NeverRetryPolicy()); } @@ -119,7 +116,8 @@ public class FaultTolerantChunkProcessorTests { try { processor.process(contribution, inputs); fail("Expected Exception"); - } catch (Exception e) { + } + catch (Exception e) { assertEquals("Skippable", e.getMessage()); } processor.process(contribution, inputs); @@ -127,7 +125,7 @@ public class FaultTolerantChunkProcessorTests { assertEquals(1, contribution.getSkipCount()); assertEquals(1, contribution.getFilterCount()); } - + @Test // BATCH-2663 public void testFilterCountOnSkipInWriteWithoutRetry() throws Exception { @@ -143,8 +141,10 @@ public class FaultTolerantChunkProcessorTests { } }); Chunk inputs = new Chunk<>(Arrays.asList("fail", "1", "2")); - processAndExpectPlannedRuntimeException(inputs); // (first attempt) Process fail, 1, 2 - // item 1 is filtered out so it is removed from the chunk => now inputs = [fail, 2] + processAndExpectPlannedRuntimeException(inputs); // (first attempt) Process fail, + // 1, 2 + // item 1 is filtered out so it is removed from the chunk => now inputs = [fail, + // 2] // using NeverRetryPolicy by default => now scanning processAndExpectPlannedRuntimeException(inputs); // (scanning) Process fail processor.process(contribution, inputs); // (scanning) Process 2 @@ -153,7 +153,7 @@ public class FaultTolerantChunkProcessorTests { assertEquals(1, contribution.getWriteSkipCount()); assertEquals(1, contribution.getFilterCount()); } - + @Test // BATCH-2663 public void testFilterCountOnSkipInWriteWithRetry() throws Exception { @@ -172,8 +172,10 @@ public class FaultTolerantChunkProcessorTests { } }); Chunk inputs = new Chunk<>(Arrays.asList("fail", "1", "2")); - processAndExpectPlannedRuntimeException(inputs); // (first attempt) Process fail, 1, 2 - // item 1 is filtered out so it is removed from the chunk => now inputs = [fail, 2] + processAndExpectPlannedRuntimeException(inputs); // (first attempt) Process fail, + // 1, 2 + // item 1 is filtered out so it is removed from the chunk => now inputs = [fail, + // 2] processAndExpectPlannedRuntimeException(inputs); // (first retry) Process fail, 2 processAndExpectPlannedRuntimeException(inputs); // (second retry) Process fail, 2 // retry exhausted (maxAttempts = 3) => now scanning @@ -187,7 +189,6 @@ public class FaultTolerantChunkProcessorTests { /** * An Error can be retried or skipped but by default it is just propagated - * * @throws Exception */ @Test @@ -201,12 +202,12 @@ public class FaultTolerantChunkProcessorTests { } } }); - Chunk inputs = new Chunk<>( - Arrays.asList("3", "fail", "2")); + Chunk inputs = new Chunk<>(Arrays.asList("3", "fail", "2")); try { processor.process(contribution, inputs); fail("Expected Error"); - } catch (Error e) { + } + catch (Error e) { assertEquals("Expected Error!", e.getMessage()); } processor.process(contribution, inputs); @@ -223,19 +224,20 @@ public class FaultTolerantChunkProcessorTests { } } }); - Chunk inputs = new Chunk<>( - Arrays.asList("3", "fail", "2")); + Chunk inputs = new Chunk<>(Arrays.asList("3", "fail", "2")); try { processor.process(contribution, inputs); fail("Expected RuntimeException"); - } catch (RuntimeException e) { + } + catch (RuntimeException e) { assertEquals("Expected Exception!", e.getMessage()); } processor.process(contribution, inputs); try { processor.process(contribution, inputs); fail("Expected RuntimeException"); - } catch (RuntimeException e) { + } + catch (RuntimeException e) { assertEquals("Expected Exception!", e.getMessage()); } assertEquals(1, contribution.getSkipCount()); @@ -258,7 +260,8 @@ public class FaultTolerantChunkProcessorTests { try { processor.process(contribution, inputs); fail("Expected RuntimeException"); - } catch (RuntimeException e) { + } + catch (RuntimeException e) { assertEquals("Expected Exception!", e.getMessage()); } // BATCH-1518: ideally we would not want this to be necessary, but it @@ -266,7 +269,8 @@ public class FaultTolerantChunkProcessorTests { try { processor.process(contribution, inputs); fail("Expected RuntimeException"); - } catch (RuntimeException e) { + } + catch (RuntimeException e) { assertEquals("Expected Exception!", e.getMessage()); } processor.process(contribution, inputs); @@ -288,11 +292,8 @@ public class FaultTolerantChunkProcessorTests { } }); processor.setProcessSkipPolicy(new AlwaysSkipItemSkipPolicy()); - processor - .setRollbackClassifier(new BinaryExceptionClassifier( - Collections - .> singleton(DataIntegrityViolationException.class), - false)); + processor.setRollbackClassifier(new BinaryExceptionClassifier( + Collections.>singleton(DataIntegrityViolationException.class), false)); Chunk inputs = new Chunk<>(Arrays.asList("1", "2")); processor.process(contribution, inputs); assertEquals(1, list.size()); @@ -300,15 +301,13 @@ public class FaultTolerantChunkProcessorTests { @Test public void testAfterWrite() throws Exception { - Chunk chunk = new Chunk<>(Arrays.asList("foo", "fail", - "bar")); - processor.setListeners(Arrays - .asList(new ItemListenerSupport() { - @Override - public void afterWrite(List item) { - after.addAll(item); - } - })); + Chunk chunk = new Chunk<>(Arrays.asList("foo", "fail", "bar")); + processor.setListeners(Arrays.asList(new ItemListenerSupport() { + @Override + public void afterWrite(List item) { + after.addAll(item); + } + })); processor.setWriteSkipPolicy(new AlwaysSkipItemSkipPolicy()); processAndExpectPlannedRuntimeException(chunk); processor.process(contribution, chunk); @@ -328,26 +327,22 @@ public class FaultTolerantChunkProcessorTests { @Test public void testAfterWriteAllPassedInRecovery() throws Exception { Chunk chunk = new Chunk<>(Arrays.asList("foo", "bar")); - processor = new FaultTolerantChunkProcessor<>( - new PassThroughItemProcessor<>(), - new ItemWriter() { - @Override - public void write(List items) - throws Exception { - // Fail if there is more than one item - if (items.size() > 1) { - throw new RuntimeException("Planned failure!"); - } - list.addAll(items); - } - }, batchRetryTemplate); - processor.setListeners(Arrays - .asList(new ItemListenerSupport() { - @Override - public void afterWrite(List item) { - after.addAll(item); - } - })); + processor = new FaultTolerantChunkProcessor<>(new PassThroughItemProcessor<>(), new ItemWriter() { + @Override + public void write(List items) throws Exception { + // Fail if there is more than one item + if (items.size() > 1) { + throw new RuntimeException("Planned failure!"); + } + list.addAll(items); + } + }, batchRetryTemplate); + processor.setListeners(Arrays.asList(new ItemListenerSupport() { + @Override + public void afterWrite(List item) { + after.addAll(item); + } + })); processor.setWriteSkipPolicy(new AlwaysSkipItemSkipPolicy()); processAndExpectPlannedRuntimeException(chunk); @@ -361,14 +356,12 @@ public class FaultTolerantChunkProcessorTests { @Test public void testOnErrorInWrite() throws Exception { Chunk chunk = new Chunk<>(Arrays.asList("foo", "fail")); - processor.setListeners(Arrays - .asList(new ItemListenerSupport() { - @Override - public void onWriteError(Exception e, - List item) { - writeError.addAll(item); - } - })); + processor.setListeners(Arrays.asList(new ItemListenerSupport() { + @Override + public void onWriteError(Exception e, List item) { + writeError.addAll(item); + } + })); processor.setWriteSkipPolicy(new AlwaysSkipItemSkipPolicy()); processAndExpectPlannedRuntimeException(chunk);// Process foo, fail @@ -381,24 +374,19 @@ public class FaultTolerantChunkProcessorTests { @Test public void testOnErrorInWriteAllItemsFail() throws Exception { Chunk chunk = new Chunk<>(Arrays.asList("foo", "bar")); - processor = new FaultTolerantChunkProcessor<>( - new PassThroughItemProcessor<>(), - new ItemWriter() { - @Override - public void write(List items) - throws Exception { - // Always fail in writer - throw new RuntimeException("Planned failure!"); - } - }, batchRetryTemplate); - processor.setListeners(Arrays - .asList(new ItemListenerSupport() { - @Override - public void onWriteError(Exception e, - List item) { - writeError.addAll(item); - } - })); + processor = new FaultTolerantChunkProcessor<>(new PassThroughItemProcessor<>(), new ItemWriter() { + @Override + public void write(List items) throws Exception { + // Always fail in writer + throw new RuntimeException("Planned failure!"); + } + }, batchRetryTemplate); + processor.setListeners(Arrays.asList(new ItemListenerSupport() { + @Override + public void onWriteError(Exception e, List item) { + writeError.addAll(item); + } + })); processor.setWriteSkipPolicy(new AlwaysSkipItemSkipPolicy()); processAndExpectPlannedRuntimeException(chunk);// Process foo, bar @@ -422,19 +410,20 @@ public class FaultTolerantChunkProcessorTests { } } }); - Chunk inputs = new Chunk<>( - Arrays.asList("3", "fail", "2")); + Chunk inputs = new Chunk<>(Arrays.asList("3", "fail", "2")); try { processor.process(contribution, inputs); fail("Expected RuntimeException"); - } catch (RuntimeException e) { + } + catch (RuntimeException e) { assertEquals("Expected Exception!", e.getMessage()); } try { // first retry processor.process(contribution, inputs); fail("Expected RuntimeException"); - } catch (RuntimeException e) { + } + catch (RuntimeException e) { assertEquals("Expected Exception!", e.getMessage()); } // retry exhausted, now scanning @@ -443,7 +432,8 @@ public class FaultTolerantChunkProcessorTests { // skip on this attempt processor.process(contribution, inputs); fail("Expected RuntimeException"); - } catch (RuntimeException e) { + } + catch (RuntimeException e) { assertEquals("Expected Exception!", e.getMessage()); } // finish chunk @@ -467,19 +457,20 @@ public class FaultTolerantChunkProcessorTests { } } }); - Chunk inputs = new Chunk<>(Arrays.asList("3", "fail", - "fail", "4")); + Chunk inputs = new Chunk<>(Arrays.asList("3", "fail", "fail", "4")); try { processor.process(contribution, inputs); fail("Expected RuntimeException"); - } catch (RuntimeException e) { + } + catch (RuntimeException e) { assertEquals("Expected Exception!", e.getMessage()); } try { // first retry processor.process(contribution, inputs); fail("Expected RuntimeException"); - } catch (RuntimeException e) { + } + catch (RuntimeException e) { assertEquals("Expected Exception!", e.getMessage()); } // retry exhausted, now scanning @@ -488,14 +479,16 @@ public class FaultTolerantChunkProcessorTests { // skip on this attempt processor.process(contribution, inputs); fail("Expected RuntimeException"); - } catch (RuntimeException e) { + } + catch (RuntimeException e) { assertEquals("Expected Exception!", e.getMessage()); } try { // 2nd exception detected processor.process(contribution, inputs); fail("Expected RuntimeException"); - } catch (RuntimeException e) { + } + catch (RuntimeException e) { assertEquals("Expected Exception!", e.getMessage()); } // still scanning @@ -512,8 +505,7 @@ public class FaultTolerantChunkProcessorTests { retryPolicy.setMaxAttempts(2); batchRetryTemplate.setRetryPolicy(retryPolicy); processor.setWriteSkipPolicy(new LimitCheckingItemSkipPolicy(1, - Collections., Boolean> singletonMap( - IllegalArgumentException.class, true))); + Collections., Boolean>singletonMap(IllegalArgumentException.class, true))); processor.setItemWriter(new ItemWriter() { @Override public void write(List items) throws Exception { @@ -521,24 +513,24 @@ public class FaultTolerantChunkProcessorTests { throw new IllegalArgumentException("Expected Exception!"); } if (items.contains("2")) { - throw new RuntimeException( - "Expected Non-Skippable Exception!"); + throw new RuntimeException("Expected Non-Skippable Exception!"); } } }); - Chunk inputs = new Chunk<>( - Arrays.asList("3", "fail", "2")); + Chunk inputs = new Chunk<>(Arrays.asList("3", "fail", "2")); try { processor.process(contribution, inputs); fail("Expected IllegalArgumentException"); - } catch (IllegalArgumentException e) { + } + catch (IllegalArgumentException e) { assertEquals("Expected Exception!", e.getMessage()); } try { // first retry processor.process(contribution, inputs); fail("Expected IllegalArgumentException"); - } catch (IllegalArgumentException e) { + } + catch (IllegalArgumentException e) { assertEquals("Expected Exception!", e.getMessage()); } // retry exhausted, now scanning @@ -547,23 +539,26 @@ public class FaultTolerantChunkProcessorTests { // skip on this attempt processor.process(contribution, inputs); fail("Expected IllegalArgumentException"); - } catch (IllegalArgumentException e) { + } + catch (IllegalArgumentException e) { assertEquals("Expected Exception!", e.getMessage()); } try { // should retry processor.process(contribution, inputs); fail("Expected RuntimeException"); - } catch (RetryException e) { + } + catch (RetryException e) { throw e; - } catch (RuntimeException e) { + } + catch (RuntimeException e) { assertEquals("Expected Non-Skippable Exception!", e.getMessage()); } assertEquals(1, contribution.getSkipCount()); assertEquals(1, contribution.getWriteCount()); assertEquals(0, contribution.getFilterCount()); } - + @Test // BATCH-2036 public void testProcessFilterAndSkippableException() throws Exception { @@ -587,18 +582,20 @@ public class FaultTolerantChunkProcessorTests { processor.afterPropertiesSet(); Chunk inputs = new Chunk<>(Arrays.asList("1", "2", "skip", "skip", "3", "fail", "fail", "4", "5")); try { - processor.process(contribution, inputs); + processor.process(contribution, inputs); fail("Expected IllegalArgumentException"); - } catch (IllegalArgumentException e) { + } + catch (IllegalArgumentException e) { assertEquals("Expected Skippable Exception!", e.getMessage()); } try { - processor.process(contribution, inputs); + processor.process(contribution, inputs); fail("Expected IllegalArgumentException"); - } catch (IllegalArgumentException e) { + } + catch (IllegalArgumentException e) { assertEquals("Expected Skippable Exception!", e.getMessage()); } - processor.process(contribution, inputs); + processor.process(contribution, inputs); assertEquals(5, list.size()); assertEquals("[1, 2, 3, 4, 5]", list.toString()); assertEquals(2, contribution.getFilterCount()); @@ -627,8 +624,8 @@ public class FaultTolerantChunkProcessorTests { return item; } }); - processor.setRollbackClassifier(new BinaryExceptionClassifier(Collections - .> singleton(IllegalArgumentException.class), false)); + processor.setRollbackClassifier(new BinaryExceptionClassifier( + Collections.>singleton(IllegalArgumentException.class), false)); processor.afterPropertiesSet(); Chunk inputs = new Chunk<>(Arrays.asList("1", "2", "skip", "skip", "3", "fail", "fail", "4", "5")); processor.process(contribution, inputs); @@ -640,13 +637,14 @@ public class FaultTolerantChunkProcessorTests { assertEquals("[1, 2, skip, skip, 3, fail, fail, 4, 5]", processedItems.toString()); } - protected void processAndExpectPlannedRuntimeException(Chunk chunk) - throws Exception { + protected void processAndExpectPlannedRuntimeException(Chunk chunk) throws Exception { try { processor.process(contribution, chunk); fail(); - } catch (RuntimeException e) { + } + catch (RuntimeException e) { assertEquals("Planned failure!", e.getMessage()); } } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantChunkProviderTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantChunkProviderTests.java index 9daf80a9e..166816abc 100755 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantChunkProviderTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantChunkProviderTests.java @@ -39,8 +39,8 @@ public class FaultTolerantChunkProviderTests { private FaultTolerantChunkProvider provider; - private StepContribution contribution = new StepContribution(new StepExecution("foo", new JobExecution( - new JobInstance(123L, "job"), new JobParameters()))); + private StepContribution contribution = new StepContribution( + new StepExecution("foo", new JobExecution(new JobInstance(123L, "job"), new JobParameters()))); @Test public void testProvide() throws Exception { @@ -60,7 +60,8 @@ public class FaultTolerantChunkProviderTests { throw new RuntimeException("Planned"); } }, new RepeatTemplate()); - provider.setSkipPolicy(new LimitCheckingItemSkipPolicy(Integer.MAX_VALUE, Collections.,Boolean>singletonMap(Exception.class, Boolean.TRUE))); + provider.setSkipPolicy(new LimitCheckingItemSkipPolicy(Integer.MAX_VALUE, + Collections., Boolean>singletonMap(Exception.class, Boolean.TRUE))); provider.setMaxSkipsOnRead(10); Chunk chunk = null; chunk = provider.provide(contribution); @@ -68,4 +69,5 @@ public class FaultTolerantChunkProviderTests { assertEquals(0, chunk.getItems().size()); assertEquals(10, chunk.getErrors().size()); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantExceptionClassesTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantExceptionClassesTests.java index e55ed6295..73f21fd37 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantExceptionClassesTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantExceptionClassesTests.java @@ -306,9 +306,9 @@ public class FaultTolerantExceptionClassesTests implements ApplicationContextAwa @Test public void testNoRollbackFatalNoRollbackException() throws Exception { // User has asked for no rollback on a fatal exception. What should the - // outcome be? As per BATCH-1333 it is interpreted as not skippable, but - // retryable if requested. Here it was not requested to be retried, but - // it was marked as no-rollback. As per BATCH-1334 this has to be ignored + // outcome be? As per BATCH-1333 it is interpreted as not skippable, but + // retryable if requested. Here it was not requested to be retried, but + // it was marked as no-rollback. As per BATCH-1334 this has to be ignored // so that the failed item can be isolated. writer.setExceptionType(FatalRuntimeException.class); StepExecution stepExecution = launchStep("noRollbackFatal"); @@ -348,8 +348,8 @@ public class FaultTolerantExceptionClassesTests implements ApplicationContextAwa stepsToExecute.add((Step) applicationContext.getBean(stepName)); job.setSteps(stepsToExecute); - JobExecution jobExecution = jobLauncher.run(job, new JobParametersBuilder().addString("uuid", - UUID.randomUUID().toString()).toJobParameters()); + JobExecution jobExecution = jobLauncher.run(job, + new JobParametersBuilder().addString("uuid", UUID.randomUUID().toString()).toJobParameters()); return jobExecution.getStepExecutions().iterator().next(); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBeanNonBufferingTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBeanNonBufferingTests.java index becfb697b..d233f65e6 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBeanNonBufferingTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBeanNonBufferingTests.java @@ -1,159 +1,159 @@ -/* - * Copyright 2008-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.step.item; - -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.junit.Before; -import org.junit.Test; - -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobInstance; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.SkipListener; -import org.springframework.batch.core.Step; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.step.JobRepositorySupport; -import org.springframework.batch.core.step.factory.FaultTolerantStepFactoryBean; -import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.item.support.ListItemReader; -import org.springframework.batch.support.transaction.ResourcelessTransactionManager; -import org.springframework.batch.support.transaction.TransactionAwareProxyFactory; -import org.springframework.util.StringUtils; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.mockito.Mockito.mock; - -public class FaultTolerantStepFactoryBeanNonBufferingTests { - - protected final Log logger = LogFactory.getLog(getClass()); - - private FaultTolerantStepFactoryBean factory = new FaultTolerantStepFactoryBean<>(); - - private List items = Arrays.asList("1", "2", "3", "4", "5"); - - private ListItemReader reader = new ListItemReader<>(TransactionAwareProxyFactory - .createTransactionalList(items)); - - private SkipWriterStub writer = new SkipWriterStub(); - - private JobExecution jobExecution; - - private static final SkippableRuntimeException exception = new SkippableRuntimeException("exception in writer"); - - int count = 0; - - @Before - public void setUp() throws Exception { - factory.setBeanName("stepName"); - factory.setJobRepository(new JobRepositorySupport()); - factory.setTransactionManager(new ResourcelessTransactionManager()); - factory.setCommitInterval(2); - factory.setItemReader(reader); - factory.setItemWriter(writer); - Map, Boolean> skippableExceptions = new HashMap<>(); - skippableExceptions.put(SkippableException.class, true); - skippableExceptions.put(SkippableRuntimeException.class, true); - factory.setSkippableExceptionClasses(skippableExceptions); - factory.setSkipLimit(2); - factory.setIsReaderTransactionalQueue(true); - - JobInstance jobInstance = new JobInstance(1L, "skipJob"); - jobExecution = new JobExecution(jobInstance, new JobParameters()); - } - - /** - * Check items causing errors are skipped as expected. - */ - @Test - public void testSkip() throws Exception { - @SuppressWarnings("unchecked") - SkipListener skipListener = mock(SkipListener.class); - skipListener.onSkipInWrite("3", exception); - skipListener.onSkipInWrite("4", exception); - - factory.setListeners(new SkipListener[] { skipListener }); - Step step = factory.getObject(); - - StepExecution stepExecution = new StepExecution(step.getName(), jobExecution); - step.execute(stepExecution); - - assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - - assertEquals(2, stepExecution.getSkipCount()); - assertEquals(0, stepExecution.getReadSkipCount()); - assertEquals(2, stepExecution.getWriteSkipCount()); - - // only one exception caused rollback, and only once in this case - // because all items in that chunk were skipped immediately - assertEquals(1, stepExecution.getRollbackCount()); - - assertFalse(writer.written.contains("4")); - - List expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,2,5")); - assertEquals(expectedOutput, writer.written); - - // 5 items + 1 rollbacks reading 2 items each time - assertEquals(7, stepExecution.getReadCount()); - - } - - /** - * Simple item writer that supports skip functionality. - */ - private static class SkipWriterStub implements ItemWriter { - - protected final Log logger = LogFactory.getLog(getClass()); - - // simulate transactional output - private List written = TransactionAwareProxyFactory.createTransactionalList(); - - private final Collection failures; - - public SkipWriterStub() { - this(Arrays.asList("4")); - } - - /** - * @param failures commaDelimitedListToSet - */ - public SkipWriterStub(Collection failures) { - this.failures = failures; - } - - @Override - public void write(List items) throws Exception { - logger.debug("Writing: " + items); - for (String item : items) { - if (failures.contains(item)) { - logger.debug("Throwing write exception on [" + item + "]"); - throw exception; - } - written.add(item); - } - } - - } - -} +/* + * Copyright 2008-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.step.item; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Before; +import org.junit.Test; + +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobInstance; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.SkipListener; +import org.springframework.batch.core.Step; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.step.JobRepositorySupport; +import org.springframework.batch.core.step.factory.FaultTolerantStepFactoryBean; +import org.springframework.batch.item.ItemWriter; +import org.springframework.batch.item.support.ListItemReader; +import org.springframework.batch.support.transaction.ResourcelessTransactionManager; +import org.springframework.batch.support.transaction.TransactionAwareProxyFactory; +import org.springframework.util.StringUtils; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.mockito.Mockito.mock; + +public class FaultTolerantStepFactoryBeanNonBufferingTests { + + protected final Log logger = LogFactory.getLog(getClass()); + + private FaultTolerantStepFactoryBean factory = new FaultTolerantStepFactoryBean<>(); + + private List items = Arrays.asList("1", "2", "3", "4", "5"); + + private ListItemReader reader = new ListItemReader<>( + TransactionAwareProxyFactory.createTransactionalList(items)); + + private SkipWriterStub writer = new SkipWriterStub(); + + private JobExecution jobExecution; + + private static final SkippableRuntimeException exception = new SkippableRuntimeException("exception in writer"); + + int count = 0; + + @Before + public void setUp() throws Exception { + factory.setBeanName("stepName"); + factory.setJobRepository(new JobRepositorySupport()); + factory.setTransactionManager(new ResourcelessTransactionManager()); + factory.setCommitInterval(2); + factory.setItemReader(reader); + factory.setItemWriter(writer); + Map, Boolean> skippableExceptions = new HashMap<>(); + skippableExceptions.put(SkippableException.class, true); + skippableExceptions.put(SkippableRuntimeException.class, true); + factory.setSkippableExceptionClasses(skippableExceptions); + factory.setSkipLimit(2); + factory.setIsReaderTransactionalQueue(true); + + JobInstance jobInstance = new JobInstance(1L, "skipJob"); + jobExecution = new JobExecution(jobInstance, new JobParameters()); + } + + /** + * Check items causing errors are skipped as expected. + */ + @Test + public void testSkip() throws Exception { + @SuppressWarnings("unchecked") + SkipListener skipListener = mock(SkipListener.class); + skipListener.onSkipInWrite("3", exception); + skipListener.onSkipInWrite("4", exception); + + factory.setListeners(new SkipListener[] { skipListener }); + Step step = factory.getObject(); + + StepExecution stepExecution = new StepExecution(step.getName(), jobExecution); + step.execute(stepExecution); + + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + + assertEquals(2, stepExecution.getSkipCount()); + assertEquals(0, stepExecution.getReadSkipCount()); + assertEquals(2, stepExecution.getWriteSkipCount()); + + // only one exception caused rollback, and only once in this case + // because all items in that chunk were skipped immediately + assertEquals(1, stepExecution.getRollbackCount()); + + assertFalse(writer.written.contains("4")); + + List expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,2,5")); + assertEquals(expectedOutput, writer.written); + + // 5 items + 1 rollbacks reading 2 items each time + assertEquals(7, stepExecution.getReadCount()); + + } + + /** + * Simple item writer that supports skip functionality. + */ + private static class SkipWriterStub implements ItemWriter { + + protected final Log logger = LogFactory.getLog(getClass()); + + // simulate transactional output + private List written = TransactionAwareProxyFactory.createTransactionalList(); + + private final Collection failures; + + public SkipWriterStub() { + this(Arrays.asList("4")); + } + + /** + * @param failures commaDelimitedListToSet + */ + public SkipWriterStub(Collection failures) { + this.failures = failures; + } + + @Override + public void write(List items) throws Exception { + logger.debug("Writing: " + items); + for (String item : items) { + if (failures.contains(item)) { + logger.debug("Throwing write exception on [" + item + "]"); + throw exception; + } + written.add(item); + } + } + + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBeanRetryTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBeanRetryTests.java index fb275b60b..16c583605 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBeanRetryTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBeanRetryTests.java @@ -79,8 +79,7 @@ public class FaultTolerantStepFactoryBeanRetryTests { private List provided = new ArrayList<>(); - private List written = TransactionAwareProxyFactory - .createTransactionalList(); + private List written = TransactionAwareProxyFactory.createTransactionalList(); int count = 0; @@ -103,9 +102,7 @@ public class FaultTolerantStepFactoryBeanRetryTests { EmbeddedDatabase embeddedDatabase = new EmbeddedDatabaseBuilder() .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("/org/springframework/batch/core/schema-hsqldb.sql") - .generateUniqueName(true) - .build(); + .addScript("/org/springframework/batch/core/schema-hsqldb.sql").generateUniqueName(true).build(); DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(embeddedDatabase); JobRepositoryFactoryBean repositoryFactoryBean = new JobRepositoryFactoryBean(); repositoryFactoryBean.setDataSource(embeddedDatabase); @@ -116,8 +113,7 @@ public class FaultTolerantStepFactoryBeanRetryTests { factory = new FaultTolerantStepFactoryBean<>(); factory.setBeanName("step"); - factory.setItemReader(new ListItemReader<>( - new ArrayList<>())); + factory.setItemReader(new ListItemReader<>(new ArrayList<>())); factory.setItemWriter(writer); factory.setJobRepository(repository); factory.setTransactionManager(transactionManager); @@ -126,8 +122,8 @@ public class FaultTolerantStepFactoryBeanRetryTests { factory.setSkippableExceptionClasses(getExceptionMap(Exception.class)); - JobParameters jobParameters = new JobParametersBuilder().addString( - "statefulTest", "make_this_unique").toJobParameters(); + JobParameters jobParameters = new JobParametersBuilder().addString("statefulTest", "make_this_unique") + .toJobParameters(); jobExecution = repository.createJobExecution("job", jobParameters); jobExecution.setEndTime(new Date()); @@ -145,10 +141,10 @@ public class FaultTolerantStepFactoryBeanRetryTests { } @Test - public void testProcessAllItemsWhenErrorInWriterTransformationWhenReaderTransactional() - throws Exception { + public void testProcessAllItemsWhenErrorInWriterTransformationWhenReaderTransactional() throws Exception { final int RETRY_LIMIT = 3; - final List ITEM_LIST = TransactionAwareProxyFactory.createTransactionalList(Arrays.asList("1", "2", "3")); + final List ITEM_LIST = TransactionAwareProxyFactory + .createTransactionalList(Arrays.asList("1", "2", "3")); FaultTolerantStepFactoryBean factory = new FaultTolerantStepFactoryBean<>(); factory.setBeanName("step"); @@ -175,7 +171,8 @@ public class FaultTolerantStepFactoryBeanRetryTests { return Integer.parseInt(item); } }; - ItemReader reader = new ListItemReader<>(TransactionAwareProxyFactory.createTransactionalList(ITEM_LIST)); + ItemReader reader = new ListItemReader<>( + TransactionAwareProxyFactory.createTransactionalList(ITEM_LIST)); factory.setCommitInterval(3); factory.setRetryLimit(RETRY_LIMIT); factory.setSkipLimit(1); @@ -189,15 +186,14 @@ public class FaultTolerantStepFactoryBeanRetryTests { factory.setItemWriter(failingWriter); Step step = factory.getObject(); - StepExecution stepExecution = new StepExecution(step.getName(), - jobExecution); + StepExecution stepExecution = new StepExecution(step.getName(), jobExecution); repository.add(stepExecution); step.execute(stepExecution); /* - * Each chunk tried up to RETRY_LIMIT, then the scan processes each item - * once, identifying the skip as it goes + * Each chunk tried up to RETRY_LIMIT, then the scan processes each item once, + * identifying the skip as it goes */ - assertEquals((RETRY_LIMIT +1) * ITEM_LIST.size(), processed.size()); + assertEquals((RETRY_LIMIT + 1) * ITEM_LIST.size(), processed.size()); } @Test @@ -237,22 +233,19 @@ public class FaultTolerantStepFactoryBeanRetryTests { factory.setItemWriter(failingWriter); Step step = factory.getObject(); - StepExecution stepExecution = new StepExecution(step.getName(), - jobExecution); + StepExecution stepExecution = new StepExecution(step.getName(), jobExecution); repository.add(stepExecution); step.execute(stepExecution); - assertEquals(ExitStatus.COMPLETED.getExitCode(), stepExecution - .getExitStatus().getExitCode()); + assertEquals(ExitStatus.COMPLETED.getExitCode(), stepExecution.getExitStatus().getExitCode()); /* - * Each chunk tried up to RETRY_LIMIT, then the scan processes each item - * once, identifying the skip as it goes + * Each chunk tried up to RETRY_LIMIT, then the scan processes each item once, + * identifying the skip as it goes */ - assertEquals((RETRY_LIMIT +1) * ITEM_LIST.size(), processed.size()); + assertEquals((RETRY_LIMIT + 1) * ITEM_LIST.size(), processed.size()); } @Test - public void testNoItemsReprocessedWhenErrorInWriterAndProcessorNotTransactional() - throws Exception { + public void testNoItemsReprocessedWhenErrorInWriterAndProcessorNotTransactional() throws Exception { ItemWriter failingWriter = new ItemWriter() { @Override public void write(List data) throws Exception { @@ -274,8 +267,7 @@ public class FaultTolerantStepFactoryBeanRetryTests { return item; } }; - ItemReader reader = new ListItemReader<>(Arrays.asList( - "a", "b", "c")); + ItemReader reader = new ListItemReader<>(Arrays.asList("a", "b", "c")); factory.setProcessorTransactional(false); factory.setCommitInterval(3); factory.setRetryLimit(3); @@ -285,26 +277,22 @@ public class FaultTolerantStepFactoryBeanRetryTests { factory.setItemWriter(failingWriter); Step step = factory.getObject(); - StepExecution stepExecution = new StepExecution(step.getName(), - jobExecution); + StepExecution stepExecution = new StepExecution(step.getName(), jobExecution); repository.add(stepExecution); step.execute(stepExecution); assertEquals(3, processed.size()); // Initial try only, then cached } /** - * N.B. this doesn't really test retry, since the retry is only on write - * failures, but it does test that read errors are re-presented for another - * try when the retryLimit is high enough (it is used to build an exception - * handler). - * + * N.B. this doesn't really test retry, since the retry is only on write failures, but + * it does test that read errors are re-presented for another try when the retryLimit + * is high enough (it is used to build an exception handler). * @throws Exception */ @SuppressWarnings("unchecked") @Test public void testSuccessfulRetryWithReadFailure() throws Exception { - ItemReader provider = new ListItemReader(Arrays.asList( - "a", "b", "c")) { + ItemReader provider = new ListItemReader(Arrays.asList("a", "b", "c")) { @Nullable @Override public String read() { @@ -312,8 +300,7 @@ public class FaultTolerantStepFactoryBeanRetryTests { provided.add(item); count++; if (count == 2) { - throw new RuntimeException( - "Temporary error - retry for success."); + throw new RuntimeException("Temporary error - retry for success."); } return item; } @@ -323,8 +310,7 @@ public class FaultTolerantStepFactoryBeanRetryTests { factory.setSkippableExceptionClasses(getExceptionMap()); Step step = factory.getObject(); - StepExecution stepExecution = new StepExecution(step.getName(), - jobExecution); + StepExecution stepExecution = new StepExecution(step.getName(), jobExecution); repository.add(stepExecution); step.execute(stepExecution); @@ -356,8 +342,7 @@ public class FaultTolerantStepFactoryBeanRetryTests { @Override protected void doOpen() throws Exception { - reader = new ListItemReader<>(Arrays.asList("a", "b", - "c", "d", "e", "f")); + reader = new ListItemReader<>(Arrays.asList("a", "b", "c", "d", "e", "f")); } @Nullable @@ -384,8 +369,7 @@ public class FaultTolerantStepFactoryBeanRetryTests { Step step = factory.getObject(); fail = true; - StepExecution stepExecution = new StepExecution(step.getName(), - jobExecution); + StepExecution stepExecution = new StepExecution(step.getName(), jobExecution); repository.add(stepExecution); step.execute(stepExecution); @@ -409,16 +393,14 @@ public class FaultTolerantStepFactoryBeanRetryTests { public void testSkipAndRetry() throws Exception { factory.setSkipLimit(2); - ItemReader provider = new ListItemReader(Arrays.asList( - "a", "b", "c", "d", "e", "f")) { + ItemReader provider = new ListItemReader(Arrays.asList("a", "b", "c", "d", "e", "f")) { @Nullable @Override public String read() { String item = super.read(); count++; if ("b".equals(item) || "d".equals(item)) { - throw new RuntimeException( - "Read error - planned but skippable."); + throw new RuntimeException("Read error - planned but skippable."); } return item; } @@ -427,8 +409,7 @@ public class FaultTolerantStepFactoryBeanRetryTests { factory.setRetryLimit(10); Step step = factory.getObject(); - StepExecution stepExecution = new StepExecution(step.getName(), - jobExecution); + StepExecution stepExecution = new StepExecution(step.getName(), jobExecution); repository.add(stepExecution); step.execute(stepExecution); @@ -446,13 +427,11 @@ public class FaultTolerantStepFactoryBeanRetryTests { @Override public void onSkipInWrite(String item, Throwable t) { recovered.add(item); - assertTrue(TransactionSynchronizationManager - .isActualTransactionActive()); + assertTrue(TransactionSynchronizationManager.isActualTransactionActive()); } } }); factory.setSkipLimit(2); - ItemReader provider = new ListItemReader(Arrays.asList( - "a", "b", "c", "d", "e", "f")) { + ItemReader provider = new ListItemReader(Arrays.asList("a", "b", "c", "d", "e", "f")) { @Nullable @Override public String read() { @@ -471,8 +450,7 @@ public class FaultTolerantStepFactoryBeanRetryTests { processed.addAll(item); written.addAll(item); if (item.contains("b") || item.contains("d")) { - throw new RuntimeException( - "Write error - planned but recoverable."); + throw new RuntimeException("Write error - planned but recoverable."); } } }; @@ -482,8 +460,7 @@ public class FaultTolerantStepFactoryBeanRetryTests { factory.setRetryableExceptionClasses(getExceptionMap(RuntimeException.class)); AbstractStep step = (AbstractStep) factory.getObject(); step.setName("mytest"); - StepExecution stepExecution = new StepExecution(step.getName(), - jobExecution); + StepExecution stepExecution = new StepExecution(step.getName(), jobExecution); repository.add(stepExecution); step.execute(stepExecution); @@ -491,33 +468,28 @@ public class FaultTolerantStepFactoryBeanRetryTests { assertEquals(2, stepExecution.getSkipCount()); assertEquals(2, stepExecution.getWriteSkipCount()); - List expectedOutput = Arrays.asList(StringUtils - .commaDelimitedListToStringArray("a,c,e,f")); + List expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("a,c,e,f")); assertEquals(expectedOutput, written); assertEquals("[a, b, c, d, e, f, null]", provided.toString()); - assertEquals("[a, b, b, b, b, b, b, c, d, d, d, d, d, d, e, f]", - processed.toString()); + assertEquals("[a, b, b, b, b, b, b, c, d, d, d, d, d, d, e, f]", processed.toString()); assertEquals("[b, d]", recovered.toString()); } @SuppressWarnings("unchecked") @Test - public void testSkipAndRetryWithWriteFailureAndNonTrivialCommitInterval() - throws Exception { + public void testSkipAndRetryWithWriteFailureAndNonTrivialCommitInterval() throws Exception { factory.setCommitInterval(3); factory.setListeners(new StepListener[] { new SkipListener() { @Override public void onSkipInWrite(String item, Throwable t) { recovered.add(item); - assertTrue(TransactionSynchronizationManager - .isActualTransactionActive()); + assertTrue(TransactionSynchronizationManager.isActualTransactionActive()); } } }); factory.setSkipLimit(2); - ItemReader provider = new ListItemReader(Arrays.asList( - "a", "b", "c", "d", "e", "f")) { + ItemReader provider = new ListItemReader(Arrays.asList("a", "b", "c", "d", "e", "f")) { @Nullable @Override public String read() { @@ -536,8 +508,7 @@ public class FaultTolerantStepFactoryBeanRetryTests { processed.addAll(item); written.addAll(item); if (item.contains("b") || item.contains("d")) { - throw new RuntimeException( - "Write error - planned but recoverable."); + throw new RuntimeException("Write error - planned but recoverable."); } } }; @@ -547,8 +518,7 @@ public class FaultTolerantStepFactoryBeanRetryTests { factory.setRetryableExceptionClasses(getExceptionMap(RuntimeException.class)); AbstractStep step = (AbstractStep) factory.getObject(); step.setName("mytest"); - StepExecution stepExecution = new StepExecution(step.getName(), - jobExecution); + StepExecution stepExecution = new StepExecution(step.getName(), jobExecution); repository.add(stepExecution); step.execute(stepExecution); @@ -556,8 +526,7 @@ public class FaultTolerantStepFactoryBeanRetryTests { assertEquals(2, stepExecution.getSkipCount()); assertEquals(2, stepExecution.getWriteSkipCount()); - List expectedOutput = Arrays.asList(StringUtils - .commaDelimitedListToStringArray("a,c,e,f")); + List expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("a,c,e,f")); assertEquals(expectedOutput, written); // [a, b, c, d, e, f, null] @@ -575,8 +544,7 @@ public class FaultTolerantStepFactoryBeanRetryTests { factory.setRetryLimit(4); factory.setSkipLimit(0); - ItemReader provider = new ListItemReader( - Arrays.asList("b")) { + ItemReader provider = new ListItemReader(Arrays.asList("b")) { @Nullable @Override public String read() { @@ -592,22 +560,19 @@ public class FaultTolerantStepFactoryBeanRetryTests { processed.addAll(item); written.addAll(item); logger.debug("Write Called! Item: [" + item + "]"); - throw new RuntimeException( - "Write error - planned but retryable."); + throw new RuntimeException("Write error - planned but retryable."); } }; factory.setItemReader(provider); factory.setItemWriter(itemWriter); Step step = factory.getObject(); - StepExecution stepExecution = new StepExecution(step.getName(), - jobExecution); + StepExecution stepExecution = new StepExecution(step.getName(), jobExecution); repository.add(stepExecution); step.execute(stepExecution); assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); - List expectedOutput = Arrays.asList(StringUtils - .commaDelimitedListToStringArray("")); + List expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("")); assertEquals(expectedOutput, written); assertEquals(0, stepExecution.getSkipCount()); @@ -631,8 +596,7 @@ public class FaultTolerantStepFactoryBeanRetryTests { factory.setRetryableExceptionClasses(getExceptionMap()); factory.setSkipLimit(1); - ItemReader provider = new ListItemReader( - Arrays.asList("b")) { + ItemReader provider = new ListItemReader(Arrays.asList("b")) { @Nullable @Override public String read() { @@ -648,25 +612,20 @@ public class FaultTolerantStepFactoryBeanRetryTests { processed.addAll(item); written.addAll(item); logger.debug("Write Called! Item: [" + item + "]"); - throw new RuntimeException( - "Write error - planned but not skippable."); + throw new RuntimeException("Write error - planned but not skippable."); } }; factory.setItemReader(provider); factory.setItemWriter(itemWriter); Step step = factory.getObject(); - StepExecution stepExecution = new StepExecution(step.getName(), - jobExecution); + StepExecution stepExecution = new StepExecution(step.getName(), jobExecution); repository.add(stepExecution); step.execute(stepExecution); - String message = stepExecution.getFailureExceptions().get(0) - .getMessage(); - assertTrue("Wrong message: " + message, - message.contains("Write error - planned but not skippable.")); + String message = stepExecution.getFailureExceptions().get(0).getMessage(); + assertTrue("Wrong message: " + message, message.contains("Write error - planned but not skippable.")); - List expectedOutput = Arrays.asList(StringUtils - .commaDelimitedListToStringArray("")); + List expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("")); assertEquals(expectedOutput, written); assertEquals(0, stepExecution.getSkipCount()); @@ -681,12 +640,10 @@ public class FaultTolerantStepFactoryBeanRetryTests { @Test public void testRetryPolicy() throws Exception { - factory.setRetryPolicy(new SimpleRetryPolicy(4, Collections - ., Boolean> singletonMap( - Exception.class, true))); + factory.setRetryPolicy(new SimpleRetryPolicy(4, + Collections., Boolean>singletonMap(Exception.class, true))); factory.setSkipLimit(0); - ItemReader provider = new ListItemReader( - Arrays.asList("b")) { + ItemReader provider = new ListItemReader(Arrays.asList("b")) { @Nullable @Override public String read() { @@ -702,22 +659,19 @@ public class FaultTolerantStepFactoryBeanRetryTests { processed.addAll(item); written.addAll(item); logger.debug("Write Called! Item: [" + item + "]"); - throw new RuntimeException( - "Write error - planned but retryable."); + throw new RuntimeException("Write error - planned but retryable."); } }; factory.setItemReader(provider); factory.setItemWriter(itemWriter); AbstractStep step = (AbstractStep) factory.getObject(); - StepExecution stepExecution = new StepExecution(step.getName(), - jobExecution); + StepExecution stepExecution = new StepExecution(step.getName(), jobExecution); repository.add(stepExecution); step.execute(stepExecution); assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); - List expectedOutput = Arrays.asList(StringUtils - .commaDelimitedListToStringArray("")); + List expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("")); assertEquals(expectedOutput, written); assertEquals(0, stepExecution.getSkipCount()); @@ -756,16 +710,14 @@ public class FaultTolerantStepFactoryBeanRetryTests { public void write(List item) throws Exception { processed.addAll(item); logger.debug("Write Called! Item: [" + item + "]"); - throw new RuntimeException( - "Write error - planned but retryable."); + throw new RuntimeException("Write error - planned but retryable."); } }; factory.setItemReader(provider); factory.setItemWriter(itemWriter); AbstractStep step = (AbstractStep) factory.getObject(); - StepExecution stepExecution = new StepExecution(step.getName(), - jobExecution); + StepExecution stepExecution = new StepExecution(step.getName(), jobExecution); repository.add(stepExecution); step.execute(stepExecution); assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); @@ -782,12 +734,12 @@ public class FaultTolerantStepFactoryBeanRetryTests { } @SuppressWarnings("unchecked") - private Map, Boolean> getExceptionMap( - Class... args) { + private Map, Boolean> getExceptionMap(Class... args) { Map, Boolean> map = new HashMap<>(); for (Class arg : args) { map.put(arg, true); } return map; } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBeanRollbackTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBeanRollbackTests.java index b9501bc3e..25548d1cc 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBeanRollbackTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBeanRollbackTests.java @@ -1,646 +1,650 @@ -/* - * Copyright 2009-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.step.item; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.ChunkListener; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.Step; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.StepListener; -import org.springframework.batch.core.repository.JobRepository; -import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; -import org.springframework.batch.core.scope.context.ChunkContext; -import org.springframework.batch.core.step.FatalStepExecutionException; -import org.springframework.batch.core.step.factory.FaultTolerantStepFactoryBean; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.support.ListItemReader; -import org.springframework.batch.support.transaction.ResourcelessTransactionManager; -import org.springframework.batch.support.transaction.TransactionAwareProxyFactory; -import org.springframework.core.task.SimpleAsyncTaskExecutor; -import org.springframework.jdbc.datasource.DataSourceTransactionManager; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; -import org.springframework.transaction.interceptor.RollbackRuleAttribute; -import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute; -import org.springframework.transaction.interceptor.TransactionAttribute; -import org.springframework.transaction.interceptor.TransactionAttributeEditor; -import org.springframework.util.StringUtils; - -import static org.hamcrest.CoreMatchers.instanceOf; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.springframework.batch.core.BatchStatus.FAILED; - -/** - * Tests for {@link FaultTolerantStepFactoryBean}. - */ -public class FaultTolerantStepFactoryBeanRollbackTests { - - protected final Log logger = LogFactory.getLog(getClass()); - - private FaultTolerantStepFactoryBean factory; - - private SkipReaderStub reader; - - private SkipProcessorStub processor; - - private SkipWriterStub writer; - - private JobExecution jobExecution; - - private StepExecution stepExecution; - - private JobRepository repository; - - @SuppressWarnings("unchecked") - @Before - public void setUp() throws Exception { - reader = new SkipReaderStub<>(); - processor = new SkipProcessorStub<>(); - writer = new SkipWriterStub<>(); - - factory = new FaultTolerantStepFactoryBean<>(); - - factory.setBeanName("stepName"); - ResourcelessTransactionManager transactionManager = new ResourcelessTransactionManager(); - factory.setTransactionManager(transactionManager); - factory.setCommitInterval(2); - - reader.clear(); - reader.setItems("1", "2", "3", "4", "5"); - factory.setItemReader(reader); - processor.clear(); - factory.setItemProcessor(processor); - writer.clear(); - factory.setItemWriter(writer); - - factory.setSkipLimit(2); - - factory.setSkippableExceptionClasses(getExceptionMap(Exception.class)); - - EmbeddedDatabase embeddedDatabase = new EmbeddedDatabaseBuilder() - .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("/org/springframework/batch/core/schema-hsqldb.sql") - .build(); - JobRepositoryFactoryBean repositoryFactory = new JobRepositoryFactoryBean(); - repositoryFactory.setDataSource(embeddedDatabase); - repositoryFactory.setTransactionManager(new DataSourceTransactionManager(embeddedDatabase)); - repositoryFactory.afterPropertiesSet(); - repository = repositoryFactory.getObject(); - factory.setJobRepository(repository); - - jobExecution = repository.createJobExecution("skipJob", new JobParameters()); - stepExecution = jobExecution.createStepExecution(factory.getName()); - repository.add(stepExecution); - } - - @After - public void tearDown() throws Exception { - reader = null; - processor = null; - writer = null; - factory = null; - } - - @Test - public void testBeforeChunkListenerException() throws Exception{ - factory.setListeners(new StepListener []{new ExceptionThrowingChunkListener(1)}); - Step step = factory.getObject(); - step.execute(stepExecution); - assertEquals(FAILED, stepExecution.getStatus()); - assertEquals(FAILED.toString(), stepExecution.getExitStatus().getExitCode()); - assertTrue(stepExecution.getCommitCount() == 0);//Make sure exception was thrown in after, not before - Throwable e = stepExecution.getFailureExceptions().get(0); - assertThat(e, instanceOf(FatalStepExecutionException.class)); - assertThat(e.getCause(), instanceOf(IllegalArgumentException.class)); - } - - @Test - public void testAfterChunkListenerException() throws Exception{ - factory.setListeners(new StepListener []{new ExceptionThrowingChunkListener(2)}); - Step step = factory.getObject(); - step.execute(stepExecution); - assertEquals(FAILED, stepExecution.getStatus()); - assertEquals(FAILED.toString(), stepExecution.getExitStatus().getExitCode()); - assertTrue(stepExecution.getCommitCount() > 0);//Make sure exception was thrown in after, not before - Throwable e = stepExecution.getFailureExceptions().get(0); - assertThat(e, instanceOf(FatalStepExecutionException.class)); - assertThat(e.getCause(), instanceOf(IllegalArgumentException.class)); - } - - @Test - public void testOverrideWithoutChangingRollbackRules() throws Exception { - TransactionAttributeEditor editor = new TransactionAttributeEditor(); - editor.setAsText("-RuntimeException"); - TransactionAttribute attr = (TransactionAttribute) editor.getValue(); - assertTrue(attr.rollbackOn(new RuntimeException(""))); - assertFalse(attr.rollbackOn(new Exception(""))); - } - - @Test - public void testChangeRollbackRules() throws Exception { - TransactionAttributeEditor editor = new TransactionAttributeEditor(); - editor.setAsText("+RuntimeException"); - TransactionAttribute attr = (TransactionAttribute) editor.getValue(); - assertFalse(attr.rollbackOn(new RuntimeException(""))); - assertFalse(attr.rollbackOn(new Exception(""))); - } - - @Test - public void testNonDefaultRollbackRules() throws Exception { - TransactionAttributeEditor editor = new TransactionAttributeEditor(); - editor.setAsText("+RuntimeException,+SkippableException"); - RuleBasedTransactionAttribute attr = (RuleBasedTransactionAttribute) editor.getValue(); - attr.getRollbackRules().add(new RollbackRuleAttribute(Exception.class)); - assertTrue(attr.rollbackOn(new Exception(""))); - assertFalse(attr.rollbackOn(new RuntimeException(""))); - assertFalse(attr.rollbackOn(new SkippableException(""))); - } - - /** - * Scenario: Exception in reader that should not cause rollback - */ - @Test - public void testReaderDefaultNoRollbackOnCheckedException() throws Exception { - reader.setItems("1", "2", "3", "4"); - reader.setFailures("2", "3"); - reader.setExceptionType(SkippableException.class); - - Step step = factory.getObject(); - - step.execute(stepExecution); - assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - assertEquals(2, stepExecution.getSkipCount()); - assertEquals(0, stepExecution.getRollbackCount()); - } - - /** - * Scenario: Exception in reader that should not cause rollback - */ - @SuppressWarnings("unchecked") - @Test - public void testReaderAttributesOverrideSkippableNoRollback() throws Exception { - reader.setFailures("2", "3"); - reader.setItems("1", "2", "3", "4"); - reader.setExceptionType(SkippableException.class); - - // No skips by default - factory.setSkippableExceptionClasses(getExceptionMap(RuntimeException.class)); - // But this one is explicit in the tx-attrs so it should be skipped - factory.setNoRollbackExceptionClasses(getExceptionList(SkippableException.class)); - - Step step = factory.getObject(); - - step.execute(stepExecution); - assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - assertEquals(0, stepExecution.getSkipCount()); - assertEquals(0, stepExecution.getRollbackCount()); - } - - /** - * Scenario: Exception in processor that should cause rollback because of - * checked exception - */ - @Test - public void testProcessorDefaultRollbackOnCheckedException() throws Exception { - reader.setItems("1", "2", "3", "4"); - - processor.setFailures("1", "3"); - processor.setExceptionType(SkippableException.class); - - Step step = factory.getObject(); - - step.execute(stepExecution); - assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - assertEquals(2, stepExecution.getSkipCount()); - assertEquals(2, stepExecution.getRollbackCount()); - } - - /** - * Scenario: Exception in processor that should cause rollback - */ - @Test - public void testProcessorDefaultRollbackOnRuntimeException() throws Exception { - reader.setItems("1", "2", "3", "4"); - - processor.setFailures("1", "3"); - processor.setExceptionType(SkippableRuntimeException.class); - - Step step = factory.getObject(); - - step.execute(stepExecution); - assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - assertEquals(2, stepExecution.getSkipCount()); - assertEquals(2, stepExecution.getRollbackCount()); - } - - @Test - public void testNoRollbackInProcessorWhenSkipExceeded() throws Throwable { - - jobExecution = repository.createJobExecution("noRollbackJob", new JobParameters()); - - factory.setSkipLimit(0); - - reader.clear(); - reader.setItems("1", "2", "3", "4", "5"); - factory.setItemReader(reader); - writer.clear(); - factory.setItemWriter(writer); - processor.clear(); - factory.setItemProcessor(processor); - - @SuppressWarnings("unchecked") - List> exceptions = Arrays.asList(Exception.class); - factory.setNoRollbackExceptionClasses(exceptions); - @SuppressWarnings("unchecked") - Map, Boolean> skippable = getExceptionMap(Exception.class); - factory.setSkippableExceptionClasses(skippable); - - processor.setFailures("2"); - - Step step = factory.getObject(); - - stepExecution = jobExecution.createStepExecution(factory.getName()); - repository.add(stepExecution); - step.execute(stepExecution); - assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - - assertEquals("[1, 3, 4, 5]", writer.getCommitted().toString()); - // No rollback on 2 so processor has side effect - assertEquals("[1, 2, 3, 4, 5]", processor.getCommitted().toString()); - List processed = new ArrayList<>(processor.getProcessed()); - Collections.sort(processed); - assertEquals("[1, 2, 3, 4, 5]", processed.toString()); - assertEquals(0, stepExecution.getSkipCount()); - - } - - @Test - public void testProcessSkipWithNoRollbackForCheckedException() throws Exception { - processor.setFailures("4"); - processor.setExceptionType(SkippableException.class); - - factory.setNoRollbackExceptionClasses(getExceptionList(SkippableException.class)); - - Step step = factory.getObject(); - - step.execute(stepExecution); - - assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - assertEquals(1, stepExecution.getSkipCount()); - assertEquals(0, stepExecution.getReadSkipCount()); - assertEquals(5, stepExecution.getReadCount()); - assertEquals(1, stepExecution.getProcessSkipCount()); - assertEquals(0, stepExecution.getRollbackCount()); - - // skips "4" - assertTrue(reader.getRead().contains("4")); - assertFalse(writer.getCommitted().contains("4")); - - List expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,2,3,5")); - assertEquals(expectedOutput, writer.getCommitted()); - - } - - /** - * Scenario: Exception in writer that should not cause rollback and scan - */ - @Test - public void testWriterDefaultRollbackOnCheckedException() throws Exception { - writer.setFailures("2", "3"); - writer.setExceptionType(SkippableException.class); - - Step step = factory.getObject(); - - step.execute(stepExecution); - assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - assertEquals(2, stepExecution.getSkipCount()); - assertEquals(4, stepExecution.getRollbackCount()); - } - - /** - * Scenario: Exception in writer that should not cause rollback and scan - */ - @Test - public void testWriterDefaultRollbackOnError() throws Exception { - writer.setFailures("2", "3"); - writer.setExceptionType(AssertionError.class); - - Step step = factory.getObject(); - - step.execute(stepExecution); - assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); - assertEquals(0, stepExecution.getSkipCount()); - assertEquals(1, stepExecution.getRollbackCount()); - } - - /** - * Scenario: Exception in writer that should not cause rollback and scan - */ - @Test - public void testWriterDefaultRollbackOnRuntimeException() throws Exception { - writer.setFailures("2", "3"); - writer.setExceptionType(SkippableRuntimeException.class); - - Step step = factory.getObject(); - - step.execute(stepExecution); - assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - assertEquals(2, stepExecution.getSkipCount()); - assertEquals(4, stepExecution.getRollbackCount()); - - } - - /** - * Scenario: Exception in writer that should not cause rollback and scan - */ - @Test - public void testWriterNoRollbackOnRuntimeException() throws Exception { - - writer.setFailures("2", "3"); - writer.setExceptionType(SkippableRuntimeException.class); - - factory.setNoRollbackExceptionClasses(getExceptionList(SkippableRuntimeException.class)); - - Step step = factory.getObject(); - - step.execute(stepExecution); - assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - assertEquals(2, stepExecution.getSkipCount()); - // Two multi-item chunks rolled back. When the item was encountered on - // its own it can proceed - assertEquals(2, stepExecution.getRollbackCount()); - - } - - /** - * Scenario: Exception in writer that should not cause rollback and scan - */ - @Test - public void testWriterNoRollbackOnCheckedException() throws Exception { - writer.setFailures("2", "3"); - writer.setExceptionType(SkippableException.class); - - factory.setNoRollbackExceptionClasses(getExceptionList(SkippableException.class)); - - Step step = factory.getObject(); - - step.execute(stepExecution); - assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - assertEquals(2, stepExecution.getSkipCount()); - // Two multi-item chunks rolled back. When the item was encountered on - // its own it can proceed - assertEquals(2, stepExecution.getRollbackCount()); - } - - @Test - public void testSkipInProcessor() throws Exception { - processor.setFailures("4"); - factory.setCommitInterval(30); - - Step step = factory.getObject(); - - step.execute(stepExecution); - assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - - assertEquals("[1, 2, 3, 4, 1, 2, 3, 5]", processor.getProcessed().toString()); - assertEquals("[1, 2, 3, 5]", processor.getCommitted().toString()); - assertEquals("[1, 2, 3, 5]", writer.getWritten().toString()); - assertEquals("[1, 2, 3, 5]", writer.getCommitted().toString()); - } - - @Test - public void testMultipleSkipsInProcessor() throws Exception { - processor.setFailures("2", "4"); - factory.setCommitInterval(30); - - Step step = factory.getObject(); - - step.execute(stepExecution); - assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - - assertEquals("[1, 3, 5]", processor.getCommitted().toString()); - assertEquals("[1, 3, 5]", writer.getWritten().toString()); - assertEquals("[1, 3, 5]", writer.getCommitted().toString()); - assertEquals("[1, 2, 1, 3, 4, 1, 3, 5]", processor.getProcessed().toString()); - } - - @Test - public void testMultipleSkipsInNonTransactionalProcessor() throws Exception { - processor.setFailures("2", "4"); - factory.setCommitInterval(30); - factory.setProcessorTransactional(false); - - Step step = factory.getObject(); - - step.execute(stepExecution); - assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - - assertEquals("[1, 3, 5]", writer.getWritten().toString()); - assertEquals("[1, 3, 5]", writer.getCommitted().toString()); - // If non-transactional, we should only process each item once - assertEquals("[1, 2, 3, 4, 5]", processor.getProcessed().toString()); - } - - @Test - public void testFilterInProcessor() throws Exception { - processor.setFailures("4"); - processor.setFilter(true); - factory.setCommitInterval(30); - - Step step = factory.getObject(); - - step.execute(stepExecution); - assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - - assertEquals("[1, 2, 3, 4, 5]", processor.getProcessed().toString()); - assertEquals("[1, 2, 3, 4, 5]", processor.getCommitted().toString()); - assertEquals("[1, 2, 3, 5]", writer.getWritten().toString()); - assertEquals("[1, 2, 3, 5]", writer.getCommitted().toString()); - } - - @Test - public void testSkipInWriter() throws Exception { - writer.setFailures("4"); - factory.setCommitInterval(30); - - Step step = factory.getObject(); - - step.execute(stepExecution); - assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - - assertEquals("[1, 2, 3, 5]", processor.getCommitted().toString()); - assertEquals("[1, 2, 3, 5]", writer.getCommitted().toString()); - assertEquals("[1, 2, 3, 4, 1, 2, 3, 4, 5]", writer.getWritten().toString()); - assertEquals("[1, 2, 3, 4, 5, 1, 2, 3, 4, 5]", processor.getProcessed().toString()); - - assertEquals(1, stepExecution.getWriteSkipCount()); - assertEquals(5, stepExecution.getReadCount()); - assertEquals(4, stepExecution.getWriteCount()); - assertEquals(0, stepExecution.getFilterCount()); - } - - @Test - public void testSkipInWriterNonTransactionalProcessor() throws Exception { - writer.setFailures("4"); - factory.setCommitInterval(30); - factory.setProcessorTransactional(false); - - Step step = factory.getObject(); - - step.execute(stepExecution); - assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - - assertEquals("[1, 2, 3, 5]", writer.getCommitted().toString()); - assertEquals("[1, 2, 3, 4, 1, 2, 3, 4, 5]", writer.getWritten().toString()); - assertEquals("[1, 2, 3, 4, 5]", processor.getProcessed().toString()); - } - - @Test - public void testSkipInWriterTransactionalReader() throws Exception { - writer.setFailures("4"); - ItemReader reader = new ListItemReader<>(TransactionAwareProxyFactory.createTransactionalList(Arrays.asList("1", "2", "3", "4", "5"))); - factory.setItemReader(reader); - factory.setCommitInterval(30); - factory.setSkipLimit(10); - factory.setIsReaderTransactionalQueue(true); - - Step step = factory.getObject(); - - step.execute(stepExecution); - assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - - assertEquals("[]", writer.getCommitted().toString()); - assertEquals("[1, 2, 3, 4]", writer.getWritten().toString()); - assertEquals("[1, 2, 3, 4, 5, 1, 2, 3, 4, 5]", processor.getProcessed().toString()); - } - - @Test - public void testMultithreadedSkipInWriter() throws Exception { - writer.setFailures("1", "2", "3", "4", "5"); - factory.setCommitInterval(3); - factory.setSkipLimit(10); - factory.setTaskExecutor(new SimpleAsyncTaskExecutor()); - - Step step = factory.getObject(); - - step.execute(stepExecution); - assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - - assertEquals("[]", writer.getCommitted().toString()); - assertEquals("[]", processor.getCommitted().toString()); - assertEquals(5, stepExecution.getSkipCount()); - } - - @Test - public void testMultipleSkipsInWriter() throws Exception { - writer.setFailures("2", "4"); - factory.setCommitInterval(30); - - Step step = factory.getObject(); - - step.execute(stepExecution); - assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - - assertEquals("[1, 3, 5]", writer.getCommitted().toString()); - assertEquals("[1, 2, 1, 2, 3, 4, 5]", writer.getWritten().toString()); - assertEquals("[1, 3, 5]", processor.getCommitted().toString()); - assertEquals("[1, 2, 3, 4, 5, 1, 2, 3, 4, 5]", processor.getProcessed().toString()); - - assertEquals(2, stepExecution.getWriteSkipCount()); - assertEquals(5, stepExecution.getReadCount()); - assertEquals(3, stepExecution.getWriteCount()); - assertEquals(0, stepExecution.getFilterCount()); - } - - @Test - public void testMultipleSkipsInWriterNonTransactionalProcessor() throws Exception { - writer.setFailures("2", "4"); - factory.setCommitInterval(30); - factory.setProcessorTransactional(false); - - Step step = factory.getObject(); - - step.execute(stepExecution); - assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - - assertEquals("[1, 3, 5]", writer.getCommitted().toString()); - assertEquals("[1, 2, 1, 2, 3, 4, 5]", writer.getWritten().toString()); - assertEquals("[1, 2, 3, 4, 5]", processor.getProcessed().toString()); - } - - @SuppressWarnings("unchecked") - private Collection> getExceptionList(Class arg) { - return Arrays.> asList(arg); - } - - @SuppressWarnings("unchecked") - private Map, Boolean> getExceptionMap(Class... args) { - Map, Boolean> map = new HashMap<>(); - for (Class arg : args) { - map.put(arg, true); - } - return map; - } - - class ExceptionThrowingChunkListener implements ChunkListener{ - - private int phase = -1; - - public ExceptionThrowingChunkListener(int throwPhase) { - this.phase = throwPhase; - } - - @Override - public void beforeChunk(ChunkContext context) { - if(phase == 1){ - throw new IllegalArgumentException("Planned exception"); - } - } - - @Override - public void afterChunk(ChunkContext context) { - if(phase == 2) { - throw new IllegalArgumentException("Planned exception"); - } - } - - @Override - public void afterChunkError(ChunkContext context) { - if(phase == 3) { - throw new IllegalArgumentException("Planned exception"); - } - } - } -} +/* + * Copyright 2009-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.step.item; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.ChunkListener; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.Step; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.StepListener; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; +import org.springframework.batch.core.scope.context.ChunkContext; +import org.springframework.batch.core.step.FatalStepExecutionException; +import org.springframework.batch.core.step.factory.FaultTolerantStepFactoryBean; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.support.ListItemReader; +import org.springframework.batch.support.transaction.ResourcelessTransactionManager; +import org.springframework.batch.support.transaction.TransactionAwareProxyFactory; +import org.springframework.core.task.SimpleAsyncTaskExecutor; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.transaction.interceptor.RollbackRuleAttribute; +import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute; +import org.springframework.transaction.interceptor.TransactionAttribute; +import org.springframework.transaction.interceptor.TransactionAttributeEditor; +import org.springframework.util.StringUtils; + +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.springframework.batch.core.BatchStatus.FAILED; + +/** + * Tests for {@link FaultTolerantStepFactoryBean}. + */ +public class FaultTolerantStepFactoryBeanRollbackTests { + + protected final Log logger = LogFactory.getLog(getClass()); + + private FaultTolerantStepFactoryBean factory; + + private SkipReaderStub reader; + + private SkipProcessorStub processor; + + private SkipWriterStub writer; + + private JobExecution jobExecution; + + private StepExecution stepExecution; + + private JobRepository repository; + + @SuppressWarnings("unchecked") + @Before + public void setUp() throws Exception { + reader = new SkipReaderStub<>(); + processor = new SkipProcessorStub<>(); + writer = new SkipWriterStub<>(); + + factory = new FaultTolerantStepFactoryBean<>(); + + factory.setBeanName("stepName"); + ResourcelessTransactionManager transactionManager = new ResourcelessTransactionManager(); + factory.setTransactionManager(transactionManager); + factory.setCommitInterval(2); + + reader.clear(); + reader.setItems("1", "2", "3", "4", "5"); + factory.setItemReader(reader); + processor.clear(); + factory.setItemProcessor(processor); + writer.clear(); + factory.setItemWriter(writer); + + factory.setSkipLimit(2); + + factory.setSkippableExceptionClasses(getExceptionMap(Exception.class)); + + EmbeddedDatabase embeddedDatabase = new EmbeddedDatabaseBuilder() + .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") + .addScript("/org/springframework/batch/core/schema-hsqldb.sql").build(); + JobRepositoryFactoryBean repositoryFactory = new JobRepositoryFactoryBean(); + repositoryFactory.setDataSource(embeddedDatabase); + repositoryFactory.setTransactionManager(new DataSourceTransactionManager(embeddedDatabase)); + repositoryFactory.afterPropertiesSet(); + repository = repositoryFactory.getObject(); + factory.setJobRepository(repository); + + jobExecution = repository.createJobExecution("skipJob", new JobParameters()); + stepExecution = jobExecution.createStepExecution(factory.getName()); + repository.add(stepExecution); + } + + @After + public void tearDown() throws Exception { + reader = null; + processor = null; + writer = null; + factory = null; + } + + @Test + public void testBeforeChunkListenerException() throws Exception { + factory.setListeners(new StepListener[] { new ExceptionThrowingChunkListener(1) }); + Step step = factory.getObject(); + step.execute(stepExecution); + assertEquals(FAILED, stepExecution.getStatus()); + assertEquals(FAILED.toString(), stepExecution.getExitStatus().getExitCode()); + assertTrue(stepExecution.getCommitCount() == 0);// Make sure exception was thrown + // in after, not before + Throwable e = stepExecution.getFailureExceptions().get(0); + assertThat(e, instanceOf(FatalStepExecutionException.class)); + assertThat(e.getCause(), instanceOf(IllegalArgumentException.class)); + } + + @Test + public void testAfterChunkListenerException() throws Exception { + factory.setListeners(new StepListener[] { new ExceptionThrowingChunkListener(2) }); + Step step = factory.getObject(); + step.execute(stepExecution); + assertEquals(FAILED, stepExecution.getStatus()); + assertEquals(FAILED.toString(), stepExecution.getExitStatus().getExitCode()); + assertTrue(stepExecution.getCommitCount() > 0);// Make sure exception was thrown + // in after, not before + Throwable e = stepExecution.getFailureExceptions().get(0); + assertThat(e, instanceOf(FatalStepExecutionException.class)); + assertThat(e.getCause(), instanceOf(IllegalArgumentException.class)); + } + + @Test + public void testOverrideWithoutChangingRollbackRules() throws Exception { + TransactionAttributeEditor editor = new TransactionAttributeEditor(); + editor.setAsText("-RuntimeException"); + TransactionAttribute attr = (TransactionAttribute) editor.getValue(); + assertTrue(attr.rollbackOn(new RuntimeException(""))); + assertFalse(attr.rollbackOn(new Exception(""))); + } + + @Test + public void testChangeRollbackRules() throws Exception { + TransactionAttributeEditor editor = new TransactionAttributeEditor(); + editor.setAsText("+RuntimeException"); + TransactionAttribute attr = (TransactionAttribute) editor.getValue(); + assertFalse(attr.rollbackOn(new RuntimeException(""))); + assertFalse(attr.rollbackOn(new Exception(""))); + } + + @Test + public void testNonDefaultRollbackRules() throws Exception { + TransactionAttributeEditor editor = new TransactionAttributeEditor(); + editor.setAsText("+RuntimeException,+SkippableException"); + RuleBasedTransactionAttribute attr = (RuleBasedTransactionAttribute) editor.getValue(); + attr.getRollbackRules().add(new RollbackRuleAttribute(Exception.class)); + assertTrue(attr.rollbackOn(new Exception(""))); + assertFalse(attr.rollbackOn(new RuntimeException(""))); + assertFalse(attr.rollbackOn(new SkippableException(""))); + } + + /** + * Scenario: Exception in reader that should not cause rollback + */ + @Test + public void testReaderDefaultNoRollbackOnCheckedException() throws Exception { + reader.setItems("1", "2", "3", "4"); + reader.setFailures("2", "3"); + reader.setExceptionType(SkippableException.class); + + Step step = factory.getObject(); + + step.execute(stepExecution); + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + assertEquals(2, stepExecution.getSkipCount()); + assertEquals(0, stepExecution.getRollbackCount()); + } + + /** + * Scenario: Exception in reader that should not cause rollback + */ + @SuppressWarnings("unchecked") + @Test + public void testReaderAttributesOverrideSkippableNoRollback() throws Exception { + reader.setFailures("2", "3"); + reader.setItems("1", "2", "3", "4"); + reader.setExceptionType(SkippableException.class); + + // No skips by default + factory.setSkippableExceptionClasses(getExceptionMap(RuntimeException.class)); + // But this one is explicit in the tx-attrs so it should be skipped + factory.setNoRollbackExceptionClasses(getExceptionList(SkippableException.class)); + + Step step = factory.getObject(); + + step.execute(stepExecution); + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + assertEquals(0, stepExecution.getSkipCount()); + assertEquals(0, stepExecution.getRollbackCount()); + } + + /** + * Scenario: Exception in processor that should cause rollback because of checked + * exception + */ + @Test + public void testProcessorDefaultRollbackOnCheckedException() throws Exception { + reader.setItems("1", "2", "3", "4"); + + processor.setFailures("1", "3"); + processor.setExceptionType(SkippableException.class); + + Step step = factory.getObject(); + + step.execute(stepExecution); + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + assertEquals(2, stepExecution.getSkipCount()); + assertEquals(2, stepExecution.getRollbackCount()); + } + + /** + * Scenario: Exception in processor that should cause rollback + */ + @Test + public void testProcessorDefaultRollbackOnRuntimeException() throws Exception { + reader.setItems("1", "2", "3", "4"); + + processor.setFailures("1", "3"); + processor.setExceptionType(SkippableRuntimeException.class); + + Step step = factory.getObject(); + + step.execute(stepExecution); + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + assertEquals(2, stepExecution.getSkipCount()); + assertEquals(2, stepExecution.getRollbackCount()); + } + + @Test + public void testNoRollbackInProcessorWhenSkipExceeded() throws Throwable { + + jobExecution = repository.createJobExecution("noRollbackJob", new JobParameters()); + + factory.setSkipLimit(0); + + reader.clear(); + reader.setItems("1", "2", "3", "4", "5"); + factory.setItemReader(reader); + writer.clear(); + factory.setItemWriter(writer); + processor.clear(); + factory.setItemProcessor(processor); + + @SuppressWarnings("unchecked") + List> exceptions = Arrays.asList(Exception.class); + factory.setNoRollbackExceptionClasses(exceptions); + @SuppressWarnings("unchecked") + Map, Boolean> skippable = getExceptionMap(Exception.class); + factory.setSkippableExceptionClasses(skippable); + + processor.setFailures("2"); + + Step step = factory.getObject(); + + stepExecution = jobExecution.createStepExecution(factory.getName()); + repository.add(stepExecution); + step.execute(stepExecution); + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + + assertEquals("[1, 3, 4, 5]", writer.getCommitted().toString()); + // No rollback on 2 so processor has side effect + assertEquals("[1, 2, 3, 4, 5]", processor.getCommitted().toString()); + List processed = new ArrayList<>(processor.getProcessed()); + Collections.sort(processed); + assertEquals("[1, 2, 3, 4, 5]", processed.toString()); + assertEquals(0, stepExecution.getSkipCount()); + + } + + @Test + public void testProcessSkipWithNoRollbackForCheckedException() throws Exception { + processor.setFailures("4"); + processor.setExceptionType(SkippableException.class); + + factory.setNoRollbackExceptionClasses(getExceptionList(SkippableException.class)); + + Step step = factory.getObject(); + + step.execute(stepExecution); + + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + assertEquals(1, stepExecution.getSkipCount()); + assertEquals(0, stepExecution.getReadSkipCount()); + assertEquals(5, stepExecution.getReadCount()); + assertEquals(1, stepExecution.getProcessSkipCount()); + assertEquals(0, stepExecution.getRollbackCount()); + + // skips "4" + assertTrue(reader.getRead().contains("4")); + assertFalse(writer.getCommitted().contains("4")); + + List expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,2,3,5")); + assertEquals(expectedOutput, writer.getCommitted()); + + } + + /** + * Scenario: Exception in writer that should not cause rollback and scan + */ + @Test + public void testWriterDefaultRollbackOnCheckedException() throws Exception { + writer.setFailures("2", "3"); + writer.setExceptionType(SkippableException.class); + + Step step = factory.getObject(); + + step.execute(stepExecution); + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + assertEquals(2, stepExecution.getSkipCount()); + assertEquals(4, stepExecution.getRollbackCount()); + } + + /** + * Scenario: Exception in writer that should not cause rollback and scan + */ + @Test + public void testWriterDefaultRollbackOnError() throws Exception { + writer.setFailures("2", "3"); + writer.setExceptionType(AssertionError.class); + + Step step = factory.getObject(); + + step.execute(stepExecution); + assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); + assertEquals(0, stepExecution.getSkipCount()); + assertEquals(1, stepExecution.getRollbackCount()); + } + + /** + * Scenario: Exception in writer that should not cause rollback and scan + */ + @Test + public void testWriterDefaultRollbackOnRuntimeException() throws Exception { + writer.setFailures("2", "3"); + writer.setExceptionType(SkippableRuntimeException.class); + + Step step = factory.getObject(); + + step.execute(stepExecution); + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + assertEquals(2, stepExecution.getSkipCount()); + assertEquals(4, stepExecution.getRollbackCount()); + + } + + /** + * Scenario: Exception in writer that should not cause rollback and scan + */ + @Test + public void testWriterNoRollbackOnRuntimeException() throws Exception { + + writer.setFailures("2", "3"); + writer.setExceptionType(SkippableRuntimeException.class); + + factory.setNoRollbackExceptionClasses(getExceptionList(SkippableRuntimeException.class)); + + Step step = factory.getObject(); + + step.execute(stepExecution); + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + assertEquals(2, stepExecution.getSkipCount()); + // Two multi-item chunks rolled back. When the item was encountered on + // its own it can proceed + assertEquals(2, stepExecution.getRollbackCount()); + + } + + /** + * Scenario: Exception in writer that should not cause rollback and scan + */ + @Test + public void testWriterNoRollbackOnCheckedException() throws Exception { + writer.setFailures("2", "3"); + writer.setExceptionType(SkippableException.class); + + factory.setNoRollbackExceptionClasses(getExceptionList(SkippableException.class)); + + Step step = factory.getObject(); + + step.execute(stepExecution); + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + assertEquals(2, stepExecution.getSkipCount()); + // Two multi-item chunks rolled back. When the item was encountered on + // its own it can proceed + assertEquals(2, stepExecution.getRollbackCount()); + } + + @Test + public void testSkipInProcessor() throws Exception { + processor.setFailures("4"); + factory.setCommitInterval(30); + + Step step = factory.getObject(); + + step.execute(stepExecution); + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + + assertEquals("[1, 2, 3, 4, 1, 2, 3, 5]", processor.getProcessed().toString()); + assertEquals("[1, 2, 3, 5]", processor.getCommitted().toString()); + assertEquals("[1, 2, 3, 5]", writer.getWritten().toString()); + assertEquals("[1, 2, 3, 5]", writer.getCommitted().toString()); + } + + @Test + public void testMultipleSkipsInProcessor() throws Exception { + processor.setFailures("2", "4"); + factory.setCommitInterval(30); + + Step step = factory.getObject(); + + step.execute(stepExecution); + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + + assertEquals("[1, 3, 5]", processor.getCommitted().toString()); + assertEquals("[1, 3, 5]", writer.getWritten().toString()); + assertEquals("[1, 3, 5]", writer.getCommitted().toString()); + assertEquals("[1, 2, 1, 3, 4, 1, 3, 5]", processor.getProcessed().toString()); + } + + @Test + public void testMultipleSkipsInNonTransactionalProcessor() throws Exception { + processor.setFailures("2", "4"); + factory.setCommitInterval(30); + factory.setProcessorTransactional(false); + + Step step = factory.getObject(); + + step.execute(stepExecution); + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + + assertEquals("[1, 3, 5]", writer.getWritten().toString()); + assertEquals("[1, 3, 5]", writer.getCommitted().toString()); + // If non-transactional, we should only process each item once + assertEquals("[1, 2, 3, 4, 5]", processor.getProcessed().toString()); + } + + @Test + public void testFilterInProcessor() throws Exception { + processor.setFailures("4"); + processor.setFilter(true); + factory.setCommitInterval(30); + + Step step = factory.getObject(); + + step.execute(stepExecution); + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + + assertEquals("[1, 2, 3, 4, 5]", processor.getProcessed().toString()); + assertEquals("[1, 2, 3, 4, 5]", processor.getCommitted().toString()); + assertEquals("[1, 2, 3, 5]", writer.getWritten().toString()); + assertEquals("[1, 2, 3, 5]", writer.getCommitted().toString()); + } + + @Test + public void testSkipInWriter() throws Exception { + writer.setFailures("4"); + factory.setCommitInterval(30); + + Step step = factory.getObject(); + + step.execute(stepExecution); + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + + assertEquals("[1, 2, 3, 5]", processor.getCommitted().toString()); + assertEquals("[1, 2, 3, 5]", writer.getCommitted().toString()); + assertEquals("[1, 2, 3, 4, 1, 2, 3, 4, 5]", writer.getWritten().toString()); + assertEquals("[1, 2, 3, 4, 5, 1, 2, 3, 4, 5]", processor.getProcessed().toString()); + + assertEquals(1, stepExecution.getWriteSkipCount()); + assertEquals(5, stepExecution.getReadCount()); + assertEquals(4, stepExecution.getWriteCount()); + assertEquals(0, stepExecution.getFilterCount()); + } + + @Test + public void testSkipInWriterNonTransactionalProcessor() throws Exception { + writer.setFailures("4"); + factory.setCommitInterval(30); + factory.setProcessorTransactional(false); + + Step step = factory.getObject(); + + step.execute(stepExecution); + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + + assertEquals("[1, 2, 3, 5]", writer.getCommitted().toString()); + assertEquals("[1, 2, 3, 4, 1, 2, 3, 4, 5]", writer.getWritten().toString()); + assertEquals("[1, 2, 3, 4, 5]", processor.getProcessed().toString()); + } + + @Test + public void testSkipInWriterTransactionalReader() throws Exception { + writer.setFailures("4"); + ItemReader reader = new ListItemReader<>( + TransactionAwareProxyFactory.createTransactionalList(Arrays.asList("1", "2", "3", "4", "5"))); + factory.setItemReader(reader); + factory.setCommitInterval(30); + factory.setSkipLimit(10); + factory.setIsReaderTransactionalQueue(true); + + Step step = factory.getObject(); + + step.execute(stepExecution); + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + + assertEquals("[]", writer.getCommitted().toString()); + assertEquals("[1, 2, 3, 4]", writer.getWritten().toString()); + assertEquals("[1, 2, 3, 4, 5, 1, 2, 3, 4, 5]", processor.getProcessed().toString()); + } + + @Test + public void testMultithreadedSkipInWriter() throws Exception { + writer.setFailures("1", "2", "3", "4", "5"); + factory.setCommitInterval(3); + factory.setSkipLimit(10); + factory.setTaskExecutor(new SimpleAsyncTaskExecutor()); + + Step step = factory.getObject(); + + step.execute(stepExecution); + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + + assertEquals("[]", writer.getCommitted().toString()); + assertEquals("[]", processor.getCommitted().toString()); + assertEquals(5, stepExecution.getSkipCount()); + } + + @Test + public void testMultipleSkipsInWriter() throws Exception { + writer.setFailures("2", "4"); + factory.setCommitInterval(30); + + Step step = factory.getObject(); + + step.execute(stepExecution); + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + + assertEquals("[1, 3, 5]", writer.getCommitted().toString()); + assertEquals("[1, 2, 1, 2, 3, 4, 5]", writer.getWritten().toString()); + assertEquals("[1, 3, 5]", processor.getCommitted().toString()); + assertEquals("[1, 2, 3, 4, 5, 1, 2, 3, 4, 5]", processor.getProcessed().toString()); + + assertEquals(2, stepExecution.getWriteSkipCount()); + assertEquals(5, stepExecution.getReadCount()); + assertEquals(3, stepExecution.getWriteCount()); + assertEquals(0, stepExecution.getFilterCount()); + } + + @Test + public void testMultipleSkipsInWriterNonTransactionalProcessor() throws Exception { + writer.setFailures("2", "4"); + factory.setCommitInterval(30); + factory.setProcessorTransactional(false); + + Step step = factory.getObject(); + + step.execute(stepExecution); + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + + assertEquals("[1, 3, 5]", writer.getCommitted().toString()); + assertEquals("[1, 2, 1, 2, 3, 4, 5]", writer.getWritten().toString()); + assertEquals("[1, 2, 3, 4, 5]", processor.getProcessed().toString()); + } + + @SuppressWarnings("unchecked") + private Collection> getExceptionList(Class arg) { + return Arrays.>asList(arg); + } + + @SuppressWarnings("unchecked") + private Map, Boolean> getExceptionMap(Class... args) { + Map, Boolean> map = new HashMap<>(); + for (Class arg : args) { + map.put(arg, true); + } + return map; + } + + class ExceptionThrowingChunkListener implements ChunkListener { + + private int phase = -1; + + public ExceptionThrowingChunkListener(int throwPhase) { + this.phase = throwPhase; + } + + @Override + public void beforeChunk(ChunkContext context) { + if (phase == 1) { + throw new IllegalArgumentException("Planned exception"); + } + } + + @Override + public void afterChunk(ChunkContext context) { + if (phase == 2) { + throw new IllegalArgumentException("Planned exception"); + } + } + + @Override + public void afterChunkError(ChunkContext context) { + if (phase == 3) { + throw new IllegalArgumentException("Planned exception"); + } + } + + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBeanTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBeanTests.java index 7de2e2644..8093925fe 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBeanTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBeanTests.java @@ -1,1152 +1,1151 @@ -/* - * Copyright 2008-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.step.item; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.aopalliance.intercept.MethodInterceptor; -import org.aopalliance.intercept.MethodInvocation; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import org.springframework.aop.framework.ProxyFactory; -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.ChunkListener; -import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.ItemProcessListener; -import org.springframework.batch.core.ItemReadListener; -import org.springframework.batch.core.ItemWriteListener; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.SkipListener; -import org.springframework.batch.core.Step; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.StepListener; -import org.springframework.batch.core.repository.JobRepository; -import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; -import org.springframework.batch.core.scope.context.ChunkContext; -import org.springframework.batch.core.step.factory.FaultTolerantStepFactoryBean; -import org.springframework.batch.core.step.skip.LimitCheckingItemSkipPolicy; -import org.springframework.batch.core.step.skip.SkipLimitExceededException; -import org.springframework.batch.core.step.skip.SkipPolicy; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.ItemStream; -import org.springframework.batch.item.ItemStreamException; -import org.springframework.batch.item.ItemStreamReader; -import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.item.ItemWriterException; -import org.springframework.batch.item.ParseException; -import org.springframework.batch.item.UnexpectedInputException; -import org.springframework.batch.item.WriteFailedException; -import org.springframework.batch.item.WriterNotOpenException; -import org.springframework.batch.item.support.AbstractItemStreamItemReader; -import org.springframework.beans.factory.FactoryBean; -import org.springframework.jdbc.datasource.DataSourceTransactionManager; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; -import org.springframework.lang.Nullable; -import org.springframework.scheduling.concurrent.ConcurrentTaskExecutor; -import org.springframework.test.util.ReflectionTestUtils; -import org.springframework.util.StringUtils; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -/** - * Tests for {@link FaultTolerantStepFactoryBean}. - */ -public class FaultTolerantStepFactoryBeanTests { - - protected final Log logger = LogFactory.getLog(getClass()); - - private FaultTolerantStepFactoryBean factory; - - private SkipReaderStub reader; - - private SkipProcessorStub processor; - - private SkipWriterStub writer; - - private JobExecution jobExecution; - - private StepExecution stepExecution; - - private JobRepository repository; - - private boolean opened = false; - - private boolean closed = false; - - public FaultTolerantStepFactoryBeanTests() throws Exception { - reader = new SkipReaderStub<>(); - processor = new SkipProcessorStub<>(); - writer = new SkipWriterStub<>(); - } - - @SuppressWarnings("unchecked") - @Before - public void setUp() throws Exception { - EmbeddedDatabase embeddedDatabase = new EmbeddedDatabaseBuilder() - .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("/org/springframework/batch/core/schema-hsqldb-extended.sql") - .generateUniqueName(true) - .build(); - DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(embeddedDatabase); - - factory = new FaultTolerantStepFactoryBean<>(); - - factory.setBeanName("stepName"); - factory.setTransactionManager(transactionManager); - factory.setCommitInterval(2); - - reader.clear(); - reader.setItems("1", "2", "3", "4", "5"); - factory.setItemReader(reader); - processor.clear(); - factory.setItemProcessor(processor); - writer.clear(); - factory.setItemWriter(writer); - - factory.setSkipLimit(2); - - factory - .setSkippableExceptionClasses(getExceptionMap(SkippableException.class, SkippableRuntimeException.class)); - - JobRepositoryFactoryBean repositoryFactoryBean = new JobRepositoryFactoryBean(); - repositoryFactoryBean.setDataSource(embeddedDatabase); - repositoryFactoryBean.setTransactionManager(transactionManager); - repositoryFactoryBean.setMaxVarCharLength(10000); - repositoryFactoryBean.afterPropertiesSet(); - repository = repositoryFactoryBean.getObject(); - factory.setJobRepository(repository); - - jobExecution = repository.createJobExecution("skipJob", new JobParameters()); - stepExecution = jobExecution.createStepExecution(factory.getName()); - repository.add(stepExecution); - } - - @Test - public void testMandatoryReader() { - // given - factory = new FaultTolerantStepFactoryBean<>(); - factory.setItemWriter(writer); - - // when - final Exception expectedException = Assert.assertThrows(IllegalStateException.class, factory::getObject); - - // then - assertEquals("ItemReader must be provided", expectedException.getMessage()); - } - - @Test - public void testMandatoryWriter() throws Exception { - // given - factory = new FaultTolerantStepFactoryBean<>(); - factory.setItemReader(reader); - - // when - final Exception expectedException = Assert.assertThrows(IllegalStateException.class, factory::getObject); - - // then - assertEquals("ItemWriter must be provided", expectedException.getMessage()); - } - - /** - * Non-skippable (and non-fatal) exception causes failure immediately. - * - * @throws Exception - */ - @SuppressWarnings("unchecked") - @Test - public void testNonSkippableExceptionOnRead() throws Exception { - reader.setFailures("2"); - - // nothing is skippable - factory.setSkippableExceptionClasses(getExceptionMap(NonExistentException.class)); - - Step step = factory.getObject(); - - step.execute(stepExecution); - assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); - assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution.getExitStatus().getExitCode()); - assertTrue(stepExecution.getExitStatus().getExitDescription().contains("Non-skippable exception during read")); - - assertStepExecutionsAreEqual(stepExecution, repository.getLastStepExecution(jobExecution.getJobInstance(), step - .getName())); - } - - @SuppressWarnings("unchecked") - @Test - public void testNonSkippableException() throws Exception { - // nothing is skippable - factory.setSkippableExceptionClasses(getExceptionMap(NonExistentException.class)); - factory.setCommitInterval(1); - - // no failures on read - reader.setItems("1", "2", "3", "4", "5"); - writer.setFailures("1"); - - Step step = factory.getObject(); - - step.execute(stepExecution); - assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); - assertEquals(1, reader.getRead().size()); - assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution.getExitStatus().getExitCode()); - assertTrue(stepExecution.getExitStatus().getExitDescription().contains("Intended Failure")); - assertStepExecutionsAreEqual(stepExecution, repository.getLastStepExecution(jobExecution.getJobInstance(), step - .getName())); - } - - /** - * Check items causing errors are skipped as expected. - */ - @Test - public void testReadSkip() throws Exception { - reader.setFailures("2"); - - Step step = factory.getObject(); - - step.execute(stepExecution); - - assertEquals(1, stepExecution.getSkipCount()); - assertEquals(1, stepExecution.getReadSkipCount()); - assertEquals(4, stepExecution.getReadCount()); - assertEquals(0, stepExecution.getWriteSkipCount()); - assertEquals(0, stepExecution.getRollbackCount()); - - // writer did not skip "2" as it never made it to writer, only "4" did - assertTrue(reader.getRead().contains("4")); - assertFalse(reader.getRead().contains("2")); - - List expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,3,4,5")); - assertEquals(expectedOutput, writer.getWritten()); - - assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - assertStepExecutionsAreEqual(stepExecution, repository.getLastStepExecution(jobExecution.getJobInstance(), step - .getName())); - } - - /** - * Check items causing errors are skipped as expected. - */ - @Test - public void testReadSkipWithPolicy() throws Exception { - // Should be ignored - factory.setSkipLimit(0); - factory.setSkipPolicy(new LimitCheckingItemSkipPolicy(2, Collections - ., Boolean> singletonMap(Exception.class, true))); - testReadSkip(); - } - - /** - * Check items causing errors are skipped as expected. - */ - @Test - public void testReadSkipWithPolicyExceptionInReader() throws Exception { - - // Should be ignored - factory.setSkipLimit(0); - - factory.setSkipPolicy(new SkipPolicy() { - @Override - public boolean shouldSkip(Throwable t, long skipCount) throws SkipLimitExceededException { - throw new RuntimeException("Planned exception in SkipPolicy"); - } - }); - - reader.setFailures("2"); - - Step step = factory.getObject(); - - step.execute(stepExecution); - - assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); - assertEquals(0, stepExecution.getReadSkipCount()); - assertEquals(1, stepExecution.getReadCount()); - - } - - /** - * Check items causing errors are skipped as expected. - */ - @Test - public void testReadSkipWithPolicyExceptionInWriter() throws Exception { - - // Should be ignored - factory.setSkipLimit(0); - - factory.setSkipPolicy(new SkipPolicy() { - @Override - public boolean shouldSkip(Throwable t, long skipCount) throws SkipLimitExceededException { - throw new RuntimeException("Planned exception in SkipPolicy"); - } - }); - - writer.setFailures("2"); - - Step step = factory.getObject(); - - step.execute(stepExecution); - - assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); - assertEquals(0, stepExecution.getWriteSkipCount()); - assertEquals(2, stepExecution.getReadCount()); - - } - - /** - * Check to make sure that ItemStreamException can be skipped. (see - * BATCH-915) - */ - @Test - public void testReadSkipItemStreamException() throws Exception { - reader.setFailures("2"); - reader.setExceptionType(ItemStreamException.class); - - Map, Boolean> map = new HashMap<>(); - map.put(ItemStreamException.class, true); - factory.setSkippableExceptionClasses(map); - - Step step = factory.getObject(); - - step.execute(stepExecution); - - assertEquals(1, stepExecution.getSkipCount()); - assertEquals(1, stepExecution.getReadSkipCount()); - assertEquals(4, stepExecution.getReadCount()); - assertEquals(0, stepExecution.getWriteSkipCount()); - assertEquals(0, stepExecution.getRollbackCount()); - - // writer did not skip "2" as it never made it to writer, only "4" did - assertTrue(reader.getRead().contains("4")); - assertFalse(reader.getRead().contains("2")); - - List expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,3,4,5")); - assertEquals(expectedOutput, writer.getWritten()); - - assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - assertStepExecutionsAreEqual(stepExecution, repository.getLastStepExecution(jobExecution.getJobInstance(), step - .getName())); - } - - /** - * Check items causing errors are skipped as expected. - */ - @Test - public void testProcessSkip() throws Exception { - processor.setFailures("4"); - writer.setFailures("4"); - - Step step = factory.getObject(); - - step.execute(stepExecution); - - assertEquals(1, stepExecution.getSkipCount()); - assertEquals(0, stepExecution.getReadSkipCount()); - assertEquals(5, stepExecution.getReadCount()); - assertEquals(1, stepExecution.getProcessSkipCount()); - assertEquals(1, stepExecution.getRollbackCount()); - - // writer skips "4" - assertTrue(reader.getRead().contains("4")); - assertFalse(writer.getWritten().contains("4")); - - List expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,2,3,5")); - assertEquals(expectedOutput, writer.getWritten()); - - assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - assertStepExecutionsAreEqual(stepExecution, repository.getLastStepExecution(jobExecution.getJobInstance(), step - .getName())); - } - - @Test - public void testProcessFilter() throws Exception { - processor.setFailures("4"); - processor.setFilter(true); - ItemProcessListenerStub listenerStub = new ItemProcessListenerStub<>(); - factory.setListeners(new StepListener[] { listenerStub }); - Step step = factory.getObject(); - - step.execute(stepExecution); - - assertEquals(0, stepExecution.getSkipCount()); - assertEquals(0, stepExecution.getReadSkipCount()); - assertEquals(5, stepExecution.getReadCount()); - assertEquals(1, stepExecution.getFilterCount()); - assertEquals(0, stepExecution.getRollbackCount()); - assertTrue(listenerStub.isFilterEncountered()); - - // writer skips "4" - assertTrue(reader.getRead().contains("4")); - assertFalse(writer.getWritten().contains("4")); - - List expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,2,3,5")); - assertEquals(expectedOutput, writer.getWritten()); - - assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - assertStepExecutionsAreEqual(stepExecution, repository.getLastStepExecution(jobExecution.getJobInstance(), step - .getName())); - } - - /** - * Check items causing errors are skipped as expected. - */ - @Test - public void testWriteSkip() throws Exception { - writer.setFailures("4"); - - Step step = factory.getObject(); - - step.execute(stepExecution); - - assertEquals(1, stepExecution.getSkipCount()); - assertEquals(0, stepExecution.getReadSkipCount()); - assertEquals(5, stepExecution.getReadCount()); - assertEquals(1, stepExecution.getWriteSkipCount()); - assertEquals(2, stepExecution.getRollbackCount()); - - // writer skips "4" - assertTrue(reader.getRead().contains("4")); - assertFalse(writer.getCommitted().contains("4")); - - List expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,2,3,5")); - assertEquals(expectedOutput, writer.getCommitted()); - - assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - assertStepExecutionsAreEqual(stepExecution, repository.getLastStepExecution(jobExecution.getJobInstance(), step - .getName())); - } - - /** - * Fatal exception should cause immediate termination provided the exception - * is not skippable (note the fatal exception is also classified as - * rollback). - */ - @Test - public void testFatalException() throws Exception { - reader.setFailures("2"); - - Map, Boolean> map = new HashMap<>(); - map.put(SkippableException.class, true); - map.put(SkippableRuntimeException.class, true); - map.put(FatalRuntimeException.class, false); - factory.setSkippableExceptionClasses(map); - factory.setItemWriter(new ItemWriter() { - @Override - public void write(List items) { - throw new FatalRuntimeException("Ouch!"); - } - }); - - Step step = factory.getObject(); - - step.execute(stepExecution); - String message = stepExecution.getFailureExceptions().get(0).getCause().getMessage(); - assertEquals("Wrong message: ", "Ouch!", message); - assertStepExecutionsAreEqual(stepExecution, repository.getLastStepExecution(jobExecution.getJobInstance(), step - .getName())); - } - - /** - * Check items causing errors are skipped as expected. - */ - @Test - public void testSkipOverLimit() throws Exception { - reader.setFailures("2"); - writer.setFailures("4"); - - factory.setSkipLimit(1); - - Step step = factory.getObject(); - - step.execute(stepExecution); - - assertEquals(1, stepExecution.getSkipCount()); - - // writer did not skip "2" as it never made it to writer, only "4" did - assertTrue(reader.getRead().contains("4")); - assertFalse(writer.getCommitted().contains("4")); - - // failure on "4" tripped the skip limit so we never got to "5" - List expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,3")); - assertEquals(expectedOutput, writer.getCommitted()); - assertStepExecutionsAreEqual(stepExecution, repository.getLastStepExecution(jobExecution.getJobInstance(), step - .getName())); - } - - /** - * Check items causing errors are skipped as expected. - */ - @SuppressWarnings("unchecked") - @Test - public void testSkipOverLimitOnRead() throws Exception { - reader.setItems(StringUtils.commaDelimitedListToStringArray("1,2,3,4,5,6")); - reader.setFailures(StringUtils.commaDelimitedListToStringArray("2,3,5")); - - writer.setFailures("4"); - - factory.setSkipLimit(3); - factory.setSkippableExceptionClasses(getExceptionMap(Exception.class)); - - Step step = factory.getObject(); - - step.execute(stepExecution); - assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); - - assertEquals(3, stepExecution.getSkipCount()); - assertEquals(2, stepExecution.getReadSkipCount()); - assertEquals(1, stepExecution.getWriteSkipCount()); - assertEquals(2, stepExecution.getReadCount()); - - // writer did not skip "2" as it never made it to writer, only "4" did - assertFalse(reader.getRead().contains("2")); - assertTrue(reader.getRead().contains("4")); - - // only "1" was ever committed - List expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("1")); - assertEquals(expectedOutput, writer.getCommitted()); - assertStepExecutionsAreEqual(stepExecution, repository.getLastStepExecution(jobExecution.getJobInstance(), step - .getName())); - } - - /** - * Check items causing errors are skipped as expected. - */ - @Test - public void testSkipOverLimitOnReadWithListener() throws Exception { - reader.setFailures("1", "3", "5"); - writer.setFailures(); - - final List listenerCalls = new ArrayList<>(); - - factory.setListeners(new StepListener[] { new SkipListener() { - @Override - public void onSkipInRead(Throwable t) { - listenerCalls.add(t); - } - } }); - factory.setCommitInterval(2); - factory.setSkipLimit(2); - - Step step = factory.getObject(); - - step.execute(stepExecution); - - // 1,3 skipped inside a committed chunk. 5 tripped the skip - // limit but it was skipped in a chunk that rolled back, so - // it will re-appear on a restart and the listener is not called. - assertEquals(2, listenerCalls.size()); - assertEquals(2, stepExecution.getReadSkipCount()); - - assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); - - } - - /** - * Check items causing errors are skipped as expected. - */ - @SuppressWarnings("unchecked") - @Test - public void testSkipListenerFailsOnRead() throws Exception { - reader.setItems(StringUtils.commaDelimitedListToStringArray("1,2,3,4,5,6")); - reader.setFailures(StringUtils.commaDelimitedListToStringArray("2,3,5")); - - writer.setFailures("4"); - - factory.setSkipLimit(3); - factory.setListeners(new StepListener[] { new SkipListener() { - @Override - public void onSkipInRead(Throwable t) { - throw new RuntimeException("oops"); - } - } }); - factory.setSkippableExceptionClasses(getExceptionMap(Exception.class)); - - Step step = factory.getObject(); - - step.execute(stepExecution); - assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); - assertEquals("oops", stepExecution.getFailureExceptions().get(0).getCause().getMessage()); - - // listeners are called only once chunk is about to commit, so - // listener failure does not affect other statistics - assertEquals(2, stepExecution.getReadSkipCount()); - // but we didn't get as far as the write skip in the scan: - assertEquals(0, stepExecution.getWriteSkipCount()); - assertEquals(2, stepExecution.getSkipCount()); - assertStepExecutionsAreEqual(stepExecution, repository.getLastStepExecution(jobExecution.getJobInstance(), step - .getName())); - } - - /** - * Check items causing errors are skipped as expected. - */ - @SuppressWarnings("unchecked") - @Test - public void testSkipListenerFailsOnWrite() throws Exception { - reader.setItems(StringUtils.commaDelimitedListToStringArray("1,2,3,4,5,6")); - - writer.setFailures("4"); - - factory.setSkipLimit(3); - factory.setListeners(new StepListener[] { new SkipListener() { - @Override - public void onSkipInWrite(String item, Throwable t) { - throw new RuntimeException("oops"); - } - } }); - factory.setSkippableExceptionClasses(getExceptionMap(Exception.class)); - - Step step = factory.getObject(); - - step.execute(stepExecution); - assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); - assertEquals("oops", stepExecution.getFailureExceptions().get(0).getCause().getMessage()); - assertEquals(1, stepExecution.getSkipCount()); - assertEquals(0, stepExecution.getReadSkipCount()); - assertEquals(1, stepExecution.getWriteSkipCount()); - assertStepExecutionsAreEqual(stepExecution, repository.getLastStepExecution(jobExecution.getJobInstance(), step - .getName())); - } - - /** - * Check items causing errors are skipped as expected. - */ - @Test - public void testSkipOnReadNotDoubleCounted() throws Exception { - reader.setItems(StringUtils.commaDelimitedListToStringArray("1,2,3,4,5,6")); - reader.setFailures(StringUtils.commaDelimitedListToStringArray("2,3,5")); - - writer.setFailures("4"); - - factory.setSkipLimit(4); - - Step step = factory.getObject(); - - step.execute(stepExecution); - assertEquals(4, stepExecution.getSkipCount()); - assertEquals(3, stepExecution.getReadSkipCount()); - assertEquals(1, stepExecution.getWriteSkipCount()); - - // skipped 2,3,4,5 - List expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,6")); - assertEquals(expectedOutput, writer.getCommitted()); - - // reader exceptions should not cause rollback, 1 writer exception - // causes 2 rollbacks - assertEquals(2, stepExecution.getRollbackCount()); - assertStepExecutionsAreEqual(stepExecution, repository.getLastStepExecution(jobExecution.getJobInstance(), step - .getName())); - } - - /** - * Check items causing errors are skipped as expected. - */ - @Test - public void testSkipOnWriteNotDoubleCounted() throws Exception { - reader.setItems(StringUtils.commaDelimitedListToStringArray("1,2,3,4,5,6,7")); - reader.setFailures(StringUtils.commaDelimitedListToStringArray("2,3")); - - writer.setFailures("4", "5"); - - factory.setSkipLimit(4); - factory.setCommitInterval(3); // includes all expected skips - - Step step = factory.getObject(); - - step.execute(stepExecution); - assertEquals(4, stepExecution.getSkipCount()); - assertEquals(2, stepExecution.getReadSkipCount()); - assertEquals(2, stepExecution.getWriteSkipCount()); - - // skipped 2,3,4,5 - List expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,6,7")); - assertEquals(expectedOutput, writer.getCommitted()); - assertStepExecutionsAreEqual(stepExecution, repository.getLastStepExecution(jobExecution.getJobInstance(), step - .getName())); - } - - @SuppressWarnings("unchecked") - @Test - public void testDefaultSkipPolicy() throws Exception { - reader.setItems("a", "b", "c"); - reader.setFailures("b"); - - factory.setSkippableExceptionClasses(getExceptionMap(Exception.class)); - factory.setSkipLimit(1); - - Step step = factory.getObject(); - - step.execute(stepExecution); - - assertEquals(1, stepExecution.getSkipCount()); - assertEquals("[a, c]", reader.getRead().toString()); - assertStepExecutionsAreEqual(stepExecution, repository.getLastStepExecution(jobExecution.getJobInstance(), step - .getName())); - } - - /** - * Check items causing errors are skipped as expected. - */ - @SuppressWarnings("unchecked") - @Test - public void testSkipOverLimitOnReadWithAllSkipsAtEnd() throws Exception { - reader.setItems(StringUtils.commaDelimitedListToStringArray("1,2,3,4,5,6,7,8,9,10,11,12,13,14,15")); - reader.setFailures(StringUtils.commaDelimitedListToStringArray("6,12,13,14,15")); - - writer.setFailures("4"); - - factory.setCommitInterval(5); - factory.setSkipLimit(3); - factory.setSkippableExceptionClasses(getExceptionMap(Exception.class)); - - Step step = factory.getObject(); - - step.execute(stepExecution); - assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); - assertEquals("bad skip count", 3, stepExecution.getSkipCount()); - assertEquals("bad read skip count", 2, stepExecution.getReadSkipCount()); - assertEquals("bad write skip count", 1, stepExecution.getWriteSkipCount()); - - // writer did not skip "6" as it never made it to writer, only "4" did - assertFalse(reader.getRead().contains("6")); - assertTrue(reader.getRead().contains("4")); - - // only "1" was ever committed - List expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,2,3,5,7,8,9,10,11")); - assertEquals(expectedOutput, writer.getCommitted()); - assertStepExecutionsAreEqual(stepExecution, repository.getLastStepExecution(jobExecution.getJobInstance(), step - .getName())); - } - - @Test - public void testReprocessingAfterWriterRollback() throws Exception { - reader.setItems("1", "2", "3", "4"); - - writer.setFailures("4"); - - Step step = factory.getObject(); - step.execute(stepExecution); - - assertEquals(1, stepExecution.getSkipCount()); - assertEquals(2, stepExecution.getRollbackCount()); - - // 1,2,3,4,3,4 - one scan until the item is - // identified and finally skipped on the second attempt - assertEquals("[1, 2, 3, 4, 3, 4]", processor.getProcessed().toString()); - assertStepExecutionsAreEqual(stepExecution, repository.getLastStepExecution(jobExecution.getJobInstance(), step - .getName())); - } - - @Test - public void testAutoRegisterItemListeners() throws Exception { - reader.setFailures("2"); - - final List listenerCalls = new ArrayList<>(); - - class TestItemListenerWriter implements ItemWriter, ItemReadListener, - ItemWriteListener, ItemProcessListener, SkipListener, - ChunkListener { - @Override - public void write(List items) throws Exception { - if (items.contains("4")) { - throw new SkippableException("skippable"); - } - } - - @Override - public void afterRead(String item) { - listenerCalls.add(1); - } - - @Override - public void beforeRead() { - } - - @Override - public void onReadError(Exception ex) { - } - - @Override - public void afterWrite(List items) { - listenerCalls.add(2); - } - - @Override - public void beforeWrite(List items) { - } - - @Override - public void onWriteError(Exception exception, List items) { - } - - @Override - public void afterProcess(String item, @Nullable String result) { - listenerCalls.add(3); - } - - @Override - public void beforeProcess(String item) { - } - - @Override - public void onProcessError(String item, Exception e) { - } - - @Override - public void afterChunk(ChunkContext context) { - listenerCalls.add(4); - } - - @Override - public void beforeChunk(ChunkContext context) { - } - - @Override - public void onSkipInProcess(String item, Throwable t) { - } - - @Override - public void onSkipInRead(Throwable t) { - listenerCalls.add(6); - } - - @Override - public void onSkipInWrite(String item, Throwable t) { - listenerCalls.add(5); - } - - @Override - public void afterChunkError(ChunkContext context) { - } - } - - factory.setItemWriter(new TestItemListenerWriter()); - - Step step = factory.getObject(); - step.execute(stepExecution); - - assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - for (int i = 1; i <= 6; i++) { - assertTrue("didn't call listener " + i, listenerCalls.contains(i)); - } - } - - /** - * Check ItemStream is opened - */ - @Test - public void testItemStreamOpenedEvenWithTaskExecutor() throws Exception { - writer.setFailures("4"); - - ItemReader reader = new AbstractItemStreamItemReader() { - @Override - public void close() { - super.close(); - closed = true; - } - - @Override - public void open(ExecutionContext executionContext) { - super.open(executionContext); - opened = true; - } - - @Nullable - @Override - public String read() { - return null; - } - }; - - factory.setItemReader(reader); - factory.setTaskExecutor(new ConcurrentTaskExecutor()); - - Step step = factory.getObject(); - - step.execute(stepExecution); - - assertTrue(opened); - assertTrue(closed); - assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - } - - /** - * Check ItemStream is opened - */ - @Test - public void testNestedItemStreamOpened() throws Exception { - writer.setFailures("4"); - - ItemStreamReader reader = new ItemStreamReader() { - @Override - public void close() throws ItemStreamException { - } - - @Override - public void open(ExecutionContext executionContext) throws ItemStreamException { - } - - @Override - public void update(ExecutionContext executionContext) throws ItemStreamException { - } - - @Nullable - @Override - public String read() throws Exception, UnexpectedInputException, ParseException { - return null; - } - }; - - ItemStreamReader stream = new ItemStreamReader() { - @Override - public void close() throws ItemStreamException { - closed = true; - } - - @Override - public void open(ExecutionContext executionContext) throws ItemStreamException { - opened = true; - } - - @Override - public void update(ExecutionContext executionContext) throws ItemStreamException { - } - - @Nullable - @Override - public String read() throws Exception, UnexpectedInputException, ParseException { - return null; - } - }; - - factory.setItemReader(reader); - factory.setStreams(new ItemStream[] { stream, reader }); - - Step step = factory.getObject(); - - step.execute(stepExecution); - - assertTrue(opened); - assertTrue(closed); - assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - } - - /** - * Check ItemStream is opened - */ - @SuppressWarnings("unchecked") - @Test - public void testProxiedItemStreamOpened() throws Exception { - writer.setFailures("4"); - - ItemStreamReader reader = new ItemStreamReader() { - @Override - public void close() throws ItemStreamException { - closed = true; - } - - @Override - public void open(ExecutionContext executionContext) throws ItemStreamException { - opened = true; - } - - @Override - public void update(ExecutionContext executionContext) throws ItemStreamException { - } - - @Nullable - @Override - public String read() throws Exception, UnexpectedInputException, ParseException { - return null; - } - }; - - ProxyFactory proxy = new ProxyFactory(); - proxy.setTarget(reader); - proxy.setInterfaces(new Class[] { ItemReader.class, ItemStream.class }); - proxy.addAdvice(new MethodInterceptor() { - @Override - public Object invoke(MethodInvocation invocation) throws Throwable { - return invocation.proceed(); - } - }); - Object advised = proxy.getProxy(); - - factory.setItemReader((ItemReader) advised); - factory.setStreams(new ItemStream[] { (ItemStream) advised }); - - Step step = factory.getObject(); - - step.execute(stepExecution); - - assertTrue(opened); - assertTrue(closed); - assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - } - - private static class ItemProcessListenerStub implements ItemProcessListener { - - private boolean filterEncountered = false; - - @Override - public void afterProcess(T item, @Nullable S result) { - if (result == null) { - filterEncountered = true; - } - } - - @Override - public void beforeProcess(T item) { - - } - - @Override - public void onProcessError(T item, Exception e) { - - } - - public boolean isFilterEncountered() { - return filterEncountered; - } - } - - private void assertStepExecutionsAreEqual(StepExecution expected, StepExecution actual) { - assertEquals(expected.getId(), actual.getId()); - assertEquals(expected.getStartTime(), actual.getStartTime()); - assertEquals(expected.getEndTime(), actual.getEndTime()); - assertEquals(expected.getSkipCount(), actual.getSkipCount()); - assertEquals(expected.getCommitCount(), actual.getCommitCount()); - assertEquals(expected.getReadCount(), actual.getReadCount()); - assertEquals(expected.getWriteCount(), actual.getWriteCount()); - assertEquals(expected.getFilterCount(), actual.getFilterCount()); - assertEquals(expected.getWriteSkipCount(), actual.getWriteSkipCount()); - assertEquals(expected.getReadSkipCount(), actual.getReadSkipCount()); - assertEquals(expected.getProcessSkipCount(), actual.getProcessSkipCount()); - assertEquals(expected.getRollbackCount(), actual.getRollbackCount()); - assertEquals(expected.getExitStatus(), actual.getExitStatus()); - assertEquals(expected.getLastUpdated(), actual.getLastUpdated()); - assertEquals(expected.getExitStatus(), actual.getExitStatus()); - assertEquals(expected.getJobExecutionId(), actual.getJobExecutionId()); - } - - /** - * condition: skippable < fatal; exception is unclassified - * - * expected: false; default classification - */ - @Test - public void testSkippableSubset_unclassified() throws Exception { - assertFalse(getSkippableSubsetSkipPolicy().shouldSkip(new RuntimeException(), 0)); - } - - /** - * condition: skippable < fatal; exception is skippable - * - * expected: true - */ - @Test - public void testSkippableSubset_skippable() throws Exception { - assertTrue(getSkippableSubsetSkipPolicy().shouldSkip(new WriteFailedException(""), 0)); - } - - /** - * condition: skippable < fatal; exception is fatal - * - * expected: false - */ - @Test - public void testSkippableSubset_fatal() throws Exception { - assertFalse(getSkippableSubsetSkipPolicy().shouldSkip(new WriterNotOpenException(""), 0)); - } - - /** - * condition: fatal < skippable; exception is unclassified - * - * expected: false; default classification - */ - @Test - public void testFatalSubsetUnclassified() throws Exception { - assertFalse(getFatalSubsetSkipPolicy().shouldSkip(new RuntimeException(), 0)); - } - - /** - * condition: fatal < skippable; exception is skippable - * - * expected: true - */ - @Test - public void testFatalSubsetSkippable() throws Exception { - assertTrue(getFatalSubsetSkipPolicy().shouldSkip(new WriterNotOpenException(""), 0)); - } - - /** - * condition: fatal < skippable; exception is fatal - * - * expected: false - */ - @Test - public void testFatalSubsetFatal() throws Exception { - assertFalse(getFatalSubsetSkipPolicy().shouldSkip(new WriteFailedException(""), 0)); - } - - private SkipPolicy getSkippableSubsetSkipPolicy() throws Exception { - Map, Boolean> skippableExceptions = new HashMap<>(); - skippableExceptions.put(WriteFailedException.class, true); - skippableExceptions.put(ItemWriterException.class, false); - factory.setSkippableExceptionClasses(skippableExceptions); - return getSkipPolicy(factory); - } - - private SkipPolicy getFatalSubsetSkipPolicy() throws Exception { - Map, Boolean> skippableExceptions = new HashMap<>(); - skippableExceptions.put(ItemWriterException.class, true); - skippableExceptions.put(WriteFailedException.class, false); - factory.setSkippableExceptionClasses(skippableExceptions); - return getSkipPolicy(factory); - } - - private SkipPolicy getSkipPolicy(FactoryBean factory) throws Exception { - Object step = factory.getObject(); - Object tasklet = ReflectionTestUtils.getField(step, "tasklet"); - Object chunkProvider = ReflectionTestUtils.getField(tasklet, "chunkProvider"); - return (SkipPolicy) ReflectionTestUtils.getField(chunkProvider, "skipPolicy"); - } - - @SuppressWarnings("unchecked") - private Map, Boolean> getExceptionMap(Class... args) { - Map, Boolean> map = new HashMap<>(); - for (Class arg : args) { - map.put(arg, true); - } - return map; - } - - @SuppressWarnings("serial") - public static class NonExistentException extends Exception { - } - -} +/* + * Copyright 2008-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.step.item; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.aopalliance.intercept.MethodInterceptor; +import org.aopalliance.intercept.MethodInvocation; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import org.springframework.aop.framework.ProxyFactory; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.ChunkListener; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.ItemProcessListener; +import org.springframework.batch.core.ItemReadListener; +import org.springframework.batch.core.ItemWriteListener; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.SkipListener; +import org.springframework.batch.core.Step; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.StepListener; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; +import org.springframework.batch.core.scope.context.ChunkContext; +import org.springframework.batch.core.step.factory.FaultTolerantStepFactoryBean; +import org.springframework.batch.core.step.skip.LimitCheckingItemSkipPolicy; +import org.springframework.batch.core.step.skip.SkipLimitExceededException; +import org.springframework.batch.core.step.skip.SkipPolicy; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemStream; +import org.springframework.batch.item.ItemStreamException; +import org.springframework.batch.item.ItemStreamReader; +import org.springframework.batch.item.ItemWriter; +import org.springframework.batch.item.ItemWriterException; +import org.springframework.batch.item.ParseException; +import org.springframework.batch.item.UnexpectedInputException; +import org.springframework.batch.item.WriteFailedException; +import org.springframework.batch.item.WriterNotOpenException; +import org.springframework.batch.item.support.AbstractItemStreamItemReader; +import org.springframework.beans.factory.FactoryBean; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.lang.Nullable; +import org.springframework.scheduling.concurrent.ConcurrentTaskExecutor; +import org.springframework.test.util.ReflectionTestUtils; +import org.springframework.util.StringUtils; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Tests for {@link FaultTolerantStepFactoryBean}. + */ +public class FaultTolerantStepFactoryBeanTests { + + protected final Log logger = LogFactory.getLog(getClass()); + + private FaultTolerantStepFactoryBean factory; + + private SkipReaderStub reader; + + private SkipProcessorStub processor; + + private SkipWriterStub writer; + + private JobExecution jobExecution; + + private StepExecution stepExecution; + + private JobRepository repository; + + private boolean opened = false; + + private boolean closed = false; + + public FaultTolerantStepFactoryBeanTests() throws Exception { + reader = new SkipReaderStub<>(); + processor = new SkipProcessorStub<>(); + writer = new SkipWriterStub<>(); + } + + @SuppressWarnings("unchecked") + @Before + public void setUp() throws Exception { + EmbeddedDatabase embeddedDatabase = new EmbeddedDatabaseBuilder() + .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") + .addScript("/org/springframework/batch/core/schema-hsqldb-extended.sql").generateUniqueName(true) + .build(); + DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(embeddedDatabase); + + factory = new FaultTolerantStepFactoryBean<>(); + + factory.setBeanName("stepName"); + factory.setTransactionManager(transactionManager); + factory.setCommitInterval(2); + + reader.clear(); + reader.setItems("1", "2", "3", "4", "5"); + factory.setItemReader(reader); + processor.clear(); + factory.setItemProcessor(processor); + writer.clear(); + factory.setItemWriter(writer); + + factory.setSkipLimit(2); + + factory.setSkippableExceptionClasses( + getExceptionMap(SkippableException.class, SkippableRuntimeException.class)); + + JobRepositoryFactoryBean repositoryFactoryBean = new JobRepositoryFactoryBean(); + repositoryFactoryBean.setDataSource(embeddedDatabase); + repositoryFactoryBean.setTransactionManager(transactionManager); + repositoryFactoryBean.setMaxVarCharLength(10000); + repositoryFactoryBean.afterPropertiesSet(); + repository = repositoryFactoryBean.getObject(); + factory.setJobRepository(repository); + + jobExecution = repository.createJobExecution("skipJob", new JobParameters()); + stepExecution = jobExecution.createStepExecution(factory.getName()); + repository.add(stepExecution); + } + + @Test + public void testMandatoryReader() { + // given + factory = new FaultTolerantStepFactoryBean<>(); + factory.setItemWriter(writer); + + // when + final Exception expectedException = Assert.assertThrows(IllegalStateException.class, factory::getObject); + + // then + assertEquals("ItemReader must be provided", expectedException.getMessage()); + } + + @Test + public void testMandatoryWriter() throws Exception { + // given + factory = new FaultTolerantStepFactoryBean<>(); + factory.setItemReader(reader); + + // when + final Exception expectedException = Assert.assertThrows(IllegalStateException.class, factory::getObject); + + // then + assertEquals("ItemWriter must be provided", expectedException.getMessage()); + } + + /** + * Non-skippable (and non-fatal) exception causes failure immediately. + * @throws Exception + */ + @SuppressWarnings("unchecked") + @Test + public void testNonSkippableExceptionOnRead() throws Exception { + reader.setFailures("2"); + + // nothing is skippable + factory.setSkippableExceptionClasses(getExceptionMap(NonExistentException.class)); + + Step step = factory.getObject(); + + step.execute(stepExecution); + assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); + assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution.getExitStatus().getExitCode()); + assertTrue(stepExecution.getExitStatus().getExitDescription().contains("Non-skippable exception during read")); + + assertStepExecutionsAreEqual(stepExecution, + repository.getLastStepExecution(jobExecution.getJobInstance(), step.getName())); + } + + @SuppressWarnings("unchecked") + @Test + public void testNonSkippableException() throws Exception { + // nothing is skippable + factory.setSkippableExceptionClasses(getExceptionMap(NonExistentException.class)); + factory.setCommitInterval(1); + + // no failures on read + reader.setItems("1", "2", "3", "4", "5"); + writer.setFailures("1"); + + Step step = factory.getObject(); + + step.execute(stepExecution); + assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); + assertEquals(1, reader.getRead().size()); + assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution.getExitStatus().getExitCode()); + assertTrue(stepExecution.getExitStatus().getExitDescription().contains("Intended Failure")); + assertStepExecutionsAreEqual(stepExecution, + repository.getLastStepExecution(jobExecution.getJobInstance(), step.getName())); + } + + /** + * Check items causing errors are skipped as expected. + */ + @Test + public void testReadSkip() throws Exception { + reader.setFailures("2"); + + Step step = factory.getObject(); + + step.execute(stepExecution); + + assertEquals(1, stepExecution.getSkipCount()); + assertEquals(1, stepExecution.getReadSkipCount()); + assertEquals(4, stepExecution.getReadCount()); + assertEquals(0, stepExecution.getWriteSkipCount()); + assertEquals(0, stepExecution.getRollbackCount()); + + // writer did not skip "2" as it never made it to writer, only "4" did + assertTrue(reader.getRead().contains("4")); + assertFalse(reader.getRead().contains("2")); + + List expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,3,4,5")); + assertEquals(expectedOutput, writer.getWritten()); + + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + assertStepExecutionsAreEqual(stepExecution, + repository.getLastStepExecution(jobExecution.getJobInstance(), step.getName())); + } + + /** + * Check items causing errors are skipped as expected. + */ + @Test + public void testReadSkipWithPolicy() throws Exception { + // Should be ignored + factory.setSkipLimit(0); + factory.setSkipPolicy(new LimitCheckingItemSkipPolicy(2, + Collections., Boolean>singletonMap(Exception.class, true))); + testReadSkip(); + } + + /** + * Check items causing errors are skipped as expected. + */ + @Test + public void testReadSkipWithPolicyExceptionInReader() throws Exception { + + // Should be ignored + factory.setSkipLimit(0); + + factory.setSkipPolicy(new SkipPolicy() { + @Override + public boolean shouldSkip(Throwable t, long skipCount) throws SkipLimitExceededException { + throw new RuntimeException("Planned exception in SkipPolicy"); + } + }); + + reader.setFailures("2"); + + Step step = factory.getObject(); + + step.execute(stepExecution); + + assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); + assertEquals(0, stepExecution.getReadSkipCount()); + assertEquals(1, stepExecution.getReadCount()); + + } + + /** + * Check items causing errors are skipped as expected. + */ + @Test + public void testReadSkipWithPolicyExceptionInWriter() throws Exception { + + // Should be ignored + factory.setSkipLimit(0); + + factory.setSkipPolicy(new SkipPolicy() { + @Override + public boolean shouldSkip(Throwable t, long skipCount) throws SkipLimitExceededException { + throw new RuntimeException("Planned exception in SkipPolicy"); + } + }); + + writer.setFailures("2"); + + Step step = factory.getObject(); + + step.execute(stepExecution); + + assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); + assertEquals(0, stepExecution.getWriteSkipCount()); + assertEquals(2, stepExecution.getReadCount()); + + } + + /** + * Check to make sure that ItemStreamException can be skipped. (see BATCH-915) + */ + @Test + public void testReadSkipItemStreamException() throws Exception { + reader.setFailures("2"); + reader.setExceptionType(ItemStreamException.class); + + Map, Boolean> map = new HashMap<>(); + map.put(ItemStreamException.class, true); + factory.setSkippableExceptionClasses(map); + + Step step = factory.getObject(); + + step.execute(stepExecution); + + assertEquals(1, stepExecution.getSkipCount()); + assertEquals(1, stepExecution.getReadSkipCount()); + assertEquals(4, stepExecution.getReadCount()); + assertEquals(0, stepExecution.getWriteSkipCount()); + assertEquals(0, stepExecution.getRollbackCount()); + + // writer did not skip "2" as it never made it to writer, only "4" did + assertTrue(reader.getRead().contains("4")); + assertFalse(reader.getRead().contains("2")); + + List expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,3,4,5")); + assertEquals(expectedOutput, writer.getWritten()); + + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + assertStepExecutionsAreEqual(stepExecution, + repository.getLastStepExecution(jobExecution.getJobInstance(), step.getName())); + } + + /** + * Check items causing errors are skipped as expected. + */ + @Test + public void testProcessSkip() throws Exception { + processor.setFailures("4"); + writer.setFailures("4"); + + Step step = factory.getObject(); + + step.execute(stepExecution); + + assertEquals(1, stepExecution.getSkipCount()); + assertEquals(0, stepExecution.getReadSkipCount()); + assertEquals(5, stepExecution.getReadCount()); + assertEquals(1, stepExecution.getProcessSkipCount()); + assertEquals(1, stepExecution.getRollbackCount()); + + // writer skips "4" + assertTrue(reader.getRead().contains("4")); + assertFalse(writer.getWritten().contains("4")); + + List expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,2,3,5")); + assertEquals(expectedOutput, writer.getWritten()); + + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + assertStepExecutionsAreEqual(stepExecution, + repository.getLastStepExecution(jobExecution.getJobInstance(), step.getName())); + } + + @Test + public void testProcessFilter() throws Exception { + processor.setFailures("4"); + processor.setFilter(true); + ItemProcessListenerStub listenerStub = new ItemProcessListenerStub<>(); + factory.setListeners(new StepListener[] { listenerStub }); + Step step = factory.getObject(); + + step.execute(stepExecution); + + assertEquals(0, stepExecution.getSkipCount()); + assertEquals(0, stepExecution.getReadSkipCount()); + assertEquals(5, stepExecution.getReadCount()); + assertEquals(1, stepExecution.getFilterCount()); + assertEquals(0, stepExecution.getRollbackCount()); + assertTrue(listenerStub.isFilterEncountered()); + + // writer skips "4" + assertTrue(reader.getRead().contains("4")); + assertFalse(writer.getWritten().contains("4")); + + List expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,2,3,5")); + assertEquals(expectedOutput, writer.getWritten()); + + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + assertStepExecutionsAreEqual(stepExecution, + repository.getLastStepExecution(jobExecution.getJobInstance(), step.getName())); + } + + /** + * Check items causing errors are skipped as expected. + */ + @Test + public void testWriteSkip() throws Exception { + writer.setFailures("4"); + + Step step = factory.getObject(); + + step.execute(stepExecution); + + assertEquals(1, stepExecution.getSkipCount()); + assertEquals(0, stepExecution.getReadSkipCount()); + assertEquals(5, stepExecution.getReadCount()); + assertEquals(1, stepExecution.getWriteSkipCount()); + assertEquals(2, stepExecution.getRollbackCount()); + + // writer skips "4" + assertTrue(reader.getRead().contains("4")); + assertFalse(writer.getCommitted().contains("4")); + + List expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,2,3,5")); + assertEquals(expectedOutput, writer.getCommitted()); + + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + assertStepExecutionsAreEqual(stepExecution, + repository.getLastStepExecution(jobExecution.getJobInstance(), step.getName())); + } + + /** + * Fatal exception should cause immediate termination provided the exception is not + * skippable (note the fatal exception is also classified as rollback). + */ + @Test + public void testFatalException() throws Exception { + reader.setFailures("2"); + + Map, Boolean> map = new HashMap<>(); + map.put(SkippableException.class, true); + map.put(SkippableRuntimeException.class, true); + map.put(FatalRuntimeException.class, false); + factory.setSkippableExceptionClasses(map); + factory.setItemWriter(new ItemWriter() { + @Override + public void write(List items) { + throw new FatalRuntimeException("Ouch!"); + } + }); + + Step step = factory.getObject(); + + step.execute(stepExecution); + String message = stepExecution.getFailureExceptions().get(0).getCause().getMessage(); + assertEquals("Wrong message: ", "Ouch!", message); + assertStepExecutionsAreEqual(stepExecution, + repository.getLastStepExecution(jobExecution.getJobInstance(), step.getName())); + } + + /** + * Check items causing errors are skipped as expected. + */ + @Test + public void testSkipOverLimit() throws Exception { + reader.setFailures("2"); + writer.setFailures("4"); + + factory.setSkipLimit(1); + + Step step = factory.getObject(); + + step.execute(stepExecution); + + assertEquals(1, stepExecution.getSkipCount()); + + // writer did not skip "2" as it never made it to writer, only "4" did + assertTrue(reader.getRead().contains("4")); + assertFalse(writer.getCommitted().contains("4")); + + // failure on "4" tripped the skip limit so we never got to "5" + List expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,3")); + assertEquals(expectedOutput, writer.getCommitted()); + assertStepExecutionsAreEqual(stepExecution, + repository.getLastStepExecution(jobExecution.getJobInstance(), step.getName())); + } + + /** + * Check items causing errors are skipped as expected. + */ + @SuppressWarnings("unchecked") + @Test + public void testSkipOverLimitOnRead() throws Exception { + reader.setItems(StringUtils.commaDelimitedListToStringArray("1,2,3,4,5,6")); + reader.setFailures(StringUtils.commaDelimitedListToStringArray("2,3,5")); + + writer.setFailures("4"); + + factory.setSkipLimit(3); + factory.setSkippableExceptionClasses(getExceptionMap(Exception.class)); + + Step step = factory.getObject(); + + step.execute(stepExecution); + assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); + + assertEquals(3, stepExecution.getSkipCount()); + assertEquals(2, stepExecution.getReadSkipCount()); + assertEquals(1, stepExecution.getWriteSkipCount()); + assertEquals(2, stepExecution.getReadCount()); + + // writer did not skip "2" as it never made it to writer, only "4" did + assertFalse(reader.getRead().contains("2")); + assertTrue(reader.getRead().contains("4")); + + // only "1" was ever committed + List expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("1")); + assertEquals(expectedOutput, writer.getCommitted()); + assertStepExecutionsAreEqual(stepExecution, + repository.getLastStepExecution(jobExecution.getJobInstance(), step.getName())); + } + + /** + * Check items causing errors are skipped as expected. + */ + @Test + public void testSkipOverLimitOnReadWithListener() throws Exception { + reader.setFailures("1", "3", "5"); + writer.setFailures(); + + final List listenerCalls = new ArrayList<>(); + + factory.setListeners(new StepListener[] { new SkipListener() { + @Override + public void onSkipInRead(Throwable t) { + listenerCalls.add(t); + } + } }); + factory.setCommitInterval(2); + factory.setSkipLimit(2); + + Step step = factory.getObject(); + + step.execute(stepExecution); + + // 1,3 skipped inside a committed chunk. 5 tripped the skip + // limit but it was skipped in a chunk that rolled back, so + // it will re-appear on a restart and the listener is not called. + assertEquals(2, listenerCalls.size()); + assertEquals(2, stepExecution.getReadSkipCount()); + + assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); + + } + + /** + * Check items causing errors are skipped as expected. + */ + @SuppressWarnings("unchecked") + @Test + public void testSkipListenerFailsOnRead() throws Exception { + reader.setItems(StringUtils.commaDelimitedListToStringArray("1,2,3,4,5,6")); + reader.setFailures(StringUtils.commaDelimitedListToStringArray("2,3,5")); + + writer.setFailures("4"); + + factory.setSkipLimit(3); + factory.setListeners(new StepListener[] { new SkipListener() { + @Override + public void onSkipInRead(Throwable t) { + throw new RuntimeException("oops"); + } + } }); + factory.setSkippableExceptionClasses(getExceptionMap(Exception.class)); + + Step step = factory.getObject(); + + step.execute(stepExecution); + assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); + assertEquals("oops", stepExecution.getFailureExceptions().get(0).getCause().getMessage()); + + // listeners are called only once chunk is about to commit, so + // listener failure does not affect other statistics + assertEquals(2, stepExecution.getReadSkipCount()); + // but we didn't get as far as the write skip in the scan: + assertEquals(0, stepExecution.getWriteSkipCount()); + assertEquals(2, stepExecution.getSkipCount()); + assertStepExecutionsAreEqual(stepExecution, + repository.getLastStepExecution(jobExecution.getJobInstance(), step.getName())); + } + + /** + * Check items causing errors are skipped as expected. + */ + @SuppressWarnings("unchecked") + @Test + public void testSkipListenerFailsOnWrite() throws Exception { + reader.setItems(StringUtils.commaDelimitedListToStringArray("1,2,3,4,5,6")); + + writer.setFailures("4"); + + factory.setSkipLimit(3); + factory.setListeners(new StepListener[] { new SkipListener() { + @Override + public void onSkipInWrite(String item, Throwable t) { + throw new RuntimeException("oops"); + } + } }); + factory.setSkippableExceptionClasses(getExceptionMap(Exception.class)); + + Step step = factory.getObject(); + + step.execute(stepExecution); + assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); + assertEquals("oops", stepExecution.getFailureExceptions().get(0).getCause().getMessage()); + assertEquals(1, stepExecution.getSkipCount()); + assertEquals(0, stepExecution.getReadSkipCount()); + assertEquals(1, stepExecution.getWriteSkipCount()); + assertStepExecutionsAreEqual(stepExecution, + repository.getLastStepExecution(jobExecution.getJobInstance(), step.getName())); + } + + /** + * Check items causing errors are skipped as expected. + */ + @Test + public void testSkipOnReadNotDoubleCounted() throws Exception { + reader.setItems(StringUtils.commaDelimitedListToStringArray("1,2,3,4,5,6")); + reader.setFailures(StringUtils.commaDelimitedListToStringArray("2,3,5")); + + writer.setFailures("4"); + + factory.setSkipLimit(4); + + Step step = factory.getObject(); + + step.execute(stepExecution); + assertEquals(4, stepExecution.getSkipCount()); + assertEquals(3, stepExecution.getReadSkipCount()); + assertEquals(1, stepExecution.getWriteSkipCount()); + + // skipped 2,3,4,5 + List expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,6")); + assertEquals(expectedOutput, writer.getCommitted()); + + // reader exceptions should not cause rollback, 1 writer exception + // causes 2 rollbacks + assertEquals(2, stepExecution.getRollbackCount()); + assertStepExecutionsAreEqual(stepExecution, + repository.getLastStepExecution(jobExecution.getJobInstance(), step.getName())); + } + + /** + * Check items causing errors are skipped as expected. + */ + @Test + public void testSkipOnWriteNotDoubleCounted() throws Exception { + reader.setItems(StringUtils.commaDelimitedListToStringArray("1,2,3,4,5,6,7")); + reader.setFailures(StringUtils.commaDelimitedListToStringArray("2,3")); + + writer.setFailures("4", "5"); + + factory.setSkipLimit(4); + factory.setCommitInterval(3); // includes all expected skips + + Step step = factory.getObject(); + + step.execute(stepExecution); + assertEquals(4, stepExecution.getSkipCount()); + assertEquals(2, stepExecution.getReadSkipCount()); + assertEquals(2, stepExecution.getWriteSkipCount()); + + // skipped 2,3,4,5 + List expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,6,7")); + assertEquals(expectedOutput, writer.getCommitted()); + assertStepExecutionsAreEqual(stepExecution, + repository.getLastStepExecution(jobExecution.getJobInstance(), step.getName())); + } + + @SuppressWarnings("unchecked") + @Test + public void testDefaultSkipPolicy() throws Exception { + reader.setItems("a", "b", "c"); + reader.setFailures("b"); + + factory.setSkippableExceptionClasses(getExceptionMap(Exception.class)); + factory.setSkipLimit(1); + + Step step = factory.getObject(); + + step.execute(stepExecution); + + assertEquals(1, stepExecution.getSkipCount()); + assertEquals("[a, c]", reader.getRead().toString()); + assertStepExecutionsAreEqual(stepExecution, + repository.getLastStepExecution(jobExecution.getJobInstance(), step.getName())); + } + + /** + * Check items causing errors are skipped as expected. + */ + @SuppressWarnings("unchecked") + @Test + public void testSkipOverLimitOnReadWithAllSkipsAtEnd() throws Exception { + reader.setItems(StringUtils.commaDelimitedListToStringArray("1,2,3,4,5,6,7,8,9,10,11,12,13,14,15")); + reader.setFailures(StringUtils.commaDelimitedListToStringArray("6,12,13,14,15")); + + writer.setFailures("4"); + + factory.setCommitInterval(5); + factory.setSkipLimit(3); + factory.setSkippableExceptionClasses(getExceptionMap(Exception.class)); + + Step step = factory.getObject(); + + step.execute(stepExecution); + assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); + assertEquals("bad skip count", 3, stepExecution.getSkipCount()); + assertEquals("bad read skip count", 2, stepExecution.getReadSkipCount()); + assertEquals("bad write skip count", 1, stepExecution.getWriteSkipCount()); + + // writer did not skip "6" as it never made it to writer, only "4" did + assertFalse(reader.getRead().contains("6")); + assertTrue(reader.getRead().contains("4")); + + // only "1" was ever committed + List expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,2,3,5,7,8,9,10,11")); + assertEquals(expectedOutput, writer.getCommitted()); + assertStepExecutionsAreEqual(stepExecution, + repository.getLastStepExecution(jobExecution.getJobInstance(), step.getName())); + } + + @Test + public void testReprocessingAfterWriterRollback() throws Exception { + reader.setItems("1", "2", "3", "4"); + + writer.setFailures("4"); + + Step step = factory.getObject(); + step.execute(stepExecution); + + assertEquals(1, stepExecution.getSkipCount()); + assertEquals(2, stepExecution.getRollbackCount()); + + // 1,2,3,4,3,4 - one scan until the item is + // identified and finally skipped on the second attempt + assertEquals("[1, 2, 3, 4, 3, 4]", processor.getProcessed().toString()); + assertStepExecutionsAreEqual(stepExecution, + repository.getLastStepExecution(jobExecution.getJobInstance(), step.getName())); + } + + @Test + public void testAutoRegisterItemListeners() throws Exception { + reader.setFailures("2"); + + final List listenerCalls = new ArrayList<>(); + + class TestItemListenerWriter implements ItemWriter, ItemReadListener, ItemWriteListener, + ItemProcessListener, SkipListener, ChunkListener { + + @Override + public void write(List items) throws Exception { + if (items.contains("4")) { + throw new SkippableException("skippable"); + } + } + + @Override + public void afterRead(String item) { + listenerCalls.add(1); + } + + @Override + public void beforeRead() { + } + + @Override + public void onReadError(Exception ex) { + } + + @Override + public void afterWrite(List items) { + listenerCalls.add(2); + } + + @Override + public void beforeWrite(List items) { + } + + @Override + public void onWriteError(Exception exception, List items) { + } + + @Override + public void afterProcess(String item, @Nullable String result) { + listenerCalls.add(3); + } + + @Override + public void beforeProcess(String item) { + } + + @Override + public void onProcessError(String item, Exception e) { + } + + @Override + public void afterChunk(ChunkContext context) { + listenerCalls.add(4); + } + + @Override + public void beforeChunk(ChunkContext context) { + } + + @Override + public void onSkipInProcess(String item, Throwable t) { + } + + @Override + public void onSkipInRead(Throwable t) { + listenerCalls.add(6); + } + + @Override + public void onSkipInWrite(String item, Throwable t) { + listenerCalls.add(5); + } + + @Override + public void afterChunkError(ChunkContext context) { + } + + } + + factory.setItemWriter(new TestItemListenerWriter()); + + Step step = factory.getObject(); + step.execute(stepExecution); + + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + for (int i = 1; i <= 6; i++) { + assertTrue("didn't call listener " + i, listenerCalls.contains(i)); + } + } + + /** + * Check ItemStream is opened + */ + @Test + public void testItemStreamOpenedEvenWithTaskExecutor() throws Exception { + writer.setFailures("4"); + + ItemReader reader = new AbstractItemStreamItemReader() { + @Override + public void close() { + super.close(); + closed = true; + } + + @Override + public void open(ExecutionContext executionContext) { + super.open(executionContext); + opened = true; + } + + @Nullable + @Override + public String read() { + return null; + } + }; + + factory.setItemReader(reader); + factory.setTaskExecutor(new ConcurrentTaskExecutor()); + + Step step = factory.getObject(); + + step.execute(stepExecution); + + assertTrue(opened); + assertTrue(closed); + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + } + + /** + * Check ItemStream is opened + */ + @Test + public void testNestedItemStreamOpened() throws Exception { + writer.setFailures("4"); + + ItemStreamReader reader = new ItemStreamReader() { + @Override + public void close() throws ItemStreamException { + } + + @Override + public void open(ExecutionContext executionContext) throws ItemStreamException { + } + + @Override + public void update(ExecutionContext executionContext) throws ItemStreamException { + } + + @Nullable + @Override + public String read() throws Exception, UnexpectedInputException, ParseException { + return null; + } + }; + + ItemStreamReader stream = new ItemStreamReader() { + @Override + public void close() throws ItemStreamException { + closed = true; + } + + @Override + public void open(ExecutionContext executionContext) throws ItemStreamException { + opened = true; + } + + @Override + public void update(ExecutionContext executionContext) throws ItemStreamException { + } + + @Nullable + @Override + public String read() throws Exception, UnexpectedInputException, ParseException { + return null; + } + }; + + factory.setItemReader(reader); + factory.setStreams(new ItemStream[] { stream, reader }); + + Step step = factory.getObject(); + + step.execute(stepExecution); + + assertTrue(opened); + assertTrue(closed); + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + } + + /** + * Check ItemStream is opened + */ + @SuppressWarnings("unchecked") + @Test + public void testProxiedItemStreamOpened() throws Exception { + writer.setFailures("4"); + + ItemStreamReader reader = new ItemStreamReader() { + @Override + public void close() throws ItemStreamException { + closed = true; + } + + @Override + public void open(ExecutionContext executionContext) throws ItemStreamException { + opened = true; + } + + @Override + public void update(ExecutionContext executionContext) throws ItemStreamException { + } + + @Nullable + @Override + public String read() throws Exception, UnexpectedInputException, ParseException { + return null; + } + }; + + ProxyFactory proxy = new ProxyFactory(); + proxy.setTarget(reader); + proxy.setInterfaces(new Class[] { ItemReader.class, ItemStream.class }); + proxy.addAdvice(new MethodInterceptor() { + @Override + public Object invoke(MethodInvocation invocation) throws Throwable { + return invocation.proceed(); + } + }); + Object advised = proxy.getProxy(); + + factory.setItemReader((ItemReader) advised); + factory.setStreams(new ItemStream[] { (ItemStream) advised }); + + Step step = factory.getObject(); + + step.execute(stepExecution); + + assertTrue(opened); + assertTrue(closed); + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + } + + private static class ItemProcessListenerStub implements ItemProcessListener { + + private boolean filterEncountered = false; + + @Override + public void afterProcess(T item, @Nullable S result) { + if (result == null) { + filterEncountered = true; + } + } + + @Override + public void beforeProcess(T item) { + + } + + @Override + public void onProcessError(T item, Exception e) { + + } + + public boolean isFilterEncountered() { + return filterEncountered; + } + + } + + private void assertStepExecutionsAreEqual(StepExecution expected, StepExecution actual) { + assertEquals(expected.getId(), actual.getId()); + assertEquals(expected.getStartTime(), actual.getStartTime()); + assertEquals(expected.getEndTime(), actual.getEndTime()); + assertEquals(expected.getSkipCount(), actual.getSkipCount()); + assertEquals(expected.getCommitCount(), actual.getCommitCount()); + assertEquals(expected.getReadCount(), actual.getReadCount()); + assertEquals(expected.getWriteCount(), actual.getWriteCount()); + assertEquals(expected.getFilterCount(), actual.getFilterCount()); + assertEquals(expected.getWriteSkipCount(), actual.getWriteSkipCount()); + assertEquals(expected.getReadSkipCount(), actual.getReadSkipCount()); + assertEquals(expected.getProcessSkipCount(), actual.getProcessSkipCount()); + assertEquals(expected.getRollbackCount(), actual.getRollbackCount()); + assertEquals(expected.getExitStatus(), actual.getExitStatus()); + assertEquals(expected.getLastUpdated(), actual.getLastUpdated()); + assertEquals(expected.getExitStatus(), actual.getExitStatus()); + assertEquals(expected.getJobExecutionId(), actual.getJobExecutionId()); + } + + /** + * condition: skippable < fatal; exception is unclassified + * + * expected: false; default classification + */ + @Test + public void testSkippableSubset_unclassified() throws Exception { + assertFalse(getSkippableSubsetSkipPolicy().shouldSkip(new RuntimeException(), 0)); + } + + /** + * condition: skippable < fatal; exception is skippable + * + * expected: true + */ + @Test + public void testSkippableSubset_skippable() throws Exception { + assertTrue(getSkippableSubsetSkipPolicy().shouldSkip(new WriteFailedException(""), 0)); + } + + /** + * condition: skippable < fatal; exception is fatal + * + * expected: false + */ + @Test + public void testSkippableSubset_fatal() throws Exception { + assertFalse(getSkippableSubsetSkipPolicy().shouldSkip(new WriterNotOpenException(""), 0)); + } + + /** + * condition: fatal < skippable; exception is unclassified + * + * expected: false; default classification + */ + @Test + public void testFatalSubsetUnclassified() throws Exception { + assertFalse(getFatalSubsetSkipPolicy().shouldSkip(new RuntimeException(), 0)); + } + + /** + * condition: fatal < skippable; exception is skippable + * + * expected: true + */ + @Test + public void testFatalSubsetSkippable() throws Exception { + assertTrue(getFatalSubsetSkipPolicy().shouldSkip(new WriterNotOpenException(""), 0)); + } + + /** + * condition: fatal < skippable; exception is fatal + * + * expected: false + */ + @Test + public void testFatalSubsetFatal() throws Exception { + assertFalse(getFatalSubsetSkipPolicy().shouldSkip(new WriteFailedException(""), 0)); + } + + private SkipPolicy getSkippableSubsetSkipPolicy() throws Exception { + Map, Boolean> skippableExceptions = new HashMap<>(); + skippableExceptions.put(WriteFailedException.class, true); + skippableExceptions.put(ItemWriterException.class, false); + factory.setSkippableExceptionClasses(skippableExceptions); + return getSkipPolicy(factory); + } + + private SkipPolicy getFatalSubsetSkipPolicy() throws Exception { + Map, Boolean> skippableExceptions = new HashMap<>(); + skippableExceptions.put(ItemWriterException.class, true); + skippableExceptions.put(WriteFailedException.class, false); + factory.setSkippableExceptionClasses(skippableExceptions); + return getSkipPolicy(factory); + } + + private SkipPolicy getSkipPolicy(FactoryBean factory) throws Exception { + Object step = factory.getObject(); + Object tasklet = ReflectionTestUtils.getField(step, "tasklet"); + Object chunkProvider = ReflectionTestUtils.getField(tasklet, "chunkProvider"); + return (SkipPolicy) ReflectionTestUtils.getField(chunkProvider, "skipPolicy"); + } + + @SuppressWarnings("unchecked") + private Map, Boolean> getExceptionMap(Class... args) { + Map, Boolean> map = new HashMap<>(); + for (Class arg : args) { + map.put(arg, true); + } + return map; + } + + @SuppressWarnings("serial") + public static class NonExistentException extends Exception { + + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBeanUnexpectedRollbackTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBeanUnexpectedRollbackTests.java index 175e52788..fe2bad839 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBeanUnexpectedRollbackTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBeanUnexpectedRollbackTests.java @@ -1,106 +1,107 @@ -/* - * Copyright 2010-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.step.item; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.Step; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.repository.JobRepository; -import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; -import org.springframework.batch.core.step.factory.FaultTolerantStepFactoryBean; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.support.ListItemReader; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.jdbc.datasource.DataSourceTransactionManager; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.transaction.TransactionException; -import org.springframework.transaction.UnexpectedRollbackException; -import org.springframework.transaction.support.DefaultTransactionStatus; - -import javax.sql.DataSource; -import java.util.Arrays; - -import static org.junit.Assert.assertEquals; - -/** - * Tests for {@link FaultTolerantStepFactoryBean} with unexpected rollback. - */ -@ContextConfiguration(locations="classpath:/org/springframework/batch/core/repository/dao/data-source-context.xml") -@RunWith(SpringJUnit4ClassRunner.class) -public class FaultTolerantStepFactoryBeanUnexpectedRollbackTests { - - protected final Log logger = LogFactory.getLog(getClass()); - - @Autowired - private DataSource dataSource; - - @Test - public void testTransactionException() throws Exception { - - final SkipWriterStub writer = new SkipWriterStub<>(); - FaultTolerantStepFactoryBean factory = new FaultTolerantStepFactoryBean<>(); - factory.setItemWriter(writer); - - @SuppressWarnings("serial") - DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource) { - private boolean failed = false; - @Override - protected void doCommit(DefaultTransactionStatus status) throws TransactionException { - if (writer.getWritten().isEmpty() || failed || !isExistingTransaction(status.getTransaction())) { - super.doCommit(status); - return; - } - failed = true; - status.setRollbackOnly(); - super.doRollback(status); - throw new UnexpectedRollbackException("Planned"); - } - }; - - factory.setBeanName("stepName"); - factory.setTransactionManager(transactionManager); - factory.setCommitInterval(2); - - ItemReader reader = new ListItemReader<>(Arrays.asList("1", "2")); - factory.setItemReader(reader); - - JobRepositoryFactoryBean repositoryFactory = new JobRepositoryFactoryBean(); - repositoryFactory.setDataSource(dataSource); - repositoryFactory.setTransactionManager(transactionManager); - repositoryFactory.afterPropertiesSet(); - JobRepository repository = repositoryFactory.getObject(); - factory.setJobRepository(repository); - - JobExecution jobExecution = repository.createJobExecution("job", new JobParameters()); - StepExecution stepExecution = jobExecution.createStepExecution(factory.getName()); - repository.add(stepExecution); - - Step step = factory.getObject(); - - step.execute(stepExecution); - assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); - - assertEquals("[]", writer.getCommitted().toString()); - } - -} +/* + * Copyright 2010-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.step.item; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.Step; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; +import org.springframework.batch.core.step.factory.FaultTolerantStepFactoryBean; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.support.ListItemReader; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.transaction.TransactionException; +import org.springframework.transaction.UnexpectedRollbackException; +import org.springframework.transaction.support.DefaultTransactionStatus; + +import javax.sql.DataSource; +import java.util.Arrays; + +import static org.junit.Assert.assertEquals; + +/** + * Tests for {@link FaultTolerantStepFactoryBean} with unexpected rollback. + */ +@ContextConfiguration(locations = "classpath:/org/springframework/batch/core/repository/dao/data-source-context.xml") +@RunWith(SpringJUnit4ClassRunner.class) +public class FaultTolerantStepFactoryBeanUnexpectedRollbackTests { + + protected final Log logger = LogFactory.getLog(getClass()); + + @Autowired + private DataSource dataSource; + + @Test + public void testTransactionException() throws Exception { + + final SkipWriterStub writer = new SkipWriterStub<>(); + FaultTolerantStepFactoryBean factory = new FaultTolerantStepFactoryBean<>(); + factory.setItemWriter(writer); + + @SuppressWarnings("serial") + DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource) { + private boolean failed = false; + + @Override + protected void doCommit(DefaultTransactionStatus status) throws TransactionException { + if (writer.getWritten().isEmpty() || failed || !isExistingTransaction(status.getTransaction())) { + super.doCommit(status); + return; + } + failed = true; + status.setRollbackOnly(); + super.doRollback(status); + throw new UnexpectedRollbackException("Planned"); + } + }; + + factory.setBeanName("stepName"); + factory.setTransactionManager(transactionManager); + factory.setCommitInterval(2); + + ItemReader reader = new ListItemReader<>(Arrays.asList("1", "2")); + factory.setItemReader(reader); + + JobRepositoryFactoryBean repositoryFactory = new JobRepositoryFactoryBean(); + repositoryFactory.setDataSource(dataSource); + repositoryFactory.setTransactionManager(transactionManager); + repositoryFactory.afterPropertiesSet(); + JobRepository repository = repositoryFactory.getObject(); + factory.setJobRepository(repository); + + JobExecution jobExecution = repository.createJobExecution("job", new JobParameters()); + StepExecution stepExecution = jobExecution.createStepExecution(factory.getName()); + repository.add(stepExecution); + + Step step = factory.getObject(); + + step.execute(stepExecution); + assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); + + assertEquals("[]", writer.getCommitted().toString()); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/ForceRollbackForWriteSkipExceptionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/ForceRollbackForWriteSkipExceptionTests.java index 84e15d544..2115780e8 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/ForceRollbackForWriteSkipExceptionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/ForceRollbackForWriteSkipExceptionTests.java @@ -17,15 +17,18 @@ package org.springframework.batch.core.step.item; import org.springframework.batch.core.AbstractExceptionWithCauseTests; - /** * @author Dave Syer * */ public class ForceRollbackForWriteSkipExceptionTests extends AbstractExceptionWithCauseTests { - /* (non-Javadoc) - * @see org.springframework.batch.core.listener.AbstractDoubleExceptionTests#getException(java.lang.String, java.lang.RuntimeException, java.lang.Throwable) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.core.listener.AbstractDoubleExceptionTests#getException( + * java.lang.String, java.lang.RuntimeException, java.lang.Throwable) */ @Override public Exception getException(String msg, Throwable e) throws Exception { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/RepeatOperationsStepFactoryBeanTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/RepeatOperationsStepFactoryBeanTests.java index e3bffbad4..8a6801af1 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/RepeatOperationsStepFactoryBeanTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/RepeatOperationsStepFactoryBeanTests.java @@ -40,7 +40,7 @@ import org.springframework.batch.support.transaction.ResourcelessTransactionMana */ public class RepeatOperationsStepFactoryBeanTests extends TestCase { - private SimpleStepFactoryBean factory = new SimpleStepFactoryBean<>(); + private SimpleStepFactoryBean factory = new SimpleStepFactoryBean<>(); private List list; diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/ScriptItemProcessorTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/ScriptItemProcessorTests.java index 05ea9b42f..0e36fd370 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/ScriptItemProcessorTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/ScriptItemProcessorTests.java @@ -30,7 +30,8 @@ import java.util.List; /** *

      - * Test job utilizing a {@link org.springframework.batch.item.support.ScriptItemProcessor}. + * Test job utilizing a + * {@link org.springframework.batch.item.support.ScriptItemProcessor}. *

      * * @author Chris Schaefer @@ -39,6 +40,7 @@ import java.util.List; @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) public class ScriptItemProcessorTests { + @Autowired private Job job; @@ -51,6 +53,7 @@ public class ScriptItemProcessorTests { } public static class TestItemWriter implements ItemWriter { + @Override public void write(List items) throws Exception { Assert.notNull(items, "Items cannot be null"); @@ -60,5 +63,7 @@ public class ScriptItemProcessorTests { String item = items.get(0); Assert.isTrue("BLAH".equals(item), "Transformed item to write should have been: BLAH but got: " + item); } + } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SimpleChunkProcessorTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SimpleChunkProcessorTests.java index 4f9a1936b..fcfaca0b0 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SimpleChunkProcessorTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SimpleChunkProcessorTests.java @@ -54,8 +54,8 @@ public class SimpleChunkProcessorTests { } }); - private StepContribution contribution = new StepContribution(new StepExecution("foo", new JobExecution( - new JobInstance(123L, "job"), new JobParameters()))); + private StepContribution contribution = new StepContribution( + new StepExecution("foo", new JobExecution(new JobInstance(123L, "job"), new JobParameters()))); private List list = new ArrayList<>(); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SimpleChunkProviderTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SimpleChunkProviderTests.java index d09c6b751..b9b290b1c 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SimpleChunkProviderTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SimpleChunkProviderTests.java @@ -33,13 +33,12 @@ public class SimpleChunkProviderTests { private SimpleChunkProvider provider; - private StepContribution contribution = new StepContribution(new StepExecution("foo", new JobExecution( - new JobInstance(123L, "job"), new JobParameters()))); + private StepContribution contribution = new StepContribution( + new StepExecution("foo", new JobExecution(new JobInstance(123L, "job"), new JobParameters()))); @Test public void testProvide() throws Exception { - provider = new SimpleChunkProvider<>(new ListItemReader<>(Arrays.asList("foo", "bar")), - new RepeatTemplate()); + provider = new SimpleChunkProvider<>(new ListItemReader<>(Arrays.asList("foo", "bar")), new RepeatTemplate()); Chunk chunk = provider.provide(contribution); assertNotNull(chunk); assertEquals(2, chunk.getItems().size()); @@ -50,8 +49,8 @@ public class SimpleChunkProviderTests { provider = new SimpleChunkProvider(new ListItemReader<>(Arrays.asList("foo", "bar")), new RepeatTemplate()) { @Override - protected String read(StepContribution contribution, Chunk chunk) throws SkipOverflowException, - Exception { + protected String read(StepContribution contribution, Chunk chunk) + throws SkipOverflowException, Exception { chunk.skip(new RuntimeException("Planned")); throw new SkipOverflowException("Overflow"); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SimpleRetryExceptionHandlerTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SimpleRetryExceptionHandlerTests.java index a43cf6e77..499350b30 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SimpleRetryExceptionHandlerTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SimpleRetryExceptionHandlerTests.java @@ -59,15 +59,16 @@ public class SimpleRetryExceptionHandlerTests extends TestCase { /** * Test method for - * {@link org.springframework.batch.core.step.item.SimpleRetryExceptionHandler#handleException(org.springframework.batch.repeat.RepeatContext, java.lang.Throwable)} . + * {@link org.springframework.batch.core.step.item.SimpleRetryExceptionHandler#handleException(org.springframework.batch.repeat.RepeatContext, java.lang.Throwable)} + * . */ public void testRethrowWhenRetryExhausted() throws Throwable { RetryPolicy retryPolicy = new NeverRetryPolicy(); RuntimeException ex = new RuntimeException("foo"); - SimpleRetryExceptionHandler handler = getHandlerAfterRetry(retryPolicy, ex, Collections - .> singleton(Error.class)); + SimpleRetryExceptionHandler handler = getHandlerAfterRetry(retryPolicy, ex, + Collections.>singleton(Error.class)); // Then pretend to handle the exception in the parent context... try { @@ -86,15 +87,16 @@ public class SimpleRetryExceptionHandlerTests extends TestCase { /** * Test method for - * {@link org.springframework.batch.core.step.item.SimpleRetryExceptionHandler#handleException(org.springframework.batch.repeat.RepeatContext, java.lang.Throwable)} . + * {@link org.springframework.batch.core.step.item.SimpleRetryExceptionHandler#handleException(org.springframework.batch.repeat.RepeatContext, java.lang.Throwable)} + * . */ public void testNoRethrowWhenRetryNotExhausted() throws Throwable { RetryPolicy retryPolicy = new AlwaysRetryPolicy(); RuntimeException ex = new RuntimeException("foo"); - SimpleRetryExceptionHandler handler = getHandlerAfterRetry(retryPolicy, ex, Collections - .> singleton(Error.class)); + SimpleRetryExceptionHandler handler = getHandlerAfterRetry(retryPolicy, ex, + Collections.>singleton(Error.class)); // Then pretend to handle the exception in the parent context... handler.handleException(context.getParent(), ex); @@ -105,15 +107,16 @@ public class SimpleRetryExceptionHandlerTests extends TestCase { /** * Test method for - * {@link org.springframework.batch.core.step.item.SimpleRetryExceptionHandler#handleException(org.springframework.batch.repeat.RepeatContext, java.lang.Throwable)} . + * {@link org.springframework.batch.core.step.item.SimpleRetryExceptionHandler#handleException(org.springframework.batch.repeat.RepeatContext, java.lang.Throwable)} + * . */ public void testRethrowWhenFatal() throws Throwable { RetryPolicy retryPolicy = new AlwaysRetryPolicy(); RuntimeException ex = new RuntimeException("foo"); - SimpleRetryExceptionHandler handler = getHandlerAfterRetry(retryPolicy, ex, Collections - .> singleton(RuntimeException.class)); + SimpleRetryExceptionHandler handler = getHandlerAfterRetry(retryPolicy, ex, + Collections.>singleton(RuntimeException.class)); // Then pretend to handle the exception in the parent context... try { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SimpleStepFactoryBeanTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SimpleStepFactoryBeanTests.java index 4068272e1..64fae37ac 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SimpleStepFactoryBeanTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SimpleStepFactoryBeanTests.java @@ -86,9 +86,7 @@ public class SimpleStepFactoryBeanTests { public void setUp() throws Exception { EmbeddedDatabase embeddedDatabase = new EmbeddedDatabaseBuilder() .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("/org/springframework/batch/core/schema-hsqldb.sql") - .generateUniqueName(true) - .build(); + .addScript("/org/springframework/batch/core/schema-hsqldb.sql").generateUniqueName(true).build(); DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(embeddedDatabase); JobRepositoryFactoryBean repositoryFactoryBean = new JobRepositoryFactoryBean(); repositoryFactoryBean.setDataSource(embeddedDatabase); @@ -267,7 +265,7 @@ public class SimpleStepFactoryBeanTests { @Override public void beforeWrite(List items) { - if(items.contains("error")) { + if (items.contains("error")) { throw new RuntimeException("rollback the last chunk"); } @@ -281,6 +279,7 @@ public class SimpleStepFactoryBeanTests { } class CountingChunkListener implements ChunkListener { + int beforeCount = 0; int afterCount = 0; @@ -311,6 +310,7 @@ public class SimpleStepFactoryBeanTests { writeListener.trail = writeListener.trail + "5"; failedCount++; } + } AssertingWriteListener writeListener = new AssertingWriteListener(); CountingChunkListener chunkListener = new CountingChunkListener(writeListener); @@ -387,8 +387,10 @@ public class SimpleStepFactoryBeanTests { final List listenerCalls = new ArrayList<>(); - class TestItemListenerWriter implements ItemWriter, ItemProcessor, - ItemReadListener, ItemWriteListener, ItemProcessListener, ChunkListener { + class TestItemListenerWriter + implements ItemWriter, ItemProcessor, ItemReadListener, + ItemWriteListener, ItemProcessListener, ChunkListener { + @Override public void write(List items) throws Exception { } @@ -479,6 +481,7 @@ public class SimpleStepFactoryBeanTests { final List listenerCalls = new ArrayList<>(); class TestItemListenerWriter implements ItemWriter, ItemWriteListener { + @Override public void write(List items) throws Exception { } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SkipProcessorStub.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SkipProcessorStub.java index dc83aea49..32dfc944c 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SkipProcessorStub.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SkipProcessorStub.java @@ -1,77 +1,78 @@ -/* - * Copyright 2006-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.step.item; - -import java.util.ArrayList; -import java.util.List; - -import org.springframework.batch.item.ItemProcessor; -import org.springframework.batch.support.transaction.TransactionAwareProxyFactory; -import org.springframework.lang.Nullable; - -/** - * @author Dan Garrette - * @since 2.0.1 - */ -public class SkipProcessorStub extends AbstractExceptionThrowingItemHandlerStub implements ItemProcessor { - - private List processed = new ArrayList<>(); - - private List committed = TransactionAwareProxyFactory.createTransactionalList(); - - private boolean filter = false; - - public SkipProcessorStub() throws Exception { - super(); - } - - public List getProcessed() { - return processed; - } - - public List getCommitted() { - return committed; - } - - public void setFilter(boolean filter) { - this.filter = filter; - } - - public void clear() { - processed.clear(); - committed.clear(); - filter = false; - } - - @Nullable - @Override - public T process(T item) throws Exception { - processed.add(item); - committed.add(item); - try { - checkFailure(item); - } - catch (Exception e) { - if (filter) { - return null; - } - else { - throw e; - } - } - return item; - } -} +/* + * Copyright 2006-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.step.item; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.batch.item.ItemProcessor; +import org.springframework.batch.support.transaction.TransactionAwareProxyFactory; +import org.springframework.lang.Nullable; + +/** + * @author Dan Garrette + * @since 2.0.1 + */ +public class SkipProcessorStub extends AbstractExceptionThrowingItemHandlerStub implements ItemProcessor { + + private List processed = new ArrayList<>(); + + private List committed = TransactionAwareProxyFactory.createTransactionalList(); + + private boolean filter = false; + + public SkipProcessorStub() throws Exception { + super(); + } + + public List getProcessed() { + return processed; + } + + public List getCommitted() { + return committed; + } + + public void setFilter(boolean filter) { + this.filter = filter; + } + + public void clear() { + processed.clear(); + committed.clear(); + filter = false; + } + + @Nullable + @Override + public T process(T item) throws Exception { + processed.add(item); + committed.add(item); + try { + checkFailure(item); + } + catch (Exception e) { + if (filter) { + return null; + } + else { + throw e; + } + } + return item; + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SkipReaderStub.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SkipReaderStub.java index 9aedbf1ad..71dd2b112 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SkipReaderStub.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SkipReaderStub.java @@ -1,76 +1,77 @@ -/* - * Copyright 2006-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.step.item; - -import java.util.ArrayList; -import java.util.List; - -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.ParseException; -import org.springframework.batch.item.UnexpectedInputException; -import org.springframework.lang.Nullable; -import org.springframework.util.Assert; - -/** - * @author Dan Garrette - * @since 2.0.1 - */ -public class SkipReaderStub extends AbstractExceptionThrowingItemHandlerStub implements ItemReader { - - private T[] items; - - private List read = new ArrayList<>(); - - private int counter = -1; - - public SkipReaderStub() throws Exception { - super(); - } - - @SuppressWarnings("unchecked") - public SkipReaderStub(T... items) throws Exception { - super(); - this.items = items; - } - - @SuppressWarnings("unchecked") - public void setItems(T... items) { - Assert.isTrue(counter < 0, "Items cannot be set once reading has started"); - this.items = items; - } - - public List getRead() { - return read; - } - - public void clear() { - counter = -1; - read.clear(); - } - - @Nullable - @Override - public T read() throws Exception, UnexpectedInputException, ParseException { - counter++; - if (counter >= items.length) { - return null; - } - T item = items[counter]; - checkFailure(item); - read.add(item); - return item; - } -} +/* + * Copyright 2006-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.step.item; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ParseException; +import org.springframework.batch.item.UnexpectedInputException; +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; + +/** + * @author Dan Garrette + * @since 2.0.1 + */ +public class SkipReaderStub extends AbstractExceptionThrowingItemHandlerStub implements ItemReader { + + private T[] items; + + private List read = new ArrayList<>(); + + private int counter = -1; + + public SkipReaderStub() throws Exception { + super(); + } + + @SuppressWarnings("unchecked") + public SkipReaderStub(T... items) throws Exception { + super(); + this.items = items; + } + + @SuppressWarnings("unchecked") + public void setItems(T... items) { + Assert.isTrue(counter < 0, "Items cannot be set once reading has started"); + this.items = items; + } + + public List getRead() { + return read; + } + + public void clear() { + counter = -1; + read.clear(); + } + + @Nullable + @Override + public T read() throws Exception, UnexpectedInputException, ParseException { + counter++; + if (counter >= items.length) { + return null; + } + T item = items[counter]; + checkFailure(item); + read.add(item); + return item; + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SkipWrapperTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SkipWrapperTests.java index b50d39798..b2977f5c4 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SkipWrapperTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SkipWrapperTests.java @@ -39,7 +39,8 @@ public class SkipWrapperTests { } /** - * Test method for {@link org.springframework.batch.core.step.item.SkipWrapper#SkipWrapper(java.lang.Object, java.lang.Throwable)}. + * Test method for + * {@link org.springframework.batch.core.step.item.SkipWrapper#SkipWrapper(java.lang.Object, java.lang.Throwable)}. */ @Test public void testItemWrapperTException() { @@ -49,7 +50,8 @@ public class SkipWrapperTests { } /** - * Test method for {@link org.springframework.batch.core.step.item.SkipWrapper#toString()}. + * Test method for + * {@link org.springframework.batch.core.step.item.SkipWrapper#toString()}. */ @Test public void testToString() { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SkipWriterStub.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SkipWriterStub.java index b15334374..f02d2c777 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SkipWriterStub.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SkipWriterStub.java @@ -1,60 +1,61 @@ -/* - * Copyright 2006-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.step.item; - -import java.util.ArrayList; -import java.util.List; - -import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.support.transaction.TransactionAwareProxyFactory; - -/** - * @author Dan Garrette - * @since 2.0.1 - */ -public class SkipWriterStub extends AbstractExceptionThrowingItemHandlerStub implements ItemWriter { - - private List written = new ArrayList<>(); - - private List committed = TransactionAwareProxyFactory.createTransactionalList(); - - public SkipWriterStub() throws Exception { - super(); - } - - public List getWritten() { - return written; - } - - public List getCommitted() { - return committed; - } - - public void clear() { - written.clear(); - committed.clear(); - } - - @Override - public void write(List items) throws Exception { - logger.debug("Writing: " + items); - for (T item : items) { - written.add(item); - committed.add(item); - checkFailure(item); - } - } -} +/* + * Copyright 2006-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.step.item; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.batch.item.ItemWriter; +import org.springframework.batch.support.transaction.TransactionAwareProxyFactory; + +/** + * @author Dan Garrette + * @since 2.0.1 + */ +public class SkipWriterStub extends AbstractExceptionThrowingItemHandlerStub implements ItemWriter { + + private List written = new ArrayList<>(); + + private List committed = TransactionAwareProxyFactory.createTransactionalList(); + + public SkipWriterStub() throws Exception { + super(); + } + + public List getWritten() { + return written; + } + + public List getCommitted() { + return committed; + } + + public void clear() { + written.clear(); + committed.clear(); + } + + @Override + public void write(List items) throws Exception { + logger.debug("Writing: " + items); + for (T item : items) { + written.add(item); + committed.add(item); + checkFailure(item); + } + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SkippableException.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SkippableException.java index 51321b4f2..0e6bb7b55 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SkippableException.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SkippableException.java @@ -1,27 +1,29 @@ -/* - * Copyright 2006-2009 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.step.item; - -/** - * @author Dan Garrette - * @since 2.0.1 - */ -@SuppressWarnings("serial") -public class SkippableException extends Exception { - public SkippableException(String message) { - super(message); - } -} +/* + * Copyright 2006-2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.step.item; + +/** + * @author Dan Garrette + * @since 2.0.1 + */ +@SuppressWarnings("serial") +public class SkippableException extends Exception { + + public SkippableException(String message) { + super(message); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SkippableRuntimeException.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SkippableRuntimeException.java index dccc67579..8a67ab8af 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SkippableRuntimeException.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SkippableRuntimeException.java @@ -1,27 +1,29 @@ -/* - * Copyright 2006-2009 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.step.item; - -/** - * @author Dan Garrette - * @since 2.0.1 - */ -@SuppressWarnings("serial") -public class SkippableRuntimeException extends RuntimeException { - public SkippableRuntimeException(String message) { - super(message); - } -} +/* + * Copyright 2006-2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.step.item; + +/** + * @author Dan Garrette + * @since 2.0.1 + */ +@SuppressWarnings("serial") +public class SkippableRuntimeException extends RuntimeException { + + public SkippableRuntimeException(String message) { + super(message); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/TaskletStepExceptionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/TaskletStepExceptionTests.java index 790607d27..481b92720 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/TaskletStepExceptionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/TaskletStepExceptionTests.java @@ -348,7 +348,7 @@ public class TaskletStepExceptionTests { } }); - + taskletStep.setTransactionManager(new FailingRollbackTransactionManager()); jobRepository.setFailOnUpdateExecutionContext(true); @@ -415,7 +415,7 @@ public class TaskletStepExceptionTests { } }); - + taskletStep.setTransactionManager(new FailingRollbackTransactionManager()); jobRepository.setFailOnUpdateStepExecution(1); @@ -478,6 +478,7 @@ public class TaskletStepExceptionTests { public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { throw taskletException; } + } private static class InterruptionListener implements StepExecutionListener { @@ -486,6 +487,7 @@ public class TaskletStepExceptionTests { public void beforeStep(StepExecution stepExecution) { stepExecution.setTerminateOnly(); } + } private static class UpdateCountingJobRepository implements JobRepository { @@ -579,21 +581,21 @@ public class TaskletStepExceptionTests { } @Override - public JobInstance createJobInstance(String jobName, - JobParameters jobParameters) { + public JobInstance createJobInstance(String jobName, JobParameters jobParameters) { return null; } } - + @SuppressWarnings("serial") private static class FailingRollbackTransactionManager extends ResourcelessTransactionManager { - + @Override protected void doRollback(DefaultTransactionStatus status) throws TransactionException { super.doRollback(status); throw new RuntimeException("Expected exception in rollback"); - } + } + } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/job/DefaultJobParametersExtractorJobParametersTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/job/DefaultJobParametersExtractorJobParametersTests.java index b1279dde5..b6d159d03 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/job/DefaultJobParametersExtractorJobParametersTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/job/DefaultJobParametersExtractorJobParametersTests.java @@ -39,7 +39,7 @@ public class DefaultJobParametersExtractorJobParametersTests { @Test public void testGetNamedJobParameters() throws Exception { StepExecution stepExecution = getStepExecution("foo=bar"); - extractor.setKeys(new String[] {"foo", "bar"}); + extractor.setKeys(new String[] { "foo", "bar" }); JobParameters jobParameters = extractor.getJobParameters(null, stepExecution); assertEquals("{foo=bar}", jobParameters.toString()); } @@ -47,7 +47,7 @@ public class DefaultJobParametersExtractorJobParametersTests { @Test public void testGetAllJobParameters() throws Exception { StepExecution stepExecution = getStepExecution("foo=bar,spam=bucket"); - extractor.setKeys(new String[] {"foo", "bar"}); + extractor.setKeys(new String[] { "foo", "bar" }); JobParameters jobParameters = extractor.getJobParameters(null, stepExecution); assertEquals("bar", jobParameters.getString("foo")); assertEquals("bucket", jobParameters.getString("spam")); @@ -56,7 +56,7 @@ public class DefaultJobParametersExtractorJobParametersTests { @Test public void testGetNamedLongStringParameters() throws Exception { StepExecution stepExecution = getStepExecution("foo=bar"); - extractor.setKeys(new String[] {"foo(string)", "bar"}); + extractor.setKeys(new String[] { "foo(string)", "bar" }); JobParameters jobParameters = extractor.getJobParameters(null, stepExecution); assertEquals("{foo=bar}", jobParameters.toString()); } @@ -64,7 +64,7 @@ public class DefaultJobParametersExtractorJobParametersTests { @Test public void testGetNamedLongJobParameters() throws Exception { StepExecution stepExecution = getStepExecution("foo(long)=11"); - extractor.setKeys(new String[] {"foo(long)", "bar"}); + extractor.setKeys(new String[] { "foo(long)", "bar" }); JobParameters jobParameters = extractor.getJobParameters(null, stepExecution); assertEquals("{foo=11}", jobParameters.toString()); } @@ -72,7 +72,7 @@ public class DefaultJobParametersExtractorJobParametersTests { @Test public void testGetNamedIntJobParameters() throws Exception { StepExecution stepExecution = getStepExecution("foo(long)=11"); - extractor.setKeys(new String[] {"foo(int)", "bar"}); + extractor.setKeys(new String[] { "foo(int)", "bar" }); JobParameters jobParameters = extractor.getJobParameters(null, stepExecution); assertEquals("{foo=11}", jobParameters.toString()); } @@ -80,7 +80,7 @@ public class DefaultJobParametersExtractorJobParametersTests { @Test public void testGetNamedDoubleJobParameters() throws Exception { StepExecution stepExecution = getStepExecution("foo(double)=11.1"); - extractor.setKeys(new String[] {"foo(double)"}); + extractor.setKeys(new String[] { "foo(double)" }); JobParameters jobParameters = extractor.getJobParameters(null, stepExecution); assertEquals("{foo=11.1}", jobParameters.toString()); } @@ -89,10 +89,10 @@ public class DefaultJobParametersExtractorJobParametersTests { public void testGetNamedDateJobParameters() throws Exception { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd"); Date date = dateFormat.parse(dateFormat.format(new Date())); - StepExecution stepExecution = getStepExecution("foo(date)="+dateFormat.format(date)); - extractor.setKeys(new String[] {"foo(date)"}); + StepExecution stepExecution = getStepExecution("foo(date)=" + dateFormat.format(date)); + extractor.setKeys(new String[] { "foo(date)" }); JobParameters jobParameters = extractor.getJobParameters(null, stepExecution); - assertEquals("{foo="+date.getTime()+"}", jobParameters.toString()); + assertEquals("{foo=" + date.getTime() + "}", jobParameters.toString()); } /** @@ -100,7 +100,8 @@ public class DefaultJobParametersExtractorJobParametersTests { * @return */ private StepExecution getStepExecution(String parameters) { - JobParameters jobParameters = new DefaultJobParametersConverter().getJobParameters(PropertiesConverter.stringToProperties(parameters)); + JobParameters jobParameters = new DefaultJobParametersConverter() + .getJobParameters(PropertiesConverter.stringToProperties(parameters)); return new StepExecution("step", new JobExecution(new JobInstance(1L, "job"), jobParameters)); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/job/DefaultJobParametersExtractorTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/job/DefaultJobParametersExtractorTests.java index 188a28a59..3fd1a23e1 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/job/DefaultJobParametersExtractorTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/job/DefaultJobParametersExtractorTests.java @@ -30,8 +30,9 @@ import org.springframework.batch.core.StepExecution; * */ public class DefaultJobParametersExtractorTests { - + private DefaultJobParametersExtractor extractor = new DefaultJobParametersExtractor(); + private StepExecution stepExecution = new StepExecution("step", new JobExecution(0L)); @Test @@ -43,39 +44,39 @@ public class DefaultJobParametersExtractorTests { @Test public void testGetNamedJobParameters() throws Exception { stepExecution.getExecutionContext().put("foo", "bar"); - extractor.setKeys(new String[] {"foo", "bar"}); + extractor.setKeys(new String[] { "foo", "bar" }); JobParameters jobParameters = extractor.getJobParameters(null, stepExecution); assertEquals("{foo=bar}", jobParameters.toString()); } @Test public void testGetNamedLongStringParameters() throws Exception { - stepExecution.getExecutionContext().putString("foo","bar"); - extractor.setKeys(new String[] {"foo(string)", "bar"}); + stepExecution.getExecutionContext().putString("foo", "bar"); + extractor.setKeys(new String[] { "foo(string)", "bar" }); JobParameters jobParameters = extractor.getJobParameters(null, stepExecution); assertEquals("{foo=bar}", jobParameters.toString()); } @Test public void testGetNamedLongJobParameters() throws Exception { - stepExecution.getExecutionContext().putLong("foo",11L); - extractor.setKeys(new String[] {"foo(long)", "bar"}); + stepExecution.getExecutionContext().putLong("foo", 11L); + extractor.setKeys(new String[] { "foo(long)", "bar" }); JobParameters jobParameters = extractor.getJobParameters(null, stepExecution); assertEquals("{foo=11}", jobParameters.toString()); } @Test public void testGetNamedIntJobParameters() throws Exception { - stepExecution.getExecutionContext().putInt("foo",11); - extractor.setKeys(new String[] {"foo(int)", "bar"}); + stepExecution.getExecutionContext().putInt("foo", 11); + extractor.setKeys(new String[] { "foo(int)", "bar" }); JobParameters jobParameters = extractor.getJobParameters(null, stepExecution); assertEquals("{foo=11}", jobParameters.toString()); } @Test public void testGetNamedDoubleJobParameters() throws Exception { - stepExecution.getExecutionContext().putDouble("foo",11.1); - extractor.setKeys(new String[] {"foo(double)"}); + stepExecution.getExecutionContext().putDouble("foo", 11.1); + extractor.setKeys(new String[] { "foo(double)" }); JobParameters jobParameters = extractor.getJobParameters(null, stepExecution); assertEquals("{foo=11.1}", jobParameters.toString()); } @@ -83,22 +84,21 @@ public class DefaultJobParametersExtractorTests { @Test public void testGetNamedDateJobParameters() throws Exception { Date date = new Date(); - stepExecution.getExecutionContext().put("foo",date); - extractor.setKeys(new String[] {"foo(date)"}); + stepExecution.getExecutionContext().put("foo", date); + extractor.setKeys(new String[] { "foo(date)" }); JobParameters jobParameters = extractor.getJobParameters(null, stepExecution); - assertEquals("{foo="+date.getTime()+"}", jobParameters.toString()); + assertEquals("{foo=" + date.getTime() + "}", jobParameters.toString()); } @Test public void testUseParentParameters() throws Exception { - JobExecution jobExecution = new JobExecution(0L, new JobParametersBuilder() - .addString("parentParam", "val") - .toJobParameters()); + JobExecution jobExecution = new JobExecution(0L, + new JobParametersBuilder().addString("parentParam", "val").toJobParameters()); StepExecution stepExecution = new StepExecution("step", jobExecution); stepExecution.getExecutionContext().putDouble("foo", 11.1); - extractor.setKeys(new String[] {"foo(double)"}); + extractor.setKeys(new String[] { "foo(double)" }); JobParameters jobParameters = extractor.getJobParameters(null, stepExecution); String jobParams = jobParameters.toString(); @@ -112,16 +112,16 @@ public class DefaultJobParametersExtractorTests { DefaultJobParametersExtractor extractor = new DefaultJobParametersExtractor(); extractor.setUseAllParentParameters(false); - JobExecution jobExecution = new JobExecution(0L, new JobParametersBuilder() - .addString("parentParam", "val") - .toJobParameters()); + JobExecution jobExecution = new JobExecution(0L, + new JobParametersBuilder().addString("parentParam", "val").toJobParameters()); StepExecution stepExecution = new StepExecution("step", jobExecution); stepExecution.getExecutionContext().putDouble("foo", 11.1); - extractor.setKeys(new String[] {"foo(double)"}); + extractor.setKeys(new String[] { "foo(double)" }); JobParameters jobParameters = extractor.getJobParameters(null, stepExecution); assertEquals("{foo=11.1}", jobParameters.toString()); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/job/JobStepTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/job/JobStepTests.java index f3d9f9260..a74072798 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/job/JobStepTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/job/JobStepTests.java @@ -56,8 +56,7 @@ public class JobStepTests { step.setName("step"); EmbeddedDatabase embeddedDatabase = new EmbeddedDatabaseBuilder() .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("/org/springframework/batch/core/schema-hsqldb.sql") - .build(); + .addScript("/org/springframework/batch/core/schema-hsqldb.sql").build(); JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); factory.setDataSource(embeddedDatabase); factory.setTransactionManager(new DataSourceTransactionManager(embeddedDatabase)); @@ -75,8 +74,7 @@ public class JobStepTests { /** * Test method for - * {@link org.springframework.batch.core.step.job.JobStep#afterPropertiesSet()} - * . + * {@link org.springframework.batch.core.step.job.JobStep#afterPropertiesSet()} . */ @Test(expected = IllegalStateException.class) public void testAfterPropertiesSet() throws Exception { @@ -85,8 +83,7 @@ public class JobStepTests { /** * Test method for - * {@link org.springframework.batch.core.step.job.JobStep#afterPropertiesSet()} - * . + * {@link org.springframework.batch.core.step.job.JobStep#afterPropertiesSet()} . */ @Test(expected = IllegalStateException.class) public void testAfterPropertiesSetWithNoLauncher() throws Exception { @@ -112,8 +109,8 @@ public class JobStepTests { step.afterPropertiesSet(); step.execute(stepExecution); assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - assertTrue("Missing job parameters in execution context: " + stepExecution.getExecutionContext(), stepExecution - .getExecutionContext().containsKey(JobStep.class.getName() + ".JOB_PARAMETERS")); + assertTrue("Missing job parameters in execution context: " + stepExecution.getExecutionContext(), + stepExecution.getExecutionContext().containsKey(JobStep.class.getName() + ".JOB_PARAMETERS")); } @Test @@ -148,7 +145,7 @@ public class JobStepTests { public void testExecuteRestart() throws Exception { DefaultJobParametersExtractor jobParametersExtractor = new DefaultJobParametersExtractor(); - jobParametersExtractor.setKeys(new String[] {"foo"}); + jobParametersExtractor.setKeys(new String[] { "foo" }); ExecutionContext executionContext = stepExecution.getExecutionContext(); executionContext.put("foo", "bar"); step.setJobParametersExtractor(jobParametersExtractor); @@ -162,6 +159,7 @@ public class JobStepTests { jobRepository.update(execution); throw new RuntimeException("FOO"); } + @Override public boolean isRestartable() { return true; @@ -188,19 +186,20 @@ public class JobStepTests { public void testStoppedChild() throws Exception { DefaultJobParametersExtractor jobParametersExtractor = new DefaultJobParametersExtractor(); - jobParametersExtractor.setKeys(new String[] {"foo"}); + jobParametersExtractor.setKeys(new String[] { "foo" }); ExecutionContext executionContext = stepExecution.getExecutionContext(); executionContext.put("foo", "bar"); step.setJobParametersExtractor(jobParametersExtractor); step.setJob(new JobSupport("child") { @Override - public void execute(JobExecution execution) { + public void execute(JobExecution execution) { assertEquals(1, execution.getJobParameters().getParameters().size()); execution.setStatus(BatchStatus.STOPPED); execution.setEndTime(new Date()); jobRepository.update(execution); } + @Override public boolean isRestartable() { return true; @@ -215,7 +214,7 @@ public class JobStepTests { assertEquals(BatchStatus.STOPPED, stepExecution.getStatus()); } - + @Test public void testStepExecutionExitStatus() throws Exception { step.setJob(new JobSupport("child") { @@ -230,4 +229,5 @@ public class JobStepTests { step.execute(stepExecution); assertEquals("CUSTOM", stepExecution.getExitStatus().getExitCode()); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/skip/LimitCheckingItemSkipPolicyTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/skip/LimitCheckingItemSkipPolicyTests.java index d89bb315e..64345cfc4 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/skip/LimitCheckingItemSkipPolicyTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/skip/LimitCheckingItemSkipPolicyTests.java @@ -33,7 +33,7 @@ import org.springframework.batch.item.file.FlatFileParseException; /** * @author Lucas Ward * @author Dave Syer - * + * */ public class LimitCheckingItemSkipPolicyTests { @@ -51,7 +51,8 @@ public class LimitCheckingItemSkipPolicyTests { try { failurePolicy.shouldSkip(new FlatFileParseException("", ""), 2); fail(); - } catch (SkipLimitExceededException ex) { + } + catch (SkipLimitExceededException ex) { // expected } } @@ -75,7 +76,7 @@ public class LimitCheckingItemSkipPolicyTests { /** * condition: skippable < fatal; exception is unclassified - * + * * expected: false; default classification */ @Test @@ -85,7 +86,7 @@ public class LimitCheckingItemSkipPolicyTests { /** * condition: skippable < fatal; exception is skippable - * + * * expected: true */ @Test @@ -95,7 +96,7 @@ public class LimitCheckingItemSkipPolicyTests { /** * condition: skippable < fatal; exception is fatal - * + * * expected: false */ @Test @@ -112,7 +113,7 @@ public class LimitCheckingItemSkipPolicyTests { /** * condition: fatal < skippable; exception is unclassified - * + * * expected: false; default classification */ @Test @@ -122,7 +123,7 @@ public class LimitCheckingItemSkipPolicyTests { /** * condition: fatal < skippable; exception is skippable - * + * * expected: true */ @Test @@ -132,11 +133,12 @@ public class LimitCheckingItemSkipPolicyTests { /** * condition: fatal < skippable; exception is fatal - * + * * expected: false */ @Test public void testFatalSubset_fatal() { assertFalse(getFatalSubsetSkipPolicy().shouldSkip(new WriteFailedException(""), 0)); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/skip/NonSkippableReadExceptionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/skip/NonSkippableReadExceptionTests.java index 6f0dd531d..d7e0e5f76 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/skip/NonSkippableReadExceptionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/skip/NonSkippableReadExceptionTests.java @@ -17,15 +17,18 @@ package org.springframework.batch.core.step.skip; import org.springframework.batch.core.AbstractExceptionWithCauseTests; - /** * @author Dave Syer * */ public class NonSkippableReadExceptionTests extends AbstractExceptionWithCauseTests { - /* (non-Javadoc) - * @see org.springframework.batch.core.listener.AbstractDoubleExceptionTests#getException(java.lang.String, java.lang.RuntimeException, java.lang.Throwable) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.core.listener.AbstractDoubleExceptionTests#getException( + * java.lang.String, java.lang.RuntimeException, java.lang.Throwable) */ @Override public Exception getException(String msg, Throwable e) throws Exception { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/skip/NonSkippableWriteExceptionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/skip/NonSkippableWriteExceptionTests.java index 1be5d29a0..4ec6c2cf9 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/skip/NonSkippableWriteExceptionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/skip/NonSkippableWriteExceptionTests.java @@ -17,15 +17,18 @@ package org.springframework.batch.core.step.skip; import org.springframework.batch.core.AbstractExceptionWithCauseTests; - /** * @author Dave Syer * */ public class NonSkippableWriteExceptionTests extends AbstractExceptionWithCauseTests { - /* (non-Javadoc) - * @see org.springframework.batch.core.listener.AbstractDoubleExceptionTests#getException(java.lang.String, java.lang.RuntimeException, java.lang.Throwable) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.core.listener.AbstractDoubleExceptionTests#getException( + * java.lang.String, java.lang.RuntimeException, java.lang.Throwable) */ @Override public Exception getException(String msg, Throwable e) throws Exception { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/skip/ReprocessExceptionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/skip/ReprocessExceptionTests.java index 074ac5a1e..7189d2401 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/skip/ReprocessExceptionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/skip/ReprocessExceptionTests.java @@ -74,9 +74,11 @@ public class ReprocessExceptionTests { return transformedPerson; } + } public static class PersonItemWriter implements ItemWriter { + @Override public void write(List persons) throws Exception { for (Person person : persons) { @@ -86,10 +88,13 @@ public class ReprocessExceptionTests { } } } + } public static class Person { + private String lastName; + private String firstName; public Person() { @@ -121,5 +126,7 @@ public class ReprocessExceptionTests { public String toString() { return "firstName: " + firstName + ", lastName: " + lastName; } + } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/skip/SkipListenerFailedExceptionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/skip/SkipListenerFailedExceptionTests.java index a8f86f9f3..29f8326c9 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/skip/SkipListenerFailedExceptionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/skip/SkipListenerFailedExceptionTests.java @@ -17,15 +17,18 @@ package org.springframework.batch.core.step.skip; import org.springframework.batch.core.listener.AbstractDoubleExceptionTests; - /** * @author Dave Syer * */ public class SkipListenerFailedExceptionTests extends AbstractDoubleExceptionTests { - /* (non-Javadoc) - * @see org.springframework.batch.core.listener.AbstractDoubleExceptionTests#getException(java.lang.String, java.lang.RuntimeException, java.lang.Throwable) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.core.listener.AbstractDoubleExceptionTests#getException( + * java.lang.String, java.lang.RuntimeException, java.lang.Throwable) */ @Override public Exception getException(String msg, RuntimeException cause, Throwable e) throws Exception { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/skip/SkipPolicyFailedExceptionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/skip/SkipPolicyFailedExceptionTests.java index 3b7545a01..f37562158 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/skip/SkipPolicyFailedExceptionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/skip/SkipPolicyFailedExceptionTests.java @@ -17,15 +17,18 @@ package org.springframework.batch.core.step.skip; import org.springframework.batch.core.listener.AbstractDoubleExceptionTests; - /** * @author Dave Syer * */ public class SkipPolicyFailedExceptionTests extends AbstractDoubleExceptionTests { - /* (non-Javadoc) - * @see org.springframework.batch.core.listener.AbstractDoubleExceptionTests#getException(java.lang.String, java.lang.RuntimeException, java.lang.Throwable) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.core.listener.AbstractDoubleExceptionTests#getException( + * java.lang.String, java.lang.RuntimeException, java.lang.Throwable) */ @Override public Exception getException(String msg, RuntimeException cause, Throwable e) throws Exception { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/AsyncChunkOrientedStepIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/AsyncChunkOrientedStepIntegrationTests.java index 1ec37dadb..6abaa5d92 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/AsyncChunkOrientedStepIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/AsyncChunkOrientedStepIntegrationTests.java @@ -124,13 +124,14 @@ public class AsyncChunkOrientedStepIntegrationTests { @Ignore public void testStatus() throws Exception { - step.setTasklet(new TestingChunkOrientedTasklet<>(getReader(new String[] { "a", "b", "c", "a", "b", "c", - "a", "b", "c", "a", "b", "c" }), new ItemWriter() { - @Override - public void write(List data) throws Exception { - written.addAll(data); - } - }, chunkOperations)); + step.setTasklet(new TestingChunkOrientedTasklet<>( + getReader(new String[] { "a", "b", "c", "a", "b", "c", "a", "b", "c", "a", "b", "c" }), + new ItemWriter() { + @Override + public void write(List data) throws Exception { + written.addAll(data); + } + }, chunkOperations)); final JobExecution jobExecution = jobRepository.createJobExecution(job.getName(), new JobParameters(Collections.singletonMap("run.id", new JobParameter(getClass().getName() + ".1")))); @@ -139,15 +140,17 @@ public class AsyncChunkOrientedStepIntegrationTests { jobRepository.add(stepExecution); step.execute(stepExecution); assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - // Need a transaction so one connection is enough to get job execution and its parameters + // Need a transaction so one connection is enough to get job execution and its + // parameters StepExecution lastStepExecution = new TransactionTemplate(transactionManager) - .execute(new TransactionCallback() { - @Override - public StepExecution doInTransaction(TransactionStatus status) { - return jobRepository.getLastStepExecution(jobExecution.getJobInstance(), step.getName()); - } - }); + .execute(new TransactionCallback() { + @Override + public StepExecution doInTransaction(TransactionStatus status) { + return jobRepository.getLastStepExecution(jobExecution.getJobInstance(), step.getName()); + } + }); assertEquals(lastStepExecution, stepExecution); assertFalse(lastStepExecution == stepExecution); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/AsyncTaskletStepTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/AsyncTaskletStepTests.java index a422a7199..c1a93773d 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/AsyncTaskletStepTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/AsyncTaskletStepTests.java @@ -104,7 +104,7 @@ public class AsyncTaskletStepTests { @Override public void update(ExecutionContext executionContext) { - super.update(executionContext); + super.update(executionContext); executionContext.putInt("counter", count++); } }); @@ -128,8 +128,8 @@ public class AsyncTaskletStepTests { step.execute(stepExecution); assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); -// assertEquals(25, stepExecution.getReadCount()); -// assertEquals(25, processed.size()); + // assertEquals(25, stepExecution.getReadCount()); + // assertEquals(25, processed.size()); assertTrue(stepExecution.getReadCount() >= 25); assertTrue(processed.size() >= 25); @@ -179,7 +179,7 @@ public class AsyncTaskletStepTests { @Nullable @Override public String process(String item) throws Exception { - logger.info("Item: "+item); + logger.info("Item: " + item); processed.add(item); if (item.equals("barf")) { throw new RuntimeException("Planned processor error"); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/CallableTaskletAdapterTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/CallableTaskletAdapterTests.java index 8164de2e7..af4cda610 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/CallableTaskletAdapterTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/CallableTaskletAdapterTests.java @@ -35,7 +35,7 @@ public class CallableTaskletAdapterTests { return RepeatStatus.FINISHED; } }); - assertEquals(RepeatStatus.FINISHED, adapter.execute(null,null)); + assertEquals(RepeatStatus.FINISHED, adapter.execute(null, null)); } @Test diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/ChunkOrientedStepIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/ChunkOrientedStepIntegrationTests.java index 856646deb..8cb116b27 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/ChunkOrientedStepIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/ChunkOrientedStepIntegrationTests.java @@ -91,18 +91,16 @@ public class ChunkOrientedStepIntegrationTests { @Ignore public void testStatusForCommitFailedException() throws Exception { - step.setTasklet(new TestingChunkOrientedTasklet<>( - getReader(new String[]{"a", "b", "c"}), + step.setTasklet(new TestingChunkOrientedTasklet<>(getReader(new String[] { "a", "b", "c" }), data -> TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { @Override public void beforeCommit(boolean readOnly) { throw new RuntimeException("Simulate commit failure"); } - }), - chunkOperations)); + }), chunkOperations)); - JobExecution jobExecution = jobRepository.createJobExecution(job.getName(), new JobParameters(Collections - .singletonMap("run.id", new JobParameter(getClass().getName() + ".1")))); + JobExecution jobExecution = jobRepository.createJobExecution(job.getName(), + new JobParameters(Collections.singletonMap("run.id", new JobParameter(getClass().getName() + ".1")))); StepExecution stepExecution = new StepExecution(step.getName(), jobExecution); stepExecution.setExecutionContext(new ExecutionContext() { @@ -115,8 +113,8 @@ public class ChunkOrientedStepIntegrationTests { step.execute(stepExecution); // Exception on commit is not necessarily fatal: it should fail and rollback assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); - StepExecution lastStepExecution = jobRepository.getLastStepExecution(jobExecution.getJobInstance(), step - .getName()); + StepExecution lastStepExecution = jobRepository.getLastStepExecution(jobExecution.getJobInstance(), + step.getName()); assertEquals(lastStepExecution, stepExecution); assertFalse(lastStepExecution == stepExecution); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/ConfigurableSystemProcessExitCodeMapperTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/ConfigurableSystemProcessExitCodeMapperTests.java index 55d3cf420..51ac0d44e 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/ConfigurableSystemProcessExitCodeMapperTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/ConfigurableSystemProcessExitCodeMapperTests.java @@ -1,87 +1,88 @@ -/* - * Copyright 2008-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.step.tasklet; - -import static org.junit.Assert.assertSame; -import static org.junit.Assert.fail; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import org.junit.Test; -import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.step.tasklet.ConfigurableSystemProcessExitCodeMapper; - -/** - * Tests for {@link ConfigurableSystemProcessExitCodeMapper} - */ -public class ConfigurableSystemProcessExitCodeMapperTests { - - private ConfigurableSystemProcessExitCodeMapper mapper = new ConfigurableSystemProcessExitCodeMapper(); - - /** - * Regular usage scenario - mapping adheres to injected values - */ - @Test - public void testMapping() { - @SuppressWarnings("serial") - Map mappings = new HashMap() { - { - put(0, ExitStatus.COMPLETED); - put(1, ExitStatus.FAILED); - put(2, ExitStatus.EXECUTING); - put(3, ExitStatus.NOOP); - put(4, ExitStatus.UNKNOWN); - put(ConfigurableSystemProcessExitCodeMapper.ELSE_KEY, ExitStatus.UNKNOWN); - } - }; - - mapper.setMappings(mappings); - - // check explicitly defined values - for (Map.Entry entry : mappings.entrySet()) { - if (entry.getKey().equals(ConfigurableSystemProcessExitCodeMapper.ELSE_KEY)) - continue; - - int exitCode = (Integer) entry.getKey(); - assertSame(entry.getValue(), mapper.getExitStatus(exitCode)); - } - - // check the else clause - assertSame(mappings.get(ConfigurableSystemProcessExitCodeMapper.ELSE_KEY), mapper.getExitStatus(5)); - } - - /** - * Else clause is required in the injected map - setter checks its presence. - */ - @Test - public void testSetMappingsMissingElseClause() { - Map missingElse = new HashMap<>(); - try { - mapper.setMappings(missingElse); - fail(); - } - catch (IllegalArgumentException e) { - // expected - } - - Map containsElse = Collections. singletonMap( - ConfigurableSystemProcessExitCodeMapper.ELSE_KEY, ExitStatus.FAILED); - // no error expected now - mapper.setMappings(containsElse); - } -} +/* + * Copyright 2008-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.step.tasklet; + +import static org.junit.Assert.assertSame; +import static org.junit.Assert.fail; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.junit.Test; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.step.tasklet.ConfigurableSystemProcessExitCodeMapper; + +/** + * Tests for {@link ConfigurableSystemProcessExitCodeMapper} + */ +public class ConfigurableSystemProcessExitCodeMapperTests { + + private ConfigurableSystemProcessExitCodeMapper mapper = new ConfigurableSystemProcessExitCodeMapper(); + + /** + * Regular usage scenario - mapping adheres to injected values + */ + @Test + public void testMapping() { + @SuppressWarnings("serial") + Map mappings = new HashMap() { + { + put(0, ExitStatus.COMPLETED); + put(1, ExitStatus.FAILED); + put(2, ExitStatus.EXECUTING); + put(3, ExitStatus.NOOP); + put(4, ExitStatus.UNKNOWN); + put(ConfigurableSystemProcessExitCodeMapper.ELSE_KEY, ExitStatus.UNKNOWN); + } + }; + + mapper.setMappings(mappings); + + // check explicitly defined values + for (Map.Entry entry : mappings.entrySet()) { + if (entry.getKey().equals(ConfigurableSystemProcessExitCodeMapper.ELSE_KEY)) + continue; + + int exitCode = (Integer) entry.getKey(); + assertSame(entry.getValue(), mapper.getExitStatus(exitCode)); + } + + // check the else clause + assertSame(mappings.get(ConfigurableSystemProcessExitCodeMapper.ELSE_KEY), mapper.getExitStatus(5)); + } + + /** + * Else clause is required in the injected map - setter checks its presence. + */ + @Test + public void testSetMappingsMissingElseClause() { + Map missingElse = new HashMap<>(); + try { + mapper.setMappings(missingElse); + fail(); + } + catch (IllegalArgumentException e) { + // expected + } + + Map containsElse = Collections + .singletonMap(ConfigurableSystemProcessExitCodeMapper.ELSE_KEY, ExitStatus.FAILED); + // no error expected now + mapper.setMappings(containsElse); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/MethodInvokingTaskletAdapterTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/MethodInvokingTaskletAdapterTests.java index 4f560296d..2942b9aab 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/MethodInvokingTaskletAdapterTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/MethodInvokingTaskletAdapterTests.java @@ -32,8 +32,11 @@ import static org.mockito.Mockito.mock; public class MethodInvokingTaskletAdapterTests { private StepContribution stepContribution; + private ChunkContext chunkContext; + private TestTasklet tasklet; + private MethodInvokingTaskletAdapter adapter; @Before @@ -147,20 +150,17 @@ public class MethodInvokingTaskletAdapterTests { } /* - - - - If the tasklet is specified as a bean definition, then a method can be - specified and a POJO will be adapted to the Tasklet interface. - The method suggested should have the same arguments as Tasklet.execute - (or a subset), and have a compatible return type (boolean, void or RepeatStatus). - - - - */ + * + * If the tasklet is specified as a bean definition, then a method + * can be specified and a POJO will be adapted to the Tasklet interface. The method + * suggested should have the same arguments as Tasklet.execute (or a subset), and have + * a compatible return type (boolean, void or RepeatStatus). + * + */ public static class TestTasklet { private StepContribution stepContribution; + private ChunkContext chunkContext; /* exactly same signature */ @@ -214,7 +214,10 @@ public class MethodInvokingTaskletAdapterTests { this.chunkContext = chunkContext; } - /* subset of arguments (only step contribution) and compatible return type (boolean) */ + /* + * subset of arguments (only step contribution) and compatible return type + * (boolean) + */ public boolean execute8(StepContribution stepContribution) throws Exception { this.stepContribution = stepContribution; return true; @@ -225,8 +228,11 @@ public class MethodInvokingTaskletAdapterTests { this.chunkContext = chunkContext; } - /* Incorrect signature: extra parameter (ie a superset not a subset as specified) */ - public RepeatStatus execute10(StepContribution stepContribution, ChunkContext chunkContext, String string) throws Exception { + /* + * Incorrect signature: extra parameter (ie a superset not a subset as specified) + */ + public RepeatStatus execute10(StepContribution stepContribution, ChunkContext chunkContext, String string) + throws Exception { this.stepContribution = stepContribution; this.chunkContext = chunkContext; return RepeatStatus.FINISHED; @@ -253,6 +259,7 @@ public class MethodInvokingTaskletAdapterTests { public ChunkContext getChunkContext() { return chunkContext; } - } -} + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/SimpleSystemProcessExitCodeMapperTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/SimpleSystemProcessExitCodeMapperTests.java index 3d8808002..66d0edf56 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/SimpleSystemProcessExitCodeMapperTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/SimpleSystemProcessExitCodeMapperTests.java @@ -1,41 +1,41 @@ -/* - * Copyright 2008-2009 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.step.tasklet; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; -import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.step.tasklet.SimpleSystemProcessExitCodeMapper; - -/** - * Tests for {@link SimpleSystemProcessExitCodeMapper}. - */ -public class SimpleSystemProcessExitCodeMapperTests { - - private SimpleSystemProcessExitCodeMapper mapper = new SimpleSystemProcessExitCodeMapper(); - - /** - * 0 -> ExitStatus.FINISHED - * else -> ExitStatus.FAILED - */ - @Test - public void testMapping() { - assertEquals(ExitStatus.COMPLETED, mapper.getExitStatus(0)); - assertEquals(ExitStatus.FAILED, mapper.getExitStatus(1)); - assertEquals(ExitStatus.FAILED, mapper.getExitStatus(-1)); - } -} +/* + * Copyright 2008-2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.step.tasklet; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.step.tasklet.SimpleSystemProcessExitCodeMapper; + +/** + * Tests for {@link SimpleSystemProcessExitCodeMapper}. + */ +public class SimpleSystemProcessExitCodeMapperTests { + + private SimpleSystemProcessExitCodeMapper mapper = new SimpleSystemProcessExitCodeMapper(); + + /** + * 0 -> ExitStatus.FINISHED else -> ExitStatus.FAILED + */ + @Test + public void testMapping() { + assertEquals(ExitStatus.COMPLETED, mapper.getExitStatus(0)); + assertEquals(ExitStatus.FAILED, mapper.getExitStatus(1)); + assertEquals(ExitStatus.FAILED, mapper.getExitStatus(-1)); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/StepExecutorInterruptionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/StepExecutorInterruptionTests.java index 2a77101ef..7a15967d8 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/StepExecutorInterruptionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/StepExecutorInterruptionTests.java @@ -67,9 +67,7 @@ public class StepExecutorInterruptionTests { public void setUp() throws Exception { EmbeddedDatabase embeddedDatabase = new EmbeddedDatabaseBuilder() .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("/org/springframework/batch/core/schema-hsqldb.sql") - .generateUniqueName(true) - .build(); + .addScript("/org/springframework/batch/core/schema-hsqldb.sql").generateUniqueName(true).build(); this.transactionManager = new DataSourceTransactionManager(embeddedDatabase); JobRepositoryFactoryBean repositoryFactoryBean = new JobRepositoryFactoryBean(); repositoryFactoryBean.setDataSource(embeddedDatabase); @@ -78,8 +76,8 @@ public class StepExecutorInterruptionTests { jobRepository = repositoryFactoryBean.getObject(); } - private void configureStep(TaskletStep step) throws JobExecutionAlreadyRunningException, JobRestartException, - JobInstanceAlreadyCompleteException { + private void configureStep(TaskletStep step) + throws JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException { this.step = step; JobSupport job = new JobSupport(); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/StepHandlerAdapterTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/StepHandlerAdapterTests.java index 6d32e01ba..4a82225f9 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/StepHandlerAdapterTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/StepHandlerAdapterTests.java @@ -33,17 +33,18 @@ import org.springframework.batch.core.StepExecution; public class StepHandlerAdapterTests { private MethodInvokingTaskletAdapter tasklet = new MethodInvokingTaskletAdapter(); + private Object result = null; - private StepExecution stepExecution = new StepExecution("systemCommandStep", new JobExecution(new JobInstance(1L, - "systemCommandJob"), new JobParameters())); + private StepExecution stepExecution = new StepExecution("systemCommandStep", + new JobExecution(new JobInstance(1L, "systemCommandJob"), new JobParameters())); public ExitStatus execute() { return ExitStatus.NOOP; } public Object process() { - return result ; + return result; } @Before @@ -55,7 +56,7 @@ public class StepHandlerAdapterTests { public void testExecuteWithExitStatus() throws Exception { tasklet.setTargetMethod("execute"); StepContribution contribution = stepExecution.createStepContribution(); - tasklet.execute(contribution,null); + tasklet.execute(contribution, null); assertEquals(ExitStatus.NOOP, contribution.getExitStatus()); } @@ -63,7 +64,7 @@ public class StepHandlerAdapterTests { public void testMapResultWithNull() throws Exception { tasklet.setTargetMethod("process"); StepContribution contribution = stepExecution.createStepContribution(); - tasklet.execute(contribution,null); + tasklet.execute(contribution, null); assertEquals(ExitStatus.COMPLETED, contribution.getExitStatus()); } @@ -72,7 +73,7 @@ public class StepHandlerAdapterTests { tasklet.setTargetMethod("process"); this.result = "foo"; StepContribution contribution = stepExecution.createStepContribution(); - tasklet.execute(contribution,null); + tasklet.execute(contribution, null); assertEquals(ExitStatus.COMPLETED, contribution.getExitStatus()); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/SystemCommandTaskletIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/SystemCommandTaskletIntegrationTests.java index 85c2ac6ae..9f728012c 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/SystemCommandTaskletIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/SystemCommandTaskletIntegrationTests.java @@ -57,8 +57,8 @@ public class SystemCommandTaskletIntegrationTests { private SystemCommandTasklet tasklet; - private StepExecution stepExecution = new StepExecution("systemCommandStep", new JobExecution(new JobInstance(1L, - "systemCommandJob"), 1L, new JobParameters())); + private StepExecution stepExecution = new StepExecution("systemCommandStep", + new JobExecution(new JobInstance(1L, "systemCommandJob"), 1L, new JobParameters())); @Mock private JobExplorer jobExplorer; @@ -139,9 +139,7 @@ public class SystemCommandTaskletIntegrationTests { */ @Test public void testExecuteTimeout() throws Exception { - String command = isRunningOnWindows() ? - "ping 127.0.0.1" : - "sleep 3"; + String command = isRunningOnWindows() ? "ping 127.0.0.1" : "sleep 3"; tasklet.setCommand(command); tasklet.setTimeout(10); tasklet.afterPropertiesSet(); @@ -161,9 +159,7 @@ public class SystemCommandTaskletIntegrationTests { */ @Test public void testInterruption() throws Exception { - String command = isRunningOnWindows() ? - "ping 127.0.0.1" : - "sleep 5"; + String command = isRunningOnWindows() ? "ping 127.0.0.1" : "sleep 5"; tasklet.setCommand(command); tasklet.setTerminationCheckInterval(10); tasklet.afterPropertiesSet(); @@ -221,8 +217,8 @@ public class SystemCommandTaskletIntegrationTests { } /* - * Working directory property must point to an existing location and it must - * be a directory + * Working directory property must point to an existing location and it must be a + * directory */ @Test public void testWorkingDirectory() throws Exception { @@ -270,11 +266,10 @@ public class SystemCommandTaskletIntegrationTests { JobExecution stoppedJobExecution = new JobExecution(stepExecution.getJobExecution()); stoppedJobExecution.setStatus(BatchStatus.STOPPING); - when(jobExplorer.getJobExecution(1L)).thenReturn(stepExecution.getJobExecution(), stepExecution.getJobExecution(), stoppedJobExecution); + when(jobExplorer.getJobExecution(1L)).thenReturn(stepExecution.getJobExecution(), + stepExecution.getJobExecution(), stoppedJobExecution); - String command = isRunningOnWindows() ? - "ping 127.0.0.1 -n 5" : - "sleep 15"; + String command = isRunningOnWindows() ? "ping 127.0.0.1 -n 5" : "sleep 15"; tasklet.setCommand(command); tasklet.setTerminationCheckInterval(10); tasklet.afterPropertiesSet(); @@ -297,7 +292,7 @@ public class SystemCommandTaskletIntegrationTests { command.append(fileSeparator); command.append("java"); - if(isRunningOnWindows()) { + if (isRunningOnWindows()) { command.append(".exe"); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/TaskletStepTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/TaskletStepTests.java index f58370142..f1592d1ef 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/TaskletStepTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/TaskletStepTests.java @@ -154,7 +154,8 @@ public class TaskletStepTests { assertEquals(4, processed.size()); assertEquals(4, stepExecution.getReadCount()); assertEquals(4, stepExecution.getWriteCount()); - assertEquals(3, stepExecution.getCommitCount()); //the empty chunk is the 3rd commit + assertEquals(3, stepExecution.getCommitCount()); // the empty chunk is the 3rd + // commit } @Test @@ -175,8 +176,7 @@ public class TaskletStepTests { JobExecution jobExecutionContext = new JobExecution(jobInstance, jobParameters); StepExecution stepExecution = new StepExecution(step.getName(), jobExecutionContext); step = getStep(new String[0]); - step.setTasklet(new TestingChunkOrientedTasklet<>(getReader(new String[0]), itemWriter, - new RepeatTemplate())); + step.setTasklet(new TestingChunkOrientedTasklet<>(getReader(new String[0]), itemWriter, new RepeatTemplate())); step.setStepOperations(new RepeatTemplate()); step.execute(stepExecution); assertEquals(0, processed.size()); @@ -230,8 +230,7 @@ public class TaskletStepTests { public void testRepository() throws Exception { EmbeddedDatabase embeddedDatabase = new EmbeddedDatabaseBuilder() .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("/org/springframework/batch/core/schema-hsqldb.sql") - .build(); + .addScript("/org/springframework/batch/core/schema-hsqldb.sql").build(); DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(embeddedDatabase); JobRepositoryFactoryBean repositoryFactoryBean = new JobRepositoryFactoryBean(); repositoryFactoryBean.setDataSource(embeddedDatabase); @@ -396,9 +395,8 @@ public class TaskletStepTests { } /* - * Test that a job that is being restarted, but has saveExecutionAttributes - * set to false, doesn't have restore or getExecutionAttributes called on - * it. + * Test that a job that is being restarted, but has saveExecutionAttributes set to + * false, doesn't have restore or getExecutionAttributes called on it. */ @Test public void testNoSaveExecutionAttributesRestartableJob() { @@ -418,9 +416,8 @@ public class TaskletStepTests { } /* - * Even though the job is restarted, and saveExecutionAttributes is true, - * nothing will be restored because the Tasklet does not implement - * Restartable. + * Even though the job is restarted, and saveExecutionAttributes is true, nothing will + * be restored because the Tasklet does not implement Restartable. */ @Test public void testRestartJobOnNonRestartableTasklet() throws Exception { @@ -448,7 +445,7 @@ public class TaskletStepTests { @Override public void update(ExecutionContext executionContext) { - super.update(executionContext); + super.update(executionContext); executionContext.putString("foo", "bar"); } }; @@ -471,7 +468,7 @@ public class TaskletStepTests { step.setStreams(new ItemStream[] { new ItemStreamSupport() { @Override public void update(ExecutionContext executionContext) { - super.update(executionContext); + super.update(executionContext); executionContext.putString("foo", "bar"); } } }); @@ -516,7 +513,7 @@ public class TaskletStepTests { @Override public void open(ExecutionContext executionContext) throws ItemStreamException { - super.open(executionContext); + super.open(executionContext); assertEquals(1, list.size()); } }; @@ -589,7 +586,7 @@ public class TaskletStepTests { @Override public void update(ExecutionContext executionContext) { - super.update(executionContext); + super.update(executionContext); executionContext.putString("foo", "bar"); } }; @@ -641,8 +638,8 @@ public class TaskletStepTests { step.execute(stepExecution); assertEquals(BatchStatus.STOPPED, stepExecution.getStatus()); String msg = stepExecution.getExitStatus().getExitDescription(); - assertTrue("Message does not contain 'JobInterruptedException': " + msg, msg - .contains("JobInterruptedException")); + assertTrue("Message does not contain 'JobInterruptedException': " + msg, + msg.contains("JobInterruptedException")); } @Test @@ -740,6 +737,7 @@ public class TaskletStepTests { // Simulate failure on commit throw new RuntimeException("Foo"); } + @Override protected void doRollback(DefaultTransactionStatus status) throws TransactionException { throw new RuntimeException("Bar"); @@ -766,7 +764,7 @@ public class TaskletStepTests { step.setStreams(new ItemStream[] { new ItemStreamSupport() { @Override public void close() throws ItemStreamException { - super.close(); + super.close(); throw new RuntimeException("Bar"); } } }); @@ -816,9 +814,8 @@ public class TaskletStepTests { } /** - * Execution context must not be left empty even if job failed before - * committing first chunk - otherwise ItemStreams won't recognize it is - * restart scenario on next run. + * Execution context must not be left empty even if job failed before committing first + * chunk - otherwise ItemStreams won't recognize it is restart scenario on next run. */ @Test public void testRestartAfterFailureInFirstChunk() throws Exception { @@ -861,8 +858,8 @@ public class TaskletStepTests { } /** - * Exception in {@link StepExecutionListener#afterStep(StepExecution)} - * doesn't cause step failure. + * Exception in {@link StepExecutionListener#afterStep(StepExecution)} doesn't cause + * step failure. * @throws JobInterruptedException */ @Test @@ -949,9 +946,11 @@ public class TaskletStepTests { throw new DataAccessResourceFailureException("stub exception"); } } + } - private class MockRestartableItemReader extends AbstractItemStreamItemReader implements StepExecutionListener { + private class MockRestartableItemReader extends AbstractItemStreamItemReader + implements StepExecutionListener { private boolean getExecutionAttributesCalled = false; @@ -965,7 +964,7 @@ public class TaskletStepTests { @Override public void update(ExecutionContext executionContext) { - super.update(executionContext); + super.update(executionContext); getExecutionAttributesCalled = true; executionContext.putString("spam", "bucket"); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/TaskletSupport.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/TaskletSupport.java index 6a608e337..60c4dcb4f 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/TaskletSupport.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/TaskletSupport.java @@ -24,9 +24,9 @@ public class TaskletSupport implements Tasklet { @Nullable @Override - public RepeatStatus execute(StepContribution contribution, - ChunkContext chunkContext) throws Exception { + public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { System.out.println("The tasklet was executed"); return RepeatStatus.FINISHED; } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/TestingChunkOrientedTasklet.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/TestingChunkOrientedTasklet.java index f19401ca8..15306d671 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/TestingChunkOrientedTasklet.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/TestingChunkOrientedTasklet.java @@ -27,10 +27,10 @@ import org.springframework.batch.repeat.policy.SimpleCompletionPolicy; import org.springframework.batch.repeat.support.RepeatTemplate; /** - * Simplest possible implementation of {@link Tasklet} with no skipping or - * recovering or processing. Just delegates all calls to the provided - * {@link ItemReader} and {@link ItemWriter}. - * + * Simplest possible implementation of {@link Tasklet} with no skipping or recovering or + * processing. Just delegates all calls to the provided {@link ItemReader} and + * {@link ItemWriter}. + * * @author Dave Syer */ public class TestingChunkOrientedTasklet extends ChunkOrientedTasklet { @@ -43,26 +43,26 @@ public class TestingChunkOrientedTasklet extends ChunkOrientedTasklet { } /** - * Creates a {@link PassThroughItemProcessor} and uses it to create an - * instance of {@link Tasklet}. + * Creates a {@link PassThroughItemProcessor} and uses it to create an instance of + * {@link Tasklet}. */ public TestingChunkOrientedTasklet(ItemReader itemReader, ItemWriter itemWriter) { this(itemReader, itemWriter, repeatTemplate); } /** - * Creates a {@link PassThroughItemProcessor} and uses it to create an - * instance of {@link Tasklet}. + * Creates a {@link PassThroughItemProcessor} and uses it to create an instance of + * {@link Tasklet}. */ - public TestingChunkOrientedTasklet(ItemReader itemReader, ItemProcessor itemProcessor, ItemWriter itemWriter, - RepeatOperations repeatOperations) { - super(new SimpleChunkProvider<>(itemReader, repeatOperations), new SimpleChunkProcessor<>( - itemProcessor, itemWriter)); + public TestingChunkOrientedTasklet(ItemReader itemReader, ItemProcessor itemProcessor, + ItemWriter itemWriter, RepeatOperations repeatOperations) { + super(new SimpleChunkProvider<>(itemReader, repeatOperations), + new SimpleChunkProcessor<>(itemProcessor, itemWriter)); } /** - * Creates a {@link PassThroughItemProcessor} and uses it to create an - * instance of {@link Tasklet}. + * Creates a {@link PassThroughItemProcessor} and uses it to create an instance of + * {@link Tasklet}. */ public TestingChunkOrientedTasklet(ItemReader itemReader, ItemWriter itemWriter, RepeatOperations repeatOperations) { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/concurrent/ConcurrentTransactionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/concurrent/ConcurrentTransactionTests.java index e137ee54d..726b22dff 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/concurrent/ConcurrentTransactionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/concurrent/ConcurrentTransactionTests.java @@ -108,63 +108,52 @@ public class ConcurrentTransactionTests { @Bean public Flow flow() { - return new FlowBuilder("flow") - .start(stepBuilderFactory.get("flow.step1") - .tasklet(new Tasklet() { - @Nullable - @Override - public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { - return RepeatStatus.FINISHED; - } - }).build() - ).next(stepBuilderFactory.get("flow.step2") - .tasklet(new Tasklet() { - @Nullable - @Override - public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { - return RepeatStatus.FINISHED; - } - }).build() - ).build(); + return new FlowBuilder("flow").start(stepBuilderFactory.get("flow.step1").tasklet(new Tasklet() { + @Nullable + @Override + public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { + return RepeatStatus.FINISHED; + } + }).build()).next(stepBuilderFactory.get("flow.step2").tasklet(new Tasklet() { + @Nullable + @Override + public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { + return RepeatStatus.FINISHED; + } + }).build()).build(); } @Bean public Step firstStep() { - return stepBuilderFactory.get("firstStep") - .tasklet(new Tasklet() { - @Nullable - @Override - public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { - System.out.println(">> Beginning concurrent job test"); - return RepeatStatus.FINISHED; - } - }).build(); + return stepBuilderFactory.get("firstStep").tasklet(new Tasklet() { + @Nullable + @Override + public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { + System.out.println(">> Beginning concurrent job test"); + return RepeatStatus.FINISHED; + } + }).build(); } @Bean public Step lastStep() { - return stepBuilderFactory.get("lastStep") - .tasklet(new Tasklet() { - @Nullable - @Override - public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { - System.out.println(">> Ending concurrent job test"); - return RepeatStatus.FINISHED; - } - }).build(); + return stepBuilderFactory.get("lastStep").tasklet(new Tasklet() { + @Nullable + @Override + public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { + System.out.println(">> Ending concurrent job test"); + return RepeatStatus.FINISHED; + } + }).build(); } @Bean public Job concurrentJob() { - Flow splitFlow = new FlowBuilder("splitflow").split(new SimpleAsyncTaskExecutor()).add(flow(), flow(), flow(), flow(), flow(), flow(), flow()).build(); + Flow splitFlow = new FlowBuilder("splitflow").split(new SimpleAsyncTaskExecutor()) + .add(flow(), flow(), flow(), flow(), flow(), flow(), flow()).build(); - return jobBuilderFactory.get("concurrentJob") - .start(firstStep()) - .next(stepBuilderFactory.get("splitFlowStep") - .flow(splitFlow) - .build()) - .next(lastStep()) - .build(); + return jobBuilderFactory.get("concurrentJob").start(firstStep()) + .next(stepBuilderFactory.get("splitFlowStep").flow(splitFlow).build()).next(lastStep()).build(); } @Override @@ -174,22 +163,23 @@ public class ConcurrentTransactionTests { factory.setIsolationLevelForCreate(Isolation.READ_COMMITTED); factory.setTransactionManager(getTransactionManager()); factory.afterPropertiesSet(); - return factory.getObject(); + return factory.getObject(); } + } @Configuration static class DataSourceConfiguration { + /** - * This datasource configuration configures the HSQLDB instance using MVCC. When + * This datasource configuration configures the HSQLDB instance using MVCC. When * configured using the default behavior, transaction serialization errors are * thrown (default configuration example below). * - * return new PooledEmbeddedDataSource(new EmbeddedDatabaseBuilder(). - * addScript("classpath:org/springframework/batch/core/schema-drop-hsqldb.sql"). - * addScript("classpath:org/springframework/batch/core/schema-hsqldb.sql"). - * build()); - + * return new PooledEmbeddedDataSource(new EmbeddedDatabaseBuilder(). + * addScript("classpath:org/springframework/batch/core/schema-drop-hsqldb.sql"). + * addScript("classpath:org/springframework/batch/core/schema-hsqldb.sql"). + * build()); * @return */ @Bean @@ -202,7 +192,8 @@ public class ConcurrentTransactionTests { @SuppressWarnings("unchecked") public void configureConnectionProperties(ConnectionProperties properties, String databaseName) { try { - properties.setDriverClass((Class) ClassUtils.forName("org.hsqldb.jdbcDriver", this.getClass().getClassLoader())); + properties.setDriverClass((Class) ClassUtils.forName("org.hsqldb.jdbcDriver", + this.getClass().getClassLoader())); } catch (Exception e) { e.printStackTrace(); @@ -225,12 +216,16 @@ public class ConcurrentTransactionTests { }); ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator(); - databasePopulator.addScript(defaultResourceLoader.getResource("classpath:org/springframework/batch/core/schema-drop-hsqldb.sql")); - databasePopulator.addScript(defaultResourceLoader.getResource("classpath:org/springframework/batch/core/schema-hsqldb.sql")); + databasePopulator.addScript(defaultResourceLoader + .getResource("classpath:org/springframework/batch/core/schema-drop-hsqldb.sql")); + databasePopulator.addScript( + defaultResourceLoader.getResource("classpath:org/springframework/batch/core/schema-hsqldb.sql")); embeddedDatabaseFactory.setDatabasePopulator(databasePopulator); embeddedDatabaseFactory.setGenerateUniqueDatabaseName(true); return embeddedDatabaseFactory.getDatabase(); } + } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/FootballJobIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/FootballJobIntegrationTests.java index a89f2edd9..bad61b3ac 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/FootballJobIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/FootballJobIntegrationTests.java @@ -38,10 +38,10 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * @author Dave Syer * @author Mahmoud Ben Hassine - * + * */ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = {"/simple-job-launcher-context.xml", "/META-INF/batch/footballJob.xml"}) +@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/META-INF/batch/footballJob.xml" }) public class FootballJobIntegrationTests extends AbstractIntegrationTests { /** Logger */ @@ -60,15 +60,14 @@ public class FootballJobIntegrationTests extends AbstractIntegrationTests { @Test public void testLaunchJob() throws Exception { - JobExecution execution = jobLauncher.run(job, new JobParametersBuilder().addLong("commit.interval", 10L) - .toJobParameters()); + JobExecution execution = jobLauncher.run(job, + new JobParametersBuilder().addLong("commit.interval", 10L).toJobParameters()); assertEquals(BatchStatus.COMPLETED, execution.getStatus()); for (StepExecution stepExecution : execution.getStepExecutions()) { logger.info("Processed: " + stepExecution); if (stepExecution.getStepName().equals("playerload")) { // The effect of the retries - assertEquals((int) Math.ceil(stepExecution.getReadCount() / 10. + 1), - stepExecution.getCommitCount()); + assertEquals((int) Math.ceil(stepExecution.getReadCount() / 10. + 1), stepExecution.getCommitCount()); } } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/FootballJobSkipIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/FootballJobSkipIntegrationTests.java index 7c39f5a58..de990f41c 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/FootballJobSkipIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/FootballJobSkipIntegrationTests.java @@ -40,10 +40,10 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * @author Dave Syer * @author Mahmoud Ben Hassine - * + * */ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = {"/simple-job-launcher-context.xml", "/META-INF/batch/footballSkipJob.xml"}) +@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/META-INF/batch/footballSkipJob.xml" }) public class FootballJobSkipIntegrationTests extends AbstractIntegrationTests { /** Logger */ @@ -72,14 +72,14 @@ public class FootballJobSkipIntegrationTests extends AbstractIntegrationTests { if (databaseType == DatabaseType.POSTGRES || databaseType == DatabaseType.ORACLE) { // Extra special test for these platforms (would have failed // the job with UNKNOWN status in Batch 2.0): - jdbcTemplate.update("SET CONSTRAINTS ALL DEFERRED"); + jdbcTemplate.update("SET CONSTRAINTS ALL DEFERRED"); } } catch (Exception e) { // Ignore (wrong platform) } - JobExecution execution = jobLauncher.run(job, new JobParametersBuilder().addLong("skip.limit", 0L) - .toJobParameters()); + JobExecution execution = jobLauncher.run(job, + new JobParametersBuilder().addLong("skip.limit", 0L).toJobParameters()); assertEquals(BatchStatus.COMPLETED, execution.getStatus()); for (StepExecution stepExecution : execution.getStepExecutions()) { logger.info("Processed: " + stepExecution); @@ -87,9 +87,8 @@ public class FootballJobSkipIntegrationTests extends AbstractIntegrationTests { // They all skip on the second execution because of a primary key // violation long retryLimit = 2L; - execution = jobLauncher.run(job, - new JobParametersBuilder().addLong("skip.limit", 100000L).addLong("retry.limit", retryLimit) - .toJobParameters()); + execution = jobLauncher.run(job, new JobParametersBuilder().addLong("skip.limit", 100000L) + .addLong("retry.limit", retryLimit).toJobParameters()); assertEquals(BatchStatus.COMPLETED, execution.getStatus()); for (StepExecution stepExecution : execution.getStepExecutions()) { logger.info("Processed: " + stepExecution); @@ -99,8 +98,8 @@ public class FootballJobSkipIntegrationTests extends AbstractIntegrationTests { long commitInterval = stepExecution.getReadCount() / (stepExecution.getCommitCount() - 1); // Account for the extra empty commit if the read count is // commensurate with the commit interval - long effectiveCommitCount = stepExecution.getReadCount() % commitInterval == 0 ? stepExecution - .getCommitCount() - 1 : stepExecution.getCommitCount(); + long effectiveCommitCount = stepExecution.getReadCount() % commitInterval == 0 + ? stepExecution.getCommitCount() - 1 : stepExecution.getCommitCount(); long expectedRollbacks = Math.max(1, retryLimit) * effectiveCommitCount + stepExecution.getReadCount(); assertEquals(expectedRollbacks, stepExecution.getRollbackCount()); assertEquals(stepExecution.getReadCount(), stepExecution.getWriteSkipCount()); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/ParallelJobIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/ParallelJobIntegrationTests.java index 0bddfcd6b..baabdf711 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/ParallelJobIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/ParallelJobIntegrationTests.java @@ -37,13 +37,12 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.jdbc.JdbcTestUtils; - /** * @author Dave Syer * */ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = {"/simple-job-launcher-context.xml", "/META-INF/batch/parallelJob.xml"}) +@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/META-INF/batch/parallelJob.xml" }) public class ParallelJobIntegrationTests { /** Logger */ @@ -51,17 +50,17 @@ public class ParallelJobIntegrationTests { @Autowired private JobLauncher jobLauncher; - + private JdbcTemplate jdbcTemplate; @Autowired private Job job; - + @Autowired public void setDataSource(DataSource dataSource) { this.jdbcTemplate = new JdbcTemplate(dataSource); } - + @Before public void clear() { JdbcTestUtils.deleteFromTables(jdbcTemplate, "PLAYER_SUMMARY", "GAMES", "PLAYERS"); @@ -72,7 +71,7 @@ public class ParallelJobIntegrationTests { JobExecution execution = jobLauncher.run(job, new JobParametersBuilder().toJobParameters()); assertEquals(BatchStatus.COMPLETED, execution.getStatus()); for (StepExecution stepExecution : execution.getStepExecutions()) { - logger.info("Processed: "+stepExecution); + logger.info("Processed: " + stepExecution); } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/domain/Player.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/domain/Player.java index 7184b09d3..3f382b0e5 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/domain/Player.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/domain/Player.java @@ -20,63 +20,72 @@ import java.io.Serializable; @SuppressWarnings("serial") public class Player implements Serializable { - - private String id; - private String lastName; - private String firstName; - private String position; - private int birthYear; + + private String id; + + private String lastName; + + private String firstName; + + private String position; + + private int birthYear; + private int debutYear; - + @Override public String toString() { - - return "PLAYER:id=" + id + ",Last Name=" + lastName + - ",First Name=" + firstName + ",Position=" + position + - ",Birth Year=" + birthYear + ",DebutYear=" + - debutYear; + + return "PLAYER:id=" + id + ",Last Name=" + lastName + ",First Name=" + firstName + ",Position=" + position + + ",Birth Year=" + birthYear + ",DebutYear=" + debutYear; } - + public String getId() { return id; } + public String getLastName() { return lastName; } + public String getFirstName() { return firstName; } + public String getPosition() { return position; } + public int getBirthYear() { return birthYear; } + public int getDebutYear() { return debutYear; } + public void setId(String id) { this.id = id; } + public void setLastName(String lastName) { this.lastName = lastName; } + public void setFirstName(String firstName) { this.firstName = firstName; } + public void setPosition(String position) { this.position = position; } + public void setBirthYear(int birthYear) { this.birthYear = birthYear; } + public void setDebutYear(int debutYear) { this.debutYear = debutYear; } - - - - - } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/domain/PlayerDao.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/domain/PlayerDao.java index 6547abb3d..be8e05b28 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/domain/PlayerDao.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/domain/PlayerDao.java @@ -16,11 +16,11 @@ package org.springframework.batch.core.test.football.domain; - /** * Interface for writing {@link Player} objects to arbitrary output. */ public interface PlayerDao { void savePlayer(Player player); + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/domain/PlayerSummary.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/domain/PlayerSummary.java index 3b8893b62..177e58efc 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/domain/PlayerSummary.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/domain/PlayerSummary.java @@ -16,109 +16,141 @@ package org.springframework.batch.core.test.football.domain; - /** - * Domain object representing the summary of a given Player's - * year. - * + * Domain object representing the summary of a given Player's year. + * * @author Lucas Ward * */ public class PlayerSummary { private String id; + private int year; + private int completes; + private int attempts; + private int passingYards; + private int passingTd; + private int interceptions; + private int rushes; + private int rushYards; + private int receptions; + private int receptionYards; + private int totalTd; - + public String getId() { return id; } + public void setId(String id) { this.id = id; } + public int getYear() { return year; } + public void setYear(int year) { this.year = year; } + public int getCompletes() { return completes; } + public void setCompletes(int completes) { this.completes = completes; } + public int getAttempts() { return attempts; } + public void setAttempts(int attempts) { this.attempts = attempts; } + public int getPassingYards() { return passingYards; } + public void setPassingYards(int passingYards) { this.passingYards = passingYards; } + public int getPassingTd() { return passingTd; } + public void setPassingTd(int passingTd) { this.passingTd = passingTd; } + public int getInterceptions() { return interceptions; } + public void setInterceptions(int interceptions) { this.interceptions = interceptions; } + public int getRushes() { return rushes; } + public void setRushes(int rushes) { this.rushes = rushes; } + public int getRushYards() { return rushYards; } + public void setRushYards(int rushYards) { this.rushYards = rushYards; } + public int getReceptions() { return receptions; } + public void setReceptions(int receptions) { this.receptions = receptions; } + public int getReceptionYards() { return receptionYards; } + public void setReceptionYards(int receptionYards) { this.receptionYards = receptionYards; } + public int getTotalTd() { return totalTd; } + public void setTotalTd(int totalTd) { this.totalTd = totalTd; } - - + @Override public String toString() { - return "Player Summary: ID=" + id + " Year=" + year + "[" + completes + ";" + attempts + ";" + passingYards + - ";" + passingTd + ";" + interceptions + ";" + rushes + ";" + rushYards + ";" + receptions + - ";" + receptionYards + ";" + totalTd; + return "Player Summary: ID=" + id + " Year=" + year + "[" + completes + ";" + attempts + ";" + passingYards + + ";" + passingTd + ";" + interceptions + ";" + rushes + ";" + rushYards + ";" + receptions + ";" + + receptionYards + ";" + totalTd; } + @Override public int hashCode() { final int prime = 31; @@ -126,6 +158,7 @@ public class PlayerSummary { result = prime * result + ((id == null) ? 0 : id.hashCode()); return result; } + @Override public boolean equals(Object obj) { if (this == obj) @@ -143,5 +176,5 @@ public class PlayerSummary { return false; return true; } - + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/internal/FootballExceptionHandler.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/internal/FootballExceptionHandler.java index 4635aaba7..46ae19c12 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/internal/FootballExceptionHandler.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/internal/FootballExceptionHandler.java @@ -23,16 +23,15 @@ import org.springframework.batch.repeat.exception.ExceptionHandler; public class FootballExceptionHandler implements ExceptionHandler { - private static final Log logger = LogFactory - .getLog(FootballExceptionHandler.class); + private static final Log logger = LogFactory.getLog(FootballExceptionHandler.class); @Override - public void handleException(RepeatContext context, Throwable throwable) - throws Throwable { + public void handleException(RepeatContext context, Throwable throwable) throws Throwable { if (!(throwable instanceof NumberFormatException)) { throw throwable; - } else { + } + else { logger.error("Number Format Exception!", throwable); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/internal/GameFieldSetMapper.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/internal/GameFieldSetMapper.java index 9628d6a2a..40de74f66 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/internal/GameFieldSetMapper.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/internal/GameFieldSetMapper.java @@ -24,11 +24,11 @@ public class GameFieldSetMapper implements FieldSetMapper { @Override public Game mapFieldSet(FieldSet fs) { - - if(fs == null){ + + if (fs == null) { return null; } - + Game game = new Game(); game.setId(fs.readString("id")); game.setYear(fs.readInt("year")); @@ -45,7 +45,7 @@ public class GameFieldSetMapper implements FieldSetMapper { game.setReceptions(fs.readInt("receptions", 0)); game.setReceptionYards(fs.readInt("receptionYards")); game.setTotalTd(fs.readInt("totalTd")); - + return game; } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/internal/JdbcGameDao.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/internal/JdbcGameDao.java index ec42ab0df..7bdbd9e65 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/internal/JdbcGameDao.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/internal/JdbcGameDao.java @@ -42,14 +42,14 @@ public class JdbcGameDao extends JdbcDaoSupport implements ItemWriter { for (Game game : games) { - SqlParameterSource values = new MapSqlParameterSource().addValue("player_id", game.getId()).addValue( - "year_no", game.getYear()).addValue("team", game.getTeam()).addValue("week", game.getWeek()) - .addValue("opponent", game.getOpponent()).addValue("completes", game.getCompletes()).addValue( - "attempts", game.getAttempts()).addValue("passing_yards", game.getPassingYards()).addValue( - "passing_td", game.getPassingTd()).addValue("interceptions", game.getInterceptions()) - .addValue("rushes", game.getRushes()).addValue("rush_yards", game.getRushYards()).addValue( - "receptions", game.getReceptions()).addValue("receptions_yards", game.getReceptionYards()) - .addValue("total_td", game.getTotalTd()); + SqlParameterSource values = new MapSqlParameterSource().addValue("player_id", game.getId()) + .addValue("year_no", game.getYear()).addValue("team", game.getTeam()) + .addValue("week", game.getWeek()).addValue("opponent", game.getOpponent()) + .addValue("completes", game.getCompletes()).addValue("attempts", game.getAttempts()) + .addValue("passing_yards", game.getPassingYards()).addValue("passing_td", game.getPassingTd()) + .addValue("interceptions", game.getInterceptions()).addValue("rushes", game.getRushes()) + .addValue("rush_yards", game.getRushYards()).addValue("receptions", game.getReceptions()) + .addValue("receptions_yards", game.getReceptionYards()).addValue("total_td", game.getTotalTd()); this.insertGame.execute(values); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/internal/JdbcPlayerDao.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/internal/JdbcPlayerDao.java index 59b59c177..eb6252f26 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/internal/JdbcPlayerDao.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/internal/JdbcPlayerDao.java @@ -27,20 +27,20 @@ import javax.sql.DataSource; * @author Lucas Ward * */ -public class JdbcPlayerDao implements PlayerDao { +public class JdbcPlayerDao implements PlayerDao { - public static final String INSERT_PLAYER = - "INSERT into PLAYERS (player_id, last_name, first_name, pos, year_of_birth, year_drafted)" + - " values (:id, :lastName, :firstName, :position, :birthYear, :debutYear)"; + public static final String INSERT_PLAYER = "INSERT into PLAYERS (player_id, last_name, first_name, pos, year_of_birth, year_drafted)" + + " values (:id, :lastName, :firstName, :position, :birthYear, :debutYear)"; - private NamedParameterJdbcTemplate namedParameterJdbcTemplate; + private NamedParameterJdbcTemplate namedParameterJdbcTemplate; - @Override + @Override public void savePlayer(Player player) { - namedParameterJdbcTemplate.update(INSERT_PLAYER, new BeanPropertySqlParameterSource(player)); + namedParameterJdbcTemplate.update(INSERT_PLAYER, new BeanPropertySqlParameterSource(player)); + } + + public void setDataSource(DataSource dataSource) { + this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource); } - public void setDataSource(DataSource dataSource) { - this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource); - } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/internal/JdbcPlayerSummaryDao.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/internal/JdbcPlayerSummaryDao.java index 261d169db..062e058fd 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/internal/JdbcPlayerSummaryDao.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/internal/JdbcPlayerSummaryDao.java @@ -32,26 +32,27 @@ public class JdbcPlayerSummaryDao implements ItemWriter { + "values(:id, :year, :completes, :attempts, :passingYards, :passingTd, " + ":interceptions, :rushes, :rushYards, :receptions, :receptionYards, :totalTd)"; - private NamedParameterJdbcTemplate namedParameterJdbcTemplate; + private NamedParameterJdbcTemplate namedParameterJdbcTemplate; - @Override + @Override public void write(List summaries) { for (PlayerSummary summary : summaries) { - MapSqlParameterSource args = new MapSqlParameterSource().addValue("id", summary.getId()).addValue("year", - summary.getYear()).addValue("completes", summary.getCompletes()).addValue("attempts", - summary.getAttempts()).addValue("passingYards", summary.getPassingYards()).addValue("passingTd", - summary.getPassingTd()).addValue("interceptions", summary.getInterceptions()).addValue("rushes", - summary.getRushes()).addValue("rushYards", summary.getRushYards()).addValue("receptions", - summary.getReceptions()).addValue("receptionYards", summary.getReceptionYards()).addValue( - "totalTd", summary.getTotalTd()); + MapSqlParameterSource args = new MapSqlParameterSource().addValue("id", summary.getId()) + .addValue("year", summary.getYear()).addValue("completes", summary.getCompletes()) + .addValue("attempts", summary.getAttempts()).addValue("passingYards", summary.getPassingYards()) + .addValue("passingTd", summary.getPassingTd()).addValue("interceptions", summary.getInterceptions()) + .addValue("rushes", summary.getRushes()).addValue("rushYards", summary.getRushYards()) + .addValue("receptions", summary.getReceptions()) + .addValue("receptionYards", summary.getReceptionYards()).addValue("totalTd", summary.getTotalTd()); namedParameterJdbcTemplate.update(INSERT_SUMMARY, args); } } - public void setDataSource(DataSource dataSource) { - this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource); - } + public void setDataSource(DataSource dataSource) { + this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource); + } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/internal/PlayerFieldSetMapper.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/internal/PlayerFieldSetMapper.java index 7434ba5ff..44ab0b6cb 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/internal/PlayerFieldSetMapper.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/internal/PlayerFieldSetMapper.java @@ -24,11 +24,11 @@ public class PlayerFieldSetMapper implements FieldSetMapper { @Override public Player mapFieldSet(FieldSet fs) { - - if(fs == null){ + + if (fs == null) { return null; } - + Player player = new Player(); player.setId(fs.readString("ID")); player.setLastName(fs.readString("lastName")); @@ -36,9 +36,8 @@ public class PlayerFieldSetMapper implements FieldSetMapper { player.setPosition(fs.readString("position")); player.setDebutYear(fs.readInt("debutYear")); player.setBirthYear(fs.readInt("birthYear")); - + return player; } - } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/internal/PlayerSummaryMapper.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/internal/PlayerSummaryMapper.java index a15afbe15..903897ed8 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/internal/PlayerSummaryMapper.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/internal/PlayerSummaryMapper.java @@ -22,22 +22,25 @@ import org.springframework.batch.core.test.football.domain.PlayerSummary; import org.springframework.jdbc.core.RowMapper; /** - * RowMapper used to map a ResultSet to a {@link org.springframework.batch.core.test.football.domain.PlayerSummary} - * + * RowMapper used to map a ResultSet to a + * {@link org.springframework.batch.core.test.football.domain.PlayerSummary} + * * @author Lucas Ward * @author Mahmoud Ben Hassine * */ public class PlayerSummaryMapper implements RowMapper { - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.springframework.jdbc.core.RowMapper#mapRow(java.sql.ResultSet, int) */ @Override public PlayerSummary mapRow(ResultSet rs, int rowNum) throws SQLException { - + PlayerSummary summary = new PlayerSummary(); - + summary.setId(rs.getString(1)); summary.setYear(rs.getInt(2)); summary.setCompletes(rs.getInt(3)); @@ -50,7 +53,7 @@ public class PlayerSummaryMapper implements RowMapper { summary.setReceptions(rs.getInt(10)); summary.setReceptionYards(rs.getInt(11)); summary.setTotalTd(rs.getInt(12)); - + return summary; } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/internal/PlayerSummaryRowMapper.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/internal/PlayerSummaryRowMapper.java index 99fce1cee..743a43df4 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/internal/PlayerSummaryRowMapper.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/football/internal/PlayerSummaryRowMapper.java @@ -22,22 +22,25 @@ import org.springframework.batch.core.test.football.domain.PlayerSummary; import org.springframework.jdbc.core.RowMapper; /** - * RowMapper used to map a ResultSet to a {@link org.springframework.batch.core.test.football.domain.PlayerSummary} - * + * RowMapper used to map a ResultSet to a + * {@link org.springframework.batch.core.test.football.domain.PlayerSummary} + * * @author Lucas Ward * @author Mahmoud Ben Hassine * */ public class PlayerSummaryRowMapper implements RowMapper { - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.springframework.jdbc.core.RowMapper#mapRow(java.sql.ResultSet, int) */ @Override public PlayerSummary mapRow(ResultSet rs, int rowNum) throws SQLException { - + PlayerSummary summary = new PlayerSummary(); - + summary.setId(rs.getString(1)); summary.setYear(rs.getInt(2)); summary.setCompletes(rs.getInt(3)); @@ -50,7 +53,7 @@ public class PlayerSummaryRowMapper implements RowMapper { summary.setReceptions(rs.getInt(10)); summary.setReceptionYards(rs.getInt(11)); summary.setTotalTd(rs.getInt(12)); - + return summary; } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/ldif/LdifReaderTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/ldif/LdifReaderTests.java index d6acf0ac0..87e292268 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/ldif/LdifReaderTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/ldif/LdifReaderTests.java @@ -40,10 +40,11 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.util.Assert; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = {"/simple-job-launcher-context.xml", "/applicationContext-test1.xml"}) +@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/applicationContext-test1.xml" }) public class LdifReaderTests { private Resource expected; + private Resource actual; @Autowired @@ -71,10 +72,11 @@ public class LdifReaderTests { public void testValidRun() throws Exception { JobExecution jobExecution = jobLauncher.run(job1, new JobParameters()); - //Ensure job completed successfully. - Assert.isTrue(jobExecution.getExitStatus().equals(ExitStatus.COMPLETED), "Step Execution did not complete normally: " + jobExecution.getExitStatus()); + // Ensure job completed successfully. + Assert.isTrue(jobExecution.getExitStatus().equals(ExitStatus.COMPLETED), + "Step Execution did not complete normally: " + jobExecution.getExitStatus()); - //Check output. + // Check output. Assert.isTrue(actual.exists(), "Actual does not exist."); compareFiles(expected.getFile(), actual.getFile()); } @@ -83,8 +85,11 @@ public class LdifReaderTests { public void testResourceNotExists() throws Exception { JobExecution jobExecution = jobLauncher.run(job2, new JobParameters()); - Assert.isTrue(jobExecution.getExitStatus().getExitCode().equals("FAILED"), "The job exit status is not FAILED."); - Assert.isTrue(jobExecution.getAllFailureExceptions().get(0).getMessage().contains("Failed to initialize the reader"), "The job failed for the wrong reason."); + Assert.isTrue(jobExecution.getExitStatus().getExitCode().equals("FAILED"), + "The job exit status is not FAILED."); + Assert.isTrue( + jobExecution.getAllFailureExceptions().get(0).getMessage().contains("Failed to initialize the reader"), + "The job failed for the wrong reason."); } private void compareFiles(File expected, File actual) throws Exception { @@ -98,11 +103,13 @@ public class LdifReaderTests { } String actualLine = actualReader.readLine(); - assertEquals("More lines than expected. There should not be a line number " + lineNum + ".", null, actualLine); + assertEquals("More lines than expected. There should not be a line number " + lineNum + ".", null, + actualLine); } finally { expectedReader.close(); actualReader.close(); } } + } \ No newline at end of file diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/ldif/MappingLdifReaderTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/ldif/MappingLdifReaderTests.java index e1eee49da..e1a92e13c 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/ldif/MappingLdifReaderTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/ldif/MappingLdifReaderTests.java @@ -42,11 +42,13 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.util.Assert; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = {"/simple-job-launcher-context.xml", "/applicationContext-test2.xml"}) +@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/applicationContext-test2.xml" }) public class MappingLdifReaderTests { + private static Logger log = LoggerFactory.getLogger(MappingLdifReaderTests.class); private Resource expected; + private Resource actual; @Autowired @@ -74,10 +76,11 @@ public class MappingLdifReaderTests { public void testValidRun() throws Exception { JobExecution jobExecution = launcher.run(job1, new JobParameters()); - //Ensure job completed successfully. - Assert.isTrue(jobExecution.getExitStatus().equals(ExitStatus.COMPLETED), "Step Execution did not complete normally: " + jobExecution.getExitStatus()); + // Ensure job completed successfully. + Assert.isTrue(jobExecution.getExitStatus().equals(ExitStatus.COMPLETED), + "Step Execution did not complete normally: " + jobExecution.getExitStatus()); - //Check output. + // Check output. Assert.isTrue(actual.exists(), "Actual does not exist."); Assert.isTrue(compareFiles(expected.getFile(), actual.getFile()), "Files were not equal"); } @@ -86,30 +89,32 @@ public class MappingLdifReaderTests { public void testResourceNotExists() throws Exception { JobExecution jobExecution = launcher.run(job2, new JobParameters()); - Assert.isTrue(jobExecution.getExitStatus().getExitCode().equals("FAILED"), "The job exit status is not FAILED."); - Assert.isTrue(jobExecution.getAllFailureExceptions().get(0).getMessage().contains("Failed to initialize the reader"), "The job failed for the wrong reason."); + Assert.isTrue(jobExecution.getExitStatus().getExitCode().equals("FAILED"), + "The job exit status is not FAILED."); + Assert.isTrue( + jobExecution.getAllFailureExceptions().get(0).getMessage().contains("Failed to initialize the reader"), + "The job failed for the wrong reason."); } - private boolean compareFiles(File expected, File actual) throws Exception { boolean equal = true; FileInputStream expectedStream = new FileInputStream(expected); FileInputStream actualStream = new FileInputStream(actual); - //Construct BufferedReader from InputStreamReader + // Construct BufferedReader from InputStreamReader BufferedReader expectedReader = new BufferedReader(new InputStreamReader(expectedStream)); BufferedReader actualReader = new BufferedReader(new InputStreamReader(actualStream)); String line = null; while ((line = expectedReader.readLine()) != null) { - if(!line.equals(actualReader.readLine())) { + if (!line.equals(actualReader.readLine())) { equal = false; break; } } - if(actualReader.readLine() != null) { + if (actualReader.readLine() != null) { equal = false; } @@ -117,4 +122,5 @@ public class MappingLdifReaderTests { return equal; } + } \ No newline at end of file diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/ldif/MyMapper.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/ldif/MyMapper.java index cbbb2a9cc..cf0a9dd68 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/ldif/MyMapper.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/ldif/MyMapper.java @@ -20,9 +20,10 @@ import org.springframework.lang.Nullable; import org.springframework.ldap.core.LdapAttributes; /** - * This default implementation simply returns the LdapAttributes object and is only intended for test. As its not required - * to return an object of a specific type to make the MappingLdifReader implementation work, this basic setting is sufficient - * to demonstrate its function. + * This default implementation simply returns the LdapAttributes object and is only + * intended for test. As its not required to return an object of a specific type to make + * the MappingLdifReader implementation work, this basic setting is sufficient to + * demonstrate its function. * * @author Keith Barlow * diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/ldif/builder/LdifReaderBuilderTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/ldif/builder/LdifReaderBuilderTests.java index 36152f402..ecd58168e 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/ldif/builder/LdifReaderBuilderTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/ldif/builder/LdifReaderBuilderTests.java @@ -68,7 +68,8 @@ public class LdifReaderBuilderTests { @Test public void testBasicRead() throws Exception { - this.ldifReader = new LdifReaderBuilder().resource(context.getResource("classpath:/test.ldif")).name("foo").build(); + this.ldifReader = new LdifReaderBuilder().resource(context.getResource("classpath:/test.ldif")).name("foo") + .build(); LdapAttributes ldapAttributes = firstRead(); assertEquals("The attribute name for the first record did not match expected result", "cn=Barbara Jensen, ou=Product Development, dc=airius, dc=com", ldapAttributes.getName().toString()); @@ -105,12 +106,12 @@ public class LdifReaderBuilderTests { @Test public void testSaveState() throws Exception { - this.ldifReader = new LdifReaderBuilder().resource(context.getResource("classpath:/test.ldif")).name("foo").build(); + this.ldifReader = new LdifReaderBuilder().resource(context.getResource("classpath:/test.ldif")).name("foo") + .build(); ExecutionContext executionContext = new ExecutionContext(); firstRead(executionContext); this.ldifReader.update(executionContext); - assertEquals("foo.read.count did not have the expected result", 1, - executionContext.getInt("foo.read.count")); + assertEquals("foo.read.count did not have the expected result", 1, executionContext.getInt("foo.read.count")); } @Test @@ -127,7 +128,8 @@ public class LdifReaderBuilderTests { public void testStrict() { // Test that strict when enabled will throw an exception. try { - this.ldifReader = new LdifReaderBuilder().resource(context.getResource("classpath:/teadsfst.ldif")).name("foo").build(); + this.ldifReader = new LdifReaderBuilder().resource(context.getResource("classpath:/teadsfst.ldif")) + .name("foo").build(); this.ldifReader.open(new ExecutionContext()); fail("IllegalStateException should have been thrown, because strict was set to true"); } @@ -161,5 +163,7 @@ public class LdifReaderBuilderTests { public void handleRecord(LdapAttributes attributes) { callbackAttributeName = attributes.getName().toString(); } + } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/ldif/builder/MappingLdifReaderBuilderTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/ldif/builder/MappingLdifReaderBuilderTests.java index f5c9383a2..ef4c41565 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/ldif/builder/MappingLdifReaderBuilderTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/ldif/builder/MappingLdifReaderBuilderTests.java @@ -43,6 +43,7 @@ import static org.junit.Assert.fail; */ @RunWith(SpringRunner.class) public class MappingLdifReaderBuilderTests { + @Autowired private ApplicationContext context; @@ -60,11 +61,8 @@ public class MappingLdifReaderBuilderTests { @Test public void testSkipRecord() throws Exception { - this.mappingLdifReader = new MappingLdifReaderBuilder() - .recordsToSkip(1) - .recordMapper(new TestMapper()) - .resource(context.getResource("classpath:/test.ldif")) - .name("foo") + this.mappingLdifReader = new MappingLdifReaderBuilder().recordsToSkip(1) + .recordMapper(new TestMapper()).resource(context.getResource("classpath:/test.ldif")).name("foo") .build(); LdapAttributes ldapAttributes = firstRead(); assertEquals("The attribute name for the second record did not match expected result", @@ -73,11 +71,8 @@ public class MappingLdifReaderBuilderTests { @Test public void testBasicRead() throws Exception { - this.mappingLdifReader = new MappingLdifReaderBuilder() - .recordMapper(new TestMapper()) - .resource(context.getResource("classpath:/test.ldif")) - .name("foo") - .build(); + this.mappingLdifReader = new MappingLdifReaderBuilder().recordMapper(new TestMapper()) + .resource(context.getResource("classpath:/test.ldif")).name("foo").build(); LdapAttributes ldapAttributes = firstRead(); assertEquals("The attribute name for the first record did not match expected result", "cn=Barbara Jensen, ou=Product Development, dc=airius, dc=com", ldapAttributes.getName().toString()); @@ -85,11 +80,8 @@ public class MappingLdifReaderBuilderTests { @Test public void testCurrentItemCount() throws Exception { - this.mappingLdifReader = new MappingLdifReaderBuilder() - .currentItemCount(3) - .recordMapper(new TestMapper()) - .resource(context.getResource("classpath:/test.ldif")) - .name("foo") + this.mappingLdifReader = new MappingLdifReaderBuilder().currentItemCount(3) + .recordMapper(new TestMapper()).resource(context.getResource("classpath:/test.ldif")).name("foo") .build(); LdapAttributes ldapAttributes = firstRead(); assertEquals("The attribute name for the third record did not match expected result", @@ -98,11 +90,8 @@ public class MappingLdifReaderBuilderTests { @Test public void testMaxItemCount() throws Exception { - this.mappingLdifReader = new MappingLdifReaderBuilder() - .maxItemCount(1) - .recordMapper(new TestMapper()) - .resource(context.getResource("classpath:/test.ldif")) - .name("foo") + this.mappingLdifReader = new MappingLdifReaderBuilder().maxItemCount(1) + .recordMapper(new TestMapper()).resource(context.getResource("classpath:/test.ldif")).name("foo") .build(); LdapAttributes ldapAttributes = firstRead(); assertEquals("The attribute name for the first record did not match expected result", @@ -113,13 +102,9 @@ public class MappingLdifReaderBuilderTests { @Test public void testSkipRecordCallback() throws Exception { - this.mappingLdifReader = new MappingLdifReaderBuilder() - .recordsToSkip(1) - .recordMapper(new TestMapper()) - .skippedRecordsCallback(new TestCallBackHandler()) - .resource(context.getResource("classpath:/test.ldif")) - .name("foo") - .build(); + this.mappingLdifReader = new MappingLdifReaderBuilder().recordsToSkip(1) + .recordMapper(new TestMapper()).skippedRecordsCallback(new TestCallBackHandler()) + .resource(context.getResource("classpath:/test.ldif")).name("foo").build(); firstRead(); assertEquals("The attribute name from the callback handler did not match the expected result", "cn=Barbara Jensen, ou=Product Development, dc=airius, dc=com", this.callbackAttributeName); @@ -127,25 +112,18 @@ public class MappingLdifReaderBuilderTests { @Test public void testSaveState() throws Exception { - this.mappingLdifReader = new MappingLdifReaderBuilder() - .recordMapper(new TestMapper()) - .resource(context.getResource("classpath:/test.ldif")) - .name("foo") - .build(); + this.mappingLdifReader = new MappingLdifReaderBuilder().recordMapper(new TestMapper()) + .resource(context.getResource("classpath:/test.ldif")).name("foo").build(); ExecutionContext executionContext = new ExecutionContext(); firstRead(executionContext); this.mappingLdifReader.update(executionContext); - assertEquals("foo.read.count did not have the expected result", 1, - executionContext.getInt("foo.read.count")); + assertEquals("foo.read.count did not have the expected result", 1, executionContext.getInt("foo.read.count")); } @Test public void testSaveStateDisabled() throws Exception { - this.mappingLdifReader = new MappingLdifReaderBuilder() - .saveState(false) - .recordMapper(new TestMapper()) - .resource(context.getResource("classpath:/test.ldif")) - .build(); + this.mappingLdifReader = new MappingLdifReaderBuilder().saveState(false) + .recordMapper(new TestMapper()).resource(context.getResource("classpath:/test.ldif")).build(); ExecutionContext executionContext = new ExecutionContext(); firstRead(executionContext); this.mappingLdifReader.update(executionContext); @@ -156,11 +134,8 @@ public class MappingLdifReaderBuilderTests { public void testStrict() { // Test that strict when enabled will throw an exception. try { - this.mappingLdifReader = new MappingLdifReaderBuilder() - .recordMapper(new TestMapper()) - .resource(context.getResource("classpath:/teadsfst.ldif")) - .name("foo") - .build(); + this.mappingLdifReader = new MappingLdifReaderBuilder().recordMapper(new TestMapper()) + .resource(context.getResource("classpath:/teadsfst.ldif")).name("foo").build(); this.mappingLdifReader.open(new ExecutionContext()); fail("IllegalStateException should have been thrown, because strict was set to true"); } @@ -178,8 +153,7 @@ public class MappingLdifReaderBuilderTests { public void testNullRecordMapper() { try { this.mappingLdifReader = new MappingLdifReaderBuilder() - .resource(context.getResource("classpath:/teadsfst.ldif")) - .build(); + .resource(context.getResource("classpath:/teadsfst.ldif")).build(); fail("IllegalArgumentException should have been thrown"); } catch (IllegalArgumentException ise) { @@ -209,13 +183,17 @@ public class MappingLdifReaderBuilderTests { public void handleRecord(LdapAttributes attributes) { callbackAttributeName = attributes.getName().toString(); } + } public class TestMapper implements RecordMapper { + @Nullable @Override public LdapAttributes mapRecord(LdapAttributes attributes) { return attributes; } + } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/namespace/config/DummyNamespaceHandler.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/namespace/config/DummyNamespaceHandler.java index 21f42f558..ec6d4a36f 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/namespace/config/DummyNamespaceHandler.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/namespace/config/DummyNamespaceHandler.java @@ -51,4 +51,5 @@ public class DummyNamespaceHandler implements NamespaceHandler { builder.addPropertyValue("name", LABEL); return builder.getBeanDefinition(); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/Db2JobRepositoryIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/Db2JobRepositoryIntegrationTests.java index 9a1fd5f72..0c9c3926c 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/Db2JobRepositoryIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/Db2JobRepositoryIntegrationTests.java @@ -56,11 +56,13 @@ public class Db2JobRepositoryIntegrationTests { @ClassRule public static Db2Container db2 = new Db2Container(DB2_IMAGE).acceptLicense(); - + @Autowired private DataSource dataSource; + @Autowired private JobLauncher jobLauncher; + @Autowired private Job job; @@ -75,7 +77,7 @@ public class Db2JobRepositoryIntegrationTests { public void testJobExecution() throws Exception { // given JobParameters jobParameters = new JobParametersBuilder().toJobParameters(); - + // when JobExecution jobExecution = this.jobLauncher.run(this.job, jobParameters); @@ -90,7 +92,7 @@ public class Db2JobRepositoryIntegrationTests { @Bean public DataSource dataSource() throws Exception { - DB2SimpleDataSource dataSource =new DB2SimpleDataSource(); + DB2SimpleDataSource dataSource = new DB2SimpleDataSource(); dataSource.setDatabaseName(db2.getDatabaseName()); dataSource.setUser(db2.getUsername()); dataSource.setPassword(db2.getPassword()); @@ -104,11 +106,10 @@ public class Db2JobRepositoryIntegrationTests { @Bean public Job job(JobBuilderFactory jobs, StepBuilderFactory steps) { return jobs.get("job") - .start(steps.get("step") - .tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED) - .build()) + .start(steps.get("step").tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED).build()) .build(); } } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/DerbyJobRepositoryIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/DerbyJobRepositoryIntegrationTests.java index feede6f27..fff5577f3 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/DerbyJobRepositoryIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/DerbyJobRepositoryIntegrationTests.java @@ -48,6 +48,7 @@ public class DerbyJobRepositoryIntegrationTests { @Autowired private JobLauncher jobLauncher; + @Autowired private Job job; @@ -55,7 +56,7 @@ public class DerbyJobRepositoryIntegrationTests { public void testJobExecution() throws Exception { // given JobParameters jobParameters = new JobParametersBuilder().toJobParameters(); - + // when JobExecution jobExecution = this.jobLauncher.run(this.job, jobParameters); @@ -70,21 +71,17 @@ public class DerbyJobRepositoryIntegrationTests { @Bean public DataSource dataSource() { - return new EmbeddedDatabaseBuilder() - .setType(EmbeddedDatabaseType.DERBY) - .addScript("/org/springframework/batch/core/schema-derby.sql") - .generateUniqueName(true) - .build(); + return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.DERBY) + .addScript("/org/springframework/batch/core/schema-derby.sql").generateUniqueName(true).build(); } @Bean public Job job(JobBuilderFactory jobs, StepBuilderFactory steps) { return jobs.get("job") - .start(steps.get("step") - .tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED) - .build()) + .start(steps.get("step").tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED).build()) .build(); } } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/H2CompatibilityModeJobRepositoryIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/H2CompatibilityModeJobRepositoryIntegrationTests.java index 8e9b6b9c0..dbd690a95 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/H2CompatibilityModeJobRepositoryIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/H2CompatibilityModeJobRepositoryIntegrationTests.java @@ -75,15 +75,11 @@ public class H2CompatibilityModeJobRepositoryIntegrationTests { } private DataSource buildDataSource() { - var connectionUrl = String.format( - "jdbc:h2:mem:%s;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false;MODE=%s", - UUID.randomUUID(), - this.compatibilityMode - ); + var connectionUrl = String.format("jdbc:h2:mem:%s;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false;MODE=%s", + UUID.randomUUID(), this.compatibilityMode); var dataSource = new SimpleDriverDataSource(new org.h2.Driver(), connectionUrl, "sa", ""); var populator = new ResourceDatabasePopulator(); - var resource = new DefaultResourceLoader() - .getResource("/org/springframework/batch/core/schema-h2.sql"); + var resource = new DefaultResourceLoader().getResource("/org/springframework/batch/core/schema-h2.sql"); populator.addScript(resource); DatabasePopulatorUtils.execute(populator, dataSource); return dataSource; @@ -92,20 +88,20 @@ public class H2CompatibilityModeJobRepositoryIntegrationTests { @Configuration @EnableBatchProcessing static class TestConfiguration { + @Bean Job job(JobBuilderFactory jobs, StepBuilderFactory steps) { return jobs.get("job") - .start(steps.get("step") - .tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED) - .build()) + .start(steps.get("step").tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED).build()) .build(); } + } @Parameters public static List data() throws Exception { - return Arrays.stream(org.h2.engine.Mode.ModeEnum.values()) - .map(mode -> new Object[]{mode.toString()}) + return Arrays.stream(org.h2.engine.Mode.ModeEnum.values()).map(mode -> new Object[] { mode.toString() }) .toList(); } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/H2JobRepositoryIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/H2JobRepositoryIntegrationTests.java index cfac294fb..d43836d6b 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/H2JobRepositoryIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/H2JobRepositoryIntegrationTests.java @@ -48,6 +48,7 @@ public class H2JobRepositoryIntegrationTests { @Autowired private JobLauncher jobLauncher; + @Autowired private Job job; @@ -55,7 +56,7 @@ public class H2JobRepositoryIntegrationTests { public void testJobExecution() throws Exception { // given JobParameters jobParameters = new JobParametersBuilder().toJobParameters(); - + // when JobExecution jobExecution = this.jobLauncher.run(this.job, jobParameters); @@ -70,21 +71,17 @@ public class H2JobRepositoryIntegrationTests { @Bean public DataSource dataSource() { - return new EmbeddedDatabaseBuilder() - .setType(EmbeddedDatabaseType.H2) - .addScript("/org/springframework/batch/core/schema-h2.sql") - .generateUniqueName(true) - .build(); + return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2) + .addScript("/org/springframework/batch/core/schema-h2.sql").generateUniqueName(true).build(); } @Bean public Job job(JobBuilderFactory jobs, StepBuilderFactory steps) { return jobs.get("job") - .start(steps.get("step") - .tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED) - .build()) + .start(steps.get("step").tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED).build()) .build(); } } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/HANAJobRepositoryIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/HANAJobRepositoryIntegrationTests.java index 038ffa168..c0d02976f 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/HANAJobRepositoryIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/HANAJobRepositoryIntegrationTests.java @@ -59,9 +59,11 @@ import com.sap.db.jdbcext.HanaDataSource; import org.testcontainers.utility.LicenseAcceptance; /** - * The official Docker image for SAP HANA is not publicly available. SAP HANA support is tested manually. - * See https://hub.docker.com/_/sap-hana-express-edition/plans/f2dc436a-d851-4c22-a2ba-9de07db7a9ac - * FTR, from the previous link: "This installation does not support Docker for Windows or Docker for Mac." + * The official Docker image for SAP HANA is not publicly available. SAP HANA support is + * tested manually. See + * https://hub.docker.com/_/sap-hana-express-edition/plans/f2dc436a-d851-4c22-a2ba-9de07db7a9ac + * FTR, from the previous link: "This installation does not support Docker for Windows or + * Docker for Mac." * * @author Jonathan Bregler * @author Mahmoud Ben Hassine @@ -71,23 +73,26 @@ import org.testcontainers.utility.LicenseAcceptance; @Ignore("Official Docker image for SAP HANA not publicly available and works only on Linux") public class HANAJobRepositoryIntegrationTests { - private static final DockerImageName HANA_IMAGE = DockerImageName.parse( "store/saplabs/hanaexpress:2.00.057.00.20211207.1" ); + private static final DockerImageName HANA_IMAGE = DockerImageName + .parse("store/saplabs/hanaexpress:2.00.057.00.20211207.1"); @ClassRule - public static HANAContainer hana = new HANAContainer<>( HANA_IMAGE ).acceptLicense(); + public static HANAContainer hana = new HANAContainer<>(HANA_IMAGE).acceptLicense(); @Autowired private DataSource dataSource; + @Autowired private JobLauncher jobLauncher; + @Autowired private Job job; @Before public void setUp() { ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator(); - databasePopulator.addScript( new ClassPathResource( "/org/springframework/batch/core/schema-hana.sql" ) ); - databasePopulator.execute( this.dataSource ); + databasePopulator.addScript(new ClassPathResource("/org/springframework/batch/core/schema-hana.sql")); + databasePopulator.execute(this.dataSource); } @Test @@ -96,11 +101,11 @@ public class HANAJobRepositoryIntegrationTests { JobParameters jobParameters = new JobParametersBuilder().toJobParameters(); // when - JobExecution jobExecution = this.jobLauncher.run( this.job, jobParameters ); + JobExecution jobExecution = this.jobLauncher.run(this.job, jobParameters); // then - Assert.assertNotNull( jobExecution ); - Assert.assertEquals( ExitStatus.COMPLETED, jobExecution.getExitStatus() ); + Assert.assertNotNull(jobExecution); + Assert.assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus()); } @Configuration @@ -110,16 +115,16 @@ public class HANAJobRepositoryIntegrationTests { @Bean public DataSource dataSource() throws Exception { HanaDataSource dataSource = new HanaDataSource(); - dataSource.setUser( hana.getUsername() ); - dataSource.setPassword( hana.getPassword() ); - dataSource.setUrl( hana.getJdbcUrl() ); + dataSource.setUser(hana.getUsername()); + dataSource.setPassword(hana.getPassword()); + dataSource.setUrl(hana.getJdbcUrl()); return dataSource; } @Bean public Job job(JobBuilderFactory jobs, StepBuilderFactory steps) { - return jobs.get( "job" ) - .start( steps.get( "step" ).tasklet( (contribution, chunkContext) -> RepeatStatus.FINISHED ).build() ) + return jobs.get("job") + .start(steps.get("step").tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED).build()) .build(); } @@ -133,69 +138,72 @@ public class HANAJobRepositoryIntegrationTests { private static final Integer PORT = 39041; private static final String SYSTEM_USER = "SYSTEM"; + private static final String SYSTEM_USER_PASSWORD = "HXEHana1"; public HANAContainer(DockerImageName image) { - super( image ); + super(image); - addExposedPorts( 39013, 39017, 39041, 39042, 39043, 39044, 39045, 1128, 1129, 59013, 59014 ); + addExposedPorts(39013, 39017, 39041, 39042, 39043, 39044, 39045, 1128, 1129, 59013, 59014); // create ulimits - Ulimit[] ulimits = new Ulimit[]{ new Ulimit( "nofile", 1048576L, 1048576L ) }; + Ulimit[] ulimits = new Ulimit[] { new Ulimit("nofile", 1048576L, 1048576L) }; // create sysctls Map. Map sysctls = new HashMap(); - sysctls.put( "kernel.shmmax", "1073741824" ); - sysctls.put( "net.ipv4.ip_local_port_range", "40000 60999" ); + sysctls.put("kernel.shmmax", "1073741824"); + sysctls.put("net.ipv4.ip_local_port_range", "40000 60999"); // Apply mounts, ulimits and sysctls. - this.withCreateContainerCmdModifier( it -> it.getHostConfig().withUlimits( ulimits ).withSysctls( sysctls ) ); + this.withCreateContainerCmdModifier(it -> it.getHostConfig().withUlimits(ulimits).withSysctls(sysctls)); // Arguments for Image. - this.withCommand( "--master-password " + SYSTEM_USER_PASSWORD + " --agree-to-sap-license" ); + this.withCommand("--master-password " + SYSTEM_USER_PASSWORD + " --agree-to-sap-license"); // Determine if container is ready. - this.waitStrategy = new LogMessageWaitStrategy().withRegEx( ".*Startup finished!*\\s" ).withTimes( 1 ) - .withStartupTimeout( Duration.of( 600, ChronoUnit.SECONDS ) ); + this.waitStrategy = new LogMessageWaitStrategy().withRegEx(".*Startup finished!*\\s").withTimes(1) + .withStartupTimeout(Duration.of(600, ChronoUnit.SECONDS)); } @Override protected void configure() { /* * Enforce that the license is accepted - do not remove. License available at: - * https://www.sap.com/docs/download/cmp/2016/06/sap-hana-express-dev-agmt-and-exhibit.pdf + * https://www.sap.com/docs/download/cmp/2016/06/sap-hana-express-dev-agmt-and + * -exhibit.pdf */ // If license was not accepted programmatically, check if it was accepted via // resource file - if ( !getEnvMap().containsKey( "AGREE_TO_SAP_LICENSE" ) ) { - LicenseAcceptance.assertLicenseAccepted( this.getDockerImageName() ); + if (!getEnvMap().containsKey("AGREE_TO_SAP_LICENSE")) { + LicenseAcceptance.assertLicenseAccepted(this.getDockerImageName()); acceptLicense(); } } /** - * Accepts the license for the SAP HANA Express container by setting the AGREE_TO_SAP_LICENSE=Y Calling this method - * will automatically accept the license at: + * Accepts the license for the SAP HANA Express container by setting the + * AGREE_TO_SAP_LICENSE=Y Calling this method will automatically accept the + * license at: * https://www.sap.com/docs/download/cmp/2016/06/sap-hana-express-dev-agmt-and-exhibit.pdf - * - * @return The container itself with an environment variable accepting the SAP HANA Express license + * @return The container itself with an environment variable accepting the SAP + * HANA Express license */ public SELF acceptLicense() { - addEnv( "AGREE_TO_SAP_LICENSE", "Y" ); + addEnv("AGREE_TO_SAP_LICENSE", "Y"); return self(); } @Override public Set getLivenessCheckPortNumbers() { - return new HashSet<>( Arrays.asList( new Integer[]{ getMappedPort( PORT ) } ) ); + return new HashSet<>(Arrays.asList(new Integer[] { getMappedPort(PORT) })); } @Override protected void waitUntilContainerStarted() { - getWaitStrategy().waitUntilReady( this ); + getWaitStrategy().waitUntilReady(this); } @Override @@ -220,7 +228,9 @@ public class HANAJobRepositoryIntegrationTests { @Override public String getJdbcUrl() { - return "jdbc:sap://" + getContainerIpAddress() + ":" + getMappedPort( PORT ) + "/"; + return "jdbc:sap://" + getContainerIpAddress() + ":" + getMappedPort(PORT) + "/"; } + } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/HSQLDBJobRepositoryIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/HSQLDBJobRepositoryIntegrationTests.java index 2c3e376b0..049c3f61e 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/HSQLDBJobRepositoryIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/HSQLDBJobRepositoryIntegrationTests.java @@ -48,6 +48,7 @@ public class HSQLDBJobRepositoryIntegrationTests { @Autowired private JobLauncher jobLauncher; + @Autowired private Job job; @@ -55,7 +56,7 @@ public class HSQLDBJobRepositoryIntegrationTests { public void testJobExecution() throws Exception { // given JobParameters jobParameters = new JobParametersBuilder().toJobParameters(); - + // when JobExecution jobExecution = this.jobLauncher.run(this.job, jobParameters); @@ -70,21 +71,17 @@ public class HSQLDBJobRepositoryIntegrationTests { @Bean public DataSource dataSource() { - return new EmbeddedDatabaseBuilder() - .setType(EmbeddedDatabaseType.HSQL) - .addScript("/org/springframework/batch/core/schema-hsqldb.sql") - .generateUniqueName(true) - .build(); + return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL) + .addScript("/org/springframework/batch/core/schema-hsqldb.sql").generateUniqueName(true).build(); } @Bean public Job job(JobBuilderFactory jobs, StepBuilderFactory steps) { return jobs.get("job") - .start(steps.get("step") - .tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED) - .build()) + .start(steps.get("step").tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED).build()) .build(); } } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/JdbcJobRepositoryTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/JdbcJobRepositoryTests.java index 1314d9f3d..149dae03e 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/JdbcJobRepositoryTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/JdbcJobRepositoryTests.java @@ -48,7 +48,7 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = {"/simple-job-launcher-context.xml"}) +@ContextConfiguration(locations = { "/simple-job-launcher-context.xml" }) public class JdbcJobRepositoryTests extends AbstractIntegrationTests { private JobSupport job; @@ -85,7 +85,8 @@ public class JdbcJobRepositoryTests extends AbstractIntegrationTests { job.setName("foo"); int before = 0; JobExecution execution = repository.createJobExecution(job.getName(), new JobParameters()); - int after = JdbcTestUtils.countRowsInTable(jdbcTemplate, "BATCH_JOB_INSTANCE");; + int after = JdbcTestUtils.countRowsInTable(jdbcTemplate, "BATCH_JOB_INSTANCE"); + ; assertEquals(before + 1, after); assertNotNull(execution.getId()); } @@ -185,7 +186,7 @@ public class JdbcJobRepositoryTests extends AbstractIntegrationTests { try { JobExecution execution = repository.createJobExecution(job.getName(), new JobParameters()); - //simulate running execution + // simulate running execution execution.setStartTime(new Date()); repository.update(execution); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/JobSupport.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/JobSupport.java index b8c3284a0..d09731a3f 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/JobSupport.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/JobSupport.java @@ -31,11 +31,10 @@ import org.springframework.lang.Nullable; import org.springframework.util.ClassUtils; /** - * Batch domain object representing a job. Job is an explicit abstraction - * representing the configuration of a job specified by a developer. It should - * be noted that restart policy is applied to the job as a whole and not to a - * step. - * + * Batch domain object representing a job. Job is an explicit abstraction representing the + * configuration of a job specified by a developer. It should be noted that restart policy + * is applied to the job as a whole and not to a step. + * * @author Lucas Ward * @author Dave Syer */ @@ -59,9 +58,7 @@ public class JobSupport implements BeanNameAware, Job { } /** - * Convenience constructor to immediately add name (which is mandatory but - * not final). - * + * Convenience constructor to immediately add name (which is mandatory but not final). * @param name the name */ public JobSupport(String name) { @@ -70,12 +67,12 @@ public class JobSupport implements BeanNameAware, Job { } /** - * Set the name property if it is not already set. Because of the order of - * the callbacks in a Spring container the name property will be set first - * if it is present. Care is needed with bean definition inheritance - if a - * parent bean has a name, then its children need an explicit name as well, - * otherwise they will not be unique. - * + * Set the name property if it is not already set. Because of the order of the + * callbacks in a Spring container the name property will be set first if it is + * present. Care is needed with bean definition inheritance - if a parent bean has a + * name, then its children need an explicit name as well, otherwise they will not be + * unique. + * * @see org.springframework.beans.factory.BeanNameAware#setBeanName(java.lang.String) */ @Override @@ -86,9 +83,9 @@ public class JobSupport implements BeanNameAware, Job { } /** - * Set the name property. Always overrides the default value if this object - * is a Spring bean. - * + * Set the name property. Always overrides the default value if this object is a + * Spring bean. + * * @see #setBeanName(java.lang.String) * @param name the name */ @@ -96,21 +93,23 @@ public class JobSupport implements BeanNameAware, Job { this.name = name; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.springframework.batch.core.domain.IJob#getName() */ @Override public String getName() { return name; } - + /** * @param jobParametersValidator the jobParametersValidator to set */ public void setJobParametersValidator(JobParametersValidator jobParametersValidator) { this.jobParametersValidator = jobParametersValidator; } - + public void setSteps(List steps) { this.steps.clear(); this.steps.addAll(steps); @@ -124,7 +123,9 @@ public class JobSupport implements BeanNameAware, Job { return steps; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.springframework.batch.core.domain.IJob#getStartLimit() */ public int getStartLimit() { @@ -139,15 +140,19 @@ public class JobSupport implements BeanNameAware, Job { this.restartable = restartable; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.springframework.batch.core.domain.IJob#isRestartable() */ @Override public boolean isRestartable() { return restartable; } - - /* (non-Javadoc) + + /* + * (non-Javadoc) + * * @see org.springframework.batch.core.Job#getJobParametersIncrementer() */ @Nullable @@ -155,22 +160,28 @@ public class JobSupport implements BeanNameAware, Job { public JobParametersIncrementer getJobParametersIncrementer() { return null; } - + @Override public JobParametersValidator getJobParametersValidator() { return jobParametersValidator; } - - /* (non-Javadoc) - * @see org.springframework.batch.core.domain.Job#run(org.springframework.batch.core.domain.JobExecution) + + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.core.domain.Job#run(org.springframework.batch.core.domain + * .JobExecution) */ @Override public void execute(JobExecution execution) throws UnexpectedJobExecutionException { - throw new UnsupportedOperationException("JobSupport does not provide an implementation of run(). Use a smarter subclass."); + throw new UnsupportedOperationException( + "JobSupport does not provide an implementation of run(). Use a smarter subclass."); } @Override public String toString() { return ClassUtils.getShortName(getClass()) + ": [name=" + name + "]"; } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/MySQLJdbcJobRepositoryIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/MySQLJdbcJobRepositoryIntegrationTests.java index a2d25eebb..b107f8cb8 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/MySQLJdbcJobRepositoryIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/MySQLJdbcJobRepositoryIntegrationTests.java @@ -64,16 +64,19 @@ public class MySQLJdbcJobRepositoryIntegrationTests { @ClassRule public static MySQLContainer mysql = new MySQLContainer<>(MYSQL_IMAGE); - + @Autowired private DataSource dataSource; + @Autowired private JobLauncher jobLauncher; + @Autowired private JobOperator jobOperator; + @Autowired private Job job; - + @Before public void setUp() { ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator(); @@ -83,15 +86,14 @@ public class MySQLJdbcJobRepositoryIntegrationTests { /* * This test is for issue https://github.com/spring-projects/spring-batch/issues/2202: - * A round trip from a `java.util.Date` JobParameter to the database and back - * again should preserve fractional seconds precision, otherwise a different - * job instance is created while the existing one should be used. - * - * This test ensures that round trip to the database with a `java.util.Date` - * parameter ends up with a single job instance (with two job executions) - * being created and not two distinct job instances (with a job execution for - * each one). - * + * A round trip from a `java.util.Date` JobParameter to the database and back again + * should preserve fractional seconds precision, otherwise a different job instance is + * created while the existing one should be used. + * + * This test ensures that round trip to the database with a `java.util.Date` parameter + * ends up with a single job instance (with two job executions) being created and not + * two distinct job instances (with a job execution for each one). + * * Note the issue does not happen if the parameter is of type Long (when using * addLong("date", date.getTime()) for instance). */ @@ -99,13 +101,13 @@ public class MySQLJdbcJobRepositoryIntegrationTests { public void testDateMillisecondPrecision() throws Exception { // given Date date = new Date(); - JobParameters jobParameters = new JobParametersBuilder() - .addDate("date", date) - .toJobParameters(); - + JobParameters jobParameters = new JobParametersBuilder().addDate("date", date).toJobParameters(); + // when JobExecution jobExecution = this.jobLauncher.run(this.job, jobParameters); - this.jobOperator.restart(jobExecution.getId()); // should load the date parameter with fractional seconds precision here + this.jobOperator.restart(jobExecution.getId()); // should load the date parameter + // with fractional seconds + // precision here // then List jobInstances = this.jobOperator.getJobInstances("job", 0, 100); @@ -130,22 +132,14 @@ public class MySQLJdbcJobRepositoryIntegrationTests { @Bean public Job job(JobBuilderFactory jobs, StepBuilderFactory steps) { - return jobs.get("job") - .start(steps.get("step") - .tasklet((contribution, chunkContext) -> { - throw new Exception("expected failure"); - }) - .build()) - .build(); + return jobs.get("job").start(steps.get("step").tasklet((contribution, chunkContext) -> { + throw new Exception("expected failure"); + }).build()).build(); } @Bean - public JobOperator jobOperator( - JobLauncher jobLauncher, - JobRegistry jobRegistry, - JobExplorer jobExplorer, - JobRepository jobRepository - ) { + public JobOperator jobOperator(JobLauncher jobLauncher, JobRegistry jobRegistry, JobExplorer jobExplorer, + JobRepository jobRepository) { SimpleJobOperator jobOperator = new SimpleJobOperator(); jobOperator.setJobExplorer(jobExplorer); jobOperator.setJobLauncher(jobLauncher); @@ -160,5 +154,7 @@ public class MySQLJdbcJobRepositoryIntegrationTests { jobRegistryBeanPostProcessor.setJobRegistry(jobRegistry); return jobRegistryBeanPostProcessor; } + } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/MySQLJobRepositoryIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/MySQLJobRepositoryIntegrationTests.java index c1b687b43..f2f8b1396 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/MySQLJobRepositoryIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/MySQLJobRepositoryIntegrationTests.java @@ -56,14 +56,16 @@ public class MySQLJobRepositoryIntegrationTests { @ClassRule public static MySQLContainer mysql = new MySQLContainer<>(MYSQL_IMAGE); - + @Autowired private DataSource dataSource; + @Autowired private JobLauncher jobLauncher; + @Autowired private Job job; - + @Before public void setUp() { ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator(); @@ -75,7 +77,7 @@ public class MySQLJobRepositoryIntegrationTests { public void testJobExecution() throws Exception { // given JobParameters jobParameters = new JobParametersBuilder().toJobParameters(); - + // when JobExecution jobExecution = this.jobLauncher.run(this.job, jobParameters); @@ -101,11 +103,10 @@ public class MySQLJobRepositoryIntegrationTests { @Bean public Job job(JobBuilderFactory jobs, StepBuilderFactory steps) { return jobs.get("job") - .start(steps.get("step") - .tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED) - .build()) + .start(steps.get("step").tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED).build()) .build(); } } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/OracleJobRepositoryIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/OracleJobRepositoryIntegrationTests.java index 05d55033a..6651f03ed 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/OracleJobRepositoryIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/OracleJobRepositoryIntegrationTests.java @@ -46,8 +46,9 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; /** - * Official Docker images for Oracle are not publicly available. Oracle support is tested semi-manually for the moment: - * 1. Build a docker image for oracle/database:11.2.0.2-xe: https://github.com/oracle/docker-images/tree/main/OracleDatabase/SingleInstance#running-oracle-database-11gr2-express-edition-in-a-container + * Official Docker images for Oracle are not publicly available. Oracle support is tested + * semi-manually for the moment: 1. Build a docker image for oracle/database:11.2.0.2-xe: + * https://github.com/oracle/docker-images/tree/main/OracleDatabase/SingleInstance#running-oracle-database-11gr2-express-edition-in-a-container * 2. Run the test `testJobExecution` * * @author Mahmoud Ben Hassine @@ -62,14 +63,16 @@ public class OracleJobRepositoryIntegrationTests { @ClassRule public static OracleContainer oracle = new OracleContainer(ORACLE_IMAGE); - + @Autowired private DataSource dataSource; + @Autowired private JobLauncher jobLauncher; + @Autowired private Job job; - + @Before public void setUp() { ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator(); @@ -81,7 +84,7 @@ public class OracleJobRepositoryIntegrationTests { public void testJobExecution() throws Exception { // given JobParameters jobParameters = new JobParametersBuilder().toJobParameters(); - + // when JobExecution jobExecution = this.jobLauncher.run(this.job, jobParameters); @@ -108,11 +111,10 @@ public class OracleJobRepositoryIntegrationTests { @Bean public Job job(JobBuilderFactory jobs, StepBuilderFactory steps) { return jobs.get("job") - .start(steps.get("step") - .tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED) - .build()) + .start(steps.get("step").tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED).build()) .build(); } } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/PostgreSQLJobRepositoryIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/PostgreSQLJobRepositoryIntegrationTests.java index e2c5f0ff8..721a663fd 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/PostgreSQLJobRepositoryIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/PostgreSQLJobRepositoryIntegrationTests.java @@ -56,14 +56,16 @@ public class PostgreSQLJobRepositoryIntegrationTests { @ClassRule public static PostgreSQLContainer postgres = new PostgreSQLContainer<>(POSTGRESQL_IMAGE); - + @Autowired private DataSource dataSource; + @Autowired private JobLauncher jobLauncher; + @Autowired private Job job; - + @Before public void setUp() { ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator(); @@ -75,7 +77,7 @@ public class PostgreSQLJobRepositoryIntegrationTests { public void testJobExecution() throws Exception { // given JobParameters jobParameters = new JobParametersBuilder().toJobParameters(); - + // when JobExecution jobExecution = this.jobLauncher.run(this.job, jobParameters); @@ -100,11 +102,10 @@ public class PostgreSQLJobRepositoryIntegrationTests { @Bean public Job job(JobBuilderFactory jobs, StepBuilderFactory steps) { return jobs.get("job") - .start(steps.get("step") - .tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED) - .build()) + .start(steps.get("step").tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED).build()) .build(); } } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/SQLServerJobRepositoryIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/SQLServerJobRepositoryIntegrationTests.java index 37800699d..c83bc8b9a 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/SQLServerJobRepositoryIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/SQLServerJobRepositoryIntegrationTests.java @@ -52,18 +52,21 @@ import org.springframework.test.context.junit4.SpringRunner; public class SQLServerJobRepositoryIntegrationTests { // TODO find the best way to externalize and manage image versions - private static final DockerImageName SQLSERVER_IMAGE = DockerImageName.parse("mcr.microsoft.com/mssql/server:2019-CU11-ubuntu-20.04"); + private static final DockerImageName SQLSERVER_IMAGE = DockerImageName + .parse("mcr.microsoft.com/mssql/server:2019-CU11-ubuntu-20.04"); @ClassRule public static MSSQLServerContainer sqlserver = new MSSQLServerContainer<>(SQLSERVER_IMAGE).acceptLicense(); - + @Autowired private DataSource dataSource; + @Autowired private JobLauncher jobLauncher; + @Autowired private Job job; - + @Before public void setUp() { ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator(); @@ -75,7 +78,7 @@ public class SQLServerJobRepositoryIntegrationTests { public void testJobExecution() throws Exception { // given JobParameters jobParameters = new JobParametersBuilder().toJobParameters(); - + // when JobExecution jobExecution = this.jobLauncher.run(this.job, jobParameters); @@ -100,11 +103,10 @@ public class SQLServerJobRepositoryIntegrationTests { @Bean public Job job(JobBuilderFactory jobs, StepBuilderFactory steps) { return jobs.get("job") - .start(steps.get("step") - .tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED) - .build()) + .start(steps.get("step").tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED).build()) .build(); } } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/SQLiteJobRepositoryIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/SQLiteJobRepositoryIntegrationTests.java index 6546afad7..081a45809 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/SQLiteJobRepositoryIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/SQLiteJobRepositoryIntegrationTests.java @@ -49,6 +49,7 @@ public class SQLiteJobRepositoryIntegrationTests { @Autowired private JobLauncher jobLauncher; + @Autowired private Job job; @@ -56,7 +57,7 @@ public class SQLiteJobRepositoryIntegrationTests { public void testJobExecution() throws Exception { // given JobParameters jobParameters = new JobParametersBuilder().toJobParameters(); - + // when JobExecution jobExecution = this.jobLauncher.run(this.job, jobParameters); @@ -74,7 +75,8 @@ public class SQLiteJobRepositoryIntegrationTests { SQLiteDataSource dataSource = new SQLiteDataSource(); dataSource.setUrl("jdbc:sqlite:target/spring-batch.sqlite"); ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator(); - databasePopulator.addScript(new ClassPathResource("/org/springframework/batch/core/schema-drop-sqlite.sql")); + databasePopulator + .addScript(new ClassPathResource("/org/springframework/batch/core/schema-drop-sqlite.sql")); databasePopulator.addScript(new ClassPathResource("/org/springframework/batch/core/schema-sqlite.sql")); databasePopulator.execute(dataSource); return dataSource; @@ -83,11 +85,10 @@ public class SQLiteJobRepositoryIntegrationTests { @Bean public Job job(JobBuilderFactory jobs, StepBuilderFactory steps) { return jobs.get("job") - .start(steps.get("step") - .tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED) - .build()) + .start(steps.get("step").tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED).build()) .build(); } } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/SybaseJobRepositoryIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/SybaseJobRepositoryIntegrationTests.java index 1839e6bfc..2cb31ab81 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/SybaseJobRepositoryIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/SybaseJobRepositoryIntegrationTests.java @@ -43,12 +43,13 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; /** - * The Sybase official jdbc driver is not freely available. This test uses the non-official jTDS driver. - * There is no official public Docker image for Sybase neither. This test uses the non-official Docker image by Jetbrains. - * Sybase in not supported in testcontainers. Sysbase support is tested manually for the moment: - * 1. Run `docker run -d -t -p 5000:5000 -eSYBASE_USER=sa -eSYBASE_PASSWORD=sa -eSYBASE_DB=test datagrip/sybase:16.0` - * 2. Update the datasource configuration with the IP of the container - * 3. Run the test `testJobExecution` + * The Sybase official jdbc driver is not freely available. This test uses the + * non-official jTDS driver. There is no official public Docker image for Sybase neither. + * This test uses the non-official Docker image by Jetbrains. Sybase in not supported in + * testcontainers. Sysbase support is tested manually for the moment: 1. Run `docker run + * -d -t -p 5000:5000 -eSYBASE_USER=sa -eSYBASE_PASSWORD=sa -eSYBASE_DB=test + * datagrip/sybase:16.0` 2. Update the datasource configuration with the IP of the + * container 3. Run the test `testJobExecution` * * @author Mahmoud Ben Hassine */ @@ -59,11 +60,13 @@ public class SybaseJobRepositoryIntegrationTests { @Autowired private DataSource dataSource; + @Autowired private JobLauncher jobLauncher; + @Autowired private Job job; - + @Before public void setUp() { ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator(); @@ -75,7 +78,7 @@ public class SybaseJobRepositoryIntegrationTests { public void testJobExecution() throws Exception { // given JobParameters jobParameters = new JobParametersBuilder().toJobParameters(); - + // when JobExecution jobExecution = this.jobLauncher.run(this.job, jobParameters); @@ -88,7 +91,8 @@ public class SybaseJobRepositoryIntegrationTests { @EnableBatchProcessing static class TestConfiguration { - // FIXME Configuration parameters are hard-coded for the moment, to update once testcontainers support is available + // FIXME Configuration parameters are hard-coded for the moment, to update once + // testcontainers support is available @Bean public DataSource dataSource() throws Exception { JtdsDataSource dataSource = new JtdsDataSource(); @@ -103,11 +107,10 @@ public class SybaseJobRepositoryIntegrationTests { @Bean public Job job(JobBuilderFactory jobs, StepBuilderFactory steps) { return jobs.get("job") - .start(steps.get("step") - .tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED) - .build()) + .start(steps.get("step").tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED).build()) .build(); } } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/step/FaultTolerantStepFactoryBeanIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/step/FaultTolerantStepFactoryBeanIntegrationTests.java index e507875be..f42adbf84 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/step/FaultTolerantStepFactoryBeanIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/step/FaultTolerantStepFactoryBeanIntegrationTests.java @@ -104,11 +104,11 @@ public class FaultTolerantStepFactoryBeanIntegrationTests { taskExecutor.setQueueCapacity(0); taskExecutor.afterPropertiesSet(); factory.setTaskExecutor(taskExecutor); - + JdbcTestUtils.deleteFromTables(new JdbcTemplate(dataSource), "ERROR_LOG"); } - + @Test public void testUpdatesNoRollback() throws Exception { @@ -200,6 +200,7 @@ public class FaultTolerantStepFactoryBeanIntegrationTests { String item = items[counter]; return item; } + } private static class SkipWriterStub implements ItemWriter { @@ -243,6 +244,7 @@ public class FaultTolerantStepFactoryBeanIntegrationTests { throw new RuntimeException("Planned failure"); } } + } private static class SkipProcessorStub implements ItemProcessor { @@ -279,10 +281,11 @@ public class FaultTolerantStepFactoryBeanIntegrationTests { @Override public String process(String item) throws Exception { processed.add(item); - logger.debug("Processed item: "+item); + logger.debug("Processed item: " + item); jdbcTemplate.update("INSERT INTO ERROR_LOG (MESSAGE, STEP_NAME) VALUES (?, ?)", item, "processed"); return item; } + } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/step/FaultTolerantStepFactoryBeanRollbackIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/step/FaultTolerantStepFactoryBeanRollbackIntegrationTests.java index d26daf362..f98b1b642 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/step/FaultTolerantStepFactoryBeanRollbackIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/step/FaultTolerantStepFactoryBeanRollbackIntegrationTests.java @@ -109,7 +109,7 @@ public class FaultTolerantStepFactoryBeanRollbackIntegrationTests { @Test public void testUpdatesNoRollback() throws Exception { - JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); + JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); writer.write(Arrays.asList("foo", "bar")); processor.process("spam"); @@ -143,7 +143,7 @@ public class FaultTolerantStepFactoryBeanRollbackIntegrationTests { logger.info("Starting step: " + i); } - JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); + JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); assertEquals(0, JdbcTestUtils.countRowsInTable(jdbcTemplate, "ERROR_LOG")); try { @@ -221,6 +221,7 @@ public class FaultTolerantStepFactoryBeanRollbackIntegrationTests { String item = items[counter]; return item; } + } private static class SkipWriterStub implements ItemWriter { @@ -268,6 +269,7 @@ public class FaultTolerantStepFactoryBeanRollbackIntegrationTests { throw new RuntimeException("Planned failure"); } } + } private static class SkipProcessorStub implements ItemProcessor { @@ -315,6 +317,7 @@ public class FaultTolerantStepFactoryBeanRollbackIntegrationTests { jdbcTemplate.update("INSERT INTO ERROR_LOG (MESSAGE, STEP_NAME) VALUES (?, ?)", item, "processed"); return item; } + } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/step/FaultTolerantStepIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/step/FaultTolerantStepIntegrationTests.java index e9f806f77..c540b700a 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/step/FaultTolerantStepIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/step/FaultTolerantStepIntegrationTests.java @@ -48,25 +48,27 @@ import org.springframework.transaction.PlatformTransactionManager; import static org.junit.Assert.assertEquals; /** - * Tests for fault tolerant {@link org.springframework.batch.core.step.item.ChunkOrientedTasklet}. + * Tests for fault tolerant + * {@link org.springframework.batch.core.step.item.ChunkOrientedTasklet}. */ @ContextConfiguration(locations = "/simple-job-launcher-context.xml") @RunWith(SpringJUnit4ClassRunner.class) public class FaultTolerantStepIntegrationTests { - + private static final int TOTAL_ITEMS = 30; + private static final int CHUNK_SIZE = TOTAL_ITEMS; - + @Autowired private JobRepository jobRepository; - + @Autowired private PlatformTransactionManager transactionManager; - + private SkipPolicy skipPolicy; - + private FaultTolerantStepBuilder stepBuilder; - + @Before public void setUp() { ItemReader itemReader = new ListItemReader<>(createItems()); @@ -77,60 +79,48 @@ public class FaultTolerantStepIntegrationTests { }; skipPolicy = new SkipIllegalArgumentExceptionSkipPolicy(); stepBuilder = new StepBuilderFactory(jobRepository, transactionManager).get("step") - .chunk(CHUNK_SIZE) - .reader(itemReader) - .processor(item -> item > 20 ? null : item) - .writer(itemWriter) - .faultTolerant(); + .chunk(CHUNK_SIZE).reader(itemReader).processor(item -> item > 20 ? null : item) + .writer(itemWriter).faultTolerant(); } - + @Test public void testFilterCountWithTransactionalProcessorWhenSkipInWrite() throws Exception { // Given - Step step = stepBuilder - .skipPolicy(skipPolicy) - .build(); - + Step step = stepBuilder.skipPolicy(skipPolicy).build(); + // When StepExecution stepExecution = execute(step); - + // Then assertEquals(TOTAL_ITEMS, stepExecution.getReadCount()); assertEquals(10, stepExecution.getFilterCount()); assertEquals(19, stepExecution.getWriteCount()); assertEquals(1, stepExecution.getWriteSkipCount()); } - + @Test public void testFilterCountWithNonTransactionalProcessorWhenSkipInWrite() throws Exception { // Given - Step step = stepBuilder - .skipPolicy(skipPolicy) - .processorNonTransactional() - .build(); - + Step step = stepBuilder.skipPolicy(skipPolicy).processorNonTransactional().build(); + // When StepExecution stepExecution = execute(step); - + // Then assertEquals(TOTAL_ITEMS, stepExecution.getReadCount()); assertEquals(10, stepExecution.getFilterCount()); assertEquals(19, stepExecution.getWriteCount()); assertEquals(1, stepExecution.getWriteSkipCount()); } - + @Test public void testFilterCountOnRetryWithTransactionalProcessorWhenSkipInWrite() throws Exception { // Given - Step step = stepBuilder - .retry(IllegalArgumentException.class) - .retryLimit(2) - .skipPolicy(skipPolicy) - .build(); - + Step step = stepBuilder.retry(IllegalArgumentException.class).retryLimit(2).skipPolicy(skipPolicy).build(); + // When StepExecution stepExecution = execute(step); - + // Then assertEquals(TOTAL_ITEMS, stepExecution.getReadCount()); // filter count is expected to be counted on each retry attempt @@ -138,20 +128,16 @@ public class FaultTolerantStepIntegrationTests { assertEquals(19, stepExecution.getWriteCount()); assertEquals(1, stepExecution.getWriteSkipCount()); } - + @Test public void testFilterCountOnRetryWithNonTransactionalProcessorWhenSkipInWrite() throws Exception { // Given - Step step = stepBuilder - .retry(IllegalArgumentException.class) - .retryLimit(2) - .skipPolicy(skipPolicy) - .processorNonTransactional() - .build(); - + Step step = stepBuilder.retry(IllegalArgumentException.class).retryLimit(2).skipPolicy(skipPolicy) + .processorNonTransactional().build(); + // When StepExecution stepExecution = execute(step); - + // Then assertEquals(TOTAL_ITEMS, stepExecution.getReadCount()); // filter count is expected to be counted on each retry attempt @@ -172,7 +158,8 @@ public class FaultTolerantStepIntegrationTests { @Override public Integer process(Integer item) throws Exception { cpt++; - if (cpt == 7) { // item 2 succeeds the first time but fails during the scan + if (cpt == 7) { // item 2 succeeds the first time but fails during the + // scan throw new Exception("Error during process"); } return item; @@ -191,15 +178,9 @@ public class FaultTolerantStepIntegrationTests { } }; - Step step = new StepBuilderFactory(jobRepository, transactionManager).get("step") - .chunk(5) - .reader(itemReader) - .processor(itemProcessor) - .writer(itemWriter) - .faultTolerant() - .skip(Exception.class) - .skipLimit(3) - .build(); + Step step = new StepBuilderFactory(jobRepository, transactionManager).get("step").chunk(5) + .reader(itemReader).processor(itemProcessor).writer(itemWriter).faultTolerant().skip(Exception.class) + .skipLimit(3).build(); // When StepExecution stepExecution = execute(step); @@ -236,14 +217,9 @@ public class FaultTolerantStepIntegrationTests { } }; - Step step = new StepBuilderFactory(jobRepository, transactionManager).get("step") - .chunk(5) - .reader(itemReader) - .processor(itemProcessor) - .writer(itemWriter) - .faultTolerant() - .skipPolicy(new AlwaysSkipItemSkipPolicy()) - .build(); + Step step = new StepBuilderFactory(jobRepository, transactionManager).get("step").chunk(5) + .reader(itemReader).processor(itemProcessor).writer(itemWriter).faultTolerant() + .skipPolicy(new AlwaysSkipItemSkipPolicy()).build(); // When StepExecution stepExecution = execute(step); @@ -266,23 +242,22 @@ public class FaultTolerantStepIntegrationTests { } return items; } - + private StepExecution execute(Step step) throws Exception { - JobExecution jobExecution = jobRepository.createJobExecution( - "job" + Math.random(), new JobParameters()); + JobExecution jobExecution = jobRepository.createJobExecution("job" + Math.random(), new JobParameters()); StepExecution stepExecution = jobExecution.createStepExecution("step"); jobRepository.add(stepExecution); step.execute(stepExecution); return stepExecution; } - + private class SkipIllegalArgumentExceptionSkipPolicy implements SkipPolicy { - + @Override - public boolean shouldSkip(Throwable throwable, long skipCount) - throws SkipLimitExceededException { + public boolean shouldSkip(Throwable throwable, long skipCount) throws SkipLimitExceededException { return throwable instanceof IllegalArgumentException; } - + } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/step/StepExecutionSerializationUtilsTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/step/StepExecutionSerializationUtilsTests.java index 9327e7585..f12ca4e75 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/step/StepExecutionSerializationUtilsTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/step/StepExecutionSerializationUtilsTests.java @@ -41,8 +41,8 @@ public class StepExecutionSerializationUtilsTests { @Test public void testCycle() throws Exception { - StepExecution stepExecution = new StepExecution("step", new JobExecution(new JobInstance(123L, - "job"), 321L, new JobParameters()), 11L); + StepExecution stepExecution = new StepExecution("step", + new JobExecution(new JobInstance(123L, "job"), 321L, new JobParameters()), 11L); stepExecution.getExecutionContext().put("foo.bar.spam", 123); StepExecution result = getCopy(stepExecution); assertEquals(stepExecution, result); @@ -78,19 +78,21 @@ public class StepExecutionSerializationUtilsTests { count++; try { future.get(); - } catch (Throwable e) { - throw new IllegalStateException("Failed on count="+count, e); + } + catch (Throwable e) { + throw new IllegalStateException("Failed on count=" + count, e); } } } } - while (count < threads*repeats) { + while (count < threads * repeats) { Future future = completionService.poll(); count++; try { future.get(); - } catch (Throwable e) { - throw new IllegalStateException("Failed on count="+count, e); + } + catch (Throwable e) { + throw new IllegalStateException("Failed on count=" + count, e); } } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/timeout/LoggingItemWriter.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/timeout/LoggingItemWriter.java index 4fbf1c1a6..43904fc25 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/timeout/LoggingItemWriter.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/timeout/LoggingItemWriter.java @@ -22,12 +22,12 @@ import org.apache.commons.logging.LogFactory; import org.springframework.batch.item.ItemWriter; public class LoggingItemWriter implements ItemWriter { - + protected Log logger = LogFactory.getLog(LoggingItemWriter.class); @Override public void write(List items) throws Exception { - logger.info(items); + logger.info(items); } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/timeout/SleepingItemProcessor.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/timeout/SleepingItemProcessor.java index d59a528b8..6551123aa 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/timeout/SleepingItemProcessor.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/timeout/SleepingItemProcessor.java @@ -19,7 +19,7 @@ import org.springframework.batch.item.ItemProcessor; import org.springframework.lang.Nullable; public class SleepingItemProcessor implements ItemProcessor { - + private long millisToSleep; @Nullable @@ -28,7 +28,7 @@ public class SleepingItemProcessor implements ItemProcessor { Thread.sleep(millisToSleep); return item; } - + public void setMillisToSleep(long millisToSleep) { this.millisToSleep = millisToSleep; } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/timeout/SleepingTasklet.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/timeout/SleepingTasklet.java index 6ba9e049c..fbaca85de 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/timeout/SleepingTasklet.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/timeout/SleepingTasklet.java @@ -22,17 +22,16 @@ import org.springframework.batch.repeat.RepeatStatus; import org.springframework.lang.Nullable; public class SleepingTasklet implements Tasklet { - + private long millisToSleep; @Nullable @Override - public RepeatStatus execute(StepContribution contribution, - ChunkContext chunkContext) throws Exception { + public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { Thread.sleep(millisToSleep); return RepeatStatus.FINISHED; } - + public void setMillisToSleep(long millisToSleep) { this.millisToSleep = millisToSleep; } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/timeout/TimeoutJobIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/timeout/TimeoutJobIntegrationTests.java index 2431be54e..64721f6ca 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/timeout/TimeoutJobIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/timeout/TimeoutJobIntegrationTests.java @@ -35,7 +35,7 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = {"/simple-job-launcher-context.xml", "/META-INF/batch/timeoutJob.xml"}) +@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/META-INF/batch/timeoutJob.xml" }) public class TimeoutJobIntegrationTests extends AbstractIntegrationTests { /** Logger */ @@ -48,7 +48,7 @@ public class TimeoutJobIntegrationTests extends AbstractIntegrationTests { @Autowired @Qualifier("chunkTimeoutJob") private Job chunkTimeoutJob; - + @Autowired @Qualifier("taskletTimeoutJob") private Job taskletTimeoutJob; @@ -60,15 +60,15 @@ public class TimeoutJobIntegrationTests extends AbstractIntegrationTests { @Test public void testChunkTimeoutShouldFail() throws Exception { - JobExecution execution = jobLauncher.run(chunkTimeoutJob, new JobParametersBuilder().addLong("id", System.currentTimeMillis()) - .toJobParameters()); + JobExecution execution = jobLauncher.run(chunkTimeoutJob, + new JobParametersBuilder().addLong("id", System.currentTimeMillis()).toJobParameters()); assertEquals(BatchStatus.FAILED, execution.getStatus()); } @Test public void testTaskletTimeoutShouldFail() throws Exception { - JobExecution execution = jobLauncher.run(taskletTimeoutJob, new JobParametersBuilder().addLong("id", System.currentTimeMillis()) - .toJobParameters()); + JobExecution execution = jobLauncher.run(taskletTimeoutJob, + new JobParametersBuilder().addLong("id", System.currentTimeMillis()).toJobParameters()); assertEquals(BatchStatus.FAILED, execution.getStatus()); } diff --git a/spring-batch-core/src/test/java/test/jdbc/datasource/DataSourceInitializer.java b/spring-batch-core/src/test/java/test/jdbc/datasource/DataSourceInitializer.java index c01bcb281..db87a77a1 100644 --- a/spring-batch-core/src/test/java/test/jdbc/datasource/DataSourceInitializer.java +++ b/spring-batch-core/src/test/java/test/jdbc/datasource/DataSourceInitializer.java @@ -39,14 +39,14 @@ import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; /** - * Wrapper for a {@link DataSource} that can run scripts on start up and shut - * down. Us as a bean definition

      + * Wrapper for a {@link DataSource} that can run scripts on start up and shut down. Us as + * a bean definition
      + *
      * - * Run this class to initialize a database in a running server process. - * Make sure the server is running first by launching the "hsql-server" from the - * hsql.server project. Then you can right click in Eclipse and - * Run As -> Java Application. Do the same any time you want to wipe the - * database and start again. + * Run this class to initialize a database in a running server process. Make sure the + * server is running first by launching the "hsql-server" from the + * hsql.server project. Then you can right click in Eclipse and Run As -> + * Java Application. Do the same any time you want to wipe the database and start again. * * @author Dave Syer * @@ -65,7 +65,6 @@ public class DataSourceInitializer implements InitializingBean { /** * Main method as convenient entry point. - * * @param args */ @SuppressWarnings("resource") @@ -106,8 +105,8 @@ public class DataSourceInitializer implements InitializingBean { JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); String[] scripts; try { - scripts = StringUtils.delimitedListToStringArray(stripComments(IOUtils.readLines(scriptResource - .getInputStream(), "UTF-8")), ";"); + scripts = StringUtils.delimitedListToStringArray( + stripComments(IOUtils.readLines(scriptResource.getInputStream(), "UTF-8")), ";"); } catch (IOException e) { throw new BeanInitializationException("Cannot load script from [" + scriptResource + "]", e); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ExecutionContext.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ExecutionContext.java index 20259a7f6..06b84dd93 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ExecutionContext.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ExecutionContext.java @@ -25,12 +25,12 @@ import java.util.concurrent.ConcurrentHashMap; import org.springframework.lang.Nullable; /** - * Object representing a context for an {@link ItemStream}. It is a thin wrapper - * for a map that allows optionally for type safety on reads. It also allows for - * dirty checking by setting a 'dirty' flag whenever any put is called. + * Object representing a context for an {@link ItemStream}. It is a thin wrapper for a map + * that allows optionally for type safety on reads. It also allows for dirty checking by + * setting a 'dirty' flag whenever any put is called. * - * Note that putting null value is equivalent to removing the entry - * for the given key. + * Note that putting null value is equivalent to removing the entry for the + * given key. * * @author Lucas Ward * @author Douglas Kaminsky @@ -44,8 +44,8 @@ public class ExecutionContext implements Serializable { private final Map map; /** - * Default constructor. Initializes a new execution context with an empty - * internal map. + * Default constructor. Initializes a new execution context with an empty internal + * map. */ public ExecutionContext() { this.map = new ConcurrentHashMap<>(); @@ -53,7 +53,6 @@ public class ExecutionContext implements Serializable { /** * Initializes a new execution context with the contents of another map. - * * @param map Initial contents of context. */ public ExecutionContext(Map map) { @@ -63,8 +62,8 @@ public class ExecutionContext implements Serializable { /** * Initializes a new {@link ExecutionContext} with the contents of another * {@code ExecutionContext}. - * - * @param executionContext containing the entries to be copied to this current context. + * @param executionContext containing the entries to be copied to this current + * context. */ public ExecutionContext(ExecutionContext executionContext) { this(); @@ -77,9 +76,8 @@ public class ExecutionContext implements Serializable { } /** - * Adds a String value to the context. Putting null - * value for a given key removes the key. - * + * Adds a String value to the context. Putting null value for a given key + * removes the key. * @param key Key to add to context * @param value Value to associate with key */ @@ -91,7 +89,6 @@ public class ExecutionContext implements Serializable { /** * Adds a Long value to the context. - * * @param key Key to add to context * @param value Value to associate with key */ @@ -102,7 +99,6 @@ public class ExecutionContext implements Serializable { /** * Adds an Integer value to the context. - * * @param key Key to add to context * @param value Value to associate with key */ @@ -112,7 +108,6 @@ public class ExecutionContext implements Serializable { /** * Add a Double value to the context. - * * @param key Key to add to context * @param value Value to associate with key */ @@ -122,28 +117,26 @@ public class ExecutionContext implements Serializable { } /** - * Add an Object value to the context. Putting null - * value for a given key removes the key. - * + * Add an Object value to the context. Putting null value for a given key + * removes the key. * @param key Key to add to context * @param value Value to associate with key */ public void put(String key, @Nullable Object value) { if (value != null) { Object result = this.map.put(key, value); - this.dirty = result==null || result!=null && !result.equals(value); + this.dirty = result == null || result != null && !result.equals(value); } else { Object result = this.map.remove(key); - this.dirty = result!=null; + this.dirty = result != null; } } /** - * Indicates if context has been changed with a "put" operation since the - * dirty flag was last cleared. Note that the last time the flag was cleared - * might correspond to creation of the context. - * + * Indicates if context has been changed with a "put" operation since the dirty flag + * was last cleared. Note that the last time the flag was cleared might correspond to + * creation of the context. * @return True if "put" operation has occurred since flag was last cleared */ public boolean isDirty() { @@ -152,7 +145,6 @@ public class ExecutionContext implements Serializable { /** * Typesafe Getter for the String represented by the provided key. - * * @param key The key to get a value for * @return The String value */ @@ -162,13 +154,12 @@ public class ExecutionContext implements Serializable { } /** - * Typesafe Getter for the String represented by the provided key with - * default value to return if key is not represented. - * + * Typesafe Getter for the String represented by the provided key with default value + * to return if key is not represented. * @param key The key to get a value for * @param defaultString Default to return if key is not represented - * @return The String value if key is represented, specified - * default otherwise + * @return The String value if key is represented, specified default + * otherwise */ public String getString(String key, String defaultString) { if (!containsKey(key)) { @@ -180,7 +171,6 @@ public class ExecutionContext implements Serializable { /** * Typesafe Getter for the Long represented by the provided key. - * * @param key The key to get a value for * @return The Long value */ @@ -190,13 +180,12 @@ public class ExecutionContext implements Serializable { } /** - * Typesafe Getter for the Long represented by the provided key with default - * value to return if key is not represented. - * + * Typesafe Getter for the Long represented by the provided key with default value to + * return if key is not represented. * @param key The key to get a value for * @param defaultLong Default to return if key is not represented - * @return The long value if key is represented, specified - * default otherwise + * @return The long value if key is represented, specified default + * otherwise */ public long getLong(String key, long defaultLong) { if (!containsKey(key)) { @@ -208,7 +197,6 @@ public class ExecutionContext implements Serializable { /** * Typesafe Getter for the Integer represented by the provided key. - * * @param key The key to get a value for * @return The Integer value */ @@ -218,13 +206,12 @@ public class ExecutionContext implements Serializable { } /** - * Typesafe Getter for the Integer represented by the provided key with - * default value to return if key is not represented. - * + * Typesafe Getter for the Integer represented by the provided key with default value + * to return if key is not represented. * @param key The key to get a value for * @param defaultInt Default to return if key is not represented - * @return The int value if key is represented, specified - * default otherwise + * @return The int value if key is represented, specified default + * otherwise */ public int getInt(String key, int defaultInt) { if (!containsKey(key)) { @@ -236,7 +223,6 @@ public class ExecutionContext implements Serializable { /** * Typesafe Getter for the Double represented by the provided key. - * * @param key The key to get a value for * @return The Double value */ @@ -245,13 +231,12 @@ public class ExecutionContext implements Serializable { } /** - * Typesafe Getter for the Double represented by the provided key with - * default value to return if key is not represented. - * + * Typesafe Getter for the Double represented by the provided key with default value + * to return if key is not represented. * @param key The key to get a value for * @param defaultDouble Default to return if key is not represented - * @return The double value if key is represented, specified - * default otherwise + * @return The double value if key is represented, specified default + * otherwise */ public double getDouble(String key, double defaultDouble) { if (!containsKey(key)) { @@ -263,10 +248,9 @@ public class ExecutionContext implements Serializable { /** * Getter for the value represented by the provided key. - * * @param key The key to get a value for - * @return The value represented by the given key or {@code null} if the key - * is not present + * @return The value represented by the given key or {@code null} if the key is not + * present */ @Nullable public Object get(String key) { @@ -274,9 +258,8 @@ public class ExecutionContext implements Serializable { } /** - * Utility method that attempts to take a value represented by a given key - * and validate it as a member of the specified type. - * + * Utility method that attempts to take a value represented by a given key and + * validate it as a member of the specified type. * @param key The key to validate a value for * @param type Class against which value should be validated * @return Value typed to the specified Class @@ -295,7 +278,6 @@ public class ExecutionContext implements Serializable { /** * Indicates whether or not the context is empty. - * * @return True if the context has no entries, false otherwise. * @see java.util.Map#isEmpty() */ @@ -312,7 +294,6 @@ public class ExecutionContext implements Serializable { /** * Returns the entry set containing the contents of this context. - * * @return A set representing the contents of the context * @see java.util.Map#entrySet() */ @@ -322,7 +303,6 @@ public class ExecutionContext implements Serializable { /** * Indicates whether or not a key is represented in this context. - * * @param key Key to check existence for * @return True if key is represented in context, false otherwise * @see java.util.Map#containsKey(Object) @@ -333,7 +313,6 @@ public class ExecutionContext implements Serializable { /** * Removes the mapping for a key from this context if it is present. - * * @param key {@link String} that identifies the entry to be removed from the context. * @return the value that was removed from the context. * @@ -346,7 +325,6 @@ public class ExecutionContext implements Serializable { /** * Indicates whether or not a value is represented in this context. - * * @param value Value to check existence for * @return True if value is represented in context, false otherwise * @see java.util.Map#containsValue(Object) @@ -394,7 +372,6 @@ public class ExecutionContext implements Serializable { /** * Returns number of entries in the context - * * @return Number of entries in the context * @see java.util.Map#size() */ diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemCountAware.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemCountAware.java index a3d0a96c1..8c39f2157 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemCountAware.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemCountAware.java @@ -1,34 +1,34 @@ -/* - * Copyright 20013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item; - -import org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader; - -/** - * Marker interface indicating that an item should have the item count set on it. Typically used within - * an {@link AbstractItemCountingItemStreamItemReader}. - * - * @author Jimmy Praet - */ -public interface ItemCountAware { - - /** - * Setter for the injection of the current item count. - * - * @param count the number of items that have been processed in this execution. - */ - void setItemCount(int count); -} +/* + * Copyright 20013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item; + +import org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader; + +/** + * Marker interface indicating that an item should have the item count set on it. + * Typically used within an {@link AbstractItemCountingItemStreamItemReader}. + * + * @author Jimmy Praet + */ +public interface ItemCountAware { + + /** + * Setter for the injection of the current item count. + * @param count the number of items that have been processed in this execution. + */ + void setItemCount(int count); + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemProcessor.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemProcessor.java index 2c3ac309a..eb86b4f61 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemProcessor.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemProcessor.java @@ -20,37 +20,38 @@ import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; /** - * Interface for item transformation. Given an item as input, this interface provides - * an extension point which allows for the application of business logic in an item - * oriented processing scenario. It should be noted that while it's possible to return - * a different type than the one provided, it's not strictly necessary. Furthermore, - * returning {@code null} indicates that the item should not be continued to be processed. - * + * Interface for item transformation. Given an item as input, this interface provides an + * extension point which allows for the application of business logic in an item oriented + * processing scenario. It should be noted that while it's possible to return a different + * type than the one provided, it's not strictly necessary. Furthermore, returning + * {@code null} indicates that the item should not be continued to be processed. + * * @author Robert Kasanicky * @author Dave Syer * @author Mahmoud Ben Hassine - * * @param type of input item * @param type of output item */ public interface ItemProcessor { /** - * Process the provided item, returning a potentially modified or new item for continued - * processing. If the returned result is {@code null}, it is assumed that processing of the item - * should not continue. - * - * A {@code null} item will never reach this method because the only possible sources are: + * Process the provided item, returning a potentially modified or new item for + * continued processing. If the returned result is {@code null}, it is assumed that + * processing of the item should not continue. + * + * A {@code null} item will never reach this method because the only possible sources + * are: *
        - *
      • an {@link ItemReader} (which indicates no more items)
      • - *
      • a previous {@link ItemProcessor} in a composite processor (which indicates a filtered item)
      • + *
      • an {@link ItemReader} (which indicates no more items)
      • + *
      • a previous {@link ItemProcessor} in a composite processor (which indicates a + * filtered item)
      • *
      - * * @param item to be processed, never {@code null}. - * @return potentially modified or new item for continued processing, {@code null} if processing of the - * provided item should not continue. + * @return potentially modified or new item for continued processing, {@code null} if + * processing of the provided item should not continue. * @throws Exception thrown if exception occurs during processing. */ @Nullable O process(@NonNull I item) throws Exception; + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemReader.java index 62fa8c9d9..f4dc80193 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemReader.java @@ -20,17 +20,17 @@ import org.springframework.lang.Nullable; /** * Strategy interface for providing the data.
      - * - * Implementations are expected to be stateful and will be called multiple times - * for each batch, with each call to {@link #read()} returning a different value - * and finally returning null when all input data is exhausted.
      - * - * Implementations need not be thread-safe and clients of a {@link ItemReader} - * need to be aware that this is the case.
      - * - * A richer interface (e.g. with a look ahead or peek) is not feasible because - * we need to support transactions in an asynchronous batch. - * + * + * Implementations are expected to be stateful and will be called multiple times for each + * batch, with each call to {@link #read()} returning a different value and finally + * returning null when all input data is exhausted.
      + * + * Implementations need not be thread-safe and clients of a {@link ItemReader} need + * to be aware that this is the case.
      + * + * A richer interface (e.g. with a look ahead or peek) is not feasible because we need to + * support transactions in an asynchronous batch. + * * @author Rob Harrop * @author Dave Syer * @author Lucas Ward @@ -41,22 +41,19 @@ public interface ItemReader { /** * Reads a piece of input data and advance to the next one. Implementations - * must return null at the end of the input - * data set. In a transactional setting, caller might get the same item - * twice from successive calls (or otherwise), if the first call was in a - * transaction that rolled back. - * - * @throws ParseException if there is a problem parsing the current record - * (but the next one may still be valid) - * @throws NonTransientResourceException if there is a fatal exception in - * the underlying resource. After throwing this exception implementations - * should endeavour to return null from subsequent calls to read. - * @throws UnexpectedInputException if there is an uncategorised problem - * with the input data. Assume potentially transient, so subsequent calls to - * read might succeed. + * must return null at the end of the input data set. In + * a transactional setting, caller might get the same item twice from successive calls + * (or otherwise), if the first call was in a transaction that rolled back. + * @throws ParseException if there is a problem parsing the current record (but the + * next one may still be valid) + * @throws NonTransientResourceException if there is a fatal exception in the + * underlying resource. After throwing this exception implementations should endeavour + * to return null from subsequent calls to read. + * @throws UnexpectedInputException if there is an uncategorised problem with the + * input data. Assume potentially transient, so subsequent calls to read might + * succeed. * @throws Exception if an there is a non-specific error. - * @return T the item to be processed or {@code null} if the data source is - * exhausted + * @return T the item to be processed or {@code null} if the data source is exhausted */ @Nullable T read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException; diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemReaderException.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemReaderException.java index 498678abf..9cfb49afa 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemReaderException.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemReaderException.java @@ -18,7 +18,7 @@ package org.springframework.batch.item; /** * A base exception class that all exceptions thrown from an {@link ItemReader} extend. - * + * * @author Ben Hale */ @SuppressWarnings("serial") @@ -26,7 +26,6 @@ public abstract class ItemReaderException extends RuntimeException { /** * Create a new {@link ItemReaderException} based on a message and another exception. - * * @param message the message for this exception * @param cause the other exception */ @@ -36,7 +35,6 @@ public abstract class ItemReaderException extends RuntimeException { /** * Create a new {@link ItemReaderException} based on a message. - * * @param message the message for this exception */ public ItemReaderException(String message) { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemStream.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemStream.java index e62bad860..5941ff145 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemStream.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemStream.java @@ -18,38 +18,40 @@ package org.springframework.batch.item; /** *

      - * Marker interface defining a contract for periodically storing state and restoring from that state should an error - * occur. + * Marker interface defining a contract for periodically storing state and restoring from + * that state should an error occur. *

      - * + * * @author Dave Syer * @author Lucas Ward * @author Mahmoud Ben Hassine - * + * */ public interface ItemStream { /** * Open the stream for the provided {@link ExecutionContext}. - * - * @param executionContext current step's {@link org.springframework.batch.item.ExecutionContext}. Will be the - * executionContext from the last run of the step on a restart. + * @param executionContext current step's + * {@link org.springframework.batch.item.ExecutionContext}. Will be the + * executionContext from the last run of the step on a restart. * @throws IllegalArgumentException if context is null */ void open(ExecutionContext executionContext) throws ItemStreamException; /** - * Indicates that the execution context provided during open is about to be saved. If any state is remaining, but - * has not been put in the context, it should be added here. - * + * Indicates that the execution context provided during open is about to be saved. If + * any state is remaining, but has not been put in the context, it should be added + * here. * @param executionContext to be updated * @throws IllegalArgumentException if executionContext is null. */ void update(ExecutionContext executionContext) throws ItemStreamException; /** - * If any resources are needed for the stream to operate they need to be destroyed here. Once this method has been - * called all other methods (except open) may throw an exception. + * If any resources are needed for the stream to operate they need to be destroyed + * here. Once this method has been called all other methods (except open) may throw an + * exception. */ void close() throws ItemStreamException; + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemStreamException.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemStreamException.java index a187629ef..162ed4e22 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemStreamException.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemStreamException.java @@ -17,7 +17,7 @@ package org.springframework.batch.item; /** * Exception representing any errors encountered while processing a stream. - * + * * @author Dave Syer * @author Lucas Ward */ @@ -33,10 +33,9 @@ public class ItemStreamException extends RuntimeException { /** * Constructs a new instance with a message and nested exception. - * * @param msg the exception message. * @param nested the cause of the exception. - * + * */ public ItemStreamException(String msg, Throwable nested) { super(msg, nested); @@ -44,10 +43,10 @@ public class ItemStreamException extends RuntimeException { /** * Constructs a new instance with a nested exception and empty message. - * * @param nested the cause of the exception. */ public ItemStreamException(Throwable nested) { super(nested); } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemStreamReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemStreamReader.java index 6cf96ef5f..da1f098ec 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemStreamReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemStreamReader.java @@ -1,26 +1,26 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item; - -/** - * Convenience interface that combines {@link ItemStream} and {@link ItemReader} - * . - * @author Dave Syer - * - */ -public interface ItemStreamReader extends ItemStream, ItemReader { - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item; + +/** + * Convenience interface that combines {@link ItemStream} and {@link ItemReader} . + * + * @author Dave Syer + * + */ +public interface ItemStreamReader extends ItemStream, ItemReader { + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemStreamSupport.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemStreamSupport.java index 87cf48557..0dd663b20 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemStreamSupport.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemStreamSupport.java @@ -51,12 +51,11 @@ public abstract class ItemStreamSupport implements ItemStream { @Override public void update(ExecutionContext executionContext) { } - + /** * The name of the component which will be used as a stem for keys in the - * {@link ExecutionContext}. Subclasses should provide a default value, e.g. - * the short form of the class name. - * + * {@link ExecutionContext}. Subclasses should provide a default value, e.g. the short + * form of the class name. * @param name the name for the component */ public void setName(String name) { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemStreamWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemStreamWriter.java index 47670a17d..fb4eca3ed 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemStreamWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemStreamWriter.java @@ -1,26 +1,26 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item; - -/** - * Convenience interface that combines {@link ItemStream} and {@link ItemWriter} - * . - * @author Dave Syer - * - */ -public interface ItemStreamWriter extends ItemStream, ItemWriter { - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item; + +/** + * Convenience interface that combines {@link ItemStream} and {@link ItemWriter} . + * + * @author Dave Syer + * + */ +public interface ItemStreamWriter extends ItemStream, ItemWriter { + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemWriter.java index 3279a5c6e..0323a204a 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemWriter.java @@ -20,31 +20,30 @@ import java.util.List; /** *

      - * Basic interface for generic output operations. Class implementing this - * interface will be responsible for serializing objects as necessary. - * Generally, it is responsibility of implementing class to decide which - * technology to use for mapping and how it should be configured. + * Basic interface for generic output operations. Class implementing this interface will + * be responsible for serializing objects as necessary. Generally, it is responsibility of + * implementing class to decide which technology to use for mapping and how it should be + * configured. *

      - * + * *

      - * The write method is responsible for making sure that any internal buffers are - * flushed. If a transaction is active it will also usually be necessary to - * discard the output on a subsequent rollback. The resource to which the writer - * is sending data should normally be able to handle this itself. + * The write method is responsible for making sure that any internal buffers are flushed. + * If a transaction is active it will also usually be necessary to discard the output on a + * subsequent rollback. The resource to which the writer is sending data should normally + * be able to handle this itself. *

      - * + * * @author Dave Syer * @author Lucas Ward */ public interface ItemWriter { /** - * Process the supplied data element. Will not be called with any null items - * in normal operation. - * + * Process the supplied data element. Will not be called with any null items in normal + * operation. * @param items items to be written - * @throws Exception if there are errors. The framework will catch the - * exception and convert or rethrow it as appropriate. + * @throws Exception if there are errors. The framework will catch the exception and + * convert or rethrow it as appropriate. */ void write(List items) throws Exception; diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemWriterException.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemWriterException.java index 67190090d..ffee7f0e8 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemWriterException.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ItemWriterException.java @@ -18,7 +18,7 @@ package org.springframework.batch.item; /** * A base exception class that all exceptions thrown from an {@link ItemWriter} extend. - * + * * @author Ben Hale */ @SuppressWarnings("serial") @@ -26,7 +26,6 @@ public abstract class ItemWriterException extends RuntimeException { /** * Create a new {@link ItemWriterException} based on a message and another exception. - * * @param message the message for this exception * @param cause the other exception */ @@ -36,7 +35,6 @@ public abstract class ItemWriterException extends RuntimeException { /** * Create a new {@link ItemWriterException} based on a message. - * * @param message the message for this exception */ public ItemWriterException(String message) { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/KeyValueItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/KeyValueItemWriter.java index b1e1141b6..ecf42abf2 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/KeyValueItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/KeyValueItemWriter.java @@ -1,11 +1,11 @@ /* * Copyright 2002-2021 the original author or authors. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at - * + * * https://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. @@ -19,9 +19,9 @@ import org.springframework.core.convert.converter.Converter; import org.springframework.util.Assert; /** - * A base class to implement any {@link ItemWriter} that writes to a key value store - * using a {@link Converter} to derive a key from an item - * + * A base class to implement any {@link ItemWriter} that writes to a key value store using + * a {@link Converter} to derive a key from an item + * * @author David Turanski * @since 2.2 * @@ -29,9 +29,12 @@ import org.springframework.util.Assert; public abstract class KeyValueItemWriter implements ItemWriter, InitializingBean { protected Converter itemKeyMapper; + protected boolean delete; - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.springframework.batch.item.ItemWriter#write(java.util.List) */ @Override @@ -48,10 +51,10 @@ public abstract class KeyValueItemWriter implements ItemWriter, Initial /** * Flush items to the key/value store. - * * @throws Exception if unable to flush items */ - protected void flush() throws Exception {} + protected void flush() throws Exception { + } /** * Subclasses implement this method to write each item to key value store @@ -67,7 +70,6 @@ public abstract class KeyValueItemWriter implements ItemWriter, Initial /** * Set the {@link Converter} to use to derive the key from the item - * * @param itemKeyMapper the {@link Converter} used to derive a key from an item. */ public void setItemKeyMapper(Converter itemKeyMapper) { @@ -76,15 +78,16 @@ public abstract class KeyValueItemWriter implements ItemWriter, Initial /** * Sets the delete flag to have the item writer perform deletes - * - * @param delete if true {@link ItemWriter} will perform deletes, - * if false not to perform deletes. + * @param delete if true {@link ItemWriter} will perform deletes, if false not to + * perform deletes. */ public void setDelete(boolean delete) { this.delete = delete; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() */ @Override @@ -92,4 +95,5 @@ public abstract class KeyValueItemWriter implements ItemWriter, Initial Assert.notNull(itemKeyMapper, "itemKeyMapper requires a Converter type."); init(); } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/NonTransientResourceException.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/NonTransientResourceException.java index 4e514199a..bc3f32aac 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/NonTransientResourceException.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/NonTransientResourceException.java @@ -16,18 +16,17 @@ package org.springframework.batch.item; /** - * Exception indicating that an error has been encountered doing I/O from a - * reader, and the exception should be considered fatal. - * + * Exception indicating that an error has been encountered doing I/O from a reader, and + * the exception should be considered fatal. + * * @author Dave Syer */ @SuppressWarnings("serial") public class NonTransientResourceException extends ItemReaderException { /** - * Create a new {@link NonTransientResourceException} based on a message and - * another exception. - * + * Create a new {@link NonTransientResourceException} based on a message and another + * exception. * @param message the message for this exception * @param cause the other exception */ @@ -37,7 +36,6 @@ public class NonTransientResourceException extends ItemReaderException { /** * Create a new {@link NonTransientResourceException} based on a message. - * * @param message the message for this exception */ public NonTransientResourceException(String message) { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ParseException.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ParseException.java index f3ab5fc68..6b07081f6 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ParseException.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ParseException.java @@ -16,8 +16,9 @@ package org.springframework.batch.item; /** - * Exception indicating that an error has been encountered parsing IO, typically from a file. - * + * Exception indicating that an error has been encountered parsing IO, typically from a + * file. + * * @author Lucas Ward * @author Ben Hale */ @@ -26,7 +27,6 @@ public class ParseException extends ItemReaderException { /** * Create a new {@link ParseException} based on a message and another exception. - * * @param message the message for this exception * @param cause the other exception */ @@ -36,7 +36,6 @@ public class ParseException extends ItemReaderException { /** * Create a new {@link ParseException} based on a message. - * * @param message the message for this exception */ public ParseException(String message) { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/PeekableItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/PeekableItemReader.java index 6058f02e9..4bf053738 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/PeekableItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/PeekableItemReader.java @@ -19,31 +19,29 @@ import org.springframework.lang.Nullable; /** *

      - * A specialisation of {@link ItemReader} that allows the user to look ahead - * into the stream of items. This is useful, for instance, when reading flat - * file data that contains record separator lines which are actually part of the - * next record. + * A specialisation of {@link ItemReader} that allows the user to look ahead into the + * stream of items. This is useful, for instance, when reading flat file data that + * contains record separator lines which are actually part of the next record. *

      - * + * *

      - * The detailed contract for {@link #peek()} has to be defined by the - * implementation because there is no general way to define it in a concurrent - * environment. The definition of "the next read()" operation is tenuous if - * multiple clients are reading concurrently, and the ability to peek implies - * that some state is likely to be stored, so implementations of - * {@link PeekableItemReader} may well be restricted to single threaded use. + * The detailed contract for {@link #peek()} has to be defined by the implementation + * because there is no general way to define it in a concurrent environment. The + * definition of "the next read()" operation is tenuous if multiple clients are reading + * concurrently, and the ability to peek implies that some state is likely to be stored, + * so implementations of {@link PeekableItemReader} may well be restricted to single + * threaded use. *

      - * + * * @author Dave Syer * @author Mahmoud Ben Hassine - * + * */ public interface PeekableItemReader extends ItemReader { /** - * Get the next item that would be returned by {@link #read()}, without - * affecting the result of {@link #read()}. - * + * Get the next item that would be returned by {@link #read()}, without affecting the + * result of {@link #read()}. * @return the next item or {@code null} if the data source is exhausted * @throws Exception if there is a problem */ diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ReaderNotOpenException.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ReaderNotOpenException.java index 6f17bec10..f6401ace3 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ReaderNotOpenException.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ReaderNotOpenException.java @@ -17,7 +17,7 @@ package org.springframework.batch.item; /** * Exception indicating that an {@link ItemReader} needed to be opened before read. - * + * * @author Ben Hale */ @SuppressWarnings("serial") @@ -25,7 +25,6 @@ public class ReaderNotOpenException extends ItemReaderException { /** * Create a new {@link ReaderNotOpenException} based on a message. - * * @param message the message for this exception */ public ReaderNotOpenException(String message) { @@ -33,12 +32,13 @@ public class ReaderNotOpenException extends ItemReaderException { } /** - * Create a new {@link ReaderNotOpenException} based on a message and another exception. - * + * Create a new {@link ReaderNotOpenException} based on a message and another + * exception. * @param msg the message for this exception * @param nested the other exception */ public ReaderNotOpenException(String msg, Throwable nested) { super(msg, nested); } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ResourceAware.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ResourceAware.java index 926f3a373..d28a23332 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ResourceAware.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ResourceAware.java @@ -19,13 +19,15 @@ import org.springframework.core.io.Resource; import org.springframework.batch.item.file.MultiResourceItemReader; /** - * Marker interface indicating that an item should have the Spring {@link Resource} in which it was read from, set on it. - * The canonical example is within {@link MultiResourceItemReader}, which will set the current resource on any items - * that implement this interface. + * Marker interface indicating that an item should have the Spring {@link Resource} in + * which it was read from, set on it. The canonical example is within + * {@link MultiResourceItemReader}, which will set the current resource on any items that + * implement this interface. * * @author Lucas Ward */ public interface ResourceAware { - void setResource(Resource resource); + void setResource(Resource resource); + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/SpELItemKeyMapper.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/SpELItemKeyMapper.java index 59a588c32..a4bb6ba18 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/SpELItemKeyMapper.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/SpELItemKeyMapper.java @@ -1,11 +1,11 @@ /* * Copyright 2002-2013 the original author or authors. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at - * + * * https://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. @@ -19,17 +19,23 @@ import org.springframework.expression.spel.standard.SpelExpressionParser; /** * An implementation of {@link Converter} that uses SpEL to map a Value to a key + * * @author David Turanski * @since 2.2 */ -public class SpELItemKeyMapper implements Converter { +public class SpELItemKeyMapper implements Converter { + private final ExpressionParser parser = new SpelExpressionParser(); + private final Expression parsedExpression; - + public SpELItemKeyMapper(String keyExpression) { - parsedExpression = parser.parseExpression(keyExpression); + parsedExpression = parser.parseExpression(keyExpression); } - /* (non-Javadoc) + + /* + * (non-Javadoc) + * * @see org.springframework.batch.item.ItemKeyMapper#mapKey(java.lang.Object) */ @SuppressWarnings("unchecked") @@ -37,4 +43,5 @@ public class SpELItemKeyMapper implements Converter { public K convert(V item) { return (K) parsedExpression.getValue(item); } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/UnexpectedInputException.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/UnexpectedInputException.java index 86a4efd16..9691e358a 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/UnexpectedInputException.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/UnexpectedInputException.java @@ -17,18 +17,18 @@ package org.springframework.batch.item; /** - * Used to signal an unexpected end of an input or message stream. This is an abnormal condition, not just the end of - * the data - e.g. if a resource becomes unavailable, or a stream becomes unreadable. - * + * Used to signal an unexpected end of an input or message stream. This is an abnormal + * condition, not just the end of the data - e.g. if a resource becomes unavailable, or a + * stream becomes unreadable. + * * @author Dave Syer * @author Ben Hale */ @SuppressWarnings("serial") public class UnexpectedInputException extends ItemReaderException { - + /** * Create a new {@link UnexpectedInputException} based on a message. - * * @param message the message for this exception */ public UnexpectedInputException(String message) { @@ -36,12 +36,13 @@ public class UnexpectedInputException extends ItemReaderException { } /** - * Create a new {@link UnexpectedInputException} based on a message and another exception. - * + * Create a new {@link UnexpectedInputException} based on a message and another + * exception. * @param msg the message for this exception * @param nested the other exception */ public UnexpectedInputException(String msg, Throwable nested) { super(msg, nested); } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/WriteFailedException.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/WriteFailedException.java index d82771ff8..be03047ed 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/WriteFailedException.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/WriteFailedException.java @@ -16,9 +16,9 @@ package org.springframework.batch.item; /** - * Unchecked exception indicating that an error has occurred while trying to - * clear a buffer on a rollback. - * + * Unchecked exception indicating that an error has occurred while trying to clear a + * buffer on a rollback. + * * @author Lucas Ward * @author Ben Hale */ @@ -26,9 +26,7 @@ package org.springframework.batch.item; public class WriteFailedException extends ItemWriterException { /** - * Create a new {@link WriteFailedException} based on a message and another - * exception. - * + * Create a new {@link WriteFailedException} based on a message and another exception. * @param message the message for this exception * @param cause the other exception */ @@ -38,7 +36,6 @@ public class WriteFailedException extends ItemWriterException { /** * Create a new {@link WriteFailedException} based on a message. - * * @param message the message for this exception */ public WriteFailedException(String message) { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/WriterNotOpenException.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/WriterNotOpenException.java index 30c26b378..29cbee216 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/WriterNotOpenException.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/WriterNotOpenException.java @@ -18,7 +18,7 @@ package org.springframework.batch.item; /** * Exception indicating that an {@link ItemWriter} needed to be opened before being * written to. - * + * * @author Lucas Ward */ @SuppressWarnings("serial") @@ -26,7 +26,6 @@ public class WriterNotOpenException extends ItemWriterException { /** * Create a new {@link WriterNotOpenException} based on a message. - * * @param message the message for this exception */ public WriterNotOpenException(String message) { @@ -34,12 +33,13 @@ public class WriterNotOpenException extends ItemWriterException { } /** - * Create a new {@link WriterNotOpenException} based on a message and another exception. - * + * Create a new {@link WriterNotOpenException} based on a message and another + * exception. * @param msg the message for this exception * @param nested the other exception */ public WriterNotOpenException(String msg, Throwable nested) { super(msg, nested); } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/adapter/AbstractMethodInvokingDelegator.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/adapter/AbstractMethodInvokingDelegator.java index 958555909..3152a6546 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/adapter/AbstractMethodInvokingDelegator.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/adapter/AbstractMethodInvokingDelegator.java @@ -28,14 +28,14 @@ import org.springframework.util.ClassUtils; import org.springframework.util.MethodInvoker; /** - * Superclass for delegating classes which dynamically call a custom method of - * injected object. Provides convenient API for dynamic method invocation - * shielding subclasses from low-level details and exception handling. + * Superclass for delegating classes which dynamically call a custom method of injected + * object. Provides convenient API for dynamic method invocation shielding subclasses from + * low-level details and exception handling. * - * {@link Exception}s thrown by a successfully invoked delegate method are - * re-thrown without wrapping. In case the delegate method throws a - * {@link Throwable} that doesn't subclass {@link Exception} it will be wrapped - * by {@link InvocationTargetThrowableWrapper}. + * {@link Exception}s thrown by a successfully invoked delegate method are re-thrown + * without wrapping. In case the delegate method throws a {@link Throwable} that doesn't + * subclass {@link Exception} it will be wrapped by + * {@link InvocationTargetThrowableWrapper}. * * @author Robert Kasanicky * @author Mahmoud Ben Hassine @@ -49,11 +49,8 @@ public abstract class AbstractMethodInvokingDelegator implements Initializing private Object[] arguments; /** - * Invoker the target method with arguments set by - * {@link #setArguments(Object[])}. - * + * Invoker the target method with arguments set by {@link #setArguments(Object[])}. * @return object returned by invoked method - * * @throws Exception exception thrown when executing the delegate method. */ protected T invokeDelegateMethod() throws Exception { @@ -64,10 +61,8 @@ public abstract class AbstractMethodInvokingDelegator implements Initializing /** * Invokes the target method with given argument. - * * @param object argument for the target method * @return object returned by target method - * * @throws Exception exception thrown when executing the delegate method. */ protected T invokeDelegateMethodWithArgument(Object object) throws Exception { @@ -78,10 +73,8 @@ public abstract class AbstractMethodInvokingDelegator implements Initializing /** * Invokes the target method with given arguments. - * * @param args arguments for the invoked method * @return object returned by invoked method - * * @throws Exception exception thrown when executing the delegate method. */ protected T invokeDelegateMethodWithArguments(Object[] args) throws Exception { @@ -140,8 +133,8 @@ public abstract class AbstractMethodInvokingDelegator implements Initializing } /** - * @return true if target class declares a method matching target method - * name with given number of arguments of appropriate type. + * @return true if target class declares a method matching target method name with + * given number of arguments of appropriate type. */ private boolean targetClassDeclaresTargetMethod() { MethodInvoker invoker = createMethodInvoker(targetObject, targetMethod); @@ -184,8 +177,8 @@ public abstract class AbstractMethodInvokingDelegator implements Initializing } /** - * @param targetObject the delegate - bean id can be used to set this value - * in Spring configuration + * @param targetObject the delegate - bean id can be used to set this value in Spring + * configuration */ public void setTargetObject(Object targetObject) { this.targetObject = targetObject; @@ -200,15 +193,14 @@ public abstract class AbstractMethodInvokingDelegator implements Initializing } /** - * @param arguments arguments values for the { - * {@link #setTargetMethod(String)}. These will be used only when the - * subclass tries to invoke the target method without providing explicit - * argument values. + * @param arguments arguments values for the { {@link #setTargetMethod(String)}. These + * will be used only when the subclass tries to invoke the target method without + * providing explicit argument values. * - * If arguments are set to not-null value {@link #afterPropertiesSet()} will - * check the values are compatible with target method's signature. In case - * arguments are null (not set) method signature will not be checked and it - * is assumed correct values will be supplied at runtime. + * If arguments are set to not-null value {@link #afterPropertiesSet()} will check the + * values are compatible with target method's signature. In case arguments are null + * (not set) method signature will not be checked and it is assumed correct values + * will be supplied at runtime. */ public void setArguments(Object[] arguments) { this.arguments = arguments == null ? null : Arrays.asList(arguments).toArray(); @@ -221,7 +213,7 @@ public abstract class AbstractMethodInvokingDelegator implements Initializing protected Object[] getArguments() { return arguments; } - + /** * Used to wrap a {@link Throwable} (not an {@link Exception}) thrown by a * reflectively-invoked delegate. @@ -236,4 +228,5 @@ public abstract class AbstractMethodInvokingDelegator implements Initializing } } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/adapter/DynamicMethodInvocationException.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/adapter/DynamicMethodInvocationException.java index 96358a9ba..d87d8bffa 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/adapter/DynamicMethodInvocationException.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/adapter/DynamicMethodInvocationException.java @@ -19,12 +19,12 @@ package org.springframework.batch.item.adapter; import org.springframework.util.MethodInvoker; /** - * Indicates an error has been encountered while trying to dynamically invoke a - * method e.g. using {@link MethodInvoker}. - * - * The exception should be caused by a failed invocation of a method, it - * shouldn't be used to wrap an exception thrown by successfully invoked method. - * + * Indicates an error has been encountered while trying to dynamically invoke a method + * e.g. using {@link MethodInvoker}. + * + * The exception should be caused by a failed invocation of a method, it shouldn't be used + * to wrap an exception thrown by successfully invoked method. + * * @author Robert Kasanicky */ public class DynamicMethodInvocationException extends RuntimeException { @@ -39,4 +39,5 @@ public class DynamicMethodInvocationException extends RuntimeException { public DynamicMethodInvocationException(String message, Throwable cause) { super(message, cause); } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/adapter/HippyMethodInvoker.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/adapter/HippyMethodInvoker.java index 2907094d1..452c60ddc 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/adapter/HippyMethodInvoker.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/adapter/HippyMethodInvoker.java @@ -22,12 +22,11 @@ import org.springframework.util.MethodInvoker; import org.springframework.util.ReflectionUtils; /** - * A {@link MethodInvoker} that is a bit relaxed about its arguments. You can - * give it arguments in the wrong order or you can give it too many arguments - * and it will try and find a method that matches a subset. - * + * A {@link MethodInvoker} that is a bit relaxed about its arguments. You can give it + * arguments in the wrong order or you can give it too many arguments and it will try and + * find a method that matches a subset. + * * @author Dave Syer - * * @since 2.1 */ public class HippyMethodInvoker extends MethodInvoker { @@ -78,4 +77,5 @@ public class HippyMethodInvoker extends MethodInvoker { return matchingMethod; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/adapter/ItemProcessorAdapter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/adapter/ItemProcessorAdapter.java index d5185bd16..1a640383c 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/adapter/ItemProcessorAdapter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/adapter/ItemProcessorAdapter.java @@ -20,12 +20,12 @@ import org.springframework.batch.item.ItemProcessor; import org.springframework.lang.Nullable; /** - * Invokes a custom method on a delegate plain old Java object which itself - * processes an item. + * Invokes a custom method on a delegate plain old Java object which itself processes an + * item. * * @author Dave Syer */ -public class ItemProcessorAdapter extends AbstractMethodInvokingDelegator implements ItemProcessor { +public class ItemProcessorAdapter extends AbstractMethodInvokingDelegator implements ItemProcessor { /** * Invoke the delegate method and return the result. diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/adapter/ItemReaderAdapter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/adapter/ItemReaderAdapter.java index 87377dd31..d89be4782 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/adapter/ItemReaderAdapter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/adapter/ItemReaderAdapter.java @@ -20,8 +20,8 @@ import org.springframework.batch.item.ItemReader; import org.springframework.lang.Nullable; /** - * Invokes a custom method on a delegate plain old Java object which itself - * provides an item. + * Invokes a custom method on a delegate plain old Java object which itself provides an + * item. * * @author Robert Kasanicky */ diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/adapter/ItemWriterAdapter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/adapter/ItemWriterAdapter.java index a276b12ce..384065e21 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/adapter/ItemWriterAdapter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/adapter/ItemWriterAdapter.java @@ -20,13 +20,11 @@ import java.util.List; import org.springframework.batch.item.ItemWriter; - /** - * Delegates item processing to a custom method - - * passes the item as an argument for the delegate method. + * Delegates item processing to a custom method - passes the item as an argument for the + * delegate method. * * @see PropertyExtractingDelegatingItemWriter - * * @author Robert Kasanicky */ public class ItemWriterAdapter extends AbstractMethodInvokingDelegator implements ItemWriter { @@ -39,4 +37,3 @@ public class ItemWriterAdapter extends AbstractMethodInvokingDelegator imp } } - diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/adapter/PropertyExtractingDelegatingItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/adapter/PropertyExtractingDelegatingItemWriter.java index db0d5a379..58da807d1 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/adapter/PropertyExtractingDelegatingItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/adapter/PropertyExtractingDelegatingItemWriter.java @@ -25,22 +25,20 @@ import org.springframework.beans.BeanWrapperImpl; import org.springframework.util.Assert; /** - * Delegates processing to a custom method - extracts property values from item - * object and uses them as arguments for the delegate method. + * Delegates processing to a custom method - extracts property values from item object and + * uses them as arguments for the delegate method. * * @see ItemWriterAdapter - * * @author Robert Kasanicky */ -public class PropertyExtractingDelegatingItemWriter extends AbstractMethodInvokingDelegator implements -ItemWriter { +public class PropertyExtractingDelegatingItemWriter extends AbstractMethodInvokingDelegator + implements ItemWriter { private String[] fieldsUsedAsTargetMethodArguments; /** - * Extracts values from item's fields named in - * fieldsUsedAsTargetMethodArguments and passes them as arguments to the - * delegate method. + * Extracts values from item's fields named in fieldsUsedAsTargetMethodArguments and + * passes them as arguments to the delegate method. */ @Override public void write(List items) throws Exception { @@ -66,13 +64,13 @@ ItemWriter { } /** - * @param fieldsUsedAsMethodArguments the values of the these item's fields - * will be used as arguments for the delegate method. Nested property values - * are supported, e.g. address.city + * @param fieldsUsedAsMethodArguments the values of the these item's fields will be + * used as arguments for the delegate method. Nested property values are supported, + * e.g. address.city */ public void setFieldsUsedAsTargetMethodArguments(String[] fieldsUsedAsMethodArguments) { - this.fieldsUsedAsTargetMethodArguments = Arrays.asList(fieldsUsedAsMethodArguments).toArray( - new String[fieldsUsedAsMethodArguments.length]); + this.fieldsUsedAsTargetMethodArguments = Arrays.asList(fieldsUsedAsMethodArguments) + .toArray(new String[fieldsUsedAsMethodArguments.length]); } } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/amqp/AmqpItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/amqp/AmqpItemReader.java index a198c8ee0..d74c58bf6 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/amqp/AmqpItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/amqp/AmqpItemReader.java @@ -24,21 +24,22 @@ import org.springframework.util.Assert; /** *

      - * AMQP {@link ItemReader} implementation using an {@link AmqpTemplate} to - * receive and/or convert messages. + * AMQP {@link ItemReader} implementation using an {@link AmqpTemplate} to receive and/or + * convert messages. *

      * * @author Chris Schaefer * @author Mahmoud Ben Hassine */ public class AmqpItemReader implements ItemReader { + private final AmqpTemplate amqpTemplate; + private Class itemType; /** * Initialize the AmqpItemReader. - * - * @param amqpTemplate the template to be used. Must not be null. + * @param amqpTemplate the template to be used. Must not be null. */ public AmqpItemReader(final AmqpTemplate amqpTemplate) { Assert.notNull(amqpTemplate, "AmqpTemplate must not be null"); @@ -66,11 +67,11 @@ public class AmqpItemReader implements ItemReader { /** * Establish the itemType for the reader. - * * @param itemType class type that will be returned by the reader. */ public void setItemType(Class itemType) { Assert.notNull(itemType, "Item type cannot be null"); this.itemType = itemType; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/amqp/AmqpItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/amqp/AmqpItemWriter.java index 691dd49ce..399040de2 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/amqp/AmqpItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/amqp/AmqpItemWriter.java @@ -26,32 +26,35 @@ import java.util.List; /** *

      - * AMQP {@link ItemWriter} implementation using an {@link AmqpTemplate} to - * send messages. Messages will be sent to the nameless exchange if not specified - * on the provided {@link AmqpTemplate}. + * AMQP {@link ItemWriter} implementation using an {@link AmqpTemplate} to send messages. + * Messages will be sent to the nameless exchange if not specified on the provided + * {@link AmqpTemplate}. *

      * * @author Chris Schaefer * @author Mahmoud Ben Hassine */ public class AmqpItemWriter implements ItemWriter { - private final AmqpTemplate amqpTemplate; - private final Log log = LogFactory.getLog(getClass()); - public AmqpItemWriter(final AmqpTemplate amqpTemplate) { - Assert.notNull(amqpTemplate, "AmqpTemplate must not be null"); + private final AmqpTemplate amqpTemplate; - this.amqpTemplate = amqpTemplate; - } + private final Log log = LogFactory.getLog(getClass()); - @Override - public void write(final List items) throws Exception { - if (log.isDebugEnabled()) { - log.debug("Writing to AMQP with " + items.size() + " items."); - } + public AmqpItemWriter(final AmqpTemplate amqpTemplate) { + Assert.notNull(amqpTemplate, "AmqpTemplate must not be null"); + + this.amqpTemplate = amqpTemplate; + } + + @Override + public void write(final List items) throws Exception { + if (log.isDebugEnabled()) { + log.debug("Writing to AMQP with " + items.size() + " items."); + } + + for (T item : items) { + amqpTemplate.convertAndSend(item); + } + } - for (T item : items) { - amqpTemplate.convertAndSend(item); - } - } } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/amqp/builder/AmqpItemReaderBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/amqp/builder/AmqpItemReaderBuilder.java index aeb4f246d..6f1619ad7 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/amqp/builder/AmqpItemReaderBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/amqp/builder/AmqpItemReaderBuilder.java @@ -59,17 +59,17 @@ public class AmqpItemReaderBuilder { /** * Validates and builds a {@link AmqpItemReader}. - * * @return a {@link AmqpItemReader} */ public AmqpItemReader build() { Assert.notNull(this.amqpTemplate, "amqpTemplate is required."); AmqpItemReader reader = new AmqpItemReader<>(this.amqpTemplate); - if(this.itemType != null) { + if (this.itemType != null) { reader.setItemType(this.itemType); } return reader; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/amqp/builder/AmqpItemWriterBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/amqp/builder/AmqpItemWriterBuilder.java index 37433a434..979a6ad99 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/amqp/builder/AmqpItemWriterBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/amqp/builder/AmqpItemWriterBuilder.java @@ -1,10 +1,10 @@ /* * Copyright 2017 the original author or authors. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software @@ -22,6 +22,7 @@ import org.springframework.util.Assert; /** * A builder implementation for the {@link AmqpItemWriter} + * * @author Glenn Renfro * @since 4.0 * @see AmqpItemWriter @@ -44,7 +45,6 @@ public class AmqpItemWriterBuilder { /** * Validates and builds a {@link AmqpItemWriter}. - * * @return a {@link AmqpItemWriter} */ public AmqpItemWriter build() { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/avro/AvroItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/avro/AvroItemReader.java index 3725ad5e6..aca9f4aa1 100755 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/avro/AvroItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/avro/AvroItemReader.java @@ -1,180 +1,182 @@ -/* - * Copyright 2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.avro; - -import java.io.IOException; -import java.io.InputStream; - -import org.apache.avro.Schema; -import org.apache.avro.file.DataFileStream; -import org.apache.avro.generic.GenericDatumReader; -import org.apache.avro.generic.GenericRecord; -import org.apache.avro.io.BinaryDecoder; -import org.apache.avro.io.DatumReader; -import org.apache.avro.io.DecoderFactory; -import org.apache.avro.reflect.ReflectDatumReader; -import org.apache.avro.specific.SpecificDatumReader; -import org.apache.avro.specific.SpecificRecordBase; - -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.ItemStreamException; -import org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader; -import org.springframework.core.io.Resource; -import org.springframework.lang.Nullable; -import org.springframework.util.Assert; - -/** - * An {@link ItemReader} that deserializes data from a {@link Resource} containing serialized Avro objects. - * - * @author David Turanski - * @author Mahmoud Ben Hassine - * @since 4.2 - */ -public class AvroItemReader extends AbstractItemCountingItemStreamItemReader { - - private boolean embeddedSchema = true; - - private InputStreamReader inputStreamReader; - - private DataFileStream dataFileReader; - - private InputStream inputStream; - - private DatumReader datumReader; - - /** - * - * @param resource the {@link Resource} containing objects serialized with Avro. - * @param clazz the data type to be deserialized. - */ - public AvroItemReader(Resource resource, Class clazz) { - Assert.notNull(resource, "'resource' is required."); - Assert.notNull(clazz, "'class' is required."); - - try { - this.inputStream = resource.getInputStream(); - this.datumReader = datumReaderForClass(clazz); - } - catch (IOException e) { - throw new IllegalArgumentException(e.getMessage(), e); - } - } - - /** - * - * @param data the {@link Resource} containing the data to be read. - * @param schema the {@link Resource} containing the Avro schema. - */ - public AvroItemReader(Resource data, Resource schema) { - Assert.notNull(data, "'data' is required."); - Assert.state(data.exists(), "'data' " + data.getFilename() +" does not exist."); - Assert.notNull(schema, "'schema' is required"); - Assert.state(schema.exists(), "'schema' " + schema.getFilename() +" does not exist."); - try { - this.inputStream = data.getInputStream(); - Schema avroSchema = new Schema.Parser().parse(schema.getInputStream()); - this.datumReader = new GenericDatumReader<>(avroSchema); - } - catch (IOException e) { - throw new IllegalArgumentException(e.getMessage(), e); - } - } - - /** - * Disable or enable reading an embedded Avro schema. True by default. - * @param embeddedSchema set to false to if the input does not embed an Avro schema. - */ - public void setEmbeddedSchema(boolean embeddedSchema) { - this.embeddedSchema = embeddedSchema; - } - - - @Nullable - @Override - protected T doRead() throws Exception { - if (this.inputStreamReader != null) { - return this.inputStreamReader.read(); - } - return this.dataFileReader.hasNext()? this.dataFileReader.next(): null; - } - - @Override - protected void doOpen() throws Exception { - initializeReader(); - } - - @Override - protected void doClose() throws Exception { - if (this.inputStreamReader != null) { - this.inputStreamReader.close(); - return; - } - this.dataFileReader.close(); - } - - private void initializeReader() throws IOException { - if (this.embeddedSchema) { - this.dataFileReader = new DataFileStream<>(this.inputStream, this.datumReader); - } else { - this.inputStreamReader = createInputStreamReader(this.inputStream, this.datumReader); - } - - } - - private InputStreamReader createInputStreamReader(InputStream inputStream, DatumReader datumReader) { - return new InputStreamReader<>(inputStream, datumReader); - } - - private static DatumReader datumReaderForClass(Class clazz) { - if (SpecificRecordBase.class.isAssignableFrom(clazz)){ - return new SpecificDatumReader<>(clazz); - } - if (GenericRecord.class.isAssignableFrom(clazz)) { - return new GenericDatumReader<>(); - } - return new ReflectDatumReader<>(clazz); - } - - - private static class InputStreamReader { - private final DatumReader datumReader; - - private final BinaryDecoder binaryDecoder; - - private final InputStream inputStream; - - private InputStreamReader(InputStream inputStream, DatumReader datumReader) { - this.inputStream = inputStream; - this.datumReader = datumReader; - this.binaryDecoder = DecoderFactory.get().binaryDecoder(inputStream, null); - } - - private T read() throws Exception { - if (!this.binaryDecoder.isEnd()) { - return this.datumReader.read(null, this.binaryDecoder); - } - return null; - } - - private void close() { - try { - this.inputStream.close(); - } catch (IOException e) { - throw new ItemStreamException(e.getMessage(), e); - } - } - } -} +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item.avro; + +import java.io.IOException; +import java.io.InputStream; + +import org.apache.avro.Schema; +import org.apache.avro.file.DataFileStream; +import org.apache.avro.generic.GenericDatumReader; +import org.apache.avro.generic.GenericRecord; +import org.apache.avro.io.BinaryDecoder; +import org.apache.avro.io.DatumReader; +import org.apache.avro.io.DecoderFactory; +import org.apache.avro.reflect.ReflectDatumReader; +import org.apache.avro.specific.SpecificDatumReader; +import org.apache.avro.specific.SpecificRecordBase; + +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemStreamException; +import org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader; +import org.springframework.core.io.Resource; +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; + +/** + * An {@link ItemReader} that deserializes data from a {@link Resource} containing + * serialized Avro objects. + * + * @author David Turanski + * @author Mahmoud Ben Hassine + * @since 4.2 + */ +public class AvroItemReader extends AbstractItemCountingItemStreamItemReader { + + private boolean embeddedSchema = true; + + private InputStreamReader inputStreamReader; + + private DataFileStream dataFileReader; + + private InputStream inputStream; + + private DatumReader datumReader; + + /** + * @param resource the {@link Resource} containing objects serialized with Avro. + * @param clazz the data type to be deserialized. + */ + public AvroItemReader(Resource resource, Class clazz) { + Assert.notNull(resource, "'resource' is required."); + Assert.notNull(clazz, "'class' is required."); + + try { + this.inputStream = resource.getInputStream(); + this.datumReader = datumReaderForClass(clazz); + } + catch (IOException e) { + throw new IllegalArgumentException(e.getMessage(), e); + } + } + + /** + * @param data the {@link Resource} containing the data to be read. + * @param schema the {@link Resource} containing the Avro schema. + */ + public AvroItemReader(Resource data, Resource schema) { + Assert.notNull(data, "'data' is required."); + Assert.state(data.exists(), "'data' " + data.getFilename() + " does not exist."); + Assert.notNull(schema, "'schema' is required"); + Assert.state(schema.exists(), "'schema' " + schema.getFilename() + " does not exist."); + try { + this.inputStream = data.getInputStream(); + Schema avroSchema = new Schema.Parser().parse(schema.getInputStream()); + this.datumReader = new GenericDatumReader<>(avroSchema); + } + catch (IOException e) { + throw new IllegalArgumentException(e.getMessage(), e); + } + } + + /** + * Disable or enable reading an embedded Avro schema. True by default. + * @param embeddedSchema set to false to if the input does not embed an Avro schema. + */ + public void setEmbeddedSchema(boolean embeddedSchema) { + this.embeddedSchema = embeddedSchema; + } + + @Nullable + @Override + protected T doRead() throws Exception { + if (this.inputStreamReader != null) { + return this.inputStreamReader.read(); + } + return this.dataFileReader.hasNext() ? this.dataFileReader.next() : null; + } + + @Override + protected void doOpen() throws Exception { + initializeReader(); + } + + @Override + protected void doClose() throws Exception { + if (this.inputStreamReader != null) { + this.inputStreamReader.close(); + return; + } + this.dataFileReader.close(); + } + + private void initializeReader() throws IOException { + if (this.embeddedSchema) { + this.dataFileReader = new DataFileStream<>(this.inputStream, this.datumReader); + } + else { + this.inputStreamReader = createInputStreamReader(this.inputStream, this.datumReader); + } + + } + + private InputStreamReader createInputStreamReader(InputStream inputStream, DatumReader datumReader) { + return new InputStreamReader<>(inputStream, datumReader); + } + + private static DatumReader datumReaderForClass(Class clazz) { + if (SpecificRecordBase.class.isAssignableFrom(clazz)) { + return new SpecificDatumReader<>(clazz); + } + if (GenericRecord.class.isAssignableFrom(clazz)) { + return new GenericDatumReader<>(); + } + return new ReflectDatumReader<>(clazz); + } + + private static class InputStreamReader { + + private final DatumReader datumReader; + + private final BinaryDecoder binaryDecoder; + + private final InputStream inputStream; + + private InputStreamReader(InputStream inputStream, DatumReader datumReader) { + this.inputStream = inputStream; + this.datumReader = datumReader; + this.binaryDecoder = DecoderFactory.get().binaryDecoder(inputStream, null); + } + + private T read() throws Exception { + if (!this.binaryDecoder.isEnd()) { + return this.datumReader.read(null, this.binaryDecoder); + } + return null; + } + + private void close() { + try { + this.inputStream.close(); + } + catch (IOException e) { + throw new ItemStreamException(e.getMessage(), e); + } + } + + } + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/avro/AvroItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/avro/AvroItemWriter.java index f82992c25..66ade7282 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/avro/AvroItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/avro/AvroItemWriter.java @@ -62,9 +62,7 @@ public class AvroItemWriter extends AbstractItemStreamItemWriter { private boolean embedSchema = true; - /** - * * @param resource a {@link WritableResource} to which the objects will be serialized. * @param schema a {@link Resource} containing the Avro schema. * @param clazz the data type to be serialized. @@ -77,7 +75,6 @@ public class AvroItemWriter extends AbstractItemStreamItemWriter { /** * This constructor will create an ItemWriter that does not embedded Avro schema. - * * @param resource a {@link WritableResource} to which the objects will be serialized. * @param clazz the data type to be serialized. */ @@ -111,7 +108,8 @@ public class AvroItemWriter extends AbstractItemStreamItemWriter { super.open(executionContext); try { initializeWriter(); - } catch (IOException e) { + } + catch (IOException e) { throw new ItemStreamException(e.getMessage(), e); } } @@ -131,7 +129,7 @@ public class AvroItemWriter extends AbstractItemStreamItemWriter { } } - private void initializeWriter() throws IOException { + private void initializeWriter() throws IOException { Assert.notNull(this.resource, "'resource' is required."); Assert.notNull(this.clazz, "'class' is required."); @@ -142,12 +140,14 @@ public class AvroItemWriter extends AbstractItemStreamItemWriter { Schema schema; try { schema = new Schema.Parser().parse(this.schemaResource.getInputStream()); - } catch (IOException e) { + } + catch (IOException e) { throw new IllegalArgumentException(e.getMessage(), e); } this.dataFileWriter = new DataFileWriter<>(datumWriterForClass(this.clazz)); this.dataFileWriter.create(schema, this.resource.getOutputStream()); - } else { + } + else { this.outputStreamWriter = createOutputStreamWriter(this.resource.getOutputStream(), datumWriterForClass(this.clazz)); } @@ -155,7 +155,7 @@ public class AvroItemWriter extends AbstractItemStreamItemWriter { } private static DatumWriter datumWriterForClass(Class clazz) { - if (SpecificRecordBase.class.isAssignableFrom(clazz)){ + if (SpecificRecordBase.class.isAssignableFrom(clazz)) { return new SpecificDatumWriter<>(clazz); } if (GenericRecord.class.isAssignableFrom(clazz)) { @@ -170,6 +170,7 @@ public class AvroItemWriter extends AbstractItemStreamItemWriter { } private static class OutputStreamWriter { + private final DatumWriter datumWriter; private final BinaryEncoder binaryEncoder; @@ -195,5 +196,7 @@ public class AvroItemWriter extends AbstractItemStreamItemWriter { throw new ItemStreamException(e.getMessage(), e); } } + } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/avro/builder/AvroItemReaderBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/avro/builder/AvroItemReaderBuilder.java index fb080f203..c9803e259 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/avro/builder/AvroItemReaderBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/avro/builder/AvroItemReaderBuilder.java @@ -47,8 +47,7 @@ public class AvroItemReaderBuilder { private Class type; - private boolean embeddedSchema =true; - + private boolean embeddedSchema = true; /** * Configure a {@link Resource} containing Avro serialized objects. @@ -62,7 +61,6 @@ public class AvroItemReaderBuilder { return this; } - /** * Configure an Avro {@link Schema} from a {@link Resource}. * @param schema an existing schema Resource. @@ -100,7 +98,7 @@ public class AvroItemReaderBuilder { /** * Disable or enable reading an embedded Avro schema. True by default. * @param embeddedSchema set to false to if the input does not contain an Avro schema. - * @return The current instance of the builder. + * @return The current instance of the builder. */ public AvroItemReaderBuilder embeddedSchema(boolean embeddedSchema) { this.embeddedSchema = embeddedSchema; @@ -108,10 +106,9 @@ public class AvroItemReaderBuilder { } /** - * Configure if the state of the {@link org.springframework.batch.item.ItemStreamSupport} - * should be persisted within the {@link org.springframework.batch.item.ExecutionContext} - * for restart purposes. - * + * Configure if the state of the + * {@link org.springframework.batch.item.ItemStreamSupport} should be persisted within + * the {@link org.springframework.batch.item.ExecutionContext} for restart purposes. * @param saveState defaults to true * @return The current instance of the builder. */ @@ -124,7 +121,6 @@ public class AvroItemReaderBuilder { * The name used to calculate the key within the * {@link org.springframework.batch.item.ExecutionContext}. Required if * {@link #saveState(boolean)} is set to true. - * * @param name name of the reader instance * @return The current instance of the builder. * @see org.springframework.batch.item.ItemStreamSupport#setName(String) @@ -136,7 +132,6 @@ public class AvroItemReaderBuilder { /** * Configure the max number of items to be read. - * * @param maxItemCount the max items to be read * @return The current instance of the builder. * @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setMaxItemCount(int) @@ -148,7 +143,6 @@ public class AvroItemReaderBuilder { /** * Index for the current item. Used on restarts to indicate where to start from. - * * @param currentItemCount current index * @return this instance for method chaining * @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setCurrentItemCount(int) @@ -158,7 +152,6 @@ public class AvroItemReaderBuilder { return this; } - /** * Build an instance of {@link AvroItemReader}. * @return the instance; @@ -177,9 +170,8 @@ public class AvroItemReaderBuilder { avroItemReader.setSaveState(this.saveState); - if(this.saveState) { - Assert.state(StringUtils.hasText(this.name), - "A name is required when saveState is set to true."); + if (this.saveState) { + Assert.state(StringUtils.hasText(this.name), "A name is required when saveState is set to true."); } avroItemReader.setName(this.name); @@ -190,7 +182,6 @@ public class AvroItemReaderBuilder { return avroItemReader; } - private AvroItemReader buildForType() { Assert.isNull(this.schema, "You cannot specify a schema and 'type'."); return new AvroItemReader<>(this.resource, this.type); @@ -201,5 +192,4 @@ public class AvroItemReaderBuilder { return new AvroItemReader<>(this.resource, this.schema); } - } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/avro/builder/AvroItemWriterBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/avro/builder/AvroItemWriterBuilder.java index a929991b2..69c9eb85c 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/avro/builder/AvroItemWriterBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/avro/builder/AvroItemWriterBuilder.java @@ -30,16 +30,16 @@ import org.springframework.util.Assert; * @since 4.2 */ public class AvroItemWriterBuilder { + private Class type; private WritableResource resource; private Resource schema; - private String name = AvroItemWriter.class.getSimpleName(); + private String name = AvroItemWriter.class.getSimpleName(); /** - * * @param resource the {@link WritableResource} used to write the serialized data. * @return The current instance of the builder. */ @@ -50,7 +50,6 @@ public class AvroItemWriterBuilder { } /** - * * @param schema the Resource containing the schema JSON used to serialize the output. * @return The current instance of the builder. */ @@ -61,10 +60,9 @@ public class AvroItemWriterBuilder { return this; } - /** - * - * @param schemaString the String containing the schema JSON used to serialize the output. + * @param schemaString the String containing the schema JSON used to serialize the + * output. * @return The current instance of the builder. */ public AvroItemWriterBuilder schema(String schemaString) { @@ -73,9 +71,7 @@ public class AvroItemWriterBuilder { return this; } - /** - * * @param type the Class of objects to be serialized. * @return The current instance of the builder. */ @@ -88,7 +84,6 @@ public class AvroItemWriterBuilder { /** * The name used to calculate the key within the * {@link org.springframework.batch.item.ExecutionContext}. - * * @param name name of the reader instance * @return The current instance of the builder. * @see org.springframework.batch.item.ItemStreamSupport#setName(String) @@ -101,7 +96,6 @@ public class AvroItemWriterBuilder { /** * Build an instance of {@link AvroItemWriter}. - * * @return the instance; */ public AvroItemWriter build() { @@ -110,9 +104,9 @@ public class AvroItemWriterBuilder { Assert.notNull(this.type, "A 'type' is required."); - AvroItemWriter avroItemWriter = this.schema != null ? - new AvroItemWriter<>(this.resource, this.schema, this.type): - new AvroItemWriter<>(this.resource, this.type); + AvroItemWriter avroItemWriter = this.schema != null + ? new AvroItemWriter<>(this.resource, this.schema, this.type) + : new AvroItemWriter<>(this.resource, this.type); avroItemWriter.setName(this.name); return avroItemWriter; } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/AbstractPaginatedDataItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/AbstractPaginatedDataItemReader.java index 2c1604ce1..2965b27c6 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/AbstractPaginatedDataItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/AbstractPaginatedDataItemReader.java @@ -24,17 +24,16 @@ import org.springframework.util.Assert; import java.util.Iterator; /** - * A base class that handles basic reading logic based on the paginated - * semantics of Spring Data's paginated facilities. It also handles the - * semantics required for restartability based on those facilities. - * + * A base class that handles basic reading logic based on the paginated semantics of + * Spring Data's paginated facilities. It also handles the semantics required for + * restartability based on those facilities. + * * @author Michael Minella * @author Glenn Renfro * @since 2.2 * @param Type of item to be read */ -public abstract class AbstractPaginatedDataItemReader extends -AbstractItemCountingItemStreamItemReader { +public abstract class AbstractPaginatedDataItemReader extends AbstractItemCountingItemStreamItemReader { protected volatile int page = 0; @@ -46,8 +45,7 @@ AbstractItemCountingItemStreamItemReader { /** * The number of items to be read with each page. - * - * @param pageSize the number of items. pageSize must be greater than zero. + * @param pageSize the number of items. pageSize must be greater than zero. */ public void setPageSize(int pageSize) { Assert.isTrue(pageSize > 0, "pageSize must be greater than zero"); @@ -59,19 +57,18 @@ AbstractItemCountingItemStreamItemReader { protected T doRead() throws Exception { synchronized (lock) { - if(results == null || !results.hasNext()) { + if (results == null || !results.hasNext()) { results = doPageRead(); - page ++; + page++; - if(results == null || !results.hasNext()) { + if (results == null || !results.hasNext()) { return null; } } - - if(results.hasNext()) { + if (results.hasNext()) { return results.next(); } else { @@ -81,15 +78,12 @@ AbstractItemCountingItemStreamItemReader { } /** - * Method this {@link ItemStreamReader} delegates to - * for the actual work of reading a page. Each time - * this method is called, the resulting {@link Iterator} - * should contain the items read within the next page. - *

      - * If the {@link Iterator} is empty or null when it is - * returned, this {@link ItemReader} will assume that the - * input has been exhausted. - * + * Method this {@link ItemStreamReader} delegates to for the actual work of reading a + * page. Each time this method is called, the resulting {@link Iterator} should + * contain the items read within the next page.
      + *
      + * If the {@link Iterator} is empty or null when it is returned, this + * {@link ItemReader} will assume that the input has been exhausted. * @return an {@link Iterator} containing the items within a page. */ protected abstract Iterator doPageRead(); @@ -110,9 +104,10 @@ AbstractItemCountingItemStreamItemReader { Iterator initialPage = doPageRead(); - for(; current >= 0; current--) { + for (; current >= 0; current--) { initialPage.next(); } } } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/GemfireItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/GemfireItemWriter.java index e37be4bff..4921af899 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/GemfireItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/GemfireItemWriter.java @@ -1,11 +1,11 @@ /* * Copyright 2002-2013 the original author or authors. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at - * + * * https://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. @@ -20,13 +20,15 @@ import org.springframework.util.Assert; /** * An {@link ItemWriter} that stores items in GemFire - * + * * @author David Turanski * @since 2.2 * */ -public class GemfireItemWriter extends KeyValueItemWriter { +public class GemfireItemWriter extends KeyValueItemWriter { + private GemfireOperations gemfireTemplate; + /** * @param gemfireTemplate the {@link GemfireTemplate} to set */ @@ -34,19 +36,26 @@ public class GemfireItemWriter extends KeyValueItemWriter { this.gemfireTemplate = gemfireTemplate; } - /* (non-Javadoc) - * @see org.springframework.batch.item.KeyValueItemWriter#writeKeyValue(java.lang.Object, java.lang.Object) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.item.KeyValueItemWriter#writeKeyValue(java.lang.Object, + * java.lang.Object) */ @Override protected void writeKeyValue(K key, V value) { if (delete) { gemfireTemplate.remove(key); - } else { + } + else { gemfireTemplate.put(key, value); } } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.springframework.batch.item.KeyValueItemWriter#init() */ @Override diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/MongoItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/MongoItemReader.java index 734fce0ad..c902e2ab6 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/MongoItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/MongoItemReader.java @@ -41,39 +41,38 @@ import org.springframework.util.StringUtils; /** *

      - * Restartable {@link ItemReader} that reads documents from MongoDB - * via a paging technique. + * Restartable {@link ItemReader} that reads documents from MongoDB via a paging + * technique. *

      * *

      - * If you set JSON String query {@link #setQuery(String)} then - * it executes the JSON to retrieve the requested documents. + * If you set JSON String query {@link #setQuery(String)} then it executes the JSON to + * retrieve the requested documents. *

      - * + * *

      - * If you set Query object {@link #setQuery(Query)} then - * it executes the Query to retrieve the requested documents. + * If you set Query object {@link #setQuery(Query)} then it executes the Query to retrieve + * the requested documents. *

      - * + * *

      - * The query is executed using paged requests specified in the - * {@link #setPageSize(int)}. Additional pages are requested as needed to - * provide data when the {@link #read()} method is called. + * The query is executed using paged requests specified in the {@link #setPageSize(int)}. + * Additional pages are requested as needed to provide data when the {@link #read()} + * method is called. *

      * *

      * The JSON String query provided supports parameter substitution via ?<index> - * placeholders where the <index> indicates the index of the - * parameterValue to substitute. + * placeholders where the <index> indicates the index of the parameterValue to + * substitute. *

      * *

      - * The implementation is thread-safe between calls to - * {@link #open(ExecutionContext)}, but remember to use saveState=false - * if used in a multi-threaded client (no restart available). + * The implementation is thread-safe between calls to {@link #open(ExecutionContext)}, but + * remember to use saveState=false if used in a multi-threaded client (no + * restart available). *

      * - * * @author Michael Minella * @author Takaaki Iida * @author Mahmoud Ben Hassine @@ -82,23 +81,30 @@ import org.springframework.util.StringUtils; public class MongoItemReader extends AbstractPaginatedDataItemReader implements InitializingBean { private MongoOperations template; + private Query query; + private String queryString; + private Class type; + private Sort sort; + private String hint; + private String fields; + private String collection; + private List parameterValues = new ArrayList<>(); public MongoItemReader() { super(); setName(ClassUtils.getShortName(MongoItemReader.class)); } - + /** * A Mongo Query to be used. - * * @param query Mongo Query to be used. */ public void setQuery(Query query) { @@ -106,9 +112,8 @@ public class MongoItemReader extends AbstractPaginatedDataItemReader imple } /** - * Used to perform operations against the MongoDB instance. Also - * handles the mapping of documents to objects. - * + * Used to perform operations against the MongoDB instance. Also handles the mapping + * of documents to objects. * @param template the MongoOperations instance to use * @see MongoOperations */ @@ -117,10 +122,9 @@ public class MongoItemReader extends AbstractPaginatedDataItemReader imple } /** - * A JSON formatted MongoDB query. Parameterization of the provided query is allowed + * A JSON formatted MongoDB query. Parameterization of the provided query is allowed * via ?<index> placeholders where the <index> indicates the index of the * parameterValue to substitute. - * * @param queryString JSON formatted Mongo query */ public void setQuery(String queryString) { @@ -129,7 +133,6 @@ public class MongoItemReader extends AbstractPaginatedDataItemReader imple /** * The type of object to be returned for each {@link #read()} call. - * * @param type the type of object to return */ public void setTargetType(Class type) { @@ -137,9 +140,8 @@ public class MongoItemReader extends AbstractPaginatedDataItemReader imple } /** - * {@link List} of values to be substituted in for each of the - * parameters in the query. - * + * {@link List} of values to be substituted in for each of the parameters in the + * query. * @param parameterValues values */ public void setParameterValues(List parameterValues) { @@ -148,9 +150,7 @@ public class MongoItemReader extends AbstractPaginatedDataItemReader imple } /** - * JSON defining the fields to be returned from the matching documents - * by MongoDB. - * + * JSON defining the fields to be returned from the matching documents by MongoDB. * @param fields JSON string that identifies the fields to sort by. */ public void setFields(String fields) { @@ -158,9 +158,9 @@ public class MongoItemReader extends AbstractPaginatedDataItemReader imple } /** - * {@link Map} of property names/{@link org.springframework.data.domain.Sort.Direction} values to - * sort the input by. - * + * {@link Map} of property + * names/{@link org.springframework.data.domain.Sort.Direction} values to sort the + * input by. * @param sorts map of properties and direction to sort each. */ public void setSort(Map sorts) { @@ -177,7 +177,6 @@ public class MongoItemReader extends AbstractPaginatedDataItemReader imple /** * JSON String telling MongoDB what index to use. - * * @param hint string indicating what index to use. */ public void setHint(String hint) { @@ -189,37 +188,40 @@ public class MongoItemReader extends AbstractPaginatedDataItemReader imple protected Iterator doPageRead() { if (queryString != null) { Pageable pageRequest = PageRequest.of(page, pageSize, sort); - + String populatedQuery = replacePlaceholders(queryString, parameterValues); - + Query mongoQuery; - - if(StringUtils.hasText(fields)) { + + if (StringUtils.hasText(fields)) { mongoQuery = new BasicQuery(populatedQuery, fields); } else { mongoQuery = new BasicQuery(populatedQuery); } - + mongoQuery.with(pageRequest); - - if(StringUtils.hasText(hint)) { + + if (StringUtils.hasText(hint)) { mongoQuery.withHint(hint); } - - if(StringUtils.hasText(collection)) { + + if (StringUtils.hasText(collection)) { return (Iterator) template.find(mongoQuery, type, collection).iterator(); - } else { + } + else { return (Iterator) template.find(mongoQuery, type).iterator(); } - - } else { + + } + else { Pageable pageRequest = PageRequest.of(page, pageSize); query.with(pageRequest); - - if(StringUtils.hasText(collection)) { + + if (StringUtils.hasText(collection)) { return (Iterator) template.find(query, type, collection).iterator(); - } else { + } + else { return (Iterator) template.find(query, type).iterator(); } } @@ -235,7 +237,7 @@ public class MongoItemReader extends AbstractPaginatedDataItemReader imple Assert.state(template != null, "An implementation of MongoOperations is required."); Assert.state(type != null, "A type to convert the input into is required."); Assert.state(queryString != null || query != null, "A query is required."); - + if (queryString != null) { Assert.state(sort != null, "A sort is required."); } @@ -257,4 +259,5 @@ public class MongoItemReader extends AbstractPaginatedDataItemReader imple return Sort.by(sortValues); } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/MongoItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/MongoItemWriter.java index 75a25e42f..85fff8b46 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/MongoItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/MongoItemWriter.java @@ -40,15 +40,16 @@ import org.springframework.util.StringUtils; /** *

      - * A {@link ItemWriter} implementation that writes to a MongoDB store using an implementation of Spring Data's - * {@link MongoOperations}. Since MongoDB is not a transactional store, a best effort is made to persist - * written data at the last moment, yet still honor job status contracts. No attempt to roll back is made - * if an error occurs during writing. + * A {@link ItemWriter} implementation that writes to a MongoDB store using an + * implementation of Spring Data's {@link MongoOperations}. Since MongoDB is not a + * transactional store, a best effort is made to persist written data at the last moment, + * yet still honor job status contracts. No attempt to roll back is made if an error + * occurs during writing. *

      * *

      - * This writer is thread-safe once all properties are set (normal singleton behavior) so it can be used in multiple - * concurrent transactions. + * This writer is thread-safe once all properties are set (normal singleton behavior) so + * it can be used in multiple concurrent transactions. *

      * * @author Michael Minella @@ -59,9 +60,13 @@ import org.springframework.util.StringUtils; public class MongoItemWriter implements ItemWriter, InitializingBean { private static final String ID_KEY = "_id"; + private MongoOperations template; + private final Object bufferKey; + private String collection; + private boolean delete = false; public MongoItemWriter() { @@ -70,10 +75,9 @@ public class MongoItemWriter implements ItemWriter, InitializingBean { } /** - * Indicates if the items being passed to the writer are to be saved or - * removed from the data store. If set to false (default), the items will - * be saved. If set to true, the items will be removed. - * + * Indicates if the items being passed to the writer are to be saved or removed from + * the data store. If set to false (default), the items will be saved. If set to true, + * the items will be removed. * @param delete removal indicator */ public void setDelete(boolean delete) { @@ -82,7 +86,6 @@ public class MongoItemWriter implements ItemWriter, InitializingBean { /** * Set the {@link MongoOperations} to be used to save items to be written. - * * @param template the template implementation to be used. */ public void setTemplate(MongoOperations template) { @@ -90,9 +93,8 @@ public class MongoItemWriter implements ItemWriter, InitializingBean { } /** - * Get the {@link MongoOperations} to be used to save items to be written. - * This can be called by a subclass if necessary. - * + * Get the {@link MongoOperations} to be used to save items to be written. This can be + * called by a subclass if necessary. * @return template the template implementation to be used. */ protected MongoOperations getTemplate() { @@ -101,7 +103,6 @@ public class MongoItemWriter implements ItemWriter, InitializingBean { /** * Set the name of the Mongo collection to be written to. - * * @param collection the name of the collection. */ public void setCollection(String collection) { @@ -116,7 +117,7 @@ public class MongoItemWriter implements ItemWriter, InitializingBean { */ @Override public void write(List items) throws Exception { - if(!transactionActive()) { + if (!transactionActive()) { doWrite(items); return; } @@ -126,9 +127,8 @@ public class MongoItemWriter implements ItemWriter, InitializingBean { } /** - * Performs the actual write to the store via the template. - * This can be overridden by a subclass if necessary. - * + * Performs the actual write to the store via the template. This can be overridden by + * a subclass if necessary. * @param items the list of items to be persisted. */ protected void doWrite(List items) { @@ -188,7 +188,7 @@ public class MongoItemWriter implements ItemWriter, InitializingBean { @SuppressWarnings("unchecked") private List getCurrentBuffer() { - if(!TransactionSynchronizationManager.hasResource(bufferKey)) { + if (!TransactionSynchronizationManager.hasResource(bufferKey)) { TransactionSynchronizationManager.bindResource(bufferKey, new ArrayList()); TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { @@ -196,8 +196,8 @@ public class MongoItemWriter implements ItemWriter, InitializingBean { public void beforeCommit(boolean readOnly) { List items = (List) TransactionSynchronizationManager.getResource(bufferKey); - if(!CollectionUtils.isEmpty(items)) { - if(!readOnly) { + if (!CollectionUtils.isEmpty(items)) { + if (!readOnly) { doWrite(items); } } @@ -205,7 +205,7 @@ public class MongoItemWriter implements ItemWriter, InitializingBean { @Override public void afterCompletion(int status) { - if(TransactionSynchronizationManager.hasResource(bufferKey)) { + if (TransactionSynchronizationManager.hasResource(bufferKey)) { TransactionSynchronizationManager.unbindResource(bufferKey); } } @@ -219,4 +219,5 @@ public class MongoItemWriter implements ItemWriter, InitializingBean { public void afterPropertiesSet() throws Exception { Assert.state(template != null, "A MongoOperations implementation is required."); } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/Neo4jItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/Neo4jItemReader.java index 420214dd0..a58b51a92 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/Neo4jItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/Neo4jItemReader.java @@ -32,34 +32,33 @@ import org.springframework.util.StringUtils; /** *

      - * Restartable {@link ItemReader} that reads objects from the graph database Neo4j - * via a paging technique. + * Restartable {@link ItemReader} that reads objects from the graph database Neo4j via a + * paging technique. *

      * *

      - * It executes cypher queries built from the statement fragments provided to - * retrieve the requested data. The query is executed using paged requests of - * a size specified in {@link #setPageSize(int)}. Additional pages are requested - * as needed when the {@link #read()} method is called. On restart, the reader - * will begin again at the same number item it left off at. + * It executes cypher queries built from the statement fragments provided to retrieve the + * requested data. The query is executed using paged requests of a size specified in + * {@link #setPageSize(int)}. Additional pages are requested as needed when the + * {@link #read()} method is called. On restart, the reader will begin again at the same + * number item it left off at. *

      * *

      - * Performance is dependent on your Neo4J configuration (embedded or remote) as - * well as page size. Setting a fairly large page size and using a commit - * interval that matches the page size should provide better performance. + * Performance is dependent on your Neo4J configuration (embedded or remote) as well as + * page size. Setting a fairly large page size and using a commit interval that matches + * the page size should provide better performance. *

      * *

      * This implementation is thread-safe between calls to - * {@link #open(org.springframework.batch.item.ExecutionContext)}, however you - * should set saveState=false if used in a multi-threaded - * environment (no restart available). + * {@link #open(org.springframework.batch.item.ExecutionContext)}, however you should set + * saveState=false if used in a multi-threaded environment (no restart + * available). *

      * * @author Michael Minella * @author Mahmoud Ben Hassine - * * @deprecated since 5.0 in favor of the item reader from * https://github.com/spring-projects/spring-batch-extensions/blob/main/spring-batch-neo4j */ @@ -71,9 +70,13 @@ public class Neo4jItemReader extends AbstractPaginatedDataItemReader imple private SessionFactory sessionFactory; private String startStatement; + private String returnStatement; + private String matchStatement; + private String whereStatement; + private String orderByStatement; private Class targetType; @@ -82,7 +85,6 @@ public class Neo4jItemReader extends AbstractPaginatedDataItemReader imple /** * Optional parameters to be used in the cypher query. - * * @param parameterValues the parameter values to be used in the cypher query */ public void setParameterValues(Map parameterValues) { @@ -94,10 +96,8 @@ public class Neo4jItemReader extends AbstractPaginatedDataItemReader imple } /** - * The start segment of the cypher query. START is prepended - * to the statement provided and should not be - * included. - * + * The start segment of the cypher query. START is prepended to the statement provided + * and should not be included. * @param startStatement the start fragment of the cypher query. */ public void setStartStatement(String startStatement) { @@ -105,10 +105,8 @@ public class Neo4jItemReader extends AbstractPaginatedDataItemReader imple } /** - * The return statement of the cypher query. RETURN is prepended - * to the statement provided and should not be - * included - * + * The return statement of the cypher query. RETURN is prepended to the statement + * provided and should not be included * @param returnStatement the return fragment of the cypher query. */ public void setReturnStatement(String returnStatement) { @@ -116,10 +114,8 @@ public class Neo4jItemReader extends AbstractPaginatedDataItemReader imple } /** - * An optional match fragment of the cypher query. MATCH is - * prepended to the statement provided and should not - * be included. - * + * An optional match fragment of the cypher query. MATCH is prepended to the statement + * provided and should not be included. * @param matchStatement the match fragment of the cypher query */ public void setMatchStatement(String matchStatement) { @@ -127,10 +123,8 @@ public class Neo4jItemReader extends AbstractPaginatedDataItemReader imple } /** - * An optional where fragment of the cypher query. WHERE is - * prepended to the statement provided and should not - * be included. - * + * An optional where fragment of the cypher query. WHERE is prepended to the statement + * provided and should not be included. * @param whereStatement where fragment of the cypher query */ public void setWhereStatement(String whereStatement) { @@ -138,11 +132,9 @@ public class Neo4jItemReader extends AbstractPaginatedDataItemReader imple } /** - * A list of properties to order the results by. This is - * required so that subsequent page requests pull back the - * segment of results correctly. ORDER BY is prepended to + * A list of properties to order the results by. This is required so that subsequent + * page requests pull back the segment of results correctly. ORDER BY is prepended to * the statement provided and should not be included. - * * @param orderByStatement order by fragment of the cypher query. */ public void setOrderByStatement(String orderByStatement) { @@ -163,7 +155,6 @@ public class Neo4jItemReader extends AbstractPaginatedDataItemReader imple /** * The object type to be returned from each call to {@link #read()} - * * @param targetType the type of object to return. */ public void setTargetType(Class targetType) { @@ -201,7 +192,7 @@ public class Neo4jItemReader extends AbstractPaginatedDataItemReader imple */ @Override public void afterPropertiesSet() throws Exception { - Assert.state(sessionFactory != null,"A SessionFactory is required"); + Assert.state(sessionFactory != null, "A SessionFactory is required"); Assert.state(targetType != null, "The type to be returned is required"); Assert.state(StringUtils.hasText(startStatement), "A START statement is required"); Assert.state(StringUtils.hasText(returnStatement), "A RETURN statement is required"); @@ -213,15 +204,14 @@ public class Neo4jItemReader extends AbstractPaginatedDataItemReader imple protected Iterator doPageRead() { Session session = getSessionFactory().openSession(); - Iterable queryResults = session.query(getTargetType(), - generateLimitCypherQuery(), - getParameterValues()); + Iterable queryResults = session.query(getTargetType(), generateLimitCypherQuery(), getParameterValues()); - if(queryResults != null) { + if (queryResults != null) { return queryResults.iterator(); } else { return new ArrayList().iterator(); } } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/Neo4jItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/Neo4jItemWriter.java index 698dcd091..6d6f826f9 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/Neo4jItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/Neo4jItemWriter.java @@ -34,14 +34,13 @@ import org.springframework.util.CollectionUtils; *

      * *

      - * This writer is thread-safe once all properties are set (normal singleton - * behavior) so it can be used in multiple concurrent transactions. + * This writer is thread-safe once all properties are set (normal singleton behavior) so + * it can be used in multiple concurrent transactions. *

      * * @author Michael Minella * @author Glenn Renfro * @author Mahmoud Ben Hassine - * * @deprecated since 5.0 in favor of the item writer from * https://github.com/spring-projects/spring-batch-extensions/blob/main/spring-batch-neo4j * @@ -49,8 +48,7 @@ import org.springframework.util.CollectionUtils; @Deprecated public class Neo4jItemWriter implements ItemWriter, InitializingBean { - protected static final Log logger = LogFactory - .getLog(Neo4jItemWriter.class); + protected static final Log logger = LogFactory.getLog(Neo4jItemWriter.class); private boolean delete = false; @@ -82,8 +80,7 @@ public class Neo4jItemWriter implements ItemWriter, InitializingBean { */ @Override public void afterPropertiesSet() throws Exception { - Assert.state(this.sessionFactory != null, - "A SessionFactory is required"); + Assert.state(this.sessionFactory != null, "A SessionFactory is required"); } /** @@ -93,19 +90,18 @@ public class Neo4jItemWriter implements ItemWriter, InitializingBean { */ @Override public void write(List items) throws Exception { - if(!CollectionUtils.isEmpty(items)) { + if (!CollectionUtils.isEmpty(items)) { doWrite(items); } } /** - * Performs the actual write using the template. This can be overridden by - * a subclass if necessary. - * + * Performs the actual write using the template. This can be overridden by a subclass + * if necessary. * @param items the list of items to be persisted. */ protected void doWrite(List items) { - if(delete) { + if (delete) { delete(items); } else { @@ -116,7 +112,7 @@ public class Neo4jItemWriter implements ItemWriter, InitializingBean { private void delete(List items) { Session session = this.sessionFactory.openSession(); - for(T item : items) { + for (T item : items) { session.delete(item); } } @@ -128,4 +124,5 @@ public class Neo4jItemWriter implements ItemWriter, InitializingBean { session.save(item); } } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/RepositoryItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/RepositoryItemReader.java index d2590a71f..3680cc99f 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/RepositoryItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/RepositoryItemReader.java @@ -40,8 +40,8 @@ import org.springframework.util.MethodInvoker; /** *

      - * A {@link org.springframework.batch.item.ItemReader} that reads records utilizing - * a {@link org.springframework.data.repository.PagingAndSortingRepository}. + * A {@link org.springframework.batch.item.ItemReader} that reads records utilizing a + * {@link org.springframework.data.repository.PagingAndSortingRepository}. *

      * *

      @@ -51,20 +51,24 @@ import org.springframework.util.MethodInvoker; *

      * *

      - * The reader must be configured with a {@link org.springframework.data.repository.PagingAndSortingRepository}, - * a {@link org.springframework.data.domain.Sort}, and a pageSize greater than 0. + * The reader must be configured with a + * {@link org.springframework.data.repository.PagingAndSortingRepository}, a + * {@link org.springframework.data.domain.Sort}, and a pageSize greater than 0. *

      * *

      - * This implementation is thread-safe between calls to {@link #open(ExecutionContext)}, but remember to use - * saveState=false if used in a multi-threaded client (no restart available). + * This implementation is thread-safe between calls to {@link #open(ExecutionContext)}, + * but remember to use saveState=false if used in a multi-threaded client (no + * restart available). *

      * - *

      It is important to note that this is a paging item reader and exceptions that are + *

      + * It is important to note that this is a paging item reader and exceptions that are * thrown while reading the page itself (mapping results to objects, etc in the * {@link RepositoryItemReader#doPageRead()}) will not be skippable since this reader has * no way of knowing if an exception should be skipped and therefore will continue to read - * the same page until the skip limit is exceeded.

      + * the same page until the skip limit is exceeded. + *

      * *

      * NOTE: The {@code RepositoryItemReader} only reads Java Objects i.e. non primitives. @@ -102,7 +106,6 @@ public class RepositoryItemReader extends AbstractItemCountingItemStreamItemR /** * Arguments to be passed to the data providing method. - * * @param arguments list of method arguments to be passed to the repository */ public void setArguments(List arguments) { @@ -111,7 +114,6 @@ public class RepositoryItemReader extends AbstractItemCountingItemStreamItemR /** * Provides ordering of the results so that order is maintained between paged queries - * * @param sorts the fields to sort by and the directions */ public void setSort(Map sorts) { @@ -128,7 +130,6 @@ public class RepositoryItemReader extends AbstractItemCountingItemStreamItemR /** * The {@link org.springframework.data.repository.PagingAndSortingRepository} * implementation used to read input from. - * * @param repository underlying repository for input to be read from. */ public void setRepository(PagingAndSortingRepository repository) { @@ -136,9 +137,8 @@ public class RepositoryItemReader extends AbstractItemCountingItemStreamItemR } /** - * Specifies what method on the repository to call. This method must take + * Specifies what method on the repository to call. This method must take * {@link org.springframework.data.domain.Pageable} as the last argument. - * * @param methodName name of the method to invoke */ public void setMethodName(String methodName) { @@ -166,9 +166,9 @@ public class RepositoryItemReader extends AbstractItemCountingItemStreamItemR } results = doPageRead(); - page ++; + page++; - if(results.size() <= 0) { + if (results.size() <= 0) { return null; } @@ -177,7 +177,7 @@ public class RepositoryItemReader extends AbstractItemCountingItemStreamItemR } } - if(current < results.size()) { + if (current < results.size()) { T curLine = results.get(current); current++; return curLine; @@ -197,12 +197,11 @@ public class RepositoryItemReader extends AbstractItemCountingItemStreamItemR } /** - * Performs the actual reading of a page via the repository. - * Available for overriding as needed. - * + * Performs the actual reading of a page via the repository. Available for overriding + * as needed. * @return the list of items that make up the page * @throws Exception Based on what the underlying method throws or related to the - * calling of the method + * calling of the method */ @SuppressWarnings("unchecked") protected List doPageRead() throws Exception { @@ -212,7 +211,7 @@ public class RepositoryItemReader extends AbstractItemCountingItemStreamItemR List parameters = new ArrayList<>(); - if(arguments != null && arguments.size() > 0) { + if (arguments != null && arguments.size() > 0) { parameters.addAll(arguments); } @@ -248,7 +247,7 @@ public class RepositoryItemReader extends AbstractItemCountingItemStreamItemR return Sort.by(sortValues); } - private Object doInvoke(MethodInvoker invoker) throws Exception{ + private Object doInvoke(MethodInvoker invoker) throws Exception { try { invoker.prepare(); } @@ -278,4 +277,5 @@ public class RepositoryItemReader extends AbstractItemCountingItemStreamItemR invoker.setTargetMethod(targetMethod); return invoker; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/RepositoryItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/RepositoryItemWriter.java index 51b188f57..808b33270 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/RepositoryItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/RepositoryItemWriter.java @@ -36,17 +36,18 @@ import org.springframework.util.MethodInvoker; *

      * *

      - * By default, this writer will use {@link CrudRepository#saveAll(Iterable)} - * to save items, unless another method is selected with {@link #setMethodName(java.lang.String)}. - * It depends on {@link org.springframework.data.repository.CrudRepository#saveAll(Iterable)} - * method to store the items for the chunk. Performance will be determined by that - * implementation more than this writer. + * By default, this writer will use {@link CrudRepository#saveAll(Iterable)} to save + * items, unless another method is selected with {@link #setMethodName(java.lang.String)}. + * It depends on + * {@link org.springframework.data.repository.CrudRepository#saveAll(Iterable)} method to + * store the items for the chunk. Performance will be determined by that implementation + * more than this writer. *

      * *

      * As long as the repository provided is thread-safe, this writer is also thread-safe once - * properties are set (normal singleton behavior), so it can be used in multiple concurrent - * transactions. + * properties are set (normal singleton behavior), so it can be used in multiple + * concurrent transactions. *

      * *

      @@ -66,9 +67,8 @@ public class RepositoryItemWriter implements ItemWriter, InitializingBean private String methodName; /** - * Specifies what method on the repository to call. This method must have the type of + * Specifies what method on the repository to call. This method must have the type of * object passed to this writer as the sole argument. - * * @param methodName {@link String} containing the method name. */ public void setMethodName(String methodName) { @@ -78,7 +78,6 @@ public class RepositoryItemWriter implements ItemWriter, InitializingBean /** * Set the {@link org.springframework.data.repository.CrudRepository} implementation * for persistence - * * @param repository the Spring Data repository to be set */ public void setRepository(CrudRepository repository) { @@ -92,24 +91,22 @@ public class RepositoryItemWriter implements ItemWriter, InitializingBean */ @Override public void write(List items) throws Exception { - if(!CollectionUtils.isEmpty(items)) { + if (!CollectionUtils.isEmpty(items)) { doWrite(items); } } /** - * Performs the actual write to the repository. This can be overridden by - * a subclass if necessary. - * + * Performs the actual write to the repository. This can be overridden by a subclass + * if necessary. * @param items the list of items to be persisted. - * * @throws Exception thrown if error occurs during writing. */ protected void doWrite(List items) throws Exception { if (logger.isDebugEnabled()) { logger.debug("Writing to the repository with " + items.size() + " items."); } - + if (this.methodName == null) { this.repository.saveAll(items); return; @@ -118,7 +115,7 @@ public class RepositoryItemWriter implements ItemWriter, InitializingBean MethodInvoker invoker = createMethodInvoker(repository, methodName); for (T object : items) { - invoker.setArguments(new Object [] {object}); + invoker.setArguments(new Object[] { object }); doInvoke(invoker); } } @@ -137,8 +134,7 @@ public class RepositoryItemWriter implements ItemWriter, InitializingBean } } - - private Object doInvoke(MethodInvoker invoker) throws Exception{ + private Object doInvoke(MethodInvoker invoker) throws Exception { try { invoker.prepare(); } @@ -171,4 +167,5 @@ public class RepositoryItemWriter implements ItemWriter, InitializingBean invoker.setTargetMethod(targetMethod); return invoker; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/SpELMappingGemfireItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/SpELMappingGemfireItemWriter.java index a9ee5d06b..df8a547cd 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/SpELMappingGemfireItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/SpELMappingGemfireItemWriter.java @@ -1,11 +1,11 @@ /* * Copyright 2002-2013 the original author or authors. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at - * + * * https://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. @@ -16,12 +16,14 @@ import org.springframework.batch.item.SpELItemKeyMapper; import org.springframework.util.Assert; /** - * A convenient {@link GemfireItemWriter} implementation that uses a {@link SpELItemKeyMapper} - * + * A convenient {@link GemfireItemWriter} implementation that uses a + * {@link SpELItemKeyMapper} + * * @author David Turanski * @since 2.2 */ public class SpELMappingGemfireItemWriter extends GemfireItemWriter { + /** * A constructor that accepts a SpEL expression used to derive the key * @param keyExpression @@ -31,4 +33,5 @@ public class SpELMappingGemfireItemWriter extends GemfireItemWriter Assert.hasText(keyExpression, "a valid keyExpression is required."); setItemKeyMapper(new SpELItemKeyMapper<>(keyExpression)); } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/GemfireItemWriterBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/GemfireItemWriterBuilder.java index 9cb26c2b6..6c69493a8 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/GemfireItemWriterBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/GemfireItemWriterBuilder.java @@ -50,7 +50,6 @@ public class GemfireItemWriterBuilder { /** * Set the {@link Converter} to use to derive the key from the item. - * * @param itemKeyMapper the Converter to use. * @return The current instance of the builder. * @see GemfireItemWriter#setItemKeyMapper(Converter) @@ -65,7 +64,6 @@ public class GemfireItemWriterBuilder { * Indicates if the items being passed to the writer are to be saved or removed from * the data store. If set to false (default), the items will be saved. If set to true, * the items will be removed. - * * @param delete removal indicator. * @return The current instance of the builder. * @see GemfireItemWriter#setDelete(boolean) @@ -76,10 +74,8 @@ public class GemfireItemWriterBuilder { return this; } - /** * Validates and builds a {@link GemfireItemWriter}. - * * @return a {@link GemfireItemWriter} */ public GemfireItemWriter build() { @@ -92,4 +88,5 @@ public class GemfireItemWriterBuilder { writer.setDelete(this.delete); return writer; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/MongoItemReaderBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/MongoItemReaderBuilder.java index 40f148fb8..596073082 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/MongoItemReaderBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/MongoItemReaderBuilder.java @@ -1,10 +1,10 @@ /* * Copyright 2017-2022 the original author or authors. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software @@ -39,6 +39,7 @@ import org.springframework.util.StringUtils; * @see MongoItemReader */ public class MongoItemReaderBuilder { + private MongoOperations template; private String jsonQuery; @@ -68,10 +69,9 @@ public class MongoItemReaderBuilder { private Query query; /** - * Configure if the state of the {@link org.springframework.batch.item.ItemStreamSupport} - * should be persisted within the {@link org.springframework.batch.item.ExecutionContext} - * for restart purposes. - * + * Configure if the state of the + * {@link org.springframework.batch.item.ItemStreamSupport} should be persisted within + * the {@link org.springframework.batch.item.ExecutionContext} for restart purposes. * @param saveState defaults to true * @return The current instance of the builder. */ @@ -85,7 +85,6 @@ public class MongoItemReaderBuilder { * The name used to calculate the key within the * {@link org.springframework.batch.item.ExecutionContext}. Required if * {@link #saveState(boolean)} is set to true. - * * @param name name of the reader instance * @return The current instance of the builder. * @see org.springframework.batch.item.ItemStreamSupport#setName(String) @@ -98,7 +97,6 @@ public class MongoItemReaderBuilder { /** * Configure the max number of items to be read. - * * @param maxItemCount the max items to be read * @return The current instance of the builder. * @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setMaxItemCount(int) @@ -111,7 +109,6 @@ public class MongoItemReaderBuilder { /** * Index for the current item. Used on restarts to indicate where to start from. - * * @param currentItemCount current index * @return this instance for method chaining * @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setCurrentItemCount(int) @@ -125,7 +122,6 @@ public class MongoItemReaderBuilder { /** * Used to perform operations against the MongoDB instance. Also handles the mapping * of documents to objects. - * * @param template the MongoOperations instance to use * @see MongoOperations * @return The current instance of the builder @@ -138,10 +134,9 @@ public class MongoItemReaderBuilder { } /** - * A JSON formatted MongoDB jsonQuery. Parameterization of the provided jsonQuery is allowed - * via ?<index> placeholders where the <index> indicates the index of the - * parameterValue to substitute. - * + * A JSON formatted MongoDB jsonQuery. Parameterization of the provided jsonQuery is + * allowed via ?<index> placeholders where the <index> indicates the index + * of the parameterValue to substitute. * @param query JSON formatted Mongo jsonQuery * @return The current instance of the builder * @see MongoItemReader#setQuery(String) @@ -154,7 +149,6 @@ public class MongoItemReaderBuilder { /** * The type of object to be returned for each {@link MongoItemReader#read()} call. - * * @param targetType the type of object to return * @return The current instance of the builder * @see MongoItemReader#setTargetType(Class) @@ -168,7 +162,6 @@ public class MongoItemReaderBuilder { /** * {@link List} of values to be substituted in for each of the parameters in the * query. - * * @param parameterValues values * @return The current instance of the builder * @see MongoItemReader#setParameterValues(List) @@ -181,7 +174,6 @@ public class MongoItemReaderBuilder { /** * Values to be substituted in for each of the parameters in the query. - * * @param parameterValues values * @return The current instance of the builder * @see MongoItemReader#setParameterValues(List) @@ -192,7 +184,6 @@ public class MongoItemReaderBuilder { /** * JSON defining the fields to be returned from the matching documents by MongoDB. - * * @param fields JSON string that identifies the fields to sort by. * @return The current instance of the builder * @see MongoItemReader#setFields(String) @@ -207,7 +198,6 @@ public class MongoItemReaderBuilder { * {@link Map} of property * names/{@link org.springframework.data.domain.Sort.Direction} values to sort the * input by. - * * @param sorts map of properties and direction to sort each. * @return The current instance of the builder * @see MongoItemReader#setSort(Map) @@ -220,7 +210,6 @@ public class MongoItemReaderBuilder { /** * Establish an optional collection that can be queried. - * * @param collection Mongo collection to be queried. * @return The current instance of the builder * @see MongoItemReader#setCollection(String) @@ -233,7 +222,6 @@ public class MongoItemReaderBuilder { /** * JSON String telling MongoDB what index to use. - * * @param hint string indicating what index to use. * @return The current instance of the builder * @see MongoItemReader#setHint(String) @@ -246,7 +234,6 @@ public class MongoItemReaderBuilder { /** * The number of items to be read with each page. - * * @param pageSize the number of items * @return this instance for method chaining * @see MongoItemReader#setPageSize(int) @@ -258,9 +245,8 @@ public class MongoItemReaderBuilder { } /** - * Provide a Spring Data Mongo {@link Query}. This will take precedence over a JSON + * Provide a Spring Data Mongo {@link Query}. This will take precedence over a JSON * configured query. - * * @param query Query to execute * @return this instance for method chaining * @see MongoItemReader#setQuery(Query) @@ -273,7 +259,6 @@ public class MongoItemReaderBuilder { /** * Validates and builds a {@link MongoItemReader}. - * * @return a {@link MongoItemReader} */ public MongoItemReader build() { @@ -307,4 +292,5 @@ public class MongoItemReaderBuilder { return reader; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/MongoItemWriterBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/MongoItemWriterBuilder.java index 4ac0cb770..efffa4691 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/MongoItemWriterBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/MongoItemWriterBuilder.java @@ -39,7 +39,6 @@ public class MongoItemWriterBuilder { * Indicates if the items being passed to the writer are to be saved or removed from * the data store. If set to false (default), the items will be saved. If set to true, * the items will be removed. - * * @param delete removal indicator * @return The current instance of the builder * @see MongoItemWriter#setDelete(boolean) @@ -52,7 +51,6 @@ public class MongoItemWriterBuilder { /** * Set the {@link MongoOperations} to be used to save items to be written. - * * @param template the template implementation to be used. * @return The current instance of the builder * @see MongoItemWriter#setTemplate(MongoOperations) @@ -65,11 +63,10 @@ public class MongoItemWriterBuilder { /** * Set the name of the Mongo collection to be written to. - * * @param collection the name of the collection. * @return The current instance of the builder * @see MongoItemWriter#setCollection(String) - * + * */ public MongoItemWriterBuilder collection(String collection) { this.collection = collection; @@ -79,7 +76,6 @@ public class MongoItemWriterBuilder { /** * Validates and builds a {@link MongoItemWriter}. - * * @return a {@link MongoItemWriter} */ public MongoItemWriter build() { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/Neo4jItemReaderBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/Neo4jItemReaderBuilder.java index 70e36fc74..eef977841 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/Neo4jItemReaderBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/Neo4jItemReaderBuilder.java @@ -30,7 +30,6 @@ import org.springframework.util.Assert; * @author Mahmoud Ben Hassine * @since 4.0 * @see Neo4jItemReader - * * @deprecated since 5.0 in favor of the item reader builder from * https://github.com/spring-projects/spring-batch-extensions/blob/main/spring-batch-neo4j */ @@ -64,10 +63,9 @@ public class Neo4jItemReaderBuilder { private int currentItemCount; /** - * Configure if the state of the {@link org.springframework.batch.item.ItemStreamSupport} - * should be persisted within the {@link org.springframework.batch.item.ExecutionContext} - * for restart purposes. - * + * Configure if the state of the + * {@link org.springframework.batch.item.ItemStreamSupport} should be persisted within + * the {@link org.springframework.batch.item.ExecutionContext} for restart purposes. * @param saveState defaults to true * @return The current instance of the builder. */ @@ -81,7 +79,6 @@ public class Neo4jItemReaderBuilder { * The name used to calculate the key within the * {@link org.springframework.batch.item.ExecutionContext}. Required if * {@link #saveState(boolean)} is set to true. - * * @param name name of the reader instance * @return The current instance of the builder. * @see org.springframework.batch.item.ItemStreamSupport#setName(String) @@ -94,7 +91,6 @@ public class Neo4jItemReaderBuilder { /** * Configure the max number of items to be read. - * * @param maxItemCount the max items to be read * @return The current instance of the builder. * @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setMaxItemCount(int) @@ -107,7 +103,6 @@ public class Neo4jItemReaderBuilder { /** * Index for the current item. Used on restarts to indicate where to start from. - * * @param currentItemCount current index * @return this instance for method chaining * @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setCurrentItemCount(int) @@ -132,7 +127,6 @@ public class Neo4jItemReaderBuilder { /** * The number of items to be read with each page. - * * @param pageSize the number of items * @return this instance for method chaining * @see Neo4jItemReader#setPageSize(int) @@ -145,7 +139,6 @@ public class Neo4jItemReaderBuilder { /** * Optional parameters to be used in the cypher query. - * * @param parameterValues the parameter values to be used in the cypher query * @return this instance for method chaining * @see Neo4jItemReader#setParameterValues(Map) @@ -159,7 +152,6 @@ public class Neo4jItemReaderBuilder { /** * The start segment of the cypher query. START is prepended to the statement provided * and should not be included. - * * @param startStatement the start fragment of the cypher query. * @return this instance for method chaining * @see Neo4jItemReader#setStartStatement(String) @@ -173,7 +165,6 @@ public class Neo4jItemReaderBuilder { /** * The return statement of the cypher query. RETURN is prepended to the statement * provided and should not be included - * * @param returnStatement the return fragment of the cypher query. * @return this instance for method chaining * @see Neo4jItemReader#setReturnStatement(String) @@ -187,7 +178,6 @@ public class Neo4jItemReaderBuilder { /** * An optional match fragment of the cypher query. MATCH is prepended to the statement * provided and should not be included. - * * @param matchStatement the match fragment of the cypher query * @return this instance for method chaining * @see Neo4jItemReader#setMatchStatement(String) @@ -201,7 +191,6 @@ public class Neo4jItemReaderBuilder { /** * An optional where fragment of the cypher query. WHERE is prepended to the statement * provided and should not be included. - * * @param whereStatement where fragment of the cypher query * @return this instance for method chaining * @see Neo4jItemReader#setWhereStatement(String) @@ -216,7 +205,6 @@ public class Neo4jItemReaderBuilder { * A list of properties to order the results by. This is required so that subsequent * page requests pull back the segment of results correctly. ORDER BY is prepended to * the statement provided and should not be included. - * * @param orderByStatement order by fragment of the cypher query. * @return this instance for method chaining * @see Neo4jItemReader#setOrderByStatement(String) @@ -229,7 +217,6 @@ public class Neo4jItemReaderBuilder { /** * The object type to be returned from each call to {@link Neo4jItemReader#read()} - * * @param targetType the type of object to return. * @return this instance for method chaining * @see Neo4jItemReader#setTargetType(Class) @@ -242,7 +229,6 @@ public class Neo4jItemReaderBuilder { /** * Returns a fully constructed {@link Neo4jItemReader}. - * * @return a new {@link Neo4jItemReader} */ public Neo4jItemReader build() { @@ -256,7 +242,7 @@ public class Neo4jItemReaderBuilder { Assert.hasText(this.orderByStatement, "orderByStatement is required."); Assert.isTrue(this.pageSize > 0, "pageSize must be greater than zero"); Assert.isTrue(this.maxItemCount > 0, "maxItemCount must be greater than zero"); - Assert.isTrue(this.maxItemCount > this.currentItemCount , "maxItemCount must be greater than currentItemCount"); + Assert.isTrue(this.maxItemCount > this.currentItemCount, "maxItemCount must be greater than currentItemCount"); Neo4jItemReader reader = new Neo4jItemReader<>(); reader.setMatchStatement(this.matchStatement); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/Neo4jItemWriterBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/Neo4jItemWriterBuilder.java index 2a8fc0734..3b85bd7f1 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/Neo4jItemWriterBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/Neo4jItemWriterBuilder.java @@ -1,10 +1,10 @@ /* * Copyright 2017-2021 the original author or authors. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software @@ -29,7 +29,6 @@ import org.springframework.util.Assert; * @author Mahmoud Ben Hassine * @since 4.0 * @see Neo4jItemWriter - * * @deprecated since 5.0 in favor of the item writer builder from * https://github.com/spring-projects/spring-batch-extensions/blob/main/spring-batch-neo4j */ @@ -69,7 +68,6 @@ public class Neo4jItemWriterBuilder { /** * Validates and builds a {@link org.springframework.batch.item.data.Neo4jItemWriter}. - * * @return a {@link Neo4jItemWriter} */ public Neo4jItemWriter build() { @@ -79,4 +77,5 @@ public class Neo4jItemWriterBuilder { writer.setSessionFactory(this.sessionFactory); return writer; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/RepositoryItemReaderBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/RepositoryItemReaderBuilder.java index aa9e245fe..c60d3cca8 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/RepositoryItemReaderBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/RepositoryItemReaderBuilder.java @@ -64,10 +64,9 @@ public class RepositoryItemReaderBuilder { private int currentItemCount; /** - * Configure if the state of the {@link org.springframework.batch.item.ItemStreamSupport} - * should be persisted within the {@link org.springframework.batch.item.ExecutionContext} - * for restart purposes. - * + * Configure if the state of the + * {@link org.springframework.batch.item.ItemStreamSupport} should be persisted within + * the {@link org.springframework.batch.item.ExecutionContext} for restart purposes. * @param saveState defaults to true * @return The current instance of the builder. */ @@ -81,7 +80,6 @@ public class RepositoryItemReaderBuilder { * The name used to calculate the key within the * {@link org.springframework.batch.item.ExecutionContext}. Required if * {@link #saveState(boolean)} is set to true. - * * @param name name of the reader instance * @return The current instance of the builder. * @see org.springframework.batch.item.ItemStreamSupport#setName(String) @@ -94,7 +92,6 @@ public class RepositoryItemReaderBuilder { /** * Configure the max number of items to be read. - * * @param maxItemCount the max items to be read * @return The current instance of the builder. * @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setMaxItemCount(int) @@ -107,7 +104,6 @@ public class RepositoryItemReaderBuilder { /** * Index for the current item. Used on restarts to indicate where to start from. - * * @param currentItemCount current index * @return this instance for method chaining * @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setCurrentItemCount(int) @@ -120,7 +116,6 @@ public class RepositoryItemReaderBuilder { /** * Arguments to be passed to the data providing method. - * * @param arguments list of method arguments to be passed to the repository. * @return The current instance of the builder. * @see RepositoryItemReader#setArguments(List) @@ -133,7 +128,6 @@ public class RepositoryItemReaderBuilder { /** * Arguments to be passed to the data providing method. - * * @param arguments the method arguments to be passed to the repository. * @return The current instance of the builder. * @see RepositoryItemReader#setArguments(List) @@ -144,7 +138,6 @@ public class RepositoryItemReaderBuilder { /** * Provides ordering of the results so that order is maintained between paged queries. - * * @param sorts the fields to sort by and the directions. * @return The current instance of the builder. * @see RepositoryItemReader#setSort(Map) @@ -157,7 +150,6 @@ public class RepositoryItemReaderBuilder { /** * Establish the pageSize for the generated RepositoryItemReader. - * * @param pageSize The number of items to retrieve per page. * @return The current instance of the builder. * @see RepositoryItemReader#setPageSize(int) @@ -171,7 +163,6 @@ public class RepositoryItemReaderBuilder { /** * The {@link org.springframework.data.repository.PagingAndSortingRepository} * implementation used to read input from. - * * @param repository underlying repository for input to be read from. * @return The current instance of the builder. * @see RepositoryItemReader#setRepository(PagingAndSortingRepository) @@ -185,7 +176,6 @@ public class RepositoryItemReaderBuilder { /** * Specifies what method on the repository to call. This method must take * {@link org.springframework.data.domain.Pageable} as the last argument. - * * @param methodName name of the method to invoke. * @return The current instance of the builder. * @see RepositoryItemReader#setMethodName(String) @@ -199,13 +189,13 @@ public class RepositoryItemReaderBuilder { /** * Specifies a repository and the type-safe method to call for the reader. The method * configured via this mechanism must take - * {@link org.springframework.data.domain.Pageable} as the last - * argument. This method can be used in place of {@link #repository(PagingAndSortingRepository)}, - * {@link #methodName(String)}, and {@link #arguments(List)}. + * {@link org.springframework.data.domain.Pageable} as the last argument. + * This method can be used in place of + * {@link #repository(PagingAndSortingRepository)}, {@link #methodName(String)}, and + * {@link #arguments(List)}. * * Note: The repository that is used by the repositoryMethodReference must be * non-final. - * * @param repositoryMethodReference of the used to get a repository and type-safe * method for use by the reader. * @return The current instance of the builder. @@ -221,7 +211,6 @@ public class RepositoryItemReaderBuilder { /** * Builds the {@link RepositoryItemReader}. - * * @return a {@link RepositoryItemReader} */ public RepositoryItemReader build() { @@ -229,7 +218,7 @@ public class RepositoryItemReaderBuilder { this.methodName = this.repositoryMethodReference.getMethodName(); this.repository = this.repositoryMethodReference.getRepository(); - if(CollectionUtils.isEmpty(this.arguments)) { + if (CollectionUtils.isEmpty(this.arguments)) { this.arguments = this.repositoryMethodReference.getArguments(); } } @@ -257,10 +246,12 @@ public class RepositoryItemReaderBuilder { /** * Establishes a proxy that will capture a the Repository and the associated * methodName that will be used by the reader. - * @param The type of repository that will be used by the reader. The class must + * + * @param The type of repository that will be used by the reader. The class must * not be final. */ public static class RepositoryMethodReference { + private RepositoryMethodInterceptor repositoryInvocationHandler; private PagingAndSortingRepository repository; @@ -294,9 +285,11 @@ public class RepositoryItemReaderBuilder { List getArguments() { return this.repositoryInvocationHandler.getArguments(); } + } private static class RepositoryMethodInterceptor implements MethodInterceptor { + private String methodName; private List arguments; @@ -320,5 +313,7 @@ public class RepositoryItemReaderBuilder { List getArguments() { return arguments; } + } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/RepositoryItemWriterBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/RepositoryItemWriterBuilder.java index 882b2dd64..95fb6add2 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/RepositoryItemWriterBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/data/builder/RepositoryItemWriterBuilder.java @@ -16,7 +16,6 @@ package org.springframework.batch.item.data.builder; - import java.lang.reflect.Method; import org.apache.commons.logging.Log; @@ -50,7 +49,6 @@ public class RepositoryItemWriterBuilder { /** * Specifies what method on the repository to call. This method must have the type of * object passed to this writer as the sole argument. - * * @param methodName the name of the method to be used for saving the item. * @return The current instance of the builder. * @see RepositoryItemWriter#setMethodName(String) @@ -64,7 +62,6 @@ public class RepositoryItemWriterBuilder { /** * Set the {@link org.springframework.data.repository.CrudRepository} implementation * for persistence - * * @param repository the Spring Data repository to be set * @return The current instance of the builder. * @see RepositoryItemWriter#setRepository(CrudRepository) @@ -78,13 +75,12 @@ public class RepositoryItemWriterBuilder { /** * Specifies a repository and the type-safe method to call for the writer. The method * configured via this mechanism must take - * {@link org.springframework.data.domain.Pageable} as the last - * argument. This method can be used in place of {@link #repository(CrudRepository)}, + * {@link org.springframework.data.domain.Pageable} as the last argument. + * This method can be used in place of {@link #repository(CrudRepository)}, * {@link #methodName(String)}}. * * Note: The repository that is used by the repositoryMethodReference must be * non-final. - * * @param repositoryMethodReference of the used to get a repository and type-safe * method for use by the writer. * @return The current instance of the builder. @@ -92,7 +88,8 @@ public class RepositoryItemWriterBuilder { * @see RepositoryItemWriter#setRepository(CrudRepository) * */ - public RepositoryItemWriterBuilder repository(RepositoryItemWriterBuilder.RepositoryMethodReference repositoryMethodReference) { + public RepositoryItemWriterBuilder repository( + RepositoryItemWriterBuilder.RepositoryMethodReference repositoryMethodReference) { this.repositoryMethodReference = repositoryMethodReference; return this; @@ -100,7 +97,6 @@ public class RepositoryItemWriterBuilder { /** * Builds the {@link RepositoryItemWriter}. - * * @return a {@link RepositoryItemWriter} */ public RepositoryItemWriter build() { @@ -116,7 +112,8 @@ public class RepositoryItemWriterBuilder { if (this.methodName != null) { Assert.hasText(this.methodName, "methodName must not be empty."); writer.setMethodName(this.methodName); - } else { + } + else { logger.debug("No method name provided, CrudRepository.saveAll will be used."); } return writer; @@ -125,10 +122,12 @@ public class RepositoryItemWriterBuilder { /** * Establishes a proxy that will capture a the Repository and the associated * methodName that will be used by the writer. - * @param The type of repository that will be used by the writer. The class must + * + * @param The type of repository that will be used by the writer. The class must * not be final. */ public static class RepositoryMethodReference { + private RepositoryMethodInterceptor repositoryInvocationHandler; private CrudRepository repository; @@ -158,14 +157,15 @@ public class RepositoryItemWriterBuilder { String getMethodName() { return this.repositoryInvocationHandler.getMethodName(); } + } private static class RepositoryMethodInterceptor implements MethodInterceptor { + private String methodName; @Override - public Object intercept(Object o, Method method, Object[] objects, - MethodProxy methodProxy) throws Throwable { + public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { this.methodName = method.getName(); return null; } @@ -175,4 +175,5 @@ public class RepositoryItemWriterBuilder { } } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/AbstractCursorItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/AbstractCursorItemReader.java index cb74fe826..e3bd731fb 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/AbstractCursorItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/AbstractCursorItemReader.java @@ -48,57 +48,57 @@ import org.springframework.util.Assert; /** *

      - * Abstract base class for any simple item reader that opens a database cursor and continually retrieves - * the next row in the ResultSet. + * Abstract base class for any simple item reader that opens a database cursor and + * continually retrieves the next row in the ResultSet. *

      * *

      - * By default the cursor will be opened using a separate connection. The ResultSet for the cursor - * is held open regardless of commits or roll backs in a surrounding transaction. Clients of this - * reader are responsible for buffering the items in the case that they need to be re-presented on a - * rollback. This buffering is handled by the step implementations provided and is only a concern for - * anyone writing their own step implementations. + * By default the cursor will be opened using a separate connection. The ResultSet for the + * cursor is held open regardless of commits or roll backs in a surrounding transaction. + * Clients of this reader are responsible for buffering the items in the case that they + * need to be re-presented on a rollback. This buffering is handled by the step + * implementations provided and is only a concern for anyone writing their own step + * implementations. *

      * *

      - * There is an option ({@link #setUseSharedExtendedConnection(boolean)} that will share the connection - * used for the cursor with the rest of the step processing. If you set this flag to true - * then you must wrap the DataSource in a {@link ExtendedConnectionDataSourceProxy} to prevent the - * connection from being closed and released after each commit performed as part of the step processing. - * You must also use a JDBC driver supporting JDBC 3.0 or later since the cursor will be opened with the + * There is an option ({@link #setUseSharedExtendedConnection(boolean)} that will share + * the connection used for the cursor with the rest of the step processing. If you set + * this flag to true then you must wrap the DataSource in a + * {@link ExtendedConnectionDataSourceProxy} to prevent the connection from being closed + * and released after each commit performed as part of the step processing. You must also + * use a JDBC driver supporting JDBC 3.0 or later since the cursor will be opened with the * additional option of 'HOLD_CURSORS_OVER_COMMIT' enabled. *

      * *

      * Each call to {@link #read()} will attempt to map the row at the current position in the - * ResultSet. There is currently no wrapping of the ResultSet to suppress calls - * to next(). However, if the RowMapper (mistakenly) increments the current row, - * the next call to read will verify that the current row is at the expected - * position and throw a DataAccessException if it is not. The reason for such strictness on the - * ResultSet is due to the need to maintain control for transactions and - * restartability. This ensures that each call to {@link #read()} returns the - * ResultSet at the correct row, regardless of rollbacks or restarts. + * ResultSet. There is currently no wrapping of the ResultSet to suppress calls to next(). + * However, if the RowMapper (mistakenly) increments the current row, the next call to + * read will verify that the current row is at the expected position and throw a + * DataAccessException if it is not. The reason for such strictness on the ResultSet is + * due to the need to maintain control for transactions and restartability. This ensures + * that each call to {@link #read()} returns the ResultSet at the correct row, regardless + * of rollbacks or restarts. *

      * *

      - * {@link ExecutionContext}: The current row is returned as restart data, and - * when restored from that same data, the cursor is opened and the current row - * set to the value within the restart data. See - * {@link #setDriverSupportsAbsolute(boolean)} for improving restart - * performance. + * {@link ExecutionContext}: The current row is returned as restart data, and when + * restored from that same data, the cursor is opened and the current row set to the value + * within the restart data. See {@link #setDriverSupportsAbsolute(boolean)} for improving + * restart performance. *

      * *

      - * Calling close on this {@link ItemStream} will cause all resources it is - * currently using to be freed. (Connection, ResultSet, etc). It is then illegal - * to call {@link #read()} again until it has been re-opened. + * Calling close on this {@link ItemStream} will cause all resources it is currently using + * to be freed. (Connection, ResultSet, etc). It is then illegal to call {@link #read()} + * again until it has been re-opened. *

      * *

      - * Known limitation: when used with Derby - * {@link #setVerifyCursorPosition(boolean)} needs to be false - * because {@link ResultSet#getRow()} call used for cursor position verification - * is not available for 'TYPE_FORWARD_ONLY' result sets. + * Known limitation: when used with Derby {@link #setVerifyCursorPosition(boolean)} needs + * to be false because {@link ResultSet#getRow()} call used for cursor + * position verification is not available for 'TYPE_FORWARD_ONLY' result sets. *

      * * @author Lucas Ward @@ -109,12 +109,13 @@ import org.springframework.util.Assert; * @author Mahmoud Ben Hassine */ public abstract class AbstractCursorItemReader extends AbstractItemCountingItemStreamItemReader -implements InitializingBean { + implements InitializingBean { /** Logger available to subclasses */ protected final Log log = LogFactory.getLog(getClass()); public static final int VALUE_NOT_SET = -1; + private Connection con; protected ResultSet rs; @@ -149,9 +150,7 @@ implements InitializingBean { /** * Assert that mandatory properties are set. - * - * @throws IllegalArgumentException if either data source or SQL properties - * not set. + * @throws IllegalArgumentException if either data source or SQL properties not set. */ @Override public void afterPropertiesSet() throws Exception { @@ -160,7 +159,6 @@ implements InitializingBean { /** * Public setter for the data source for injection purposes. - * * @param dataSource {@link javax.sql.DataSource} to be used */ public void setDataSource(DataSource dataSource) { @@ -169,7 +167,6 @@ implements InitializingBean { /** * Public getter for the data source. - * * @return the dataSource */ public DataSource getDataSource() { @@ -177,12 +174,10 @@ implements InitializingBean { } /** - * Prepare the given JDBC Statement (or PreparedStatement or - * CallableStatement), applying statement settings such as fetch size, max - * rows, and query timeout. @param stmt the JDBC Statement to prepare - * + * Prepare the given JDBC Statement (or PreparedStatement or CallableStatement), + * applying statement settings such as fetch size, max rows, and query timeout. @param + * stmt the JDBC Statement to prepare * @param stmt {@link java.sql.PreparedStatement} to be configured - * * @throws SQLException if interactions with provided stmt fail * * @see #setFetchSize @@ -203,13 +198,12 @@ implements InitializingBean { } /** - * Creates a default SQLErrorCodeSQLExceptionTranslator for the specified - * DataSource if none is set. - * + * Creates a default SQLErrorCodeSQLExceptionTranslator for the specified DataSource + * if none is set. * @return the exception translator for this instance. */ protected SQLExceptionTranslator getExceptionTranslator() { - synchronized(this) { + synchronized (this) { if (exceptionTranslator == null) { if (dataSource != null) { exceptionTranslator = new SQLErrorCodeSQLExceptionTranslator(dataSource); @@ -231,16 +225,15 @@ implements InitializingBean { } /** - * Throw a SQLWarningException if we're not ignoring warnings, else log the - * warnings (at debug level). - * - * @param statement the current statement to obtain the warnings from, if there are any. + * Throw a SQLWarningException if we're not ignoring warnings, else log the warnings + * (at debug level). + * @param statement the current statement to obtain the warnings from, if there are + * any. * @throws SQLException if interaction with provided statement fails. * * @see org.springframework.jdbc.SQLWarningException */ - protected void handleWarnings(Statement statement) throws SQLWarningException, - SQLException { + protected void handleWarnings(Statement statement) throws SQLWarningException, SQLException { if (ignoreWarnings) { if (log.isDebugEnabled()) { SQLWarning warningToLog = statement.getWarnings(); @@ -260,8 +253,8 @@ implements InitializingBean { } /** - * Moves the cursor in the ResultSet to the position specified by the row - * parameter by traversing the ResultSet. + * Moves the cursor in the ResultSet to the position specified by the row parameter by + * traversing the ResultSet. * @param row The index of the row to move to */ private void moveCursorToRow(int row) { @@ -277,11 +270,9 @@ implements InitializingBean { } /** - * Gives the JDBC driver a hint as to the number of rows that should be - * fetched from the database when more rows are needed for this - * ResultSet object. If the fetch size specified is zero, the - * JDBC driver ignores the value. - * + * Gives the JDBC driver a hint as to the number of rows that should be fetched from + * the database when more rows are needed for this ResultSet object. If + * the fetch size specified is zero, the JDBC driver ignores the value. * @param fetchSize the number of rows to fetch * @see ResultSet#setFetchSize(int) */ @@ -290,9 +281,8 @@ implements InitializingBean { } /** - * Sets the limit for the maximum number of rows that any - * ResultSet object can contain to the given number. - * + * Sets the limit for the maximum number of rows that any ResultSet + * object can contain to the given number. * @param maxRows the new max rows limit; zero means there is no limit * @see Statement#setMaxRows(int) */ @@ -301,12 +291,11 @@ implements InitializingBean { } /** - * Sets the number of seconds the driver will wait for a - * Statement object to execute to the given number of seconds. - * If the limit is exceeded, an SQLException is thrown. - * - * @param queryTimeout seconds the new query timeout limit in seconds; zero - * means there is no limit + * Sets the number of seconds the driver will wait for a Statement object + * to execute to the given number of seconds. If the limit is exceeded, an + * SQLException is thrown. + * @param queryTimeout seconds the new query timeout limit in seconds; zero means + * there is no limit * @see Statement#setQueryTimeout(int) */ public void setQueryTimeout(int queryTimeout) { @@ -314,9 +303,8 @@ implements InitializingBean { } /** - * Set whether SQLWarnings should be ignored (only logged) or exception - * should be thrown. - * + * Set whether SQLWarnings should be ignored (only logged) or exception should be + * thrown. * @param ignoreWarnings if TRUE, warnings are ignored */ public void setIgnoreWarnings(boolean ignoreWarnings) { @@ -324,9 +312,8 @@ implements InitializingBean { } /** - * Allow verification of cursor position after current row is processed by - * RowMapper or RowCallbackHandler. Default value is TRUE. - * + * Allow verification of cursor position after current row is processed by RowMapper + * or RowCallbackHandler. Default value is TRUE. * @param verifyCursorPosition if true, cursor position is verified */ public void setVerifyCursorPosition(boolean verifyCursorPosition) { @@ -335,13 +322,11 @@ implements InitializingBean { /** * Indicate whether the JDBC driver supports setting the absolute row on a - * {@link ResultSet}. It is recommended that this is set to - * true for JDBC drivers that supports ResultSet.absolute() as - * it may improve performance, especially if a step fails while working with - * a large data set. + * {@link ResultSet}. It is recommended that this is set to true for JDBC + * drivers that supports ResultSet.absolute() as it may improve performance, + * especially if a step fails while working with a large data set. * * @see ResultSet#absolute(int) - * * @param driverSupportsAbsolute false by default */ public void setDriverSupportsAbsolute(boolean driverSupportsAbsolute) { @@ -349,19 +334,19 @@ implements InitializingBean { } /** - * Indicate whether the connection used for the cursor should be used by all other processing - * thus sharing the same transaction. If this is set to false, which is the default, then the - * cursor will be opened using in its connection and will not participate in any transactions - * started for the rest of the step processing. If you set this flag to true then you must - * wrap the DataSource in a {@link ExtendedConnectionDataSourceProxy} to prevent the - * connection from being closed and released after each commit. - * - * When you set this option to true then the statement used to open the cursor - * will be created with both 'READ_ONLY' and 'HOLD_CURSORS_OVER_COMMIT' options. This allows - * holding the cursor open over transaction start and commits performed in the step processing. - * To use this feature you need a database that supports this and a JDBC driver supporting - * JDBC 3.0 or later. + * Indicate whether the connection used for the cursor should be used by all other + * processing thus sharing the same transaction. If this is set to false, which is the + * default, then the cursor will be opened using in its connection and will not + * participate in any transactions started for the rest of the step processing. If you + * set this flag to true then you must wrap the DataSource in a + * {@link ExtendedConnectionDataSourceProxy} to prevent the connection from being + * closed and released after each commit. * + * When you set this option to true then the statement used to open the + * cursor will be created with both 'READ_ONLY' and 'HOLD_CURSORS_OVER_COMMIT' + * options. This allows holding the cursor open over transaction start and commits + * performed in the step processing. To use this feature you need a database that + * supports this and a JDBC driver supporting JDBC 3.0 or later. * @param useSharedExtendedConnection false by default */ public void setUseSharedExtendedConnection(boolean useSharedExtendedConnection) { @@ -373,9 +358,8 @@ implements InitializingBean { } /** - * Set whether "autoCommit" should be overridden for the connection used by the cursor. If not set, defaults to - * Connection / Datasource default configuration. - * + * Set whether "autoCommit" should be overridden for the connection used by the + * cursor. If not set, defaults to Connection / Datasource default configuration. * @param autoCommit value used for {@link Connection#setAutoCommit(boolean)}. * @since 4.0 */ @@ -386,8 +370,8 @@ implements InitializingBean { public abstract String getSql(); /** - * Check the result set is in sync with the currentRow attribute. This is - * important to ensure that the user hasn't modified the current row. + * Check the result set is in sync with the currentRow attribute. This is important to + * ensure that the user hasn't modified the current row. */ private void verifyCursorPosition(long expectedCurrentRow) throws SQLException { if (verifyCursorPosition) { @@ -398,8 +382,8 @@ implements InitializingBean { } /** - * Close the cursor and database connection. Make call to cleanupOnClose so sub classes can cleanup - * any resources they have allocated. + * Close the cursor and database connection. Make call to cleanupOnClose so sub + * classes can cleanup any resources they have allocated. */ @Override protected void doClose() throws Exception { @@ -408,12 +392,12 @@ implements InitializingBean { rs = null; cleanupOnClose(con); - if(this.con != null && !this.con.isClosed()) { + if (this.con != null && !this.con.isClosed()) { this.con.setAutoCommit(this.initialConnectionAutoCommit); } if (useSharedExtendedConnection && dataSource instanceof ExtendedConnectionDataSourceProxy) { - ((ExtendedConnectionDataSourceProxy)dataSource).stopCloseSuppression(this.con); + ((ExtendedConnectionDataSourceProxy) dataSource).stopCloseSuppression(this.con); if (!TransactionSynchronizationManager.isActualTransactionActive()) { DataSourceUtils.releaseConnection(con, dataSource); } @@ -428,7 +412,7 @@ implements InitializingBean { * @param connection to the database * @throws Exception If unable to clean up resources */ - protected abstract void cleanupOnClose(Connection connection) throws Exception; + protected abstract void cleanupOnClose(Connection connection) throws Exception; /** * Execute the statement to open the cursor. @@ -452,11 +436,11 @@ implements InitializingBean { if (useSharedExtendedConnection) { if (!(getDataSource() instanceof ExtendedConnectionDataSourceProxy)) { throw new InvalidDataAccessApiUsageException( - "You must use a ExtendedConnectionDataSourceProxy for the dataSource when " + - "useSharedExtendedConnection is set to true."); + "You must use a ExtendedConnectionDataSourceProxy for the dataSource when " + + "useSharedExtendedConnection is set to true."); } this.con = DataSourceUtils.getConnection(dataSource); - ((ExtendedConnectionDataSourceProxy)dataSource).startCloseSuppression(this.con); + ((ExtendedConnectionDataSourceProxy) dataSource).startCloseSuppression(this.con); } else { this.con = dataSource.getConnection(); @@ -502,9 +486,8 @@ implements InitializingBean { } /** - * Read the cursor and map to the type of object this reader should return. This method must be - * overridden by subclasses. - * + * Read the cursor and map to the type of object this reader should return. This + * method must be overridden by subclasses. * @param rs The current result set * @param currentRow Current position of the result set * @return the mapped object at the cursor position @@ -514,8 +497,8 @@ implements InitializingBean { protected abstract T readCursor(ResultSet rs, int currentRow) throws SQLException; /** - * Use {@link ResultSet#absolute(int)} if possible, otherwise scroll by - * calling {@link ResultSet#next()}. + * Use {@link ResultSet#absolute(int)} if possible, otherwise scroll by calling + * {@link ResultSet#next()}. */ @Override protected void jumpToItem(int itemIndex) throws Exception { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/AbstractPagingItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/AbstractPagingItemReader.java index 57a975e39..39518bde1 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/AbstractPagingItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/AbstractPagingItemReader.java @@ -30,18 +30,18 @@ import org.springframework.util.ClassUtils; * reading database records in a paging fashion. * *

      - * Implementations should execute queries using paged requests of a size - * specified in {@link #setPageSize(int)}. Additional pages are requested when - * needed as {@link #read()} method is called, returning an object corresponding - * to current position. + * Implementations should execute queries using paged requests of a size specified in + * {@link #setPageSize(int)}. Additional pages are requested when needed as + * {@link #read()} method is called, returning an object corresponding to current + * position. *

      * * @author Thomas Risberg * @author Dave Syer * @since 2.0 */ -public abstract class AbstractPagingItemReader extends AbstractItemCountingItemStreamItemReader - implements InitializingBean { +public abstract class AbstractPagingItemReader extends AbstractItemCountingItemStreamItemReader + implements InitializingBean { protected Log logger = LogFactory.getLog(getClass()); @@ -79,7 +79,6 @@ public abstract class AbstractPagingItemReader extends AbstractItemCountingIt /** * The number of rows to retrieve at a time. - * * @param pageSize the number of rows to fetch per page */ public void setPageSize(int pageSize) { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/BeanPropertyItemSqlParameterSourceProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/BeanPropertyItemSqlParameterSourceProvider.java index aa07d50b2..3b9977679 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/BeanPropertyItemSqlParameterSourceProvider.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/BeanPropertyItemSqlParameterSourceProvider.java @@ -19,8 +19,9 @@ import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource; import org.springframework.jdbc.core.namedparam.SqlParameterSource; /** - * A convenient implementation for providing BeanPropertySqlParameterSource when the item has JavaBean properties - * that correspond to names used for parameters in the SQL statement. + * A convenient implementation for providing BeanPropertySqlParameterSource when the item + * has JavaBean properties that correspond to names used for parameters in the SQL + * statement. * * @author Thomas Risberg * @since 2.0 @@ -28,8 +29,8 @@ import org.springframework.jdbc.core.namedparam.SqlParameterSource; public class BeanPropertyItemSqlParameterSourceProvider implements ItemSqlParameterSourceProvider { /** - * Provide parameter values in an {@link BeanPropertySqlParameterSource} based on values from - * the provided item. + * Provide parameter values in an {@link BeanPropertySqlParameterSource} based on + * values from the provided item. * @param item the item to use for parameter values */ @Override diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/ExtendedConnectionDataSourceProxy.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/ExtendedConnectionDataSourceProxy.java index 8ad3fbf5b..6a910dd9a 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/ExtendedConnectionDataSourceProxy.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/ExtendedConnectionDataSourceProxy.java @@ -37,43 +37,39 @@ import org.springframework.util.Assert; import org.springframework.util.MethodInvoker; /** - * Implementation of {@link SmartDataSource} that is capable of keeping a single - * JDBC Connection which is NOT closed after each use even if - * {@link Connection#close()} is called. + * Implementation of {@link SmartDataSource} that is capable of keeping a single JDBC + * Connection which is NOT closed after each use even if {@link Connection#close()} is + * called. * - * The connection can be kept open over multiple transactions when used together - * with any of Spring's - * {@link org.springframework.transaction.PlatformTransactionManager} + * The connection can be kept open over multiple transactions when used together with any + * of Spring's {@link org.springframework.transaction.PlatformTransactionManager} * implementations. * *

      - * Loosely based on the SingleConnectionDataSource implementation in Spring - * Core. Intended to be used with the {@link JdbcCursorItemReader} to provide a - * connection that remains open across transaction boundaries, It remains open - * for the life of the cursor, and can be shared with the main transaction of - * the rest of the step processing. + * Loosely based on the SingleConnectionDataSource implementation in Spring Core. Intended + * to be used with the {@link JdbcCursorItemReader} to provide a connection that remains + * open across transaction boundaries, It remains open for the life of the cursor, and can + * be shared with the main transaction of the rest of the step processing. * *

      - * Once close suppression has been turned on for a connection, it will be - * returned for the first {@link #getConnection()} call. Any subsequent calls to - * {@link #getConnection()} will retrieve a new connection from the wrapped - * {@link DataSource} until the {@link DataSourceUtils} queries whether the - * connection should be closed or not by calling - * {@link #shouldClose(Connection)} for the close-suppressed {@link Connection}. - * At that point the cycle starts over again, and the next - * {@link #getConnection()} call will have the {@link Connection} that is being - * close-suppressed returned. This allows the use of the close-suppressed - * {@link Connection} to be the main {@link Connection} for an extended data - * access process. The close suppression is turned off by calling + * Once close suppression has been turned on for a connection, it will be returned for the + * first {@link #getConnection()} call. Any subsequent calls to {@link #getConnection()} + * will retrieve a new connection from the wrapped {@link DataSource} until the + * {@link DataSourceUtils} queries whether the connection should be closed or not by + * calling {@link #shouldClose(Connection)} for the close-suppressed {@link Connection}. + * At that point the cycle starts over again, and the next {@link #getConnection()} call + * will have the {@link Connection} that is being close-suppressed returned. This allows + * the use of the close-suppressed {@link Connection} to be the main {@link Connection} + * for an extended data access process. The close suppression is turned off by calling * {@link #stopCloseSuppression(Connection)}. * *

      * This class is not multi-threading capable. * *

      - * The connection returned will be a close-suppressing proxy instead of the - * physical {@link Connection}. Be aware that you will not be able to cast this - * to a native OracleConnection or the like anymore; you'd be required to use + * The connection returned will be a close-suppressing proxy instead of the physical + * {@link Connection}. Be aware that you will not be able to cast this to a native + * OracleConnection or the like anymore; you'd be required to use * {@link java.sql.Connection#unwrap(Class)}. * * @author Thomas Risberg @@ -104,9 +100,7 @@ public class ExtendedConnectionDataSourceProxy implements SmartDataSource, Initi } /** - * Constructor that takes as a parameter with the {@link DataSource} to be - * wrapped. - * + * Constructor that takes as a parameter with the {@link DataSource} to be wrapped. * @param dataSource DataSource to be used */ public ExtendedConnectionDataSourceProxy(DataSource dataSource) { @@ -115,7 +109,6 @@ public class ExtendedConnectionDataSourceProxy implements SmartDataSource, Initi /** * Setter for the {@link DataSource} that is to be wrapped. - * * @param dataSource the DataSource */ public void setDataSource(DataSource dataSource) { @@ -137,9 +130,8 @@ public class ExtendedConnectionDataSourceProxy implements SmartDataSource, Initi /** * Return the status of close suppression being activated for a given * {@link Connection} - * - * @param connection the {@link Connection} that the close suppression - * status is requested for + * @param connection the {@link Connection} that the close suppression status is + * requested for * @return true or false */ public boolean isCloseSuppressionActive(Connection connection) { @@ -147,9 +139,7 @@ public class ExtendedConnectionDataSourceProxy implements SmartDataSource, Initi } /** - * - * @param connection the {@link Connection} that close suppression is - * requested for + * @param connection the {@link Connection} that close suppression is requested for */ public void startCloseSuppression(Connection connection) { synchronized (this.connectionMonitor) { @@ -161,9 +151,8 @@ public class ExtendedConnectionDataSourceProxy implements SmartDataSource, Initi } /** - * - * @param connection the {@link Connection} that close suppression should be - * turned off for + * @param connection the {@link Connection} that close suppression should be turned + * off for */ public void stopCloseSuppression(Connection connection) { synchronized (this.connectionMonitor) { @@ -232,8 +221,8 @@ public class ExtendedConnectionDataSourceProxy implements SmartDataSource, Initi } /** - * Wrap the given Connection with a proxy that delegates every method call - * to it but suppresses close calls. + * Wrap the given Connection with a proxy that delegates every method call to it but + * suppresses close calls. * @param target the original Connection to wrap * @return the wrapped Connection */ @@ -243,9 +232,9 @@ public class ExtendedConnectionDataSourceProxy implements SmartDataSource, Initi } /** - * Invocation handler that suppresses close calls on JDBC Connections until - * the associated instance of the ExtendedConnectionDataSourceProxy - * determines the connection should actually be closed. + * Invocation handler that suppresses close calls on JDBC Connections until the + * associated instance of the ExtendedConnectionDataSourceProxy determines the + * connection should actually be closed. */ private static class CloseSuppressingInvocationHandler implements InvocationHandler { @@ -263,26 +252,26 @@ public class ExtendedConnectionDataSourceProxy implements SmartDataSource, Initi // Invocation on ConnectionProxy interface coming in... switch (method.getName()) { - case "equals": - // Only consider equal when proxies are identical. - return (proxy == args[0] ? Boolean.TRUE : Boolean.FALSE); - case "hashCode": - // Use hashCode of Connection proxy. - return System.identityHashCode(proxy); - case "close": - // Handle close method: don't pass the call on if we are - // suppressing close calls. - if (dataSource.completeCloseCall((Connection) proxy)) { - return null; - } - else { - target.close(); - return null; - } - case "getTargetConnection": - // Handle getTargetConnection method: return underlying - // Connection. - return this.target; + case "equals": + // Only consider equal when proxies are identical. + return (proxy == args[0] ? Boolean.TRUE : Boolean.FALSE); + case "hashCode": + // Use hashCode of Connection proxy. + return System.identityHashCode(proxy); + case "close": + // Handle close method: don't pass the call on if we are + // suppressing close calls. + if (dataSource.completeCloseCall((Connection) proxy)) { + return null; + } + else { + target.close(); + return null; + } + case "getTargetConnection": + // Handle getTargetConnection method: return underlying + // Connection. + return this.target; } // Invoke method on target Connection. @@ -293,11 +282,12 @@ public class ExtendedConnectionDataSourceProxy implements SmartDataSource, Initi throw ex.getTargetException(); } } + } /** - * Performs only a 'shallow' non-recursive check of self's and delegate's - * class to retain Java 5 compatibility. + * Performs only a 'shallow' non-recursive check of self's and delegate's class to + * retain Java 5 compatibility. */ @Override public boolean isWrapperFor(Class iface) throws SQLException { @@ -305,9 +295,9 @@ public class ExtendedConnectionDataSourceProxy implements SmartDataSource, Initi } /** - * Returns either self or delegate (in this order) if one of them can be - * cast to supplied parameter class. Does *not* support recursive unwrapping - * of the delegate to retain Java 5 compatibility. + * Returns either self or delegate (in this order) if one of them can be cast to + * supplied parameter class. Does *not* support recursive unwrapping of the delegate + * to retain Java 5 compatibility. */ @Override public T unwrap(Class iface) throws SQLException { @@ -332,7 +322,7 @@ public class ExtendedConnectionDataSourceProxy implements SmartDataSource, Initi /** * Added due to JDK 7 compatibility. */ - public Logger getParentLogger() throws SQLFeatureNotSupportedException{ + public Logger getParentLogger() throws SQLFeatureNotSupportedException { MethodInvoker invoker = new MethodInvoker(); invoker.setTargetObject(dataSource); invoker.setTargetMethod("getParentLogger"); @@ -340,8 +330,11 @@ public class ExtendedConnectionDataSourceProxy implements SmartDataSource, Initi try { invoker.prepare(); return (Logger) invoker.invoke(); - } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException nsme) { + } + catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException + | InvocationTargetException nsme) { throw new SQLFeatureNotSupportedException(nsme); } } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/HibernateCursorItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/HibernateCursorItemReader.java index 5769e267f..b78f89984 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/HibernateCursorItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/HibernateCursorItemReader.java @@ -33,21 +33,19 @@ import org.springframework.util.ClassUtils; /** * {@link ItemStreamReader} for reading database records built on top of Hibernate. It - * executes the HQL query when initialized iterates over the result set as - * {@link #read()} method is called, returning an object corresponding to - * current row. The query can be set directly using - * {@link #setQueryString(String)}, a named query can be used by - * {@link #setQueryName(String)}, or a query provider strategy can be supplied - * via {@link #setQueryProvider(HibernateQueryProvider)}. + * executes the HQL query when initialized iterates over the result set as {@link #read()} + * method is called, returning an object corresponding to current row. The query can be + * set directly using {@link #setQueryString(String)}, a named query can be used by + * {@link #setQueryName(String)}, or a query provider strategy can be supplied via + * {@link #setQueryProvider(HibernateQueryProvider)}. * * *

      - * The reader can be configured to use either {@link StatelessSession} - * sufficient for simple mappings without the need to cascade to associated - * objects or standard hibernate {@link Session} for more advanced mappings or - * when caching is desired. When stateful session is used it will be cleared in - * the {@link #update(ExecutionContext)} method without being flushed (no data - * modifications are expected). + * The reader can be configured to use either {@link StatelessSession} sufficient for + * simple mappings without the need to cascade to associated objects or standard hibernate + * {@link Session} for more advanced mappings or when caching is desired. When stateful + * session is used it will be cleared in the {@link #update(ExecutionContext)} method + * without being flushed (no data modifications are expected). *

      * * The implementation is not thread-safe. @@ -55,8 +53,8 @@ import org.springframework.util.ClassUtils; * @author Robert Kasanicky * @author Dave Syer */ -public class HibernateCursorItemReader extends AbstractItemCountingItemStreamItemReader - implements InitializingBean { +public class HibernateCursorItemReader extends AbstractItemCountingItemStreamItemReader + implements InitializingBean { private HibernateItemReaderHelper helper = new HibernateItemReaderHelper<>(); @@ -80,7 +78,6 @@ public class HibernateCursorItemReader extends AbstractItemCountingItemStream /** * The parameter values to apply to a query (map of name:value). - * * @param parameterValues the parameter values to set */ public void setParameterValues(Map parameterValues) { @@ -90,9 +87,7 @@ public class HibernateCursorItemReader extends AbstractItemCountingItemStream /** * A query name for an externalized query. Either this or the { * {@link #setQueryString(String) query string} or the { - * {@link #setQueryProvider(HibernateQueryProvider) query provider} should - * be set. - * + * {@link #setQueryProvider(HibernateQueryProvider) query provider} should be set. * @param queryName name of a hibernate named query */ public void setQueryName(String queryName) { @@ -100,9 +95,8 @@ public class HibernateCursorItemReader extends AbstractItemCountingItemStream } /** - * Fetch size used internally by Hibernate to limit amount of data fetched - * from database per round trip. - * + * Fetch size used internally by Hibernate to limit amount of data fetched from + * database per round trip. * @param fetchSize the fetch size to pass down to Hibernate */ public void setFetchSize(int fetchSize) { @@ -110,10 +104,8 @@ public class HibernateCursorItemReader extends AbstractItemCountingItemStream } /** - * A query provider. Either this or the {{@link #setQueryString(String) - * query string} or the {{@link #setQueryName(String) query name} should be - * set. - * + * A query provider. Either this or the {{@link #setQueryString(String) query string} + * or the {{@link #setQueryName(String) query name} should be set. * @param queryProvider Hibernate query provider */ public void setQueryProvider(HibernateQueryProvider queryProvider) { @@ -124,7 +116,6 @@ public class HibernateCursorItemReader extends AbstractItemCountingItemStream * A query string in HQL. Either this or the { * {@link #setQueryProvider(HibernateQueryProvider) query provider} or the { * {@link #setQueryName(String) query name} should be set. - * * @param queryString HQL query string */ public void setQueryString(String queryString) { @@ -133,7 +124,6 @@ public class HibernateCursorItemReader extends AbstractItemCountingItemStream /** * The Hibernate SessionFactory to use the create a session. - * * @param sessionFactory the {@link SessionFactory} to set */ public void setSessionFactory(SessionFactory sessionFactory) { @@ -142,10 +132,8 @@ public class HibernateCursorItemReader extends AbstractItemCountingItemStream /** * Can be set only in uninitialized state. - * - * @param useStatelessSession true to use - * {@link StatelessSession} false to use standard hibernate - * {@link Session} + * @param useStatelessSession true to use {@link StatelessSession} + * false to use standard hibernate {@link Session} */ public void setUseStatelessSession(boolean useStatelessSession) { helper.setUseStatelessSession(useStatelessSession); @@ -190,7 +178,6 @@ public class HibernateCursorItemReader extends AbstractItemCountingItemStream /** * Update the context and clear the session if stateful. - * * @param executionContext the current {@link ExecutionContext} * @throws ItemStreamException if there is a problem */ @@ -201,11 +188,9 @@ public class HibernateCursorItemReader extends AbstractItemCountingItemStream } /** - * Wind forward through the result set to the item requested. Also clears - * the session every now and then (if stateful) to avoid memory problems. - * The frequency of session clearing is the larger of the fetch size (if - * set) and 100. - * + * Wind forward through the result set to the item requested. Also clears the session + * every now and then (if stateful) to avoid memory problems. The frequency of session + * clearing is the larger of the fetch size (if set) and 100. * @param itemIndex the first item to read * @throws Exception if there is a problem * @see AbstractItemCountingItemStreamItemReader#jumpToItem(int) @@ -222,7 +207,7 @@ public class HibernateCursorItemReader extends AbstractItemCountingItemStream @Override protected void doClose() throws Exception { - if(initialized) { + if (initialized) { if (cursor != null) { cursor.close(); } @@ -232,4 +217,5 @@ public class HibernateCursorItemReader extends AbstractItemCountingItemStream initialized = false; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/HibernateItemReaderHelper.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/HibernateItemReaderHelper.java index 4722750e7..1a923328f 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/HibernateItemReaderHelper.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/HibernateItemReaderHelper.java @@ -32,8 +32,7 @@ import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; /** - * Internal shared state helper for hibernate readers managing sessions and - * queries. + * Internal shared state helper for hibernate readers managing sessions and queries. * * @author Dave Syer * @author Mahmoud Ben Hassine @@ -78,14 +77,12 @@ public class HibernateItemReaderHelper implements InitializingBean { /** * Can be set only in uninitialized state. - * - * @param useStatelessSession true to use - * {@link StatelessSession} false to use standard hibernate - * {@link Session} + * @param useStatelessSession true to use {@link StatelessSession} + * false to use standard hibernate {@link Session} */ public void setUseStatelessSession(boolean useStatelessSession) { Assert.state(statefulSession == null && statelessSession == null, - "The useStatelessSession flag can only be set before a session is initialized."); + "The useStatelessSession flag can only be set before a session is initialized."); this.useStatelessSession = useStatelessSession; } @@ -104,16 +101,14 @@ public class HibernateItemReaderHelper implements InitializingBean { if (queryProvider == null) { Assert.notNull(sessionFactory, "session factory must be set"); Assert.state(StringUtils.hasText(queryString) ^ StringUtils.hasText(queryName), - "queryString or queryName must be set"); + "queryString or queryName must be set"); } } /** * Get a cursor over all of the results, with the forward-only flag set. - * * @param fetchSize the fetch size to use retrieving the results * @param parameterValues the parameter values to use (or null if none). - * * @return a forward-only {@link ScrollableResults} */ public ScrollableResults getForwardOnlyCursor(int fetchSize, Map parameterValues) { @@ -126,7 +121,6 @@ public class HibernateItemReaderHelper implements InitializingBean { /** * Open appropriate type of hibernate session and create the query. - * * @return a Hibernate Query */ @SuppressWarnings("unchecked") // Hibernate APIs do not use a typed Query @@ -172,7 +166,6 @@ public class HibernateItemReaderHelper implements InitializingBean { /** * Scroll through the results up to the item specified. - * * @param cursor the results to scroll over * @param itemIndex index to scroll to * @param flushInterval the number of items to scroll past before flushing @@ -201,17 +194,16 @@ public class HibernateItemReaderHelper implements InitializingBean { } /** - * Read a page of data, clearing the existing session (if necessary) first, - * and creating a new session before executing the query. - * + * Read a page of data, clearing the existing session (if necessary) first, and + * creating a new session before executing the query. * @param page the page to read (starting at 0) * @param pageSize the size of the page or maximum number of items to read * @param fetchSize the fetch size to use - * @param parameterValues the parameter values to use (if any, otherwise - * null) + * @param parameterValues the parameter values to use (if any, otherwise null) * @return a collection of items */ - public Collection readPage(int page, int pageSize, int fetchSize, Map parameterValues) { + public Collection readPage(int page, int pageSize, int fetchSize, + Map parameterValues) { clear(); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/HibernateItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/HibernateItemWriter.java index 35a9825b3..f9b621804 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/HibernateItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/HibernateItemWriter.java @@ -28,16 +28,15 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; /** - * {@link ItemWriter} that uses a Hibernate session to save or update entities - * that are not part of the current Hibernate session. It will also flush the - * session after writing (i.e. at chunk boundaries if used in a Spring Batch - * TaskletStep). It will also clear the session on write - * default (see {@link #setClearSession(boolean) clearSession} property).
      + * {@link ItemWriter} that uses a Hibernate session to save or update entities that are + * not part of the current Hibernate session. It will also flush the session after writing + * (i.e. at chunk boundaries if used in a Spring Batch TaskletStep). It will also clear + * the session on write default (see {@link #setClearSession(boolean) clearSession} + * property).
      *
      * - * The writer is thread-safe once properties are set (normal singleton behavior) - * if a {@link CurrentSessionContext} that uses only one session per thread is - * used. + * The writer is thread-safe once properties are set (normal singleton behavior) if a + * {@link CurrentSessionContext} that uses only one session per thread is used. * * @author Dave Syer * @author Thomas Risberg @@ -47,19 +46,16 @@ import org.springframework.util.Assert; */ public class HibernateItemWriter implements ItemWriter, InitializingBean { - protected static final Log logger = LogFactory - .getLog(HibernateItemWriter.class); + protected static final Log logger = LogFactory.getLog(HibernateItemWriter.class); private SessionFactory sessionFactory; private boolean clearSession = true; /** - * Flag to indicate that the session should be cleared and flushed at the - * end of the write (default true). - * - * @param clearSession - * the flag value to set + * Flag to indicate that the session should be cleared and flushed at the end of the + * write (default true). + * @param clearSession the flag value to set */ public void setClearSession(boolean clearSession) { this.clearSession = clearSession; @@ -67,7 +63,6 @@ public class HibernateItemWriter implements ItemWriter, InitializingBean { /** * Set the Hibernate SessionFactory to be used internally. - * * @param sessionFactory session factory to be used by the writer */ public void setSessionFactory(SessionFactory sessionFactory) { @@ -79,13 +74,12 @@ public class HibernateItemWriter implements ItemWriter, InitializingBean { */ @Override public void afterPropertiesSet() { - Assert.state(sessionFactory != null, - "SessionFactory must be provided"); + Assert.state(sessionFactory != null, "SessionFactory must be provided"); } /** - * Save or update any entities not in the current hibernate session and then - * flush the hibernate session. + * Save or update any entities not in the current hibernate session and then flush the + * hibernate session. * * @see org.springframework.batch.item.ItemWriter#write(java.util.List) */ @@ -93,22 +87,20 @@ public class HibernateItemWriter implements ItemWriter, InitializingBean { public void write(List items) { doWrite(sessionFactory, items); sessionFactory.getCurrentSession().flush(); - if(clearSession) { + if (clearSession) { sessionFactory.getCurrentSession().clear(); } } /** - * Do perform the actual write operation using Hibernate's API. - * This can be overridden in a subclass if necessary. - * + * Do perform the actual write operation using Hibernate's API. This can be overridden + * in a subclass if necessary. * @param sessionFactory Hibernate SessionFactory to be used * @param items the list of items to use for the write */ protected void doWrite(SessionFactory sessionFactory, List items) { if (logger.isDebugEnabled()) { - logger.debug("Writing to Hibernate with " + items.size() - + " items."); + logger.debug("Writing to Hibernate with " + items.size() + " items."); } Session currentSession = sessionFactory.getCurrentSession(); @@ -123,8 +115,7 @@ public class HibernateItemWriter implements ItemWriter, InitializingBean { } if (logger.isDebugEnabled()) { logger.debug(saveOrUpdateCount + " entities saved/updated."); - logger.debug((items.size() - saveOrUpdateCount) - + " entities found in session."); + logger.debug((items.size() - saveOrUpdateCount) + " entities found in session."); } } } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/HibernatePagingItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/HibernatePagingItemReader.java index 92d71d583..4ca8bed42 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/HibernatePagingItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/HibernatePagingItemReader.java @@ -29,36 +29,31 @@ import org.springframework.util.Assert; import org.springframework.util.ClassUtils; /** - * {@link ItemReader} for reading database records built on top of Hibernate and - * reading only up to a fixed number of items at a time. It executes an HQL - * query when initialized is paged as the {@link #read()} method is called. The - * query can be set directly using {@link #setQueryString(String)}, a named - * query can be used by {@link #setQueryName(String)}, or a query provider - * strategy can be supplied via + * {@link ItemReader} for reading database records built on top of Hibernate and reading + * only up to a fixed number of items at a time. It executes an HQL query when initialized + * is paged as the {@link #read()} method is called. The query can be set directly using + * {@link #setQueryString(String)}, a named query can be used by + * {@link #setQueryName(String)}, or a query provider strategy can be supplied via * {@link #setQueryProvider(HibernateQueryProvider)}. * *

      - * The reader can be configured to use either {@link StatelessSession} - * sufficient for simple mappings without the need to cascade to associated - * objects or standard hibernate {@link Session} for more advanced mappings or - * when caching is desired. When stateful session is used it will be cleared in - * the {@link #update(ExecutionContext)} method without being flushed (no data - * modifications are expected). + * The reader can be configured to use either {@link StatelessSession} sufficient for + * simple mappings without the need to cascade to associated objects or standard hibernate + * {@link Session} for more advanced mappings or when caching is desired. When stateful + * session is used it will be cleared in the {@link #update(ExecutionContext)} method + * without being flushed (no data modifications are expected). *

      * *

      - * The implementation is thread-safe in between calls to - * {@link #open(ExecutionContext)}, but remember to use - * saveState=false if used in a multi-threaded client (no restart - * available). + * The implementation is thread-safe in between calls to {@link #open(ExecutionContext)}, + * but remember to use saveState=false if used in a multi-threaded client (no + * restart available). *

      * * @author Dave Syer - * * @since 2.1 */ -public class HibernatePagingItemReader extends AbstractPagingItemReader - implements InitializingBean { +public class HibernatePagingItemReader extends AbstractPagingItemReader implements InitializingBean { private HibernateItemReaderHelper helper = new HibernateItemReaderHelper<>(); @@ -72,7 +67,6 @@ public class HibernatePagingItemReader extends AbstractPagingItemReader /** * The parameter values to apply to a query (map of name:value). - * * @param parameterValues the parameter values to set */ public void setParameterValues(Map parameterValues) { @@ -82,9 +76,7 @@ public class HibernatePagingItemReader extends AbstractPagingItemReader /** * A query name for an externalized query. Either this or the { * {@link #setQueryString(String) query string} or the { - * {@link #setQueryProvider(HibernateQueryProvider) query provider} should - * be set. - * + * {@link #setQueryProvider(HibernateQueryProvider) query provider} should be set. * @param queryName name of a hibernate named query */ public void setQueryName(String queryName) { @@ -92,9 +84,8 @@ public class HibernatePagingItemReader extends AbstractPagingItemReader } /** - * Fetch size used internally by Hibernate to limit amount of data fetched - * from database per round trip. - * + * Fetch size used internally by Hibernate to limit amount of data fetched from + * database per round trip. * @param fetchSize the fetch size to pass down to Hibernate */ public void setFetchSize(int fetchSize) { @@ -102,10 +93,8 @@ public class HibernatePagingItemReader extends AbstractPagingItemReader } /** - * A query provider. Either this or the {{@link #setQueryString(String) - * query string} or the {{@link #setQueryName(String) query name} should be - * set. - * + * A query provider. Either this or the {{@link #setQueryString(String) query string} + * or the {{@link #setQueryName(String) query name} should be set. * @param queryProvider Hibernate query provider */ public void setQueryProvider(HibernateQueryProvider queryProvider) { @@ -116,7 +105,6 @@ public class HibernatePagingItemReader extends AbstractPagingItemReader * A query string in HQL. Either this or the { * {@link #setQueryProvider(HibernateQueryProvider) query provider} or the { * {@link #setQueryName(String) query name} should be set. - * * @param queryString HQL query string */ public void setQueryString(String queryString) { @@ -125,7 +113,6 @@ public class HibernatePagingItemReader extends AbstractPagingItemReader /** * The Hibernate SessionFactory to use the create a session. - * * @param sessionFactory the {@link SessionFactory} to set */ public void setSessionFactory(SessionFactory sessionFactory) { @@ -134,10 +121,8 @@ public class HibernatePagingItemReader extends AbstractPagingItemReader /** * Can be set only in uninitialized state. - * - * @param useStatelessSession true to use - * {@link StatelessSession} false to use standard hibernate - * {@link Session} + * @param useStatelessSession true to use {@link StatelessSession} + * false to use standard hibernate {@link Session} */ public void setUseStatelessSession(boolean useStatelessSession) { helper.setUseStatelessSession(useStatelessSession); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/ItemPreparedStatementSetter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/ItemPreparedStatementSetter.java index 61264d2bf..6c9383784 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/ItemPreparedStatementSetter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/ItemPreparedStatementSetter.java @@ -23,18 +23,19 @@ import org.springframework.jdbc.core.RowMapper; /** * A convenient strategy for SQL updates, acting effectively as the inverse of * {@link RowMapper}. - * + * * @author Dave Syer - * + * */ public interface ItemPreparedStatementSetter { + /** - * Set parameter values on the given PreparedStatement as determined from - * the provided item. + * Set parameter values on the given PreparedStatement as determined from the provided + * item. * @param item the item to obtain the values from * @param ps the PreparedStatement to invoke setter methods on - * @throws SQLException if a SQLException is encountered (i.e. there is no - * need to catch SQLException) + * @throws SQLException if a SQLException is encountered (i.e. there is no need to + * catch SQLException) */ void setValues(T item, PreparedStatement ps) throws SQLException; diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/ItemSqlParameterSourceProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/ItemSqlParameterSourceProvider.java index 45634769a..1885a9958 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/ItemSqlParameterSourceProvider.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/ItemSqlParameterSourceProvider.java @@ -19,15 +19,15 @@ import org.springframework.jdbc.core.namedparam.SqlParameterSource; /** * A convenient strategy for providing SqlParameterSource for named parameter SQL updates. - * + * * @author Thomas Risberg * @since 2.0 */ public interface ItemSqlParameterSourceProvider { /** - * Provide parameter values in an {@link SqlParameterSource} based on values from - * the provided item. + * Provide parameter values in an {@link SqlParameterSource} based on values from the + * provided item. * @param item the item to use for parameter values * @return parameters extracted from the item */ diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JdbcBatchItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JdbcBatchItemWriter.java index 7ca7e1730..9e19791f6 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JdbcBatchItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JdbcBatchItemWriter.java @@ -37,22 +37,24 @@ import org.springframework.jdbc.core.namedparam.SqlParameterSource; import org.springframework.util.Assert; /** - *

      {@link ItemWriter} that uses the batching features from + *

      + * {@link ItemWriter} that uses the batching features from * {@link NamedParameterJdbcTemplate} to execute a batch of statements for all items - * provided.

      + * provided. + *

      * * The user must provide an SQL query and a special callback for either of - * {@link ItemPreparedStatementSetter} or {@link ItemSqlParameterSourceProvider}. - * You can use either named parameters or the traditional '?' placeholders. If you use the - * named parameter support then you should provide a {@link ItemSqlParameterSourceProvider}, - * otherwise you should provide a {@link ItemPreparedStatementSetter}. - * This callback would be responsible for mapping the item to the parameters needed to - * execute the SQL statement.
      + * {@link ItemPreparedStatementSetter} or {@link ItemSqlParameterSourceProvider}. You can + * use either named parameters or the traditional '?' placeholders. If you use the named + * parameter support then you should provide a {@link ItemSqlParameterSourceProvider}, + * otherwise you should provide a {@link ItemPreparedStatementSetter}. This callback would + * be responsible for mapping the item to the parameters needed to execute the SQL + * statement.
      * * It is expected that {@link #write(List)} is called inside a transaction.
      * - * The writer is thread-safe after its properties are set (normal singleton - * behavior), so it can be used to write in multiple concurrent transactions. + * The writer is thread-safe after its properties are set (normal singleton behavior), so + * it can be used to write in multiple concurrent transactions. * * @author Dave Syer * @author Thomas Risberg @@ -78,8 +80,8 @@ public class JdbcBatchItemWriter implements ItemWriter, InitializingBean { protected boolean usingNamedParameters; /** - * Public setter for the flag that determines whether an assertion is made - * that all items cause at least one row to be updated. + * Public setter for the flag that determines whether an assertion is made that all + * items cause at least one row to be updated. * @param assertUpdates the flag to set. Defaults to true; */ public void setAssertUpdates(boolean assertUpdates) { @@ -87,9 +89,8 @@ public class JdbcBatchItemWriter implements ItemWriter, InitializingBean { } /** - * Public setter for the query string to execute on write. The parameters - * should correspond to those known to the - * {@link ItemPreparedStatementSetter}. + * Public setter for the query string to execute on write. The parameters should + * correspond to those known to the {@link ItemPreparedStatementSetter}. * @param sql the query to set */ public void setSql(String sql) { @@ -98,8 +99,8 @@ public class JdbcBatchItemWriter implements ItemWriter, InitializingBean { /** * Public setter for the {@link ItemPreparedStatementSetter}. - * @param preparedStatementSetter the {@link ItemPreparedStatementSetter} to - * set. This is required when using traditional '?' placeholders for the SQL statement. + * @param preparedStatementSetter the {@link ItemPreparedStatementSetter} to set. This + * is required when using traditional '?' placeholders for the SQL statement. */ public void setItemPreparedStatementSetter(ItemPreparedStatementSetter preparedStatementSetter) { this.itemPreparedStatementSetter = preparedStatementSetter; @@ -108,8 +109,8 @@ public class JdbcBatchItemWriter implements ItemWriter, InitializingBean { /** * Public setter for the {@link ItemSqlParameterSourceProvider}. * @param itemSqlParameterSourceProvider the {@link ItemSqlParameterSourceProvider} to - * set. This is required when using named parameters for the SQL statement and the type - * to be written does not implement {@link Map}. + * set. This is required when using named parameters for the SQL statement and the + * type to be written does not implement {@link Map}. */ public void setItemSqlParameterSourceProvider(ItemSqlParameterSourceProvider itemSqlParameterSourceProvider) { this.itemSqlParameterSourceProvider = itemSqlParameterSourceProvider; @@ -117,7 +118,6 @@ public class JdbcBatchItemWriter implements ItemWriter, InitializingBean { /** * Public setter for the data source for injection purposes. - * * @param dataSource {@link javax.sql.DataSource} to use for querying against */ public void setDataSource(DataSource dataSource) { @@ -135,8 +135,8 @@ public class JdbcBatchItemWriter implements ItemWriter, InitializingBean { } /** - * Check mandatory properties - there must be a SimpleJdbcTemplate and an SQL statement plus a - * parameter source. + * Check mandatory properties - there must be a SimpleJdbcTemplate and an SQL + * statement plus a parameter source. */ @Override public void afterPropertiesSet() { @@ -146,16 +146,20 @@ public class JdbcBatchItemWriter implements ItemWriter, InitializingBean { parameterCount = JdbcParameterUtils.countParameterPlaceholders(sql, namedParameters); if (namedParameters.size() > 0) { if (parameterCount != namedParameters.size()) { - throw new InvalidDataAccessApiUsageException("You can't use both named parameters and classic \"?\" placeholders: " + sql); + throw new InvalidDataAccessApiUsageException( + "You can't use both named parameters and classic \"?\" placeholders: " + sql); } usingNamedParameters = true; } if (!usingNamedParameters) { - Assert.notNull(itemPreparedStatementSetter, "Using SQL statement with '?' placeholders requires an ItemPreparedStatementSetter"); + Assert.notNull(itemPreparedStatementSetter, + "Using SQL statement with '?' placeholders requires an ItemPreparedStatementSetter"); } } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.springframework.batch.item.ItemWriter#write(java.util.List) */ @SuppressWarnings("unchecked") @@ -171,9 +175,10 @@ public class JdbcBatchItemWriter implements ItemWriter, InitializingBean { int[] updateCounts; if (usingNamedParameters) { - if(items.get(0) instanceof Map && this.itemSqlParameterSourceProvider == null) { + if (items.get(0) instanceof Map && this.itemSqlParameterSourceProvider == null) { updateCounts = namedParameterJdbcTemplate.batchUpdate(sql, items.toArray(new Map[items.size()])); - } else { + } + else { SqlParameterSource[] batchArgs = new SqlParameterSource[items.size()]; int i = 0; for (T item : items) { @@ -183,16 +188,18 @@ public class JdbcBatchItemWriter implements ItemWriter, InitializingBean { } } else { - updateCounts = namedParameterJdbcTemplate.getJdbcOperations().execute(sql, new PreparedStatementCallback() { - @Override - public int[] doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException { - for (T item : items) { - itemPreparedStatementSetter.setValues(item, ps); - ps.addBatch(); - } - return ps.executeBatch(); - } - }); + updateCounts = namedParameterJdbcTemplate.getJdbcOperations().execute(sql, + new PreparedStatementCallback() { + @Override + public int[] doInPreparedStatement(PreparedStatement ps) + throws SQLException, DataAccessException { + for (T item : items) { + itemPreparedStatementSetter.setValues(item, ps); + ps.addBatch(); + } + return ps.executeBatch(); + } + }); } if (assertUpdates) { @@ -206,4 +213,5 @@ public class JdbcBatchItemWriter implements ItemWriter, InitializingBean { } } } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JdbcCursorItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JdbcCursorItemReader.java index 920b785c3..844312576 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JdbcCursorItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JdbcCursorItemReader.java @@ -30,15 +30,16 @@ import org.springframework.util.ClassUtils; /** *

      - * Simple item reader implementation that opens a JDBC cursor and continually retrieves the - * next row in the ResultSet. + * Simple item reader implementation that opens a JDBC cursor and continually retrieves + * the next row in the ResultSet. *

      * *

      - * The statement used to open the cursor is created with the 'READ_ONLY' option since a non read-only - * cursor may unnecessarily lock tables or rows. It is also opened with 'TYPE_FORWARD_ONLY' option. - * By default the cursor will be opened using a separate connection which means that it will not participate - * in any transactions created as part of the step processing. + * The statement used to open the cursor is created with the 'READ_ONLY' option since a + * non read-only cursor may unnecessarily lock tables or rows. It is also opened with + * 'TYPE_FORWARD_ONLY' option. By default the cursor will be opened using a separate + * connection which means that it will not participate in any transactions created as part + * of the step processing. *

      * *

      @@ -69,7 +70,6 @@ public class JdbcCursorItemReader extends AbstractCursorItemReader { /** * Set the RowMapper to be used for all calls to read(). - * * @param rowMapper the mapper used to map each item */ public void setRowMapper(RowMapper rowMapper) { @@ -77,10 +77,9 @@ public class JdbcCursorItemReader extends AbstractCursorItemReader { } /** - * Set the SQL statement to be used when creating the cursor. This statement - * should be a complete and valid SQL statement, as it will be run directly - * without any modification. - * + * Set the SQL statement to be used when creating the cursor. This statement should be + * a complete and valid SQL statement, as it will be run directly without any + * modification. * @param sql SQL statement */ public void setSql(String sql) { @@ -88,10 +87,10 @@ public class JdbcCursorItemReader extends AbstractCursorItemReader { } /** - * Set the PreparedStatementSetter to use if any parameter values that need - * to be set in the supplied query. - * - * @param preparedStatementSetter PreparedStatementSetter responsible for filling out the statement + * Set the PreparedStatementSetter to use if any parameter values that need to be set + * in the supplied query. + * @param preparedStatementSetter PreparedStatementSetter responsible for filling out + * the statement */ public void setPreparedStatementSetter(PreparedStatementSetter preparedStatementSetter) { this.preparedStatementSetter = preparedStatementSetter; @@ -99,9 +98,7 @@ public class JdbcCursorItemReader extends AbstractCursorItemReader { /** * Assert that mandatory properties are set. - * - * @throws IllegalArgumentException if either data source or SQL properties - * not set. + * @throws IllegalArgumentException if either data source or SQL properties not set. */ @Override public void afterPropertiesSet() throws Exception { @@ -110,7 +107,6 @@ public class JdbcCursorItemReader extends AbstractCursorItemReader { Assert.notNull(rowMapper, "RowMapper must be provided"); } - @Override protected void openCursor(Connection con) { try { @@ -135,7 +131,6 @@ public class JdbcCursorItemReader extends AbstractCursorItemReader { } - @Nullable @Override protected T readCursor(ResultSet rs, int currentRow) throws SQLException { @@ -156,4 +151,5 @@ public class JdbcCursorItemReader extends AbstractCursorItemReader { public String getSql() { return this.sql; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JdbcPagingItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JdbcPagingItemReader.java index 5ba05e23f..0af57b9d3 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JdbcPagingItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JdbcPagingItemReader.java @@ -40,35 +40,33 @@ import org.springframework.util.ClassUtils; /** *

      - * {@link org.springframework.batch.item.ItemReader} for reading database - * records using JDBC in a paging fashion. + * {@link org.springframework.batch.item.ItemReader} for reading database records using + * JDBC in a paging fashion. *

      - * + * *

      - * It executes the SQL built by the {@link PagingQueryProvider} to retrieve - * requested data. The query is executed using paged requests of a size - * specified in {@link #setPageSize(int)}. Additional pages are requested when - * needed as {@link #read()} method is called, returning an object corresponding - * to current position. On restart it uses the last sort key value to locate the - * first page to read (so it doesn't matter if the successfully processed items - * have been removed or modified). It is important to have a unique key constraint - * on the sort key to guarantee that no data is lost between executions. + * It executes the SQL built by the {@link PagingQueryProvider} to retrieve requested + * data. The query is executed using paged requests of a size specified in + * {@link #setPageSize(int)}. Additional pages are requested when needed as + * {@link #read()} method is called, returning an object corresponding to current + * position. On restart it uses the last sort key value to locate the first page to read + * (so it doesn't matter if the successfully processed items have been removed or + * modified). It is important to have a unique key constraint on the sort key to guarantee + * that no data is lost between executions. *

      - * + * *

      - * The performance of the paging depends on the database specific features - * available to limit the number of returned rows. Setting a fairly large page - * size and using a commit interval that matches the page size should provide - * better performance. + * The performance of the paging depends on the database specific features available to + * limit the number of returned rows. Setting a fairly large page size and using a commit + * interval that matches the page size should provide better performance. *

      - * + * *

      - * The implementation is thread-safe in between calls to - * {@link #open(ExecutionContext)}, but remember to use - * saveState=false if used in a multi-threaded client (no restart - * available). + * The implementation is thread-safe in between calls to {@link #open(ExecutionContext)}, + * but remember to use saveState=false if used in a multi-threaded client (no + * restart available). *

      - * + * * @author Thomas Risberg * @author Dave Syer * @author Michael Minella @@ -76,6 +74,7 @@ import org.springframework.util.ClassUtils; * @since 2.0 */ public class JdbcPagingItemReader extends AbstractPagingItemReader implements InitializingBean { + private static final String START_AFTER_VALUE = "start.after"; public static final int VALUE_NOT_SET = -1; @@ -95,7 +94,7 @@ public class JdbcPagingItemReader extends AbstractPagingItemReader impleme private String remainingPagesSql; private Map startAfterValues; - + private Map previousStartAfterValues; private int fetchSize = VALUE_NOT_SET; @@ -109,11 +108,9 @@ public class JdbcPagingItemReader extends AbstractPagingItemReader impleme } /** - * Gives the JDBC driver a hint as to the number of rows that should be - * fetched from the database when more rows are needed for this - * ResultSet object. If the fetch size specified is zero, the - * JDBC driver ignores the value. - * + * Gives the JDBC driver a hint as to the number of rows that should be fetched from + * the database when more rows are needed for this ResultSet object. If + * the fetch size specified is zero, the JDBC driver ignores the value. * @param fetchSize the number of rows to fetch * @see ResultSet#setFetchSize(int) */ @@ -122,9 +119,8 @@ public class JdbcPagingItemReader extends AbstractPagingItemReader impleme } /** - * A {@link PagingQueryProvider}. Supplies all the platform dependent query - * generation capabilities needed by the reader. - * + * A {@link PagingQueryProvider}. Supplies all the platform dependent query generation + * capabilities needed by the reader. * @param queryProvider the {@link PagingQueryProvider} to use */ public void setQueryProvider(PagingQueryProvider queryProvider) { @@ -132,13 +128,9 @@ public class JdbcPagingItemReader extends AbstractPagingItemReader impleme } /** - * The row mapper implementation to be used by this reader. The row mapper - * is used to convert result set rows into objects, which are then returned - * by the reader. - * - * @param rowMapper a - * {@link RowMapper} - * implementation + * The row mapper implementation to be used by this reader. The row mapper is used to + * convert result set rows into objects, which are then returned by the reader. + * @param rowMapper a {@link RowMapper} implementation */ public void setRowMapper(RowMapper rowMapper) { this.rowMapper = rowMapper; @@ -146,13 +138,11 @@ public class JdbcPagingItemReader extends AbstractPagingItemReader impleme /** * The parameter values to be used for the query execution. If you use named - * parameters then the key should be the name used in the query clause. If - * you use "?" placeholders then the key should be the relative index that - * the parameter appears in the query string built using the select, from - * and where clauses specified. - * - * @param parameterValues the values keyed by the parameter named/index used - * in the query string. + * parameters then the key should be the name used in the query clause. If you use "?" + * placeholders then the key should be the relative index that the parameter appears + * in the query string built using the select, from and where clauses specified. + * @param parameterValues the values keyed by the parameter named/index used in the + * query string. */ public void setParameterValues(Map parameterValues) { this.parameterValues = parameterValues; @@ -197,8 +187,8 @@ public class JdbcPagingItemReader extends AbstractPagingItemReader impleme } if (parameterValues != null && parameterValues.size() > 0) { if (this.queryProvider.isUsingNamedParameters()) { - query = namedParameterJdbcTemplate.query(firstPageSql, - getParameterMap(parameterValues, null), rowCallback); + query = namedParameterJdbcTemplate.query(firstPageSql, getParameterMap(parameterValues, null), + rowCallback); } else { query = getJdbcTemplate().query(firstPageSql, rowCallback, @@ -237,14 +227,15 @@ public class JdbcPagingItemReader extends AbstractPagingItemReader impleme if (isSaveState()) { if (isAtEndOfPage() && startAfterValues != null) { // restart on next page - executionContext.put(getExecutionContextKey(START_AFTER_VALUE), startAfterValues); - } else if (previousStartAfterValues != null) { + executionContext.put(getExecutionContextKey(START_AFTER_VALUE), startAfterValues); + } + else if (previousStartAfterValues != null) { // restart on current page executionContext.put(getExecutionContextKey(START_AFTER_VALUE), previousStartAfterValues); } } } - + private boolean isAtEndOfPage() { return getCurrentItemCount() % getPageSize() == 0; } @@ -255,7 +246,7 @@ public class JdbcPagingItemReader extends AbstractPagingItemReader impleme if (isSaveState()) { startAfterValues = (Map) executionContext.get(getExecutionContextKey(START_AFTER_VALUE)); - if(startAfterValues == null) { + if (startAfterValues == null) { startAfterValues = new LinkedHashMap<>(); } } @@ -266,10 +257,11 @@ public class JdbcPagingItemReader extends AbstractPagingItemReader impleme @Override protected void doJumpToPage(int itemIndex) { /* - * Normally this would be false (the startAfterValue is enough - * information to restart from. + * Normally this would be false (the startAfterValue is enough information to + * restart from. */ - // TODO: this is dead code, startAfterValues is never null - see #open(ExecutionContext) + // TODO: this is dead code, startAfterValues is never null - see + // #open(ExecutionContext) if (startAfterValues == null && getPage() > 0) { String jumpToItemSql = queryProvider.generateJumpToItemQuery(itemIndex, getPageSize()); @@ -277,12 +269,14 @@ public class JdbcPagingItemReader extends AbstractPagingItemReader impleme if (logger.isDebugEnabled()) { logger.debug("SQL used for jumping: [" + jumpToItemSql + "]"); } - + if (this.queryProvider.isUsingNamedParameters()) { - startAfterValues = namedParameterJdbcTemplate.queryForMap(jumpToItemSql, getParameterMap(parameterValues, null)); + startAfterValues = namedParameterJdbcTemplate.queryForMap(jumpToItemSql, + getParameterMap(parameterValues, null)); } else { - startAfterValues = getJdbcTemplate().queryForMap(jumpToItemSql, getParameterList(parameterValues, null).toArray()); + startAfterValues = getJdbcTemplate().queryForMap(jumpToItemSql, + getParameterList(parameterValues, null).toArray()); } } } @@ -313,8 +307,8 @@ public class JdbcPagingItemReader extends AbstractPagingItemReader impleme if (sortKeyValue != null && sortKeyValue.size() > 0) { List> keys = new ArrayList<>(sortKeyValue.entrySet()); - for(int i = 0; i < keys.size(); i++) { - for(int j = 0; j < i; j++) { + for (int i = 0; i < keys.size(); i++) { + for (int j = 0; j < i; j++) { parameterList.add(keys.get(j).getValue()); } @@ -329,6 +323,7 @@ public class JdbcPagingItemReader extends AbstractPagingItemReader impleme } private class PagingRowMapper implements RowMapper { + @Override public T mapRow(ResultSet rs, int rowNum) throws SQLException { startAfterValues = new LinkedHashMap<>(); @@ -338,9 +333,11 @@ public class JdbcPagingItemReader extends AbstractPagingItemReader impleme return rowMapper.mapRow(rs, rowNum); } + } private JdbcTemplate getJdbcTemplate() { return (JdbcTemplate) namedParameterJdbcTemplate.getJdbcOperations(); } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JdbcParameterUtils.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JdbcParameterUtils.java index bf718117f..de5b59815 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JdbcParameterUtils.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JdbcParameterUtils.java @@ -34,22 +34,21 @@ public class JdbcParameterUtils { /** * Count the occurrences of the character placeholder in an SQL string - * sql. The character placeholder is not counted if it appears - * within a literal, that is, surrounded by single or double quotes. This method will - * count traditional placeholders in the form of a question mark ('?') as well as - * named parameters indicated with a leading ':' or '&'. + * sql. The character placeholder is not counted if it appears within a + * literal, that is, surrounded by single or double quotes. This method will count + * traditional placeholders in the form of a question mark ('?') as well as named + * parameters indicated with a leading ':' or '&'. * * The code for this method is taken from an early version of the - * {@link org.springframework.jdbc.core.namedparam.NamedParameterUtils} - * class. That method was later removed after some refactoring, but the code - * is useful here for the Spring Batch project. The code has been altered to better - * suite the batch processing requirements. - * + * {@link org.springframework.jdbc.core.namedparam.NamedParameterUtils} class. That + * method was later removed after some refactoring, but the code is useful here for + * the Spring Batch project. The code has been altered to better suite the batch + * processing requirements. * @param sql String to search in. Returns 0 if the given String is null. * @param namedParameterHolder holder for the named parameters * @return the number of named parameter placeholders */ - public static int countParameterPlaceholders(String sql, List namedParameterHolder ) { + public static int countParameterPlaceholders(String sql, List namedParameterHolder) { if (sql == null) { return 0; } @@ -103,16 +102,15 @@ public class JdbcParameterUtils { } /** - * Determine whether a parameter name continues at the current position, - * that is, does not end delimited by any whitespace character yet. + * Determine whether a parameter name continues at the current position, that is, does + * not end delimited by any whitespace character yet. * @param statement the SQL statement * @param pos the position within the statement */ private static boolean parameterNameContinues(String statement, int pos) { char character = statement.charAt(pos); - return (character != ' ' && character != ',' && character != ')' && - character != '"' && character != '\'' && character != '|' && - character != ';' && character != '\n' && character != '\r'); + return (character != ' ' && character != ',' && character != ')' && character != '"' && character != '\'' + && character != '|' && character != ';' && character != '\n' && character != '\r'); } } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JpaCursorItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JpaCursorItemReader.java index 2f300c2e7..8b31239e4 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JpaCursorItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JpaCursorItemReader.java @@ -32,27 +32,31 @@ import org.springframework.util.Assert; import org.springframework.util.ClassUtils; /** - * {@link org.springframework.batch.item.ItemStreamReader} implementation based - * on JPA {@link Query#getResultStream()}. It executes the JPQL query when - * initialized and iterates over the result set as {@link #read()} method is called, - * returning an object corresponding to the current row. The query can be set - * directly using {@link #setQueryString(String)}, or using a query provider via - * {@link #setQueryProvider(JpaQueryProvider)}. - * + * {@link org.springframework.batch.item.ItemStreamReader} implementation based on JPA + * {@link Query#getResultStream()}. It executes the JPQL query when initialized and + * iterates over the result set as {@link #read()} method is called, returning an object + * corresponding to the current row. The query can be set directly using + * {@link #setQueryString(String)}, or using a query provider via + * {@link #setQueryProvider(JpaQueryProvider)}. + * * The implementation is not thread-safe. - * + * * @author Mahmoud Ben Hassine * @param type of items to read * @since 4.3 */ -public class JpaCursorItemReader extends AbstractItemCountingItemStreamItemReader - implements InitializingBean { +public class JpaCursorItemReader extends AbstractItemCountingItemStreamItemReader implements InitializingBean { private EntityManagerFactory entityManagerFactory; + private EntityManager entityManager; + private String queryString; + private JpaQueryProvider queryProvider; + private Map parameterValues; + private Iterator iterator; /** @@ -64,7 +68,6 @@ public class JpaCursorItemReader extends AbstractItemCountingItemStreamItemRe /** * Set the JPA entity manager factory. - * * @param entityManagerFactory JPA entity manager factory */ public void setEntityManagerFactory(EntityManagerFactory entityManagerFactory) { @@ -73,7 +76,6 @@ public class JpaCursorItemReader extends AbstractItemCountingItemStreamItemRe /** * Set the JPA query provider. - * * @param queryProvider JPA query provider */ public void setQueryProvider(JpaQueryProvider queryProvider) { @@ -82,7 +84,6 @@ public class JpaCursorItemReader extends AbstractItemCountingItemStreamItemRe /** * Set the JPQL query string. - * * @param queryString JPQL query string */ public void setQueryString(String queryString) { @@ -91,9 +92,8 @@ public class JpaCursorItemReader extends AbstractItemCountingItemStreamItemRe /** * Set the parameter values to be used for the query execution. - * - * @param parameterValues the values keyed by parameter names used in - * the query string. + * @param parameterValues the values keyed by parameter names used in the query + * string. */ public void setParameterValues(Map parameterValues) { this.parameterValues = parameterValues; @@ -150,4 +150,5 @@ public class JpaCursorItemReader extends AbstractItemCountingItemStreamItemRe this.entityManager.close(); } } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JpaItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JpaItemWriter.java index 5a02cbe52..8ca7b0c01 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JpaItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JpaItemWriter.java @@ -30,17 +30,15 @@ import java.util.List; /** * {@link org.springframework.batch.item.ItemWriter} that is using a JPA - * EntityManagerFactory to merge any Entities that aren't part of the - * persistence context. + * EntityManagerFactory to merge any Entities that aren't part of the persistence context. * * It is required that {@link #write(List)} is called inside a transaction.
      * - * The reader must be configured with an - * {@link jakarta.persistence.EntityManagerFactory} that is capable of - * participating in Spring managed transactions. + * The reader must be configured with an {@link jakarta.persistence.EntityManagerFactory} + * that is capable of participating in Spring managed transactions. * - * The writer is thread-safe after its properties are set (normal singleton - * behaviour), so it can be used to write in multiple concurrent transactions. + * The writer is thread-safe after its properties are set (normal singleton behaviour), so + * it can be used to write in multiple concurrent transactions. * * @author Thomas Risberg * @author Mahmoud Ben Hassine @@ -51,20 +49,19 @@ public class JpaItemWriter implements ItemWriter, InitializingBean { protected static final Log logger = LogFactory.getLog(JpaItemWriter.class); private EntityManagerFactory entityManagerFactory; + private boolean usePersist = false; /** * Set the EntityManager to be used internally. - * * @param entityManagerFactory the entityManagerFactory to set */ public void setEntityManagerFactory(EntityManagerFactory entityManagerFactory) { this.entityManagerFactory = entityManagerFactory; } - + /** * Set whether the EntityManager should perform a persist instead of a merge. - * * @param usePersist whether to use persist instead of merge. */ public void setUsePersist(boolean usePersist) { @@ -80,8 +77,8 @@ public class JpaItemWriter implements ItemWriter, InitializingBean { } /** - * Merge all provided items that aren't already in the persistence context - * and then flush the entity manager. + * Merge all provided items that aren't already in the persistence context and then + * flush the entity manager. * * @see org.springframework.batch.item.ItemWriter#write(java.util.List) */ @@ -96,9 +93,8 @@ public class JpaItemWriter implements ItemWriter, InitializingBean { } /** - * Do perform the actual write operation. This can be overridden in a - * subclass if necessary. - * + * Do perform the actual write operation. This can be overridden in a subclass if + * necessary. * @param entityManager the EntityManager to use for the operation * @param items the list of items to use for the write */ @@ -112,12 +108,12 @@ public class JpaItemWriter implements ItemWriter, InitializingBean { long addedToContextCount = 0; for (T item : items) { if (!entityManager.contains(item)) { - if(usePersist) { + if (usePersist) { entityManager.persist(item); } else { entityManager.merge(item); - } + } addedToContextCount++; } } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JpaPagingItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JpaPagingItemReader.java index 0bf649a10..33e9d83df 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JpaPagingItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JpaPagingItemReader.java @@ -34,50 +34,47 @@ import org.springframework.util.ClassUtils; /** *

      - * {@link org.springframework.batch.item.ItemReader} for reading database - * records built on top of JPA. + * {@link org.springframework.batch.item.ItemReader} for reading database records built on + * top of JPA. *

      * *

      - * It executes the JPQL {@link #setQueryString(String)} to retrieve requested - * data. The query is executed using paged requests of a size specified in + * It executes the JPQL {@link #setQueryString(String)} to retrieve requested data. The + * query is executed using paged requests of a size specified in * {@link #setPageSize(int)}. Additional pages are requested when needed as - * {@link #read()} method is called, returning an object corresponding to - * current position. + * {@link #read()} method is called, returning an object corresponding to current + * position. *

      * *

      - * The performance of the paging depends on the JPA implementation and its use - * of database specific features to limit the number of returned rows. + * The performance of the paging depends on the JPA implementation and its use of database + * specific features to limit the number of returned rows. *

      * *

      - * Setting a fairly large page size and using a commit interval that matches the - * page size should provide better performance. + * Setting a fairly large page size and using a commit interval that matches the page size + * should provide better performance. *

      * *

      - * In order to reduce the memory usage for large results the persistence context - * is flushed and cleared after each page is read. This causes any entities read - * to be detached. If you make changes to the entities and want the changes - * persisted then you must explicitly merge the entities. + * In order to reduce the memory usage for large results the persistence context is + * flushed and cleared after each page is read. This causes any entities read to be + * detached. If you make changes to the entities and want the changes persisted then you + * must explicitly merge the entities. *

      * *

      - * The reader must be configured with an - * {@link jakarta.persistence.EntityManagerFactory}. All entity access is - * performed within a new transaction, independent of any existing Spring - * managed transactions. + * The reader must be configured with an {@link jakarta.persistence.EntityManagerFactory}. + * All entity access is performed within a new transaction, independent of any existing + * Spring managed transactions. *

      * *

      - * The implementation is thread-safe in between calls to - * {@link #open(ExecutionContext)}, but remember to use - * saveState=false if used in a multi-threaded client (no restart - * available). + * The implementation is thread-safe in between calls to {@link #open(ExecutionContext)}, + * but remember to use saveState=false if used in a multi-threaded client (no + * restart available). *

      * - * * @author Thomas Risberg * @author Dave Syer * @author Will Schipp @@ -97,8 +94,8 @@ public class JpaPagingItemReader extends AbstractPagingItemReader { private JpaQueryProvider queryProvider; private Map parameterValues; - - private boolean transacted = true;//default value + + private boolean transacted = true;// default value public JpaPagingItemReader() { setName(ClassUtils.getShortName(JpaPagingItemReader.class)); @@ -123,25 +120,24 @@ public class JpaPagingItemReader extends AbstractPagingItemReader { /** * The parameter values to be used for the query execution. - * - * @param parameterValues the values keyed by the parameter named used in - * the query string. + * @param parameterValues the values keyed by the parameter named used in the query + * string. */ public void setParameterValues(Map parameterValues) { this.parameterValues = parameterValues; } - + /** - * By default (true) the EntityTransaction will be started and committed around the read. - * Can be overridden (false) in cases where the JPA implementation doesn't support a - * particular transaction. (e.g. Hibernate with a JTA transaction). NOTE: may cause - * problems in guaranteeing the object consistency in the EntityManagerFactory. - * + * By default (true) the EntityTransaction will be started and committed around the + * read. Can be overridden (false) in cases where the JPA implementation doesn't + * support a particular transaction. (e.g. Hibernate with a JTA transaction). NOTE: + * may cause problems in guaranteeing the object consistency in the + * EntityManagerFactory. * @param transacted indicator */ public void setTransacted(boolean transacted) { this.transacted = transacted; - } + } @Override public void afterPropertiesSet() throws Exception { @@ -188,14 +184,14 @@ public class JpaPagingItemReader extends AbstractPagingItemReader { protected void doReadPage() { EntityTransaction tx = null; - + if (transacted) { tx = entityManager.getTransaction(); tx.begin(); - + entityManager.flush(); entityManager.clear(); - }//end if + } // end if Query query = createQuery().setFirstResult(getPage() * getPageSize()).setMaxResults(getPageSize()); @@ -211,17 +207,18 @@ public class JpaPagingItemReader extends AbstractPagingItemReader { else { results.clear(); } - + if (!transacted) { List queryResult = query.getResultList(); for (T entity : queryResult) { entityManager.detach(entity); results.add(entity); - }//end if - } else { + } // end if + } + else { results.addAll(query.getResultList()); tx.commit(); - }//end if + } // end if } @Override diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/Order.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/Order.java index a4edf5bc9..78291db9d 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/Order.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/Order.java @@ -17,9 +17,11 @@ package org.springframework.batch.item.database; /** * The direction of the sort in an ORDER BY clause. - * + * * @author Michael Minella */ public enum Order { + ASCENDING, DESCENDING + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/PagingQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/PagingQueryProvider.java index dc26c9075..ce4bd1322 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/PagingQueryProvider.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/PagingQueryProvider.java @@ -19,10 +19,9 @@ package org.springframework.batch.item.database; import java.util.Map; import javax.sql.DataSource; - /** - * Interface defining the functionality to be provided for generating paging queries for use with Paging - * Item Readers. + * Interface defining the functionality to be provided for generating paging queries for + * use with Paging Item Readers. * * @author Thomas Risberg * @author Michael Minella @@ -32,7 +31,6 @@ public interface PagingQueryProvider { /** * Initialize the query provider using the provided {@link DataSource} if necessary. - * * @param dataSource DataSource to use for any initialization * @throws Exception for errors when initializing */ @@ -40,7 +38,6 @@ public interface PagingQueryProvider { /** * Generate the query that will provide the first page, limited by the page size. - * * @param pageSize number of rows to read for each page * @return the generated query */ @@ -48,7 +45,6 @@ public interface PagingQueryProvider { /** * Generate the query that will provide the first page, limited by the page size. - * * @param pageSize number of rows to read for each page * @return the generated query */ @@ -56,10 +52,10 @@ public interface PagingQueryProvider { /** * - * Generate the query that will provide the jump to item query. The itemIndex provided could be in the middle of - * the page and together with the page size it will be used to calculate the last index of the preceding page - * to be able to retrieve the sort key for this row. - * + * Generate the query that will provide the jump to item query. The itemIndex provided + * could be in the middle of the page and together with the page size it will be used + * to calculate the last index of the preceding page to be able to retrieve the sort + * key for this row. * @param itemIndex the index for the next item to be read * @param pageSize number of rows to read for each page * @return the generated query @@ -74,23 +70,20 @@ public interface PagingQueryProvider { /** * Indicate whether the generated queries use named parameter syntax. - * * @return true if named parameter syntax is used */ boolean isUsingNamedParameters(); /** - * The sort keys. A Map of the columns that make up the key and a Boolean indicating ascending or descending - * (ascending = true). - * + * The sort keys. A Map of the columns that make up the key and a Boolean indicating + * ascending or descending (ascending = true). * @return the sort keys used to order the query */ Map getSortKeys(); - + /** - * Returns either a String to be used as the named placeholder for a sort key value (based on the column name) - * or a ? for unnamed parameters. - * + * Returns either a String to be used as the named placeholder for a sort key value + * (based on the column name) or a ? for unnamed parameters. * @param keyName The sort key name * @return The string to be used for a parameterized query. */ @@ -98,8 +91,8 @@ public interface PagingQueryProvider { /** * The sort key (unique single column name) without alias. - * * @return the sort key used to order the query (without alias) */ Map getSortKeysWithoutAliases(); + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/StoredProcedureItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/StoredProcedureItemReader.java index e5341ea8f..73a7ccddf 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/StoredProcedureItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/StoredProcedureItemReader.java @@ -35,14 +35,15 @@ import org.springframework.util.ClassUtils; /** *

      - * Item reader implementation that executes a stored procedure and then reads the returned cursor - * and continually retrieves the next row in the ResultSet. + * Item reader implementation that executes a stored procedure and then reads the returned + * cursor and continually retrieves the next row in the ResultSet. *

      * *

      - * The callable statement used to open the cursor is created with the 'READ_ONLY' option as well as with the - * 'TYPE_FORWARD_ONLY' option. By default the cursor will be opened using a separate connection which means - * that it will not participate in any transactions created as part of the step processing. + * The callable statement used to open the cursor is created with the 'READ_ONLY' option + * as well as with the 'TYPE_FORWARD_ONLY' option. By default the cursor will be opened + * using a separate connection which means that it will not participate in any + * transactions created as part of the step processing. *

      * *

      @@ -82,7 +83,6 @@ public class StoredProcedureItemReader extends AbstractCursorItemReader { /** * Set the RowMapper to be used for all calls to read(). - * * @param rowMapper the RowMapper to use to map the results */ public void setRowMapper(RowMapper rowMapper) { @@ -90,10 +90,9 @@ public class StoredProcedureItemReader extends AbstractCursorItemReader { } /** - * Set the SQL statement to be used when creating the cursor. This statement - * should be a complete and valid SQL statement, as it will be run directly - * without any modification. - * + * Set the SQL statement to be used when creating the cursor. This statement should be + * a complete and valid SQL statement, as it will be run directly without any + * modification. * @param sprocedureName the SQL used to call the statement */ public void setProcedureName(String sprocedureName) { @@ -101,9 +100,8 @@ public class StoredProcedureItemReader extends AbstractCursorItemReader { } /** - * Set the PreparedStatementSetter to use if any parameter values that need - * to be set in the supplied query. - * + * Set the PreparedStatementSetter to use if any parameter values that need to be set + * in the supplied query. * @param preparedStatementSetter used to populate the SQL */ public void setPreparedStatementSetter(PreparedStatementSetter preparedStatementSetter) { @@ -111,9 +109,9 @@ public class StoredProcedureItemReader extends AbstractCursorItemReader { } /** - * Add one or more declared parameters. Used for configuring this operation when used in a - * bean factory. Each parameter will specify SQL type and (optionally) the parameter's name. - * + * Add one or more declared parameters. Used for configuring this operation when used + * in a bean factory. Each parameter will specify SQL type and (optionally) the + * parameter's name. * @param parameters Array containing the declared SqlParameter objects */ public void setParameters(SqlParameter[] parameters) { @@ -122,7 +120,6 @@ public class StoredProcedureItemReader extends AbstractCursorItemReader { /** * Set whether this stored procedure is a function. - * * @param function indicator */ public void setFunction(boolean function) { @@ -130,10 +127,9 @@ public class StoredProcedureItemReader extends AbstractCursorItemReader { } /** - * Set the parameter position of the REF CURSOR. Only used for Oracle and - * PostgreSQL that use REF CURSORs. For any other database this should be - * kept as 0 which is the default. - * + * Set the parameter position of the REF CURSOR. Only used for Oracle and PostgreSQL + * that use REF CURSORs. For any other database this should be kept as 0 which is the + * default. * @param refCursorPosition The parameter position of the REF CURSOR */ public void setRefCursorPosition(int refCursorPosition) { @@ -142,9 +138,7 @@ public class StoredProcedureItemReader extends AbstractCursorItemReader { /** * Assert that mandatory properties are set. - * - * @throws IllegalArgumentException if either data source or SQL properties - * not set. + * @throws IllegalArgumentException if either data source or SQL properties not set. */ @Override public void afterPropertiesSet() throws Exception { @@ -157,12 +151,10 @@ public class StoredProcedureItemReader extends AbstractCursorItemReader { protected void openCursor(Connection con) { Assert.state(procedureName != null, "Procedure Name must not be null."); - Assert.state(refCursorPosition >= 0, - "invalid refCursorPosition specified as " + refCursorPosition + "; it can't be " + - "specified as a negative number."); - Assert.state(refCursorPosition == 0 || refCursorPosition > 0, - "invalid refCursorPosition specified as " + refCursorPosition + "; there are " + - parameters.length + " parameters defined."); + Assert.state(refCursorPosition >= 0, "invalid refCursorPosition specified as " + refCursorPosition + + "; it can't be " + "specified as a negative number."); + Assert.state(refCursorPosition == 0 || refCursorPosition > 0, "invalid refCursorPosition specified as " + + refCursorPosition + "; there are " + parameters.length + " parameters defined."); CallMetaDataContext callContext = new CallMetaDataContext(); callContext.setAccessCallParameterMetaData(false); @@ -173,7 +165,6 @@ public class StoredProcedureItemReader extends AbstractCursorItemReader { SqlParameter cursorParameter = callContext.createReturnResultSetParameter("cursor", rowMapper); this.callString = callContext.createCallString(); - if (log.isDebugEnabled()) { log.debug("Call string is: " + callString); } @@ -196,7 +187,8 @@ public class StoredProcedureItemReader extends AbstractCursorItemReader { ResultSet.HOLD_CURSORS_OVER_COMMIT); } else { - callableStatement = con.prepareCall(callString, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); + callableStatement = con.prepareCall(callString, ResultSet.TYPE_FORWARD_ONLY, + ResultSet.CONCUR_READ_ONLY); } applyStatementSettings(callableStatement); if (this.preparedStatementSetter != null) { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/HibernateCursorItemReaderBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/HibernateCursorItemReaderBuilder.java index 408f9404e..db0e5c692 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/HibernateCursorItemReaderBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/HibernateCursorItemReaderBuilder.java @@ -26,13 +26,13 @@ import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** - * This is a builder for the {@link HibernateCursorItemReader}. When configuring, one of + * This is a builder for the {@link HibernateCursorItemReader}. When configuring, one of * the following should be provided (listed in order of precedence): *

        - *
      • {@link #queryProvider(HibernateQueryProvider)}
      • - *
      • {@link #queryName(String)}
      • - *
      • {@link #queryString(String)}
      • - *
      • {@link #nativeQuery(String)} and {@link #entityClass(Class)}
      • + *
      • {@link #queryProvider(HibernateQueryProvider)}
      • + *
      • {@link #queryName(String)}
      • + *
      • {@link #queryString(String)}
      • + *
      • {@link #nativeQuery(String)} and {@link #entityClass(Class)}
      • *
      * * @author Michael Minella @@ -70,10 +70,9 @@ public class HibernateCursorItemReaderBuilder { private int currentItemCount; /** - * Configure if the state of the {@link org.springframework.batch.item.ItemStreamSupport} - * should be persisted within the {@link org.springframework.batch.item.ExecutionContext} - * for restart purposes. - * + * Configure if the state of the + * {@link org.springframework.batch.item.ItemStreamSupport} should be persisted within + * the {@link org.springframework.batch.item.ExecutionContext} for restart purposes. * @param saveState defaults to true * @return The current instance of the builder. */ @@ -87,7 +86,6 @@ public class HibernateCursorItemReaderBuilder { * The name used to calculate the key within the * {@link org.springframework.batch.item.ExecutionContext}. Required if * {@link #saveState(boolean)} is set to true. - * * @param name name of the reader instance * @return The current instance of the builder. * @see org.springframework.batch.item.ItemStreamSupport#setName(String) @@ -100,7 +98,6 @@ public class HibernateCursorItemReaderBuilder { /** * Configure the max number of items to be read. - * * @param maxItemCount the max items to be read * @return The current instance of the builder. * @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setMaxItemCount(int) @@ -113,7 +110,6 @@ public class HibernateCursorItemReaderBuilder { /** * Index for the current item. Used on restarts to indicate where to start from. - * * @param currentItemCount current index * @return this instance for method chaining * @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setCurrentItemCount(int) @@ -125,9 +121,8 @@ public class HibernateCursorItemReaderBuilder { } /** - * A map of parameter values to be set on the query. The key of the map is the name - * of the parameter to be set with the value being the value to be set. - * + * A map of parameter values to be set on the query. The key of the map is the name of + * the parameter to be set with the value being the value to be set. * @param parameterValues map of values * @return this instance for method chaining * @see HibernateCursorItemReader#setParameterValues(Map) @@ -140,7 +135,6 @@ public class HibernateCursorItemReaderBuilder { /** * The name of the Hibernate named query to be executed for this reader. - * * @param queryName name of the query to execute * @return this instance for method chaining * @see HibernateCursorItemReader#setQueryName(String) @@ -152,9 +146,8 @@ public class HibernateCursorItemReaderBuilder { } /** - * The number of items to be returned with each round trip to the database. Used + * The number of items to be returned with each round trip to the database. Used * internally by Hibernate. - * * @param fetchSize number of records to return per fetch * @return this instance for method chaining * @see HibernateCursorItemReader#setFetchSize(int) @@ -166,9 +159,8 @@ public class HibernateCursorItemReaderBuilder { } /** - * A query provider. This should be set only if {@link #queryString(String)} and + * A query provider. This should be set only if {@link #queryString(String)} and * {@link #queryName(String)} have not been set. - * * @param queryProvider the query provider * @return this instance for method chaining * @see HibernateCursorItemReader#setQueryProvider(HibernateQueryProvider) @@ -180,10 +172,9 @@ public class HibernateCursorItemReaderBuilder { } /** - * The HQL query string to execute. This should only be set if + * The HQL query string to execute. This should only be set if * {@link #queryProvider(HibernateQueryProvider)} and {@link #queryName(String)} have * not been set. - * * @param queryString the HQL query * @return this instance for method chaining * @see HibernateCursorItemReader#setQueryString(String) @@ -196,7 +187,6 @@ public class HibernateCursorItemReaderBuilder { /** * The Hibernate {@link SessionFactory} to execute the query against. - * * @param sessionFactory the session factory * @return this instance for method chaining * @see HibernateCursorItemReader#setSessionFactory(SessionFactory) @@ -210,7 +200,6 @@ public class HibernateCursorItemReaderBuilder { /** * Indicator for whether to use a {@link org.hibernate.StatelessSession} * (true) or a {@link org.hibernate.Session} (false). - * * @param useStatelessSession Defaults to false * @return this instance for method chaining * @see HibernateCursorItemReader#setUseStatelessSession(boolean) @@ -222,8 +211,7 @@ public class HibernateCursorItemReaderBuilder { } /** - * Used to configure a {@link HibernateNativeQueryProvider}. This is ignored if - * + * Used to configure a {@link HibernateNativeQueryProvider}. This is ignored if * @param nativeQuery {@link String} containing the native query. * @return this instance for method chaining */ @@ -241,16 +229,14 @@ public class HibernateCursorItemReaderBuilder { /** * Returns a fully constructed {@link HibernateCursorItemReader}. - * * @return a new {@link HibernateCursorItemReader} */ public HibernateCursorItemReader build() { Assert.state(this.fetchSize >= 0, "fetchSize must not be negative"); Assert.state(this.sessionFactory != null, "A SessionFactory must be provided"); - if(this.saveState) { - Assert.state(StringUtils.hasText(this.name), - "A name is required when saveState is set to true."); + if (this.saveState) { + Assert.state(StringUtils.hasText(this.name), "A name is required when saveState is set to true."); } HibernateCursorItemReader reader = new HibernateCursorItemReader<>(); @@ -258,16 +244,16 @@ public class HibernateCursorItemReaderBuilder { reader.setFetchSize(this.fetchSize); reader.setParameterValues(this.parameterValues); - if(this.queryProvider != null) { + if (this.queryProvider != null) { reader.setQueryProvider(this.queryProvider); } - else if(StringUtils.hasText(this.queryName)) { + else if (StringUtils.hasText(this.queryName)) { reader.setQueryName(this.queryName); } - else if(StringUtils.hasText(this.queryString)) { + else if (StringUtils.hasText(this.queryString)) { reader.setQueryString(this.queryString); } - else if(StringUtils.hasText(this.nativeQuery) && this.nativeClass != null) { + else if (StringUtils.hasText(this.nativeQuery) && this.nativeClass != null) { HibernateNativeQueryProvider provider = new HibernateNativeQueryProvider<>(); provider.setSqlQuery(this.nativeQuery); provider.setEntityClass(this.nativeClass); @@ -282,8 +268,8 @@ public class HibernateCursorItemReaderBuilder { reader.setQueryProvider(provider); } else { - throw new IllegalStateException("A HibernateQueryProvider, queryName, queryString, " + - "or both the nativeQuery and entityClass must be configured"); + throw new IllegalStateException("A HibernateQueryProvider, queryName, queryString, " + + "or both the nativeQuery and entityClass must be configured"); } reader.setSessionFactory(this.sessionFactory); @@ -296,4 +282,4 @@ public class HibernateCursorItemReaderBuilder { return reader; } - } +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/HibernateItemWriterBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/HibernateItemWriterBuilder.java index e08343a7a..cf15b899e 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/HibernateItemWriterBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/HibernateItemWriterBuilder.java @@ -36,7 +36,6 @@ public class HibernateItemWriterBuilder { /** * If set to false, the {@link org.hibernate.Session} will not be cleared at the end * of the chunk. - * * @param clearSession defaults to true * @return this instance for method chaining * @see HibernateItemWriter#setClearSession(boolean) @@ -48,8 +47,7 @@ public class HibernateItemWriterBuilder { } /** - * The Hibernate {@link SessionFactory} to obtain a session from. Required. - * + * The Hibernate {@link SessionFactory} to obtain a session from. Required. * @param sessionFactory the {@link SessionFactory} * @return this instance for method chaining * @see HibernateItemWriter#setSessionFactory(SessionFactory) @@ -62,12 +60,10 @@ public class HibernateItemWriterBuilder { /** * Returns a fully built {@link HibernateItemWriter} - * * @return the writer */ public HibernateItemWriter build() { - Assert.state(this.sessionFactory != null, - "SessionFactory must be provided"); + Assert.state(this.sessionFactory != null, "SessionFactory must be provided"); HibernateItemWriter writer = new HibernateItemWriter<>(); writer.setSessionFactory(this.sessionFactory); @@ -75,4 +71,5 @@ public class HibernateItemWriterBuilder { return writer; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/HibernatePagingItemReaderBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/HibernatePagingItemReaderBuilder.java index 90c32de81..d22b8811b 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/HibernatePagingItemReaderBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/HibernatePagingItemReaderBuilder.java @@ -25,12 +25,12 @@ import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** - * A builder for the {@link HibernatePagingItemReader}. When configuring, only one of the + * A builder for the {@link HibernatePagingItemReader}. When configuring, only one of the * following should be provided: *
        - *
      • {@link #queryString(String)}
      • - *
      • {@link #queryName(String)}
      • - *
      • {@link #queryProvider(HibernateQueryProvider)}
      • + *
      • {@link #queryString(String)}
      • + *
      • {@link #queryName(String)}
      • + *
      • {@link #queryProvider(HibernateQueryProvider)}
      • *
      * * @author Michael Minella @@ -66,10 +66,9 @@ public class HibernatePagingItemReaderBuilder { private int currentItemCount; /** - * Configure if the state of the {@link org.springframework.batch.item.ItemStreamSupport} - * should be persisted within the {@link org.springframework.batch.item.ExecutionContext} - * for restart purposes. - * + * Configure if the state of the + * {@link org.springframework.batch.item.ItemStreamSupport} should be persisted within + * the {@link org.springframework.batch.item.ExecutionContext} for restart purposes. * @param saveState defaults to true * @return The current instance of the builder. */ @@ -83,7 +82,6 @@ public class HibernatePagingItemReaderBuilder { * The name used to calculate the key within the * {@link org.springframework.batch.item.ExecutionContext}. Required if * {@link #saveState(boolean)} is set to true. - * * @param name name of the reader instance * @return The current instance of the builder. * @see org.springframework.batch.item.ItemStreamSupport#setName(String) @@ -96,7 +94,6 @@ public class HibernatePagingItemReaderBuilder { /** * Configure the max number of items to be read. - * * @param maxItemCount the max items to be read * @return The current instance of the builder. * @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setMaxItemCount(int) @@ -109,7 +106,6 @@ public class HibernatePagingItemReaderBuilder { /** * Index for the current item. Used on restarts to indicate where to start from. - * * @param currentItemCount current index * @return this instance for method chaining * @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setCurrentItemCount(int) @@ -121,9 +117,8 @@ public class HibernatePagingItemReaderBuilder { } /** - * The number of records to request per page/query. Defaults to 10. Must be greater + * The number of records to request per page/query. Defaults to 10. Must be greater * than zero. - * * @param pageSize number of items * @return this instance for method chaining * @see HibernatePagingItemReader#setPageSize(int) @@ -135,9 +130,8 @@ public class HibernatePagingItemReaderBuilder { } /** - * A map of parameter values to be set on the query. The key of the map is the name - * of the parameter to be set with the value being the value to be set. - * + * A map of parameter values to be set on the query. The key of the map is the name of + * the parameter to be set with the value being the value to be set. * @param parameterValues map of values * @return this instance for method chaining * @see HibernatePagingItemReader#setParameterValues(Map) @@ -150,7 +144,6 @@ public class HibernatePagingItemReaderBuilder { /** * The name of the Hibernate named query to be executed for this reader. - * * @param queryName name of the query to execute * @return this instance for method chaining * @see HibernatePagingItemReader#setQueryName(String) @@ -162,9 +155,8 @@ public class HibernatePagingItemReaderBuilder { } /** - * Fetch size used internally by Hibernate to limit amount of data fetched - * from database per round trip. - * + * Fetch size used internally by Hibernate to limit amount of data fetched from + * database per round trip. * @param fetchSize number of records * @return this instance for method chaining * @see HibernatePagingItemReader#setFetchSize(int) @@ -176,9 +168,8 @@ public class HibernatePagingItemReaderBuilder { } /** - * A query provider. This should be set only if {@link #queryString(String)} and + * A query provider. This should be set only if {@link #queryString(String)} and * {@link #queryName(String)} have not been set. - * * @param queryProvider the query provider * @return this instance for method chaining * @see HibernatePagingItemReader#setQueryProvider(HibernateQueryProvider) @@ -190,10 +181,9 @@ public class HibernatePagingItemReaderBuilder { } /** - * The HQL query string to execute. This should only be set if + * The HQL query string to execute. This should only be set if * {@link #queryProvider(HibernateQueryProvider)} and {@link #queryName(String)} have * not been set. - * * @param queryString the HQL query * @return this instance for method chaining * @see HibernatePagingItemReader#setQueryString(String) @@ -206,7 +196,6 @@ public class HibernatePagingItemReaderBuilder { /** * The Hibernate {@link SessionFactory} to execute the query against. - * * @param sessionFactory the session factory * @return this instance for method chaining * @see HibernatePagingItemReader#setSessionFactory(SessionFactory) @@ -220,7 +209,6 @@ public class HibernatePagingItemReaderBuilder { /** * Indicator for whether to use a {@link org.hibernate.StatelessSession} * (true) or a {@link org.hibernate.Session} (false). - * * @param useStatelessSession Defaults to false * @return this instance for method chaining * @see HibernatePagingItemReader#setUseStatelessSession(boolean) @@ -233,19 +221,17 @@ public class HibernatePagingItemReaderBuilder { /** * Returns a fully constructed {@link HibernatePagingItemReader}. - * * @return a new {@link HibernatePagingItemReader} */ public HibernatePagingItemReader build() { Assert.notNull(this.sessionFactory, "A SessionFactory must be provided"); Assert.state(this.fetchSize >= 0, "fetchSize must not be negative"); - if(this.saveState) { - Assert.hasText(this.name, - "A name is required when saveState is set to true"); + if (this.saveState) { + Assert.hasText(this.name, "A name is required when saveState is set to true"); } - if(this.queryProvider == null) { + if (this.queryProvider == null) { Assert.state(StringUtils.hasText(queryString) ^ StringUtils.hasText(queryName), "queryString or queryName must be set"); } @@ -267,4 +253,5 @@ public class HibernatePagingItemReaderBuilder { return reader; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/JdbcBatchItemWriterBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/JdbcBatchItemWriterBuilder.java index b93d207b2..e2808566f 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/JdbcBatchItemWriterBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/JdbcBatchItemWriterBuilder.java @@ -53,7 +53,6 @@ public class JdbcBatchItemWriterBuilder { /** * Configure the {@link DataSource} to be used. - * * @param dataSource the DataSource * @return The current instance of the builder for chaining. * @see JdbcBatchItemWriter#setDataSource(DataSource) @@ -66,8 +65,7 @@ public class JdbcBatchItemWriterBuilder { /** * If set to true, confirms that every insert results in the update of at least one - * row in the database. Defaults to true. - * + * row in the database. Defaults to true. * @param assertUpdates boolean indicator * @return The current instance of the builder for chaining * @see JdbcBatchItemWriter#setAssertUpdates(boolean) @@ -79,9 +77,7 @@ public class JdbcBatchItemWriterBuilder { } /** - * Set the SQL statement to be used for each item's updates. This is a required - * field. - * + * Set the SQL statement to be used for each item's updates. This is a required field. * @param sql SQL string * @return The current instance of the builder for chaining * @see JdbcBatchItemWriter#setSql(String) @@ -93,41 +89,41 @@ public class JdbcBatchItemWriterBuilder { } /** - * Configures a {@link ItemPreparedStatementSetter} for use by the writer. This - * should only be used if {@link #columnMapped()} isn't called. - * + * Configures a {@link ItemPreparedStatementSetter} for use by the writer. This should + * only be used if {@link #columnMapped()} isn't called. * @param itemPreparedStatementSetter The {@link ItemPreparedStatementSetter} * @return The current instance of the builder for chaining * @see JdbcBatchItemWriter#setItemPreparedStatementSetter(ItemPreparedStatementSetter) */ - public JdbcBatchItemWriterBuilder itemPreparedStatementSetter(ItemPreparedStatementSetter itemPreparedStatementSetter) { + public JdbcBatchItemWriterBuilder itemPreparedStatementSetter( + ItemPreparedStatementSetter itemPreparedStatementSetter) { this.itemPreparedStatementSetter = itemPreparedStatementSetter; return this; } /** - * Configures a {@link ItemSqlParameterSourceProvider} for use by the writer. This + * Configures a {@link ItemSqlParameterSourceProvider} for use by the writer. This * should only be used if {@link #beanMapped()} isn't called. - * * @param itemSqlParameterSourceProvider The {@link ItemSqlParameterSourceProvider} * @return The current instance of the builder for chaining * @see JdbcBatchItemWriter#setItemSqlParameterSourceProvider(ItemSqlParameterSourceProvider) */ - public JdbcBatchItemWriterBuilder itemSqlParameterSourceProvider(ItemSqlParameterSourceProvider itemSqlParameterSourceProvider) { + public JdbcBatchItemWriterBuilder itemSqlParameterSourceProvider( + ItemSqlParameterSourceProvider itemSqlParameterSourceProvider) { this.itemSqlParameterSourceProvider = itemSqlParameterSourceProvider; return this; } /** - * The {@link NamedParameterJdbcOperations} instance to use. If one isn't provided, - * a {@link DataSource} is required. - * + * The {@link NamedParameterJdbcOperations} instance to use. If one isn't provided, a + * {@link DataSource} is required. * @param namedParameterJdbcOperations The template * @return The current instance of the builder for chaining */ - public JdbcBatchItemWriterBuilder namedParametersJdbcTemplate(NamedParameterJdbcOperations namedParameterJdbcOperations) { + public JdbcBatchItemWriterBuilder namedParametersJdbcTemplate( + NamedParameterJdbcOperations namedParameterJdbcOperations) { this.namedParameterJdbcTemplate = namedParameterJdbcOperations; return this; @@ -139,7 +135,6 @@ public class JdbcBatchItemWriterBuilder { * * NOTE: The item type for this {@link org.springframework.batch.item.ItemWriter} must * be castable to Map<String,Object>>. - * * @return The current instance of the builder for chaining * @see ColumnMapItemPreparedStatementSetter */ @@ -152,7 +147,6 @@ public class JdbcBatchItemWriterBuilder { /** * Creates a {@link BeanPropertyItemSqlParameterSourceProvider} to be used as your * {@link ItemSqlParameterSourceProvider}. - * * @return The current instance of the builder for chaining * @see BeanPropertyItemSqlParameterSourceProvider */ @@ -164,7 +158,6 @@ public class JdbcBatchItemWriterBuilder { /** * Validates configuration and builds the {@link JdbcBatchItemWriter}. - * * @return a {@link JdbcBatchItemWriter} */ @SuppressWarnings("unchecked") @@ -174,8 +167,7 @@ public class JdbcBatchItemWriterBuilder { Assert.notNull(this.sql, "A SQL statement is required"); int mappedValue = this.mapped.intValue(); - Assert.state(mappedValue != 3, - "Either an item can be mapped via db column or via bean spec, can't be both"); + Assert.state(mappedValue != 3, "Either an item can be mapped via db column or via bean spec, can't be both"); JdbcBatchItemWriter writer = new JdbcBatchItemWriter<>(); writer.setSql(this.sql); @@ -183,13 +175,15 @@ public class JdbcBatchItemWriterBuilder { writer.setItemSqlParameterSourceProvider(this.itemSqlParameterSourceProvider); writer.setItemPreparedStatementSetter(this.itemPreparedStatementSetter); - if(mappedValue == 1) { - ((JdbcBatchItemWriter>)writer).setItemPreparedStatementSetter(new ColumnMapItemPreparedStatementSetter()); - } else if(mappedValue == 2) { + if (mappedValue == 1) { + ((JdbcBatchItemWriter>) writer) + .setItemPreparedStatementSetter(new ColumnMapItemPreparedStatementSetter()); + } + else if (mappedValue == 2) { writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>()); } - if(this.dataSource != null) { + if (this.dataSource != null) { this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(this.dataSource); } @@ -197,4 +191,5 @@ public class JdbcBatchItemWriterBuilder { return writer; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/JdbcCursorItemReaderBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/JdbcCursorItemReaderBuilder.java index 1a7e62dda..a747228fa 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/JdbcCursorItemReaderBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/JdbcCursorItemReaderBuilder.java @@ -74,10 +74,9 @@ public class JdbcCursorItemReaderBuilder { private boolean connectionAutoCommit; /** - * Configure if the state of the {@link org.springframework.batch.item.ItemStreamSupport} - * should be persisted within the {@link org.springframework.batch.item.ExecutionContext} - * for restart purposes. - * + * Configure if the state of the + * {@link org.springframework.batch.item.ItemStreamSupport} should be persisted within + * the {@link org.springframework.batch.item.ExecutionContext} for restart purposes. * @param saveState defaults to true * @return The current instance of the builder. */ @@ -91,7 +90,6 @@ public class JdbcCursorItemReaderBuilder { * The name used to calculate the key within the * {@link org.springframework.batch.item.ExecutionContext}. Required if * {@link #saveState(boolean)} is set to true. - * * @param name name of the reader instance * @return The current instance of the builder. * @see org.springframework.batch.item.ItemStreamSupport#setName(String) @@ -104,7 +102,6 @@ public class JdbcCursorItemReaderBuilder { /** * Configure the max number of items to be read. - * * @param maxItemCount the max items to be read * @return The current instance of the builder. * @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setMaxItemCount(int) @@ -117,7 +114,6 @@ public class JdbcCursorItemReaderBuilder { /** * Index for the current item. Used on restarts to indicate where to start from. - * * @param currentItemCount current index * @return this instance for method chaining * @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setCurrentItemCount(int) @@ -130,7 +126,6 @@ public class JdbcCursorItemReaderBuilder { /** * The {@link DataSource} to read from - * * @param dataSource a relational data base * @return this instance for method chaining * @see JdbcCursorItemReader#setDataSource(DataSource) @@ -143,7 +138,6 @@ public class JdbcCursorItemReaderBuilder { /** * A hint to the driver as to how many rows to return with each fetch. - * * @param fetchSize the hint * @return this instance for method chaining * @see JdbcCursorItemReader#setFetchSize(int) @@ -156,7 +150,6 @@ public class JdbcCursorItemReaderBuilder { /** * The max number of rows the {@link java.sql.ResultSet} can contain - * * @param maxRows the max * @return this instance for method chaining * @see JdbcCursorItemReader#setMaxRows(int) @@ -169,7 +162,6 @@ public class JdbcCursorItemReaderBuilder { /** * The time in milliseconds for the query to timeout - * * @param queryTimeout timeout * @return this instance for method chaining * @see JdbcCursorItemReader#setQueryTimeout(int) @@ -188,9 +180,8 @@ public class JdbcCursorItemReaderBuilder { /** * Indicates if the reader should verify the current position of the - * {@link java.sql.ResultSet} after being passed to the {@link RowMapper}. Defaults - * to true. - * + * {@link java.sql.ResultSet} after being passed to the {@link RowMapper}. Defaults to + * true. * @param verifyCursorPosition indicator * @return this instance for method chaining * @see JdbcCursorItemReader#setVerifyCursorPosition(boolean) @@ -204,7 +195,6 @@ public class JdbcCursorItemReaderBuilder { /** * Indicates if the JDBC driver supports setting the absolute row on the * {@link java.sql.ResultSet}. - * * @param driverSupportsAbsolute indicator * @return this instance for method chaining * @see JdbcCursorItemReader#setDriverSupportsAbsolute(boolean) @@ -218,7 +208,6 @@ public class JdbcCursorItemReaderBuilder { /** * Indicates that the connection used for the cursor is being used by all other * processing, therefor part of the same transaction. - * * @param useSharedExtendedConnection indicator * @return this instance for method chaining * @see JdbcCursorItemReader#setUseSharedExtendedConnection(boolean) @@ -232,7 +221,6 @@ public class JdbcCursorItemReaderBuilder { /** * Configures the provided {@link PreparedStatementSetter} to be used to populate any * arguments in the SQL query to be executed for the reader. - * * @param preparedStatementSetter setter * @return this instance for method chaining * @see JdbcCursorItemReader#setPreparedStatementSetter(PreparedStatementSetter) @@ -246,7 +234,6 @@ public class JdbcCursorItemReaderBuilder { /** * Configures a {@link PreparedStatementSetter} that will use the array as the values * to be set on the query to be executed for this reader. - * * @param args values to set on the reader query * @return this instance for method chaining */ @@ -258,9 +245,8 @@ public class JdbcCursorItemReaderBuilder { /** * Configures a {@link PreparedStatementSetter} that will use the Object [] as the - * values to be set on the query to be executed for this reader. The int[] will + * values to be set on the query to be executed for this reader. The int[] will * provide the types ({@link java.sql.Types}) for each of the values provided. - * * @param args values to set on the query * @param types the type for each value in the args array * @return this instance for method chaining @@ -274,7 +260,6 @@ public class JdbcCursorItemReaderBuilder { /** * Configures a {@link PreparedStatementSetter} that will use the List as the values * to be set on the query to be executed for this reader. - * * @param args values to set on the query * @return this instance for method chaining */ @@ -287,7 +272,6 @@ public class JdbcCursorItemReaderBuilder { /** * The query to be executed for this reader - * * @param sql query * @return this instance for method chaining * @see JdbcCursorItemReader#setSql(String) @@ -300,7 +284,6 @@ public class JdbcCursorItemReaderBuilder { /** * The {@link RowMapper} used to map the results of the cursor to each item. - * * @param rowMapper {@link RowMapper} * @return this instance for method chaining * @see JdbcCursorItemReader#setRowMapper(RowMapper) @@ -312,9 +295,7 @@ public class JdbcCursorItemReaderBuilder { } /** - * Creates a {@link BeanPropertyRowMapper} to be used as your - * {@link RowMapper}. - * + * Creates a {@link BeanPropertyRowMapper} to be used as your {@link RowMapper}. * @param mappedClass the class for the row mapper * @return this instance for method chaining * @see BeanPropertyRowMapper @@ -326,9 +307,8 @@ public class JdbcCursorItemReaderBuilder { } /** - * Set whether "autoCommit" should be overridden for the connection used by the cursor. - * If not set, defaults to Connection / Datasource default configuration. - * + * Set whether "autoCommit" should be overridden for the connection used by the + * cursor. If not set, defaults to Connection / Datasource default configuration. * @param connectionAutoCommit value to set on underlying JDBC connection * @return this instance for method chaining * @see JdbcCursorItemReader#setConnectionAutoCommit(boolean) @@ -341,13 +321,11 @@ public class JdbcCursorItemReaderBuilder { /** * Validates configuration and builds a new reader instance. - * * @return a fully constructed {@link JdbcCursorItemReader} */ public JdbcCursorItemReader build() { - if(this.saveState) { - Assert.hasText(this.name, - "A name is required when saveState is set to true"); + if (this.saveState) { + Assert.hasText(this.name, "A name is required when saveState is set to true"); } Assert.hasText(this.sql, "A query is required"); @@ -356,7 +334,7 @@ public class JdbcCursorItemReaderBuilder { JdbcCursorItemReader reader = new JdbcCursorItemReader<>(); - if(StringUtils.hasText(this.name)) { + if (StringUtils.hasText(this.name)) { reader.setName(this.name); } @@ -378,4 +356,5 @@ public class JdbcCursorItemReaderBuilder { return reader; } - } + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/JdbcPagingItemReaderBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/JdbcPagingItemReaderBuilder.java index 2dec50fb1..f54df6cdd 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/JdbcPagingItemReaderBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/JdbcPagingItemReaderBuilder.java @@ -40,10 +40,10 @@ import org.springframework.jdbc.support.MetaDataAccessException; import org.springframework.util.Assert; /** - * This is a builder for the {@link JdbcPagingItemReader}. When configuring, either a - * {@link PagingQueryProvider} or the SQL fragments should be provided. If the SQL + * This is a builder for the {@link JdbcPagingItemReader}. When configuring, either a + * {@link PagingQueryProvider} or the SQL fragments should be provided. If the SQL * fragments are provided, the metadata from the provided {@link DataSource} will be used - * to create a PagingQueryProvider for you. If both are provided, the PagingQueryProvider + * to create a PagingQueryProvider for you. If both are provided, the PagingQueryProvider * will be used. * * @author Michael Minella @@ -85,10 +85,9 @@ public class JdbcPagingItemReaderBuilder { private int currentItemCount; /** - * Configure if the state of the {@link org.springframework.batch.item.ItemStreamSupport} - * should be persisted within the {@link org.springframework.batch.item.ExecutionContext} - * for restart purposes. - * + * Configure if the state of the + * {@link org.springframework.batch.item.ItemStreamSupport} should be persisted within + * the {@link org.springframework.batch.item.ExecutionContext} for restart purposes. * @param saveState defaults to true * @return The current instance of the builder. */ @@ -102,7 +101,6 @@ public class JdbcPagingItemReaderBuilder { * The name used to calculate the key within the * {@link org.springframework.batch.item.ExecutionContext}. Required if * {@link #saveState(boolean)} is set to true. - * * @param name name of the reader instance * @return The current instance of the builder. * @see org.springframework.batch.item.ItemStreamSupport#setName(String) @@ -115,7 +113,6 @@ public class JdbcPagingItemReaderBuilder { /** * Configure the max number of items to be read. - * * @param maxItemCount the max items to be read * @return The current instance of the builder. * @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setMaxItemCount(int) @@ -128,7 +125,6 @@ public class JdbcPagingItemReaderBuilder { /** * Index for the current item. Used on restarts to indicate where to start from. - * * @param currentItemCount current index * @return this instance for method chaining * @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setCurrentItemCount(int) @@ -140,8 +136,7 @@ public class JdbcPagingItemReaderBuilder { } /** - * The {@link DataSource} to query against. Required. - * + * The {@link DataSource} to query against. Required. * @param dataSource the {@link DataSource} * @return this instance for method chaining * @see JdbcPagingItemReader#setDataSource(DataSource) @@ -154,7 +149,6 @@ public class JdbcPagingItemReaderBuilder { /** * A hint to the underlying RDBMS as to how many records to return with each fetch. - * * @param fetchSize number of records * @return this instance for method chaining * @see JdbcPagingItemReader#setFetchSize(int) @@ -166,8 +160,7 @@ public class JdbcPagingItemReaderBuilder { } /** - * The {@link RowMapper} used to map the query results to objects. Required. - * + * The {@link RowMapper} used to map the query results to objects. Required. * @param rowMapper a {@link RowMapper} implementation * @return this instance for method chaining * @see JdbcPagingItemReader#setRowMapper(RowMapper) @@ -179,9 +172,7 @@ public class JdbcPagingItemReaderBuilder { } /** - * Creates a {@link BeanPropertyRowMapper} to be used as your - * {@link RowMapper}. - * + * Creates a {@link BeanPropertyRowMapper} to be used as your {@link RowMapper}. * @param mappedClass the class for the row mapper * @return this instance for method chaining * @see BeanPropertyRowMapper @@ -194,7 +185,6 @@ public class JdbcPagingItemReaderBuilder { /** * A {@link Map} of values to set on the SQL's prepared statement. - * * @param parameterValues Map of values * @return this instance for method chaining * @see JdbcPagingItemReader#setParameterValues(Map) @@ -206,9 +196,8 @@ public class JdbcPagingItemReaderBuilder { } /** - * The number of records to request per page/query. Defaults to 10. Must be greater + * The number of records to request per page/query. Defaults to 10. Must be greater * than zero. - * * @param pageSize number of items * @return this instance for method chaining * @see JdbcPagingItemReader#setPageSize(int) @@ -220,9 +209,9 @@ public class JdbcPagingItemReaderBuilder { } /** - * The SQL GROUP BY clause for a db specific @{@link PagingQueryProvider}. - * This is only used if a PagingQueryProvider is not provided. - * + * The SQL GROUP BY clause for a db + * specific @{@link PagingQueryProvider}. This is only used if a PagingQueryProvider + * is not provided. * @param groupClause the SQL clause * @return this instance for method chaining * @see AbstractSqlPagingQueryProvider#setGroupClause(String) @@ -236,7 +225,6 @@ public class JdbcPagingItemReaderBuilder { /** * The SQL SELECT clause for a db specific {@link PagingQueryProvider}. * This is only used if a PagingQueryProvider is not provided. - * * @param selectClause the SQL clause * @return this instance for method chaining * @see AbstractSqlPagingQueryProvider#setSelectClause(String) @@ -250,7 +238,6 @@ public class JdbcPagingItemReaderBuilder { /** * The SQL FROM clause for a db specific {@link PagingQueryProvider}. * This is only used if a PagingQueryProvider is not provided. - * * @param fromClause the SQL clause * @return this instance for method chaining * @see AbstractSqlPagingQueryProvider#setFromClause(String) @@ -264,7 +251,6 @@ public class JdbcPagingItemReaderBuilder { /** * The SQL WHERE clause for a db specific {@link PagingQueryProvider}. * This is only used if a PagingQueryProvider is not provided. - * * @param whereClause the SQL clause * @return this instance for method chaining * @see AbstractSqlPagingQueryProvider#setWhereClause(String) @@ -276,8 +262,7 @@ public class JdbcPagingItemReaderBuilder { } /** - * The keys to sort by. These keys must create a unique key. - * + * The keys to sort by. These keys must create a unique key. * @param sortKeys keys to sort by and the direction for each. * @return this instance for method chaining * @see AbstractSqlPagingQueryProvider#setSortKeys(Map) @@ -289,11 +274,10 @@ public class JdbcPagingItemReaderBuilder { } /** - * A {@link PagingQueryProvider} to provide the queries required. If provided, the - * SQL fragments configured via {@link #selectClause(String)}, + * A {@link PagingQueryProvider} to provide the queries required. If provided, the SQL + * fragments configured via {@link #selectClause(String)}, * {@link #fromClause(String)}, {@link #whereClause(String)}, {@link #groupClause}, * and {@link #sortKeys(Map)} are ignored. - * * @param provider the db specific query provider * @return this instance for method chaining * @see JdbcPagingItemReader#setQueryProvider(PagingQueryProvider) @@ -306,16 +290,14 @@ public class JdbcPagingItemReaderBuilder { /** * Provides a completely built instance of the {@link JdbcPagingItemReader} - * * @return a {@link JdbcPagingItemReader} */ public JdbcPagingItemReader build() { Assert.isTrue(this.pageSize > 0, "pageSize must be greater than zero"); Assert.notNull(this.dataSource, "dataSource is required"); - if(this.saveState) { - Assert.hasText(this.name, - "A name is required when saveState is set to true"); + if (this.saveState) { + Assert.hasText(this.name, "A name is required when saveState is set to true"); } JdbcPagingItemReader reader = new JdbcPagingItemReader<>(); @@ -328,7 +310,7 @@ public class JdbcPagingItemReaderBuilder { reader.setFetchSize(this.fetchSize); reader.setParameterValues(this.parameterValues); - if(this.queryProvider == null) { + if (this.queryProvider == null) { Assert.hasLength(this.selectClause, "selectClause is required when not providing a PagingQueryProvider"); Assert.hasLength(this.fromClause, "fromClause is required when not providing a PagingQueryProvider"); Assert.notEmpty(this.sortKeys, "sortKeys are required when not providing a PagingQueryProvider"); @@ -354,23 +336,45 @@ public class JdbcPagingItemReaderBuilder { switch (databaseType) { - case DERBY: provider = new DerbyPagingQueryProvider(); break; - case DB2: - case DB2VSE: - case DB2ZOS: - case DB2AS400: provider = new Db2PagingQueryProvider(); break; - case H2: provider = new H2PagingQueryProvider(); break; - case HANA: provider = new HanaPagingQueryProvider(); break; - case HSQL: provider = new HsqlPagingQueryProvider(); break; - case SQLSERVER: provider = new SqlServerPagingQueryProvider(); break; - case MYSQL: provider = new MySqlPagingQueryProvider(); break; - case ORACLE: provider = new OraclePagingQueryProvider(); break; - case POSTGRES: provider = new PostgresPagingQueryProvider(); break; - case SYBASE: provider = new SybasePagingQueryProvider(); break; - case SQLITE: provider = new SqlitePagingQueryProvider(); break; - default: - throw new IllegalArgumentException("Unable to determine PagingQueryProvider type " + - "from database type: " + databaseType); + case DERBY: + provider = new DerbyPagingQueryProvider(); + break; + case DB2: + case DB2VSE: + case DB2ZOS: + case DB2AS400: + provider = new Db2PagingQueryProvider(); + break; + case H2: + provider = new H2PagingQueryProvider(); + break; + case HANA: + provider = new HanaPagingQueryProvider(); + break; + case HSQL: + provider = new HsqlPagingQueryProvider(); + break; + case SQLSERVER: + provider = new SqlServerPagingQueryProvider(); + break; + case MYSQL: + provider = new MySqlPagingQueryProvider(); + break; + case ORACLE: + provider = new OraclePagingQueryProvider(); + break; + case POSTGRES: + provider = new PostgresPagingQueryProvider(); + break; + case SYBASE: + provider = new SybasePagingQueryProvider(); + break; + case SQLITE: + provider = new SqlitePagingQueryProvider(); + break; + default: + throw new IllegalArgumentException( + "Unable to determine PagingQueryProvider type " + "from database type: " + databaseType); } provider.setSelectClause(this.selectClause); @@ -385,4 +389,5 @@ public class JdbcPagingItemReaderBuilder { throw new IllegalArgumentException("Unable to determine PagingQueryProvider type", e); } } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/JpaCursorItemReaderBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/JpaCursorItemReaderBuilder.java index a3ec3d343..5a1c874fb 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/JpaCursorItemReaderBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/JpaCursorItemReaderBuilder.java @@ -30,25 +30,29 @@ import org.springframework.util.Assert; * Builder for {@link JpaCursorItemReader}. * * @author Mahmoud Ben Hassine - * * @since 4.3 */ public class JpaCursorItemReaderBuilder { private EntityManagerFactory entityManagerFactory; + private String queryString; + private JpaQueryProvider queryProvider; + private Map parameterValues; + private boolean saveState = true; + private String name; + private int maxItemCount = Integer.MAX_VALUE; + private int currentItemCount; /** - * Configure if the state of the {@link ItemStreamSupport} - * should be persisted within the {@link ExecutionContext} - * for restart purposes. - * + * Configure if the state of the {@link ItemStreamSupport} should be persisted within + * the {@link ExecutionContext} for restart purposes. * @param saveState defaults to true * @return The current instance of the builder. */ @@ -59,9 +63,8 @@ public class JpaCursorItemReaderBuilder { } /** - * The name used to calculate the key within the {@link ExecutionContext}. - * Required if {@link #saveState(boolean)} is set to true. - * + * The name used to calculate the key within the {@link ExecutionContext}. Required if + * {@link #saveState(boolean)} is set to true. * @param name name of the reader instance * @return The current instance of the builder. * @see ItemStreamSupport#setName(String) @@ -74,7 +77,6 @@ public class JpaCursorItemReaderBuilder { /** * Configure the max number of items to be read. - * * @param maxItemCount the max items to be read * @return The current instance of the builder. * @see AbstractItemCountingItemStreamItemReader#setMaxItemCount(int) @@ -87,7 +89,6 @@ public class JpaCursorItemReaderBuilder { /** * Index for the current item. Used on restarts to indicate where to start from. - * * @param currentItemCount current index * @return this instance for method chaining * @see AbstractItemCountingItemStreamItemReader#setCurrentItemCount(int) @@ -99,9 +100,8 @@ public class JpaCursorItemReaderBuilder { } /** - * A map of parameter values to be set on the query. The key of the map is - * the name of the parameter to be set with the value being the value to be set. - * + * A map of parameter values to be set on the query. The key of the map is the name of + * the parameter to be set with the value being the value to be set. * @param parameterValues map of values * @return this instance for method chaining * @see JpaCursorItemReader#setParameterValues(Map) @@ -113,9 +113,8 @@ public class JpaCursorItemReaderBuilder { } /** - * A query provider. This should be set only if {@link #queryString(String)} - * have not been set. - * + * A query provider. This should be set only if {@link #queryString(String)} have not + * been set. * @param queryProvider the query provider * @return this instance for method chaining * @see JpaCursorItemReader#setQueryProvider(JpaQueryProvider) @@ -129,7 +128,6 @@ public class JpaCursorItemReaderBuilder { /** * The JPQL query string to execute. This should only be set if * {@link #queryProvider(JpaQueryProvider)} has not been set. - * * @param queryString the JPQL query * @return this instance for method chaining * @see JpaCursorItemReader#setQueryString(String) @@ -143,7 +141,6 @@ public class JpaCursorItemReaderBuilder { /** * The {@link EntityManagerFactory} to be used for executing the configured * {@link #queryString}. - * * @param entityManagerFactory {@link EntityManagerFactory} used to create * {@link jakarta.persistence.EntityManager} * @return this instance for method chaining @@ -156,7 +153,6 @@ public class JpaCursorItemReaderBuilder { /** * Returns a fully constructed {@link JpaCursorItemReader}. - * * @return a new {@link JpaCursorItemReader} */ public JpaCursorItemReader build() { @@ -179,4 +175,5 @@ public class JpaCursorItemReaderBuilder { reader.setName(this.name); return reader; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/JpaItemWriterBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/JpaItemWriterBuilder.java index 5e1fc699a..7fd536d1a 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/JpaItemWriterBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/JpaItemWriterBuilder.java @@ -30,11 +30,11 @@ import org.springframework.util.Assert; public class JpaItemWriterBuilder { private EntityManagerFactory entityManagerFactory; + private boolean usePersist = false; /** * The JPA {@link EntityManagerFactory} to obtain an entity manager from. Required. - * * @param entityManagerFactory the {@link EntityManagerFactory} * @return this instance for method chaining * @see JpaItemWriter#setEntityManagerFactory(EntityManagerFactory) @@ -47,7 +47,6 @@ public class JpaItemWriterBuilder { /** * Set whether the entity manager should perform a persist instead of a merge. - * * @param usePersist defaults to false * @return this instance for method chaining * @see JpaItemWriter#setUsePersist(boolean) @@ -60,12 +59,10 @@ public class JpaItemWriterBuilder { /** * Returns a fully built {@link JpaItemWriter}. - * * @return the writer */ public JpaItemWriter build() { - Assert.state(this.entityManagerFactory != null, - "EntityManagerFactory must be provided"); + Assert.state(this.entityManagerFactory != null, "EntityManagerFactory must be provided"); JpaItemWriter writer = new JpaItemWriter<>(); writer.setEntityManagerFactory(this.entityManagerFactory); @@ -73,4 +70,5 @@ public class JpaItemWriterBuilder { return writer; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/JpaPagingItemReaderBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/JpaPagingItemReaderBuilder.java index 254b2b3ef..adf62a5d8 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/JpaPagingItemReaderBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/JpaPagingItemReaderBuilder.java @@ -27,7 +27,6 @@ import org.springframework.util.Assert; * * @author Michael Minella * @author Glenn Renfro - * * @since 4.0 */ @@ -54,10 +53,9 @@ public class JpaPagingItemReaderBuilder { private int currentItemCount; /** - * Configure if the state of the {@link org.springframework.batch.item.ItemStreamSupport} - * should be persisted within the {@link org.springframework.batch.item.ExecutionContext} - * for restart purposes. - * + * Configure if the state of the + * {@link org.springframework.batch.item.ItemStreamSupport} should be persisted within + * the {@link org.springframework.batch.item.ExecutionContext} for restart purposes. * @param saveState defaults to true * @return The current instance of the builder. */ @@ -71,7 +69,6 @@ public class JpaPagingItemReaderBuilder { * The name used to calculate the key within the * {@link org.springframework.batch.item.ExecutionContext}. Required if * {@link #saveState(boolean)} is set to true. - * * @param name name of the reader instance * @return The current instance of the builder. * @see org.springframework.batch.item.ItemStreamSupport#setName(String) @@ -84,7 +81,6 @@ public class JpaPagingItemReaderBuilder { /** * Configure the max number of items to be read. - * * @param maxItemCount the max items to be read * @return The current instance of the builder. * @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setMaxItemCount(int) @@ -97,7 +93,6 @@ public class JpaPagingItemReaderBuilder { /** * Index for the current item. Used on restarts to indicate where to start from. - * * @param currentItemCount current index * @return this instance for method chaining * @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setCurrentItemCount(int) @@ -109,9 +104,8 @@ public class JpaPagingItemReaderBuilder { } /** - * The number of records to request per page/query. Defaults to 10. Must be greater + * The number of records to request per page/query. Defaults to 10. Must be greater * than zero. - * * @param pageSize number of items * @return this instance for method chaining * @see JpaPagingItemReader#setPageSize(int) @@ -123,9 +117,8 @@ public class JpaPagingItemReaderBuilder { } /** - * A map of parameter values to be set on the query. The key of the map is the name - * of the parameter to be set with the value being the value to be set. - * + * A map of parameter values to be set on the query. The key of the map is the name of + * the parameter to be set with the value being the value to be set. * @param parameterValues map of values * @return this instance for method chaining * @see JpaPagingItemReader#setParameterValues(Map) @@ -137,9 +130,8 @@ public class JpaPagingItemReaderBuilder { } /** - * A query provider. This should be set only if {@link #queryString(String)} have not + * A query provider. This should be set only if {@link #queryString(String)} have not * been set. - * * @param queryProvider the query provider * @return this instance for method chaining * @see JpaPagingItemReader#setQueryProvider(JpaQueryProvider) @@ -151,9 +143,8 @@ public class JpaPagingItemReaderBuilder { } /** - * The HQL query string to execute. This should only be set if + * The HQL query string to execute. This should only be set if * {@link #queryProvider(JpaQueryProvider)} has not been set. - * * @param queryString the HQL query * @return this instance for method chaining * @see JpaPagingItemReader#setQueryString(String) @@ -165,10 +156,10 @@ public class JpaPagingItemReaderBuilder { } /** - * Indicates if a transaction should be created around the read (true by default). - * Can be set to false in cases where JPA implementation doesn't support a particular - * transaction, however this may cause object inconsistency in the EntityManagerFactory. - * + * Indicates if a transaction should be created around the read (true by default). Can + * be set to false in cases where JPA implementation doesn't support a particular + * transaction, however this may cause object inconsistency in the + * EntityManagerFactory. * @param transacted defaults to true * @return this instance for method chaining * @see JpaPagingItemReader#setTransacted(boolean) @@ -182,7 +173,6 @@ public class JpaPagingItemReaderBuilder { /** * The {@link EntityManagerFactory} to be used for executing the configured * {@link #queryString}. - * * @param entityManagerFactory {@link EntityManagerFactory} used to create * {@link jakarta.persistence.EntityManager} * @return this instance for method chaining @@ -195,19 +185,17 @@ public class JpaPagingItemReaderBuilder { /** * Returns a fully constructed {@link JpaPagingItemReader}. - * * @return a new {@link JpaPagingItemReader} */ public JpaPagingItemReader build() { Assert.isTrue(this.pageSize > 0, "pageSize must be greater than zero"); Assert.notNull(this.entityManagerFactory, "An EntityManagerFactory is required"); - if(this.saveState) { - Assert.hasText(this.name, - "A name is required when saveState is set to true"); + if (this.saveState) { + Assert.hasText(this.name, "A name is required when saveState is set to true"); } - if(this.queryProvider == null) { + if (this.queryProvider == null) { Assert.hasLength(this.queryString, "Query string is required when queryProvider is null"); } @@ -226,4 +214,5 @@ public class JpaPagingItemReaderBuilder { return reader; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/StoredProcedureItemReaderBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/StoredProcedureItemReaderBuilder.java index b87145e6e..f359e8e87 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/StoredProcedureItemReaderBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/StoredProcedureItemReaderBuilder.java @@ -76,10 +76,9 @@ public class StoredProcedureItemReaderBuilder { private String name; /** - * Configure if the state of the {@link org.springframework.batch.item.ItemStreamSupport} - * should be persisted within the {@link org.springframework.batch.item.ExecutionContext} - * for restart purposes. - * + * Configure if the state of the + * {@link org.springframework.batch.item.ItemStreamSupport} should be persisted within + * the {@link org.springframework.batch.item.ExecutionContext} for restart purposes. * @param saveState defaults to true * @return The current instance of the builder. */ @@ -93,7 +92,6 @@ public class StoredProcedureItemReaderBuilder { * The name used to calculate the key within the * {@link org.springframework.batch.item.ExecutionContext}. Required if * {@link #saveState(boolean)} is set to true. - * * @param name name of the reader instance * @return The current instance of the builder. * @see org.springframework.batch.item.ItemStreamSupport#setName(String) @@ -106,7 +104,6 @@ public class StoredProcedureItemReaderBuilder { /** * Configure the max number of items to be read. - * * @param maxItemCount the max items to be read * @return The current instance of the builder. * @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setMaxItemCount(int) @@ -119,7 +116,6 @@ public class StoredProcedureItemReaderBuilder { /** * Index for the current item. Used on restarts to indicate where to start from. - * * @param currentItemCount current index * @return this instance for method chaining * @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setCurrentItemCount(int) @@ -132,7 +128,6 @@ public class StoredProcedureItemReaderBuilder { /** * The {@link DataSource} to read from - * * @param dataSource a relational data base * @return this instance for method chaining * @see StoredProcedureItemReader#setDataSource(DataSource) @@ -145,7 +140,6 @@ public class StoredProcedureItemReaderBuilder { /** * A hint to the driver as to how many rows to return with each fetch. - * * @param fetchSize the hint * @return this instance for method chaining * @see StoredProcedureItemReader#setFetchSize(int) @@ -158,7 +152,6 @@ public class StoredProcedureItemReaderBuilder { /** * The max number of rows the {@link java.sql.ResultSet} can contain - * * @param maxRows the max * @return this instance for method chaining * @see StoredProcedureItemReader#setMaxRows(int) @@ -171,7 +164,6 @@ public class StoredProcedureItemReaderBuilder { /** * The time in milliseconds for the query to timeout - * * @param queryTimeout timeout * @return this instance for method chaining * @see StoredProcedureItemReader#setQueryTimeout(int) @@ -184,7 +176,6 @@ public class StoredProcedureItemReaderBuilder { /** * Indicates if SQL warnings should be ignored or if an exception should be thrown. - * * @param ignoreWarnings indicator. Defaults to true * @return this instance for method chaining * @see AbstractCursorItemReader#setIgnoreWarnings(boolean) @@ -197,9 +188,8 @@ public class StoredProcedureItemReaderBuilder { /** * Indicates if the reader should verify the current position of the - * {@link java.sql.ResultSet} after being passed to the {@link RowMapper}. Defaults - * to true. - * + * {@link java.sql.ResultSet} after being passed to the {@link RowMapper}. Defaults to + * true. * @param verifyCursorPosition indicator * @return this instance for method chaining * @see StoredProcedureItemReader#setVerifyCursorPosition(boolean) @@ -213,7 +203,6 @@ public class StoredProcedureItemReaderBuilder { /** * Indicates if the JDBC driver supports setting the absolute row on the * {@link java.sql.ResultSet}. - * * @param driverSupportsAbsolute indicator * @return this instance for method chaining * @see StoredProcedureItemReader#setDriverSupportsAbsolute(boolean) @@ -227,7 +216,6 @@ public class StoredProcedureItemReaderBuilder { /** * Indicates that the connection used for the cursor is being used by all other * processing, therefor part of the same transaction. - * * @param useSharedExtendedConnection indicator * @return this instance for method chaining * @see StoredProcedureItemReader#setUseSharedExtendedConnection(boolean) @@ -241,12 +229,12 @@ public class StoredProcedureItemReaderBuilder { /** * Configures the provided {@link PreparedStatementSetter} to be used to populate any * arguments in the SQL query to be executed for the reader. - * * @param preparedStatementSetter setter * @return this instance for method chaining * @see StoredProcedureItemReader#setPreparedStatementSetter(PreparedStatementSetter) */ - public StoredProcedureItemReaderBuilder preparedStatementSetter(PreparedStatementSetter preparedStatementSetter) { + public StoredProcedureItemReaderBuilder preparedStatementSetter( + PreparedStatementSetter preparedStatementSetter) { this.preparedStatementSetter = preparedStatementSetter; return this; @@ -254,7 +242,6 @@ public class StoredProcedureItemReaderBuilder { /** * The {@link RowMapper} used to map the results of the cursor to each item. - * * @param rowMapper {@link RowMapper} * @return this instance for method chaining * @see StoredProcedureItemReader#setRowMapper(RowMapper) @@ -267,7 +254,6 @@ public class StoredProcedureItemReaderBuilder { /** * The name of the stored procedure to execute - * * @param procedureName name of the procedure * @return this instance for method chaining * @see StoredProcedureItemReader#setProcedureName(String) @@ -280,7 +266,6 @@ public class StoredProcedureItemReaderBuilder { /** * SQL parameters to be set when executing the stored procedure - * * @param parameters parameters to be set * @return this instance for method chaining * @see StoredProcedureItemReader#setParameters(SqlParameter[]) @@ -293,7 +278,6 @@ public class StoredProcedureItemReaderBuilder { /** * Indicates the stored procedure is a function - * * @return this instance for method chaining * @see StoredProcedureItemReader#setFunction(boolean) */ @@ -304,9 +288,8 @@ public class StoredProcedureItemReaderBuilder { } /** - * The parameter position of the REF CURSOR. Only used for Oracle and PostgreSQL that - * use REF CURSORs. For any other database, this should remain as the default (0). - * + * The parameter position of the REF CURSOR. Only used for Oracle and PostgreSQL that + * use REF CURSORs. For any other database, this should remain as the default (0). * @param refCursorPosition the parameter position * @return this instance for method chaining * @see StoredProcedureItemReader#setRefCursorPosition(int) @@ -319,13 +302,11 @@ public class StoredProcedureItemReaderBuilder { /** * Validates configuration and builds a new reader instance - * * @return a fully constructed {@link StoredProcedureItemReader} */ public StoredProcedureItemReader build() { - if(this.saveState) { - Assert.hasText(this.name, - "A name is required when saveSate is set to true"); + if (this.saveState) { + Assert.hasText(this.name, "A name is required when saveSate is set to true"); } Assert.notNull(this.procedureName, "The name of the stored procedure must be provided"); @@ -334,7 +315,7 @@ public class StoredProcedureItemReaderBuilder { StoredProcedureItemReader itemReader = new StoredProcedureItemReader<>(); - if(StringUtils.hasText(this.name)) { + if (StringUtils.hasText(this.name)) { itemReader.setName(this.name); } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/orm/AbstractHibernateQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/orm/AbstractHibernateQueryProvider.java index 0de7ce35a..60cbcddbe 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/orm/AbstractHibernateQueryProvider.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/orm/AbstractHibernateQueryProvider.java @@ -21,23 +21,27 @@ import org.hibernate.Session; import org.hibernate.StatelessSession; /** - *

      Abstract Hibernate Query Provider to serve as a base class for all - * Hibernate {@link Query} providers.

      + *

      + * Abstract Hibernate Query Provider to serve as a base class for all Hibernate + * {@link Query} providers. + *

      * - *

      The implementing provider can be configured to use either - * {@link StatelessSession} sufficient for simple mappings without the need - * to cascade to associated objects or standard Hibernate {@link Session} - * for more advanced mappings or when caching is desired.

      + *

      + * The implementing provider can be configured to use either {@link StatelessSession} + * sufficient for simple mappings without the need to cascade to associated objects or + * standard Hibernate {@link Session} for more advanced mappings or when caching is + * desired. + *

      * * @author Anatoly Polinsky * @author Dave Syer - * * @since 2.1 * */ public abstract class AbstractHibernateQueryProvider implements HibernateQueryProvider { private StatelessSession statelessSession; + private Session statefulSession; @Override @@ -51,7 +55,7 @@ public abstract class AbstractHibernateQueryProvider implements HibernateQuer } public boolean isStatelessSession() { - return this.statefulSession==null && this.statelessSession!=null; + return this.statefulSession == null && this.statelessSession != null; } protected StatelessSession getStatelessSession() { @@ -61,4 +65,5 @@ public abstract class AbstractHibernateQueryProvider implements HibernateQuer protected Session getStatefulSession() { return statefulSession; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/orm/AbstractJpaQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/orm/AbstractJpaQueryProvider.java index 75edf736d..0da409e53 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/orm/AbstractJpaQueryProvider.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/orm/AbstractJpaQueryProvider.java @@ -23,14 +23,13 @@ import org.springframework.beans.factory.InitializingBean; /** *

      - * Abstract JPA Query Provider to serve as a base class for all JPA - * {@link Query} providers. + * Abstract JPA Query Provider to serve as a base class for all JPA {@link Query} + * providers. *

      * * @author Anatoly Polinsky * @author Dave Syer * @author Mahmoud Ben Hassine - * * @since 2.1 */ public abstract class AbstractJpaQueryProvider implements JpaQueryProvider, InitializingBean { @@ -43,7 +42,6 @@ public abstract class AbstractJpaQueryProvider implements JpaQueryProvider, Init * {@link HibernateQueryProvider}. This is currently needed to allow * {@link HibernateQueryProvider} to participate in a user's managed transaction. *

      - * * @param entityManager EntityManager to use */ @Override @@ -55,10 +53,10 @@ public abstract class AbstractJpaQueryProvider implements JpaQueryProvider, Init *

      * Getter for {@link EntityManager} *

      - * * @return entityManager the injected {@link EntityManager} */ protected EntityManager getEntityManager() { return entityManager; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/orm/HibernateNativeQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/orm/HibernateNativeQueryProvider.java index 196389428..6218f9419 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/orm/HibernateNativeQueryProvider.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/orm/HibernateNativeQueryProvider.java @@ -24,13 +24,12 @@ import org.springframework.util.StringUtils; /** *

      - * This query provider creates Hibernate {@link Query}s from injected native SQL - * queries. This is useful if there is a need to utilize database-specific - * features such as query hints, the CONNECT keyword in Oracle, etc. + * This query provider creates Hibernate {@link Query}s from injected native SQL queries. + * This is useful if there is a need to utilize database-specific features such as query + * hints, the CONNECT keyword in Oracle, etc. *

      - * + * * @author Anatoly Polinsky - * * @param entity returned by executing the query */ public class HibernateNativeQueryProvider extends AbstractHibernateQueryProvider { @@ -41,11 +40,11 @@ public class HibernateNativeQueryProvider extends AbstractHibernateQueryProvi /** *

      - * Create an {@link NativeQuery} from the session provided (preferring - * stateless if both are available). + * Create an {@link NativeQuery} from the session provided (preferring stateless if + * both are available). *

      */ - @Override + @Override @SuppressWarnings("unchecked") public NativeQuery createQuery() { @@ -69,4 +68,5 @@ public class HibernateNativeQueryProvider extends AbstractHibernateQueryProvi Assert.isTrue(StringUtils.hasText(sqlQuery), "Native SQL query cannot be empty"); Assert.notNull(entityClass, "Entity class cannot be NULL"); } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/orm/HibernateQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/orm/HibernateQueryProvider.java index ef823a5bd..13171081b 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/orm/HibernateQueryProvider.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/orm/HibernateQueryProvider.java @@ -23,15 +23,14 @@ import org.springframework.batch.item.ItemReader; /** *

      - * Interface defining the functionality to be provided for generating queries - * for use with Hibernate {@link ItemReader}s or other custom built artifacts. + * Interface defining the functionality to be provided for generating queries for use with + * Hibernate {@link ItemReader}s or other custom built artifacts. *

      - * + * * @author Anatoly Polinsky * @author Dave Syer - * * @since 2.1 - * + * */ public interface HibernateQueryProvider { @@ -40,37 +39,33 @@ public interface HibernateQueryProvider { * Create the query object which type will be determined by the underline * implementation (e.g. Hibernate, JPA, etc.) *

      - * * @return created query */ Query createQuery(); /** *

      - * Inject a {@link Session} that can be used as a factory for queries. The - * state of the session is controlled by the caller (i.e. it should be - * closed if necessary). + * Inject a {@link Session} that can be used as a factory for queries. The state of + * the session is controlled by the caller (i.e. it should be closed if necessary). *

      - * + * *

      * Use either this method or {@link #setStatelessSession(StatelessSession)} *

      - * * @param session the {@link Session} to set */ void setSession(Session session); /** *

      - * Inject a {@link StatelessSession} that can be used as a factory for - * queries. The state of the session is controlled by the caller (i.e. it - * should be closed if necessary). + * Inject a {@link StatelessSession} that can be used as a factory for queries. The + * state of the session is controlled by the caller (i.e. it should be closed if + * necessary). *

      - * + * *

      * Use either this method or {@link #setSession(Session)} *

      - * * @param session the {@link StatelessSession} to set */ void setStatelessSession(StatelessSession session); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/orm/JpaNamedQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/orm/JpaNamedQueryProvider.java index c91ed17c4..dc4ea290b 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/orm/JpaNamedQueryProvider.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/orm/JpaNamedQueryProvider.java @@ -28,7 +28,6 @@ import org.springframework.util.StringUtils; * @author Mahmoud Ben Hassine * @author Parikshit Dutta * @since 4.3 - * * @param entity returned by executing the query */ public class JpaNamedQueryProvider extends AbstractJpaQueryProvider { @@ -61,4 +60,5 @@ public class JpaNamedQueryProvider extends AbstractJpaQueryProvider { Assert.isTrue(StringUtils.hasText(this.namedQuery), "Named query cannot be empty"); Assert.notNull(this.entityClass, "Entity class cannot be NULL"); } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/orm/JpaNativeQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/orm/JpaNativeQueryProvider.java index 9c6a2f76a..9dbf9d5ca 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/orm/JpaNativeQueryProvider.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/orm/JpaNativeQueryProvider.java @@ -23,14 +23,13 @@ import org.springframework.util.StringUtils; /** *

      - * This query provider creates JPA {@link Query}s from injected native SQL - * queries. This is useful if there is a need to utilize database-specific - * features such as query hints, the CONNECT keyword in Oracle, etc. + * This query provider creates JPA {@link Query}s from injected native SQL queries. This + * is useful if there is a need to utilize database-specific features such as query hints, + * the CONNECT keyword in Oracle, etc. *

      - * + * * @author Anatoly Polinsky * @author Mahmoud Ben Hassine - * * @param entity returned by executing the query */ public class JpaNativeQueryProvider extends AbstractJpaQueryProvider { @@ -39,7 +38,7 @@ public class JpaNativeQueryProvider extends AbstractJpaQueryProvider { private String sqlQuery; - @Override + @Override public Query createQuery() { return getEntityManager().createNativeQuery(sqlQuery, entityClass); } @@ -52,9 +51,10 @@ public class JpaNativeQueryProvider extends AbstractJpaQueryProvider { this.entityClass = entityClazz; } - @Override + @Override public void afterPropertiesSet() throws Exception { Assert.isTrue(StringUtils.hasText(sqlQuery), "Native SQL query cannot be empty"); Assert.notNull(entityClass, "Entity class cannot be NULL"); } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/orm/JpaQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/orm/JpaQueryProvider.java index dc6acdca0..654a0921f 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/orm/JpaQueryProvider.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/orm/JpaQueryProvider.java @@ -22,29 +22,31 @@ import jakarta.persistence.Query; import org.springframework.batch.item.ItemReader; /** - *

      Interface defining the functionality to be provided for generating queries - * for use with JPA {@link ItemReader}s or other custom built artifacts.

      - * + *

      + * Interface defining the functionality to be provided for generating queries for use with + * JPA {@link ItemReader}s or other custom built artifacts. + *

      + * * @author Anatoly Polinsky * @author Dave Syer * @author Mahmoud Ben Hassine * @since 2.1 - * + * */ public interface JpaQueryProvider { - /** - *

      Create the query object.

      - * - * @return created query - */ + /** + *

      + * Create the query object. + *

      + * @return created query + */ public Query createQuery(); - - /** - * Provide an {@link EntityManager} for the query to be built. - * - * @param entityManager to be used by the {@link JpaQueryProvider}. - */ - void setEntityManager(EntityManager entityManager); + + /** + * Provide an {@link EntityManager} for the query to be built. + * @param entityManager to be used by the {@link JpaQueryProvider}. + */ + void setEntityManager(EntityManager entityManager); } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/AbstractSqlPagingQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/AbstractSqlPagingQueryProvider.java index 9f726a7a7..81a5a564b 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/AbstractSqlPagingQueryProvider.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/AbstractSqlPagingQueryProvider.java @@ -30,22 +30,21 @@ import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** - * Abstract SQL Paging Query Provider to serve as a base class for all provided - * SQL paging query providers. - * - * Any implementation must provide a way to specify the select clause, from - * clause and optionally a where clause. In addition a way to specify a single - * column sort key must also be provided. This sort key will be used to provide - * the paging functionality. It is recommended that there should be an index for - * the sort key to provide better performance. - * - * Provides properties and preparation for the mandatory "selectClause" and - * "fromClause" as well as for the optional "whereClause". Also provides - * property for the mandatory "sortKeys". Note: The columns that make up - * the sort key must be a true key and not just a column to order by. It is important - * to have a unique key constraint on the sort key to guarantee that no data is lost - * between executions. - * + * Abstract SQL Paging Query Provider to serve as a base class for all provided SQL paging + * query providers. + * + * Any implementation must provide a way to specify the select clause, from clause and + * optionally a where clause. In addition a way to specify a single column sort key must + * also be provided. This sort key will be used to provide the paging functionality. It is + * recommended that there should be an index for the sort key to provide better + * performance. + * + * Provides properties and preparation for the mandatory "selectClause" and "fromClause" + * as well as for the optional "whereClause". Also provides property for the mandatory + * "sortKeys". Note: The columns that make up the sort key must be a true key and + * not just a column to order by. It is important to have a unique key constraint on the + * sort key to guarantee that no data is lost between executions. + * * @author Thomas Risberg * @author Dave Syer * @author Michael Minella @@ -60,7 +59,7 @@ public abstract class AbstractSqlPagingQueryProvider implements PagingQueryProvi private String fromClause; private String whereClause; - + private Map sortKeys = new LinkedHashMap<>(); private String groupClause; @@ -68,10 +67,9 @@ public abstract class AbstractSqlPagingQueryProvider implements PagingQueryProvi private int parameterCount; private boolean usingNamedParameters; - + /** * The setter for the group by clause - * * @param groupClause SQL GROUP BY clause part of the SQL query string */ public void setGroupClause(String groupClause) { @@ -82,10 +80,9 @@ public abstract class AbstractSqlPagingQueryProvider implements PagingQueryProvi this.groupClause = null; } } - + /** * The getter for the group by clause - * * @return SQL GROUP BY clause part of the SQL query string */ public String getGroupClause() { @@ -100,7 +97,6 @@ public abstract class AbstractSqlPagingQueryProvider implements PagingQueryProvi } /** - * * @return SQL SELECT clause part of SQL query string */ protected String getSelectClause() { @@ -115,7 +111,6 @@ public abstract class AbstractSqlPagingQueryProvider implements PagingQueryProvi } /** - * * @return SQL FROM clause part of SQL query string */ protected String getFromClause() { @@ -135,7 +130,6 @@ public abstract class AbstractSqlPagingQueryProvider implements PagingQueryProvi } /** - * * @return SQL WHERE clause part of SQL query string */ protected String getWhereClause() { @@ -150,32 +144,31 @@ public abstract class AbstractSqlPagingQueryProvider implements PagingQueryProvi } /** - * A Map<String, Boolean> of sort columns as the key and boolean for ascending/descending (ascending = true). - * + * A Map<String, Boolean> of sort columns as the key and boolean for + * ascending/descending (ascending = true). * @return sortKey key to use to sort and limit page content */ - @Override + @Override public Map getSortKeys() { return sortKeys; } - @Override + @Override public int getParameterCount() { return parameterCount; } - @Override + @Override public boolean isUsingNamedParameters() { return usingNamedParameters; } /** - * The sort key placeholder will vary depending on whether named parameters - * or traditional placeholders are used in query strings. - * + * The sort key placeholder will vary depending on whether named parameters or + * traditional placeholders are used in query strings. * @return place holder for sortKey. */ - @Override + @Override public String getSortKeyPlaceHolder(String keyName) { return usingNamedParameters ? ":_" + keyName : "?"; } @@ -184,7 +177,7 @@ public abstract class AbstractSqlPagingQueryProvider implements PagingQueryProvi * Check mandatory properties. * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() */ - @Override + @Override public void init(DataSource dataSource) throws Exception { Assert.notNull(dataSource, "A DataSource is required"); Assert.hasLength(selectClause, "selectClause must be specified"); @@ -196,7 +189,7 @@ public abstract class AbstractSqlPagingQueryProvider implements PagingQueryProvi if (whereClause != null) { sql.append(" WHERE ").append(whereClause); } - if(groupClause != null) { + if (groupClause != null) { sql.append(" GROUP BY ").append(groupClause); } List namedParameters = new ArrayList<>(); @@ -211,40 +204,38 @@ public abstract class AbstractSqlPagingQueryProvider implements PagingQueryProvi } /** - * Method generating the query string to be used for retrieving the first - * page. This method must be implemented in sub classes. - * + * Method generating the query string to be used for retrieving the first page. This + * method must be implemented in sub classes. * @param pageSize number of rows to read per page * @return query string */ - @Override + @Override public abstract String generateFirstPageQuery(int pageSize); /** - * Method generating the query string to be used for retrieving the pages - * following the first page. This method must be implemented in sub classes. - * + * Method generating the query string to be used for retrieving the pages following + * the first page. This method must be implemented in sub classes. * @param pageSize number of rows to read per page * @return query string */ - @Override + @Override public abstract String generateRemainingPagesQuery(int pageSize); /** - * Method generating the query string to be used for jumping to a specific - * item position. This method must be implemented in sub classes. - * + * Method generating the query string to be used for jumping to a specific item + * position. This method must be implemented in sub classes. * @param itemIndex the index of the item to jump to * @param pageSize number of rows to read per page * @return query string */ - @Override + @Override public abstract String generateJumpToItemQuery(int itemIndex, int pageSize); private String removeKeyWord(String keyWord, String clause) { String temp = clause.trim(); int length = keyWord.length(); - if (temp.toLowerCase().startsWith(keyWord) && Character.isWhitespace(temp.charAt(length)) && temp.length() > length + 1) { + if (temp.toLowerCase().startsWith(keyWord) && Character.isWhitespace(temp.charAt(length)) + && temp.length() > length + 1) { return temp.substring(length + 1); } else { @@ -253,7 +244,6 @@ public abstract class AbstractSqlPagingQueryProvider implements PagingQueryProvi } /** - * * @return sortKey key to use to sort and limit page content (without alias) */ @Override @@ -268,11 +258,13 @@ public abstract class AbstractSqlPagingQueryProvider implements PagingQueryProvi if (columnIndex < key.length()) { sortKeysWithoutAliases.put(key.substring(columnIndex), sortKeyEntry.getValue()); } - } else { + } + else { sortKeysWithoutAliases.put(sortKeyEntry.getKey(), sortKeyEntry.getValue()); } } return sortKeysWithoutAliases; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/ColumnMapItemPreparedStatementSetter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/ColumnMapItemPreparedStatementSetter.java index dde96eda9..777917246 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/ColumnMapItemPreparedStatementSetter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/ColumnMapItemPreparedStatementSetter.java @@ -27,11 +27,13 @@ import java.sql.SQLException; import java.util.Map; /** - *

      Implementation of the {@link ItemPreparedStatementSetter} interface that assumes all - * keys are contained within a {@link Map} with the column name as the key. It assumes nothing - * about ordering, and assumes that the order the entry set can be iterated over is the same as - * the PreparedStatement should be set.

      - * + *

      + * Implementation of the {@link ItemPreparedStatementSetter} interface that assumes all + * keys are contained within a {@link Map} with the column name as the key. It assumes + * nothing about ordering, and assumes that the order the entry set can be iterated over + * is the same as the PreparedStatement should be set. + *

      + * * @author Lucas Ward * @author Dave Syer * @see ItemPreparedStatementSetter @@ -39,11 +41,11 @@ import java.util.Map; */ public class ColumnMapItemPreparedStatementSetter implements ItemPreparedStatementSetter> { - @Override + @Override public void setValues(Map item, PreparedStatement ps) throws SQLException { Assert.isInstanceOf(Map.class, item, "Input to map PreparedStatement parameters must be of type Map."); int counter = 1; - for(Object value : item.values()){ + for (Object value : item.values()) { StatementCreatorUtils.setParameterValue(ps, counter, SqlTypeValue.TYPE_UNKNOWN, value); counter++; } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/DataFieldMaxValueIncrementerFactory.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/DataFieldMaxValueIncrementerFactory.java index 764c4b70b..889930a3c 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/DataFieldMaxValueIncrementerFactory.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/DataFieldMaxValueIncrementerFactory.java @@ -18,9 +18,9 @@ package org.springframework.batch.item.database.support; import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer; /** - * Factory for creating {@link DataFieldMaxValueIncrementer} implementations - * based upon a provided string. - * + * Factory for creating {@link DataFieldMaxValueIncrementer} implementations based upon a + * provided string. + * * @author Lucas Ward * */ @@ -28,29 +28,28 @@ public interface DataFieldMaxValueIncrementerFactory { /** * Return the {@link DataFieldMaxValueIncrementer} for the provided database type. - * * @param databaseType string represented database type * @param incrementerName incrementer name to create. In many cases this may be the - * sequence name + * sequence name * @return incrementer - * @throws IllegalArgumentException if databaseType is invalid type, or incrementerName - * is null. + * @throws IllegalArgumentException if databaseType is invalid type, or + * incrementerName is null. */ public DataFieldMaxValueIncrementer getIncrementer(String databaseType, String incrementerName); - + /** * Returns boolean indicated whether or not the provided string is supported by this * factory. - * * @param databaseType {@link String} containing the database type. - * @return true if the incrementerType is supported by this database type. Else false is returned. + * @return true if the incrementerType is supported by this database type. Else false + * is returned. */ public boolean isSupportedIncrementerType(String databaseType); /** * Returns the list of supported database incrementer types - * - * @return an array of {@link String}s containing the supported incrementer types. + * @return an array of {@link String}s containing the supported incrementer types. */ public String[] getSupportedIncrementerTypes(); + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/Db2PagingQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/Db2PagingQueryProvider.java index 9da4484cb..f29f86819 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/Db2PagingQueryProvider.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/Db2PagingQueryProvider.java @@ -20,8 +20,7 @@ import org.springframework.batch.item.database.PagingQueryProvider; import org.springframework.util.StringUtils; /** - * DB2 implementation of a {@link PagingQueryProvider} using - * database specific features. + * DB2 implementation of a {@link PagingQueryProvider} using database specific features. * * @author Thomas Risberg * @author Michael Minella @@ -37,7 +36,7 @@ public class Db2PagingQueryProvider extends SqlWindowingPagingQueryProvider { @Override public String generateRemainingPagesQuery(int pageSize) { - if(StringUtils.hasText(getGroupClause())) { + if (StringUtils.hasText(getGroupClause())) { return SqlPagingQueryUtils.generateLimitGroupedSqlQuery(this, buildLimitClause(pageSize)); } else { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/DefaultDataFieldMaxValueIncrementerFactory.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/DefaultDataFieldMaxValueIncrementerFactory.java index a4e2e9459..c4df120af 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/DefaultDataFieldMaxValueIncrementerFactory.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/DefaultDataFieldMaxValueIncrementerFactory.java @@ -48,12 +48,12 @@ import static org.springframework.batch.support.DatabaseType.SQLSERVER; import static org.springframework.batch.support.DatabaseType.SYBASE; /** - * Default implementation of the {@link DataFieldMaxValueIncrementerFactory} - * interface. Valid database types are given by the {@link DatabaseType} enum. + * Default implementation of the {@link DataFieldMaxValueIncrementerFactory} interface. + * Valid database types are given by the {@link DatabaseType} enum. * * Note: For MySql databases, the * {@link MySQLMaxValueIncrementer#setUseNewConnection(boolean)} will be set to true. - * + * * @author Lucas Ward * @author Michael Minella * @author Drummond Dawson @@ -67,11 +67,10 @@ public class DefaultDataFieldMaxValueIncrementerFactory implements DataFieldMaxV private String incrementerColumnName = "ID"; /** - * Public setter for the column name (defaults to "ID") in the incrementer. - * Only used by some platforms (Derby, HSQL, MySQL, SQL Server and Sybase), - * and should be fine for use with Spring Batch meta data as long as the - * default batch schema hasn't been changed. - * + * Public setter for the column name (defaults to "ID") in the incrementer. Only used + * by some platforms (Derby, HSQL, MySQL, SQL Server and Sybase), and should be fine + * for use with Spring Batch meta data as long as the default batch schema hasn't been + * changed. * @param incrementerColumnName the primary key column name to set */ public void setIncrementerColumnName(String incrementerColumnName) { @@ -105,7 +104,8 @@ public class DefaultDataFieldMaxValueIncrementerFactory implements DataFieldMaxV return new HanaSequenceMaxValueIncrementer(dataSource, incrementerName); } else if (databaseType == MYSQL) { - MySQLMaxValueIncrementer mySQLMaxValueIncrementer = new MySQLMaxValueIncrementer(dataSource, incrementerName, incrementerColumnName); + MySQLMaxValueIncrementer mySQLMaxValueIncrementer = new MySQLMaxValueIncrementer(dataSource, + incrementerName, incrementerColumnName); mySQLMaxValueIncrementer.setUseNewConnection(true); return mySQLMaxValueIncrementer; } @@ -126,8 +126,8 @@ public class DefaultDataFieldMaxValueIncrementerFactory implements DataFieldMaxV } throw new IllegalArgumentException("databaseType argument was not on the approved list"); } - - @Override + + @Override public boolean isSupportedIncrementerType(String incrementerType) { for (DatabaseType type : DatabaseType.values()) { if (type.name().equalsIgnoreCase(incrementerType)) { @@ -138,7 +138,7 @@ public class DefaultDataFieldMaxValueIncrementerFactory implements DataFieldMaxV return false; } - @Override + @Override public String[] getSupportedIncrementerTypes() { List types = new ArrayList<>(); @@ -149,4 +149,5 @@ public class DefaultDataFieldMaxValueIncrementerFactory implements DataFieldMaxV return types.toArray(new String[types.size()]); } + } \ No newline at end of file diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/DerbyPagingQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/DerbyPagingQueryProvider.java index 75c61ba9c..ac6422191 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/DerbyPagingQueryProvider.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/DerbyPagingQueryProvider.java @@ -24,11 +24,11 @@ import org.springframework.dao.InvalidDataAccessResourceUsageException; import org.springframework.jdbc.support.JdbcUtils; /** - * Derby implementation of a {@link PagingQueryProvider} using standard SQL:2003 windowing functions. - * These features are supported starting with Apache Derby version 10.4.1.3. + * Derby implementation of a {@link PagingQueryProvider} using standard SQL:2003 windowing + * functions. These features are supported starting with Apache Derby version 10.4.1.3. * - * As the OVER() function does not support the ORDER BY clause a sub query is instead used to order the results - * before the ROW_NUM restriction is applied + * As the OVER() function does not support the ORDER BY clause a sub query is instead used + * to order the results before the ROW_NUM restriction is applied * * @author Thomas Risberg * @author David Thexton @@ -36,7 +36,7 @@ import org.springframework.jdbc.support.JdbcUtils; * @since 2.0 */ public class DerbyPagingQueryProvider extends SqlWindowingPagingQueryProvider { - + private static final String MINIMAL_DERBY_VERSION = "10.4.1.3"; @Override @@ -44,11 +44,14 @@ public class DerbyPagingQueryProvider extends SqlWindowingPagingQueryProvider { super.init(dataSource); String version = JdbcUtils.extractDatabaseMetaData(dataSource, DatabaseMetaData::getDatabaseProductVersion); if (!isDerbyVersionSupported(version)) { - throw new InvalidDataAccessResourceUsageException("Apache Derby version " + version + " is not supported by this class, Only version " + MINIMAL_DERBY_VERSION + " or later is supported"); + throw new InvalidDataAccessResourceUsageException( + "Apache Derby version " + version + " is not supported by this class, Only version " + + MINIMAL_DERBY_VERSION + " or later is supported"); } } - - // derby version numbering is M.m.f.p [ {alpha|beta} ] see https://db.apache.org/derby/papers/versionupgrade.html#Basic+Numbering+Scheme + + // derby version numbering is M.m.f.p [ {alpha|beta} ] see + // https://db.apache.org/derby/papers/versionupgrade.html#Basic+Numbering+Scheme private boolean isDerbyVersionSupported(String version) { String[] minimalVersionParts = MINIMAL_DERBY_VERSION.split("\\."); String[] versionParts = version.split("[\\. ]"); @@ -57,13 +60,14 @@ public class DerbyPagingQueryProvider extends SqlWindowingPagingQueryProvider { int versionPart = Integer.parseInt(versionParts[i]); if (versionPart < minimalVersionPart) { return false; - } else if (versionPart > minimalVersionPart) { + } + else if (versionPart > minimalVersionPart) { return true; } } - return true; + return true; } - + @Override protected String getOrderedQueryAlias() { return "TMP_ORDERED"; @@ -74,12 +78,12 @@ public class DerbyPagingQueryProvider extends SqlWindowingPagingQueryProvider { return ""; } - @Override + @Override protected String getOverSubstituteClauseStart() { return " FROM (SELECT " + getSelectClause(); } - @Override + @Override protected String getOverSubstituteClauseEnd() { return " ) AS " + getOrderedQueryAlias(); } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/H2PagingQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/H2PagingQueryProvider.java index c371d67b1..93d38fb25 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/H2PagingQueryProvider.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/H2PagingQueryProvider.java @@ -17,7 +17,9 @@ package org.springframework.batch.item.database.support; /** - * H2 implementation of a {@link org.springframework.batch.item.database.PagingQueryProvider} using database specific features. + * H2 implementation of a + * {@link org.springframework.batch.item.database.PagingQueryProvider} using database + * specific features. * * @author Dave Syer * @author Henning Pöttker @@ -43,10 +45,9 @@ public class H2PagingQueryProvider extends AbstractSqlPagingQueryProvider { public String generateJumpToItemQuery(int itemIndex, int pageSize) { int page = itemIndex / pageSize; int offset = (page * pageSize) - 1; - offset = offset<0 ? 0 : offset; + offset = offset < 0 ? 0 : offset; - String limitClause = new StringBuilder().append("OFFSET ") - .append(offset).append(" ROWS FETCH NEXT 1 ROWS ONLY") + String limitClause = new StringBuilder().append("OFFSET ").append(offset).append(" ROWS FETCH NEXT 1 ROWS ONLY") .toString(); return SqlPagingQueryUtils.generateLimitJumpToQuery(this, limitClause); } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/HanaPagingQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/HanaPagingQueryProvider.java index 98d7b5201..10c744082 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/HanaPagingQueryProvider.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/HanaPagingQueryProvider.java @@ -20,7 +20,8 @@ import org.springframework.batch.item.database.PagingQueryProvider; import org.springframework.util.StringUtils; /** - * SAP HANA implementation of a {@link PagingQueryProvider} using database specific features. + * SAP HANA implementation of a {@link PagingQueryProvider} using database specific + * features. * * @author Jonathan Bregler * @since 5.0 @@ -34,7 +35,7 @@ public class HanaPagingQueryProvider extends AbstractSqlPagingQueryProvider { @Override public String generateRemainingPagesQuery(int pageSize) { - if(StringUtils.hasText(getGroupClause())) { + if (StringUtils.hasText(getGroupClause())) { return SqlPagingQueryUtils.generateLimitGroupedSqlQuery(this, buildLimitClause(pageSize)); } else { @@ -50,7 +51,7 @@ public class HanaPagingQueryProvider extends AbstractSqlPagingQueryProvider { public String generateJumpToItemQuery(int itemIndex, int pageSize) { int page = itemIndex / pageSize; int offset = (page * pageSize) - 1; - offset = offset<0 ? 0 : offset; + offset = offset < 0 ? 0 : offset; String limitClause = new StringBuilder().append("LIMIT 1 OFFSET ").append(offset).toString(); return SqlPagingQueryUtils.generateLimitJumpToQuery(this, limitClause); } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/HsqlPagingQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/HsqlPagingQueryProvider.java index ee117e786..cc4304351 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/HsqlPagingQueryProvider.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/HsqlPagingQueryProvider.java @@ -19,7 +19,9 @@ package org.springframework.batch.item.database.support; import org.springframework.util.StringUtils; /** - * HSQLDB implementation of a {@link org.springframework.batch.item.database.PagingQueryProvider} using database specific features. + * HSQLDB implementation of a + * {@link org.springframework.batch.item.database.PagingQueryProvider} using database + * specific features. * * @author Thomas Risberg * @author Michael Minella @@ -34,7 +36,7 @@ public class HsqlPagingQueryProvider extends AbstractSqlPagingQueryProvider { @Override public String generateRemainingPagesQuery(int pageSize) { - if(StringUtils.hasText(getGroupClause())) { + if (StringUtils.hasText(getGroupClause())) { return SqlPagingQueryUtils.generateGroupedTopSqlQuery(this, true, buildTopClause(pageSize)); } else { @@ -50,7 +52,7 @@ public class HsqlPagingQueryProvider extends AbstractSqlPagingQueryProvider { public String generateJumpToItemQuery(int itemIndex, int pageSize) { int page = itemIndex / pageSize; int offset = (page * pageSize) - 1; - offset = offset<0 ? 0 : offset; + offset = offset < 0 ? 0 : offset; String topClause = new StringBuilder().append("LIMIT ").append(offset).append(" 1").toString(); return SqlPagingQueryUtils.generateTopJumpToQuery(this, topClause); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/MySqlPagingQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/MySqlPagingQueryProvider.java index a94728684..751302167 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/MySqlPagingQueryProvider.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/MySqlPagingQueryProvider.java @@ -36,7 +36,7 @@ public class MySqlPagingQueryProvider extends AbstractSqlPagingQueryProvider { @Override public String generateRemainingPagesQuery(int pageSize) { - if(StringUtils.hasText(getGroupClause())) { + if (StringUtils.hasText(getGroupClause())) { return SqlPagingQueryUtils.generateLimitGroupedSqlQuery(this, buildLimitClause(pageSize)); } else { @@ -52,7 +52,7 @@ public class MySqlPagingQueryProvider extends AbstractSqlPagingQueryProvider { public String generateJumpToItemQuery(int itemIndex, int pageSize) { int page = itemIndex / pageSize; int offset = (page * pageSize) - 1; - offset = offset<0 ? 0 : offset; + offset = offset < 0 ? 0 : offset; String limitClause = new StringBuilder().append("LIMIT ").append(offset).append(", 1").toString(); return SqlPagingQueryUtils.generateLimitJumpToQuery(this, limitClause); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/OraclePagingQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/OraclePagingQueryProvider.java index 9e2e90263..360baac51 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/OraclePagingQueryProvider.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/OraclePagingQueryProvider.java @@ -22,9 +22,9 @@ import org.springframework.batch.item.database.Order; /** * Oracle implementation of a - * {@link org.springframework.batch.item.database.PagingQueryProvider} using - * database specific features. - * + * {@link org.springframework.batch.item.database.PagingQueryProvider} using database + * specific features. + * * @author Thomas Risberg * @author Michael Minella * @since 2.0 @@ -47,20 +47,20 @@ public class OraclePagingQueryProvider extends AbstractSqlPagingQueryProvider { int offset = (page * pageSize); offset = offset == 0 ? 1 : offset; String sortKeySelect = this.getSortKeySelect(); - return SqlPagingQueryUtils.generateRowNumSqlQueryWithNesting(this, sortKeySelect, sortKeySelect, false, "TMP_ROW_NUM = " - + offset); + return SqlPagingQueryUtils.generateRowNumSqlQueryWithNesting(this, sortKeySelect, sortKeySelect, false, + "TMP_ROW_NUM = " + offset); } - + private String getSortKeySelect() { StringBuilder sql = new StringBuilder(); String prefix = ""; - + for (Map.Entry sortKey : this.getSortKeys().entrySet()) { sql.append(prefix); prefix = ", "; sql.append(sortKey.getKey()); } - + return sql.toString(); } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/PostgresPagingQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/PostgresPagingQueryProvider.java index 11932e9d3..5220cfc34 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/PostgresPagingQueryProvider.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/PostgresPagingQueryProvider.java @@ -19,10 +19,13 @@ package org.springframework.batch.item.database.support; import org.springframework.util.StringUtils; /** - * Postgres implementation of a {@link org.springframework.batch.item.database.PagingQueryProvider} using database specific features. - * - * When using the groupClause, this implementation expects all select fields not used in aggregate functions to be included in the - * groupClause (the provider does not add them for you). + * Postgres implementation of a + * {@link org.springframework.batch.item.database.PagingQueryProvider} using database + * specific features. + * + * When using the groupClause, this implementation expects all select fields not used in + * aggregate functions to be included in the groupClause (the provider does not add them + * for you). * * @author Thomas Risberg * @author Michael Minella @@ -38,7 +41,7 @@ public class PostgresPagingQueryProvider extends AbstractSqlPagingQueryProvider @Override public String generateRemainingPagesQuery(int pageSize) { - if(StringUtils.hasText(getGroupClause())) { + if (StringUtils.hasText(getGroupClause())) { return SqlPagingQueryUtils.generateLimitGroupedSqlQuery(this, buildLimitClause(pageSize)); } else { @@ -49,12 +52,12 @@ public class PostgresPagingQueryProvider extends AbstractSqlPagingQueryProvider private String buildLimitClause(int pageSize) { return new StringBuilder().append("LIMIT ").append(pageSize).toString(); } - + @Override public String generateJumpToItemQuery(int itemIndex, int pageSize) { int page = itemIndex / pageSize; int offset = (page * pageSize) - 1; - offset = offset<0 ? 0 : offset; + offset = offset < 0 ? 0 : offset; String limitClause = new StringBuilder().append("LIMIT 1 OFFSET ").append(offset).toString(); return SqlPagingQueryUtils.generateLimitJumpToQuery(this, limitClause); } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlPagingQueryProviderFactoryBean.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlPagingQueryProviderFactoryBean.java index b1100f6f4..3aae98615 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlPagingQueryProviderFactoryBean.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlPagingQueryProviderFactoryBean.java @@ -45,10 +45,10 @@ import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** - * Factory bean for {@link PagingQueryProvider} interface. The database type - * will be determined from the data source if not provided explicitly. Valid - * types are given by the {@link DatabaseType} enum. - * + * Factory bean for {@link PagingQueryProvider} interface. The database type will be + * determined from the data source if not provided explicitly. Valid types are given by + * the {@link DatabaseType} enum. + * * @author Dave Syer * @author Michael Minella */ @@ -63,31 +63,30 @@ public class SqlPagingQueryProviderFactoryBean implements FactoryBean sortKeys; private Map providers = new HashMap<>(); - { providers.put(DB2, new Db2PagingQueryProvider()); providers.put(DB2VSE, new Db2PagingQueryProvider()); providers.put(DB2ZOS, new Db2PagingQueryProvider()); providers.put(DB2AS400, new Db2PagingQueryProvider()); - providers.put(DERBY,new DerbyPagingQueryProvider()); - providers.put(HSQL,new HsqlPagingQueryProvider()); - providers.put(H2,new H2PagingQueryProvider()); - providers.put(HANA,new HanaPagingQueryProvider()); - providers.put(MYSQL,new MySqlPagingQueryProvider()); - providers.put(ORACLE,new OraclePagingQueryProvider()); - providers.put(POSTGRES,new PostgresPagingQueryProvider()); + providers.put(DERBY, new DerbyPagingQueryProvider()); + providers.put(HSQL, new HsqlPagingQueryProvider()); + providers.put(H2, new H2PagingQueryProvider()); + providers.put(HANA, new HanaPagingQueryProvider()); + providers.put(MYSQL, new MySqlPagingQueryProvider()); + providers.put(ORACLE, new OraclePagingQueryProvider()); + providers.put(POSTGRES, new PostgresPagingQueryProvider()); providers.put(SQLITE, new SqlitePagingQueryProvider()); - providers.put(SQLSERVER,new SqlServerPagingQueryProvider()); - providers.put(SYBASE,new SybasePagingQueryProvider()); + providers.put(SQLSERVER, new SqlServerPagingQueryProvider()); + providers.put(SYBASE, new SybasePagingQueryProvider()); } - + /** * @param groupClause SQL GROUP BY clause part of the SQL query string */ @@ -136,29 +135,29 @@ public class SqlPagingQueryProviderFactoryBean implements FactoryBean sortKeys) { this.sortKeys = sortKeys; } - + public void setSortKey(String key) { Assert.doesNotContain(key, ",", "String setter is valid for a single ASC key only"); - + Map keys = new LinkedHashMap<>(); keys.put(key, Order.ASCENDING); - + this.sortKeys = keys; } /** - * Get a {@link PagingQueryProvider} instance using the provided properties - * and appropriate for the given database type. - * + * Get a {@link PagingQueryProvider} instance using the provided properties and + * appropriate for the given database type. + * * @see FactoryBean#getObject() */ - @Override + @Override public PagingQueryProvider getObject() throws Exception { DatabaseType type; try { - type = databaseType != null ? DatabaseType.valueOf(databaseType.toUpperCase()) : DatabaseType - .fromMetaData(dataSource); + type = databaseType != null ? DatabaseType.valueOf(databaseType.toUpperCase()) + : DatabaseType.fromMetaData(dataSource); } catch (MetaDataAccessException e) { throw new IllegalArgumentException( @@ -166,7 +165,7 @@ public class SqlPagingQueryProviderFactoryBean implements FactoryBean sortKeys) { StringBuilder builder = new StringBuilder(); String prefix = ""; - + for (Map.Entry sortKey : sortKeys.entrySet()) { builder.append(prefix); - + prefix = ", "; - + builder.append(sortKey.getKey()); - - if(sortKey.getValue() != null && sortKey.getValue() == Order.DESCENDING) { + + if (sortKey.getValue() != null && sortKey.getValue() == Order.DESCENDING) { builder.append(" DESC"); } else { builder.append(" ASC"); } } - + return builder.toString(); } /** * Appends the where conditions required to query for the subsequent pages. - * * @param provider the {@link AbstractSqlPagingQueryProvider} to be used for * pagination. - * @param sql {@link StringBuilder} containing the sql to be used for the - * query. + * @param sql {@link StringBuilder} containing the sql to be used for the query. */ - public static void buildSortConditions( - AbstractSqlPagingQueryProvider provider, StringBuilder sql) { + public static void buildSortConditions(AbstractSqlPagingQueryProvider provider, StringBuilder sql) { List> keys = new ArrayList<>(provider.getSortKeys().entrySet()); List clauses = new ArrayList<>(); - - for(int i = 0; i < keys.size(); i++) { + + for (int i = 0; i < keys.size(); i++) { StringBuilder clause = new StringBuilder(); - + String prefix = ""; - for(int j = 0; j < i; j++) { + for (int j = 0; j < i; j++) { clause.append(prefix); prefix = " AND "; Entry entry = keys.get(j); @@ -333,13 +321,13 @@ public class SqlPagingQueryUtils { clause.append(" = "); clause.append(provider.getSortKeyPlaceHolder(entry.getKey())); } - - if(clause.length() > 0) { + + if (clause.length() > 0) { clause.append(" AND "); } clause.append(keys.get(i).getKey()); - - if(keys.get(i).getValue() != null && keys.get(i).getValue() == Order.DESCENDING) { + + if (keys.get(i).getValue() != null && keys.get(i).getValue() == Order.DESCENDING) { clause.append(" < "); } else { @@ -347,13 +335,13 @@ public class SqlPagingQueryUtils { } clause.append(provider.getSortKeyPlaceHolder(keys.get(i).getKey())); - + clauses.add(clause.toString()); } - + sql.append("("); String prefix = ""; - + for (String curClause : clauses) { sql.append(prefix); prefix = " OR "; @@ -366,17 +354,17 @@ public class SqlPagingQueryUtils { private static String buildSortKeySelect(AbstractSqlPagingQueryProvider provider) { StringBuilder select = new StringBuilder(); - + String prefix = ""; - + for (Map.Entry sortKey : provider.getSortKeys().entrySet()) { select.append(prefix); - + prefix = ", "; - + select.append(sortKey.getKey()); } - + return select.toString(); } @@ -396,9 +384,9 @@ public class SqlPagingQueryUtils { sql.append(provider.getWhereClause() == null ? "" : " WHERE " + provider.getWhereClause()); } } - + private static void buildGroupByClause(AbstractSqlPagingQueryProvider provider, StringBuilder sql) { - if(StringUtils.hasText(provider.getGroupClause())) { + if (StringUtils.hasText(provider.getGroupClause())) { sql.append(" GROUP BY "); sql.append(provider.getGroupClause()); } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlServerPagingQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlServerPagingQueryProvider.java index 5913f2652..59332cf27 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlServerPagingQueryProvider.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlServerPagingQueryProvider.java @@ -20,9 +20,9 @@ import org.springframework.util.StringUtils; /** * SQL Server implementation of a - * {@link org.springframework.batch.item.database.PagingQueryProvider} using - * database specific features. - * + * {@link org.springframework.batch.item.database.PagingQueryProvider} using database + * specific features. + * * @author Thomas Risberg * @author Michael Minella * @since 2.0 @@ -36,7 +36,7 @@ public class SqlServerPagingQueryProvider extends SqlWindowingPagingQueryProvide @Override public String generateRemainingPagesQuery(int pageSize) { - if(StringUtils.hasText(getGroupClause())) { + if (StringUtils.hasText(getGroupClause())) { return SqlPagingQueryUtils.generateGroupedTopSqlQuery(this, true, buildTopClause(pageSize)); } else { @@ -52,4 +52,5 @@ public class SqlServerPagingQueryProvider extends SqlWindowingPagingQueryProvide private String buildTopClause(int pageSize) { return new StringBuilder().append("TOP ").append(pageSize).toString(); } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlServerSequenceMaxValueIncrementer.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlServerSequenceMaxValueIncrementer.java index 9bf20815d..7679b0436 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlServerSequenceMaxValueIncrementer.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlServerSequenceMaxValueIncrementer.java @@ -27,12 +27,13 @@ import org.springframework.jdbc.support.incrementer.AbstractSequenceMaxValueIncr */ public class SqlServerSequenceMaxValueIncrementer extends AbstractSequenceMaxValueIncrementer { - public SqlServerSequenceMaxValueIncrementer(DataSource dataSource, String incrementerName) { - super(dataSource, incrementerName); - } + public SqlServerSequenceMaxValueIncrementer(DataSource dataSource, String incrementerName) { + super(dataSource, incrementerName); + } + + @Override + protected String getSequenceQuery() { + return "select next value for " + getIncrementerName(); + } - @Override - protected String getSequenceQuery() { - return "select next value for " + getIncrementerName(); - } } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlWindowingPagingQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlWindowingPagingQueryProvider.java index 56e5dc549..3d17a3584 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlWindowingPagingQueryProvider.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlWindowingPagingQueryProvider.java @@ -23,10 +23,10 @@ import org.springframework.batch.item.database.Order; import org.springframework.util.StringUtils; /** - * Generic Paging Query Provider using standard SQL:2003 windowing functions. - * These features are supported by DB2, Oracle, SQL Server 2005, Sybase and - * Apache Derby version 10.4.1.3 - * + * Generic Paging Query Provider using standard SQL:2003 windowing functions. These + * features are supported by DB2, Oracle, SQL Server 2005, Sybase and Apache Derby version + * 10.4.1.3 + * * @author Thomas Risberg * @author Michael Minella * @since 2.0 @@ -37,18 +37,19 @@ public class SqlWindowingPagingQueryProvider extends AbstractSqlPagingQueryProvi public String generateFirstPageQuery(int pageSize) { StringBuilder sql = new StringBuilder(); sql.append("SELECT * FROM ( "); - sql.append("SELECT ").append(StringUtils.hasText(getOrderedQueryAlias()) ? getOrderedQueryAlias() + ".*, " : "*, "); + sql.append("SELECT ") + .append(StringUtils.hasText(getOrderedQueryAlias()) ? getOrderedQueryAlias() + ".*, " : "*, "); sql.append("ROW_NUMBER() OVER (").append(getOverClause()); sql.append(") AS ROW_NUMBER"); sql.append(getOverSubstituteClauseStart()); - sql.append(" FROM ").append(getFromClause()).append( - getWhereClause() == null ? "" : " WHERE " + getWhereClause()); + sql.append(" FROM ").append(getFromClause()) + .append(getWhereClause() == null ? "" : " WHERE " + getWhereClause()); sql.append(getGroupClause() == null ? "" : " GROUP BY " + getGroupClause()); sql.append(getOverSubstituteClauseEnd()); - sql.append(") ").append(getSubQueryAlias()).append("WHERE ").append(extractTableAlias()).append( - "ROW_NUMBER <= ").append(pageSize); + sql.append(") ").append(getSubQueryAlias()).append("WHERE ").append(extractTableAlias()) + .append("ROW_NUMBER <= ").append(pageSize); sql.append(" ORDER BY ").append(SqlPagingQueryUtils.buildSortClause(this)); - + return sql.toString(); } @@ -72,7 +73,8 @@ public class SqlWindowingPagingQueryProvider extends AbstractSqlPagingQueryProvi public String generateRemainingPagesQuery(int pageSize) { StringBuilder sql = new StringBuilder(); sql.append("SELECT * FROM ( "); - sql.append("SELECT ").append(StringUtils.hasText(getOrderedQueryAlias()) ? getOrderedQueryAlias() + ".*, " : "*, "); + sql.append("SELECT ") + .append(StringUtils.hasText(getOrderedQueryAlias()) ? getOrderedQueryAlias() + ".*, " : "*, "); sql.append("ROW_NUMBER() OVER (").append(getOverClause()); sql.append(") AS ROW_NUMBER"); sql.append(getOverSubstituteClauseStart()); @@ -81,11 +83,11 @@ public class SqlWindowingPagingQueryProvider extends AbstractSqlPagingQueryProvi sql.append(" WHERE "); sql.append(getWhereClause()); } - + sql.append(getGroupClause() == null ? "" : " GROUP BY " + getGroupClause()); sql.append(getOverSubstituteClauseEnd()); - sql.append(") ").append(getSubQueryAlias()).append("WHERE ").append(extractTableAlias()).append( - "ROW_NUMBER <= ").append(pageSize); + sql.append(") ").append(getSubQueryAlias()).append("WHERE ").append(extractTableAlias()) + .append("ROW_NUMBER <= ").append(pageSize); sql.append(" AND "); SqlPagingQueryUtils.buildSortConditions(this, sql); sql.append(" ORDER BY ").append(SqlPagingQueryUtils.buildSortClause(this)); @@ -114,8 +116,8 @@ public class SqlWindowingPagingQueryProvider extends AbstractSqlPagingQueryProvi sql.append(getWhereClause() == null ? "" : " WHERE " + getWhereClause()); sql.append(getGroupClause() == null ? "" : " GROUP BY " + getGroupClause()); sql.append(getOverSubstituteClauseEnd()); - sql.append(") ").append(getSubQueryAlias()).append("WHERE ").append(extractTableAlias()).append( - "ROW_NUMBER = ").append(lastRowNum); + sql.append(") ").append(getSubQueryAlias()).append("WHERE ").append(extractTableAlias()).append("ROW_NUMBER = ") + .append(lastRowNum); sql.append(" ORDER BY ").append(SqlPagingQueryUtils.buildSortClause(getSortKeysReplaced(extractTableAlias()))); return sql.toString(); @@ -129,11 +131,11 @@ public class SqlWindowingPagingQueryProvider extends AbstractSqlPagingQueryProvi } return sortKeys; } - + private void buildSortKeySelect(StringBuilder sql) { buildSortKeySelect(sql, null); } - + private void buildSortKeySelect(StringBuilder sql, Map sortKeys) { String prefix = ""; if (sortKeys == null) { @@ -148,9 +150,9 @@ public class SqlWindowingPagingQueryProvider extends AbstractSqlPagingQueryProvi protected String getOverClause() { StringBuilder sql = new StringBuilder(); - + sql.append(" ORDER BY ").append(buildSortClause(this)); - + return sql.toString(); } @@ -162,10 +164,8 @@ public class SqlWindowingPagingQueryProvider extends AbstractSqlPagingQueryProvi return ""; } - /** * Generates ORDER BY attributes based on the sort keys. - * * @param provider * @return a String that can be appended to an ORDER BY clause. */ diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqliteMaxValueIncrementer.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqliteMaxValueIncrementer.java index 5e00046f6..bc0b3ea22 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqliteMaxValueIncrementer.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqliteMaxValueIncrementer.java @@ -40,8 +40,12 @@ class SqliteMaxValueIncrementer extends AbstractColumnMaxValueIncrementer { super(dataSource, incrementerName, columnName); } - /* (non-Javadoc) - * @see org.springframework.jdbc.support.incrementer.AbstractDataFieldMaxValueIncrementer#getNextKey() + /* + * (non-Javadoc) + * + * @see + * org.springframework.jdbc.support.incrementer.AbstractDataFieldMaxValueIncrementer# + * getNextKey() */ @Override protected long getNextKey() { @@ -67,4 +71,5 @@ class SqliteMaxValueIncrementer extends AbstractColumnMaxValueIncrementer { DataSourceUtils.releaseConnection(con, getDataSource()); } } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlitePagingQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlitePagingQueryProvider.java index 3d0e534f8..f36938886 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlitePagingQueryProvider.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SqlitePagingQueryProvider.java @@ -19,28 +19,38 @@ package org.springframework.batch.item.database.support; import org.springframework.util.StringUtils; /** - * SQLite implementation of a {@link org.springframework.batch.item.database.PagingQueryProvider} using database specific - * features. + * SQLite implementation of a + * {@link org.springframework.batch.item.database.PagingQueryProvider} using database + * specific features. * * @author Luke Taylor * @author Mahmoud Ben Hassine * @since 3.0.0 */ public class SqlitePagingQueryProvider extends AbstractSqlPagingQueryProvider { - /* (non-Javadoc) - * @see org.springframework.batch.item.database.support.AbstractSqlPagingQueryProvider#generateFirstPageQuery(int) + + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.item.database.support.AbstractSqlPagingQueryProvider# + * generateFirstPageQuery(int) */ @Override public String generateFirstPageQuery(int pageSize) { return SqlPagingQueryUtils.generateLimitSqlQuery(this, false, buildLimitClause(pageSize)); } - /* (non-Javadoc) - * @see org.springframework.batch.item.database.support.AbstractSqlPagingQueryProvider#generateRemainingPagesQuery(int) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.item.database.support.AbstractSqlPagingQueryProvider# + * generateRemainingPagesQuery(int) */ @Override public String generateRemainingPagesQuery(int pageSize) { - if(StringUtils.hasText(getGroupClause())) { + if (StringUtils.hasText(getGroupClause())) { return SqlPagingQueryUtils.generateLimitGroupedSqlQuery(this, buildLimitClause(pageSize)); } else { @@ -48,14 +58,18 @@ public class SqlitePagingQueryProvider extends AbstractSqlPagingQueryProvider { } } - /* (non-Javadoc) - * @see org.springframework.batch.item.database.support.AbstractSqlPagingQueryProvider#generateJumpToItemQuery(int, int) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.item.database.support.AbstractSqlPagingQueryProvider# + * generateJumpToItemQuery(int, int) */ @Override public String generateJumpToItemQuery(int itemIndex, int pageSize) { int page = itemIndex / pageSize; int offset = (page * pageSize) - 1; - offset = offset<0 ? 0 : offset; + offset = offset < 0 ? 0 : offset; String limitClause = new StringBuilder().append("LIMIT ").append(offset).append(", 1").toString(); return SqlPagingQueryUtils.generateLimitJumpToQuery(this, limitClause); @@ -64,5 +78,5 @@ public class SqlitePagingQueryProvider extends AbstractSqlPagingQueryProvider { private String buildLimitClause(int pageSize) { return new StringBuilder().append("LIMIT ").append(pageSize).toString(); } -} +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SybasePagingQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SybasePagingQueryProvider.java index 88e00e9a3..d91e1f44c 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SybasePagingQueryProvider.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/SybasePagingQueryProvider.java @@ -20,8 +20,8 @@ import org.springframework.batch.item.database.PagingQueryProvider; import org.springframework.util.StringUtils; /** - * Sybase implementation of a {@link PagingQueryProvider} using - * database specific features. + * Sybase implementation of a {@link PagingQueryProvider} using database specific + * features. * * @author Thomas Risberg * @author Michael Minella @@ -36,7 +36,7 @@ public class SybasePagingQueryProvider extends SqlWindowingPagingQueryProvider { @Override public String generateRemainingPagesQuery(int pageSize) { - if(StringUtils.hasText(getGroupClause())) { + if (StringUtils.hasText(getGroupClause())) { return SqlPagingQueryUtils.generateGroupedTopSqlQuery(this, true, buildTopClause(pageSize)); } else { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/BufferedReaderFactory.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/BufferedReaderFactory.java index f8d3aef95..8c9d7ce15 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/BufferedReaderFactory.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/BufferedReaderFactory.java @@ -24,23 +24,20 @@ import org.springframework.core.io.Resource; /** * A factory strategy for custom extensions of {@link BufferedReader} allowing * customisation of the standard behaviour of the java.io variety. - * + * * @author Dave Syer - * * @since 2.1 */ public interface BufferedReaderFactory { /** - * Create a {@link BufferedReader} for reading String items from the - * provided resource. - * + * Create a {@link BufferedReader} for reading String items from the provided + * resource. * @param resource a {@link Resource} containing the data to be read - * @param encoding the encoding required for converting binary data to - * String + * @param encoding the encoding required for converting binary data to String * @return a {@link BufferedReader} - * @throws UnsupportedEncodingException if the encoding is not supported by - * the platform + * @throws UnsupportedEncodingException if the encoding is not supported by the + * platform * @throws IOException if there is a problem creating the reader */ BufferedReader create(Resource resource, String encoding) throws UnsupportedEncodingException, IOException; diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/DefaultBufferedReaderFactory.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/DefaultBufferedReaderFactory.java index ad63a099e..44854bd06 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/DefaultBufferedReaderFactory.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/DefaultBufferedReaderFactory.java @@ -24,14 +24,13 @@ import org.springframework.core.io.Resource; /** * @author Dave Syer - * * @since 2.1 */ public class DefaultBufferedReaderFactory implements BufferedReaderFactory { - @Override + @Override public BufferedReader create(Resource resource, String encoding) throws UnsupportedEncodingException, IOException { return new BufferedReader(new InputStreamReader(resource.getInputStream(), encoding)); } - + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FlatFileFooterCallback.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FlatFileFooterCallback.java index e0694c44e..6a54a655b 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FlatFileFooterCallback.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FlatFileFooterCallback.java @@ -21,18 +21,17 @@ import java.io.IOException; /** * Callback interface for writing a footer to a file. - * + * * @author Robert Kasanicky */ public interface FlatFileFooterCallback { /** - * Write contents to a file using the supplied {@link Writer}. It is not - * required to flush the writer inside this method. - * + * Write contents to a file using the supplied {@link Writer}. It is not required to + * flush the writer inside this method. * @param writer the {@link Writer} to be used to write the footer. - * * @throws IOException if error occurs during writing. */ void writeFooter(Writer writer) throws IOException; + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FlatFileHeaderCallback.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FlatFileHeaderCallback.java index 941b6a4d8..36fa1755c 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FlatFileHeaderCallback.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FlatFileHeaderCallback.java @@ -21,19 +21,18 @@ import java.io.IOException; /** * Callback interface for writing a header to a file. - * + * * @author Robert Kasanicky * @author Mahmoud Ben Hassine */ public interface FlatFileHeaderCallback { /** - * Write contents to a file using the supplied {@link Writer}. It is not - * required to flush the writer inside this method. - * + * Write contents to a file using the supplied {@link Writer}. It is not required to + * flush the writer inside this method. * @param writer the {@link Writer} to be used to write the header. - * * @throws IOException if error occurs during writing. */ void writeHeader(Writer writer) throws IOException; + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FlatFileItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FlatFileItemReader.java index 1b1eca32b..34545fc57 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FlatFileItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FlatFileItemReader.java @@ -36,16 +36,18 @@ import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; /** - * Restartable {@link ItemReader} that reads lines from input {@link #setResource(Resource)}. Line is defined by the - * {@link #setRecordSeparatorPolicy(RecordSeparatorPolicy)} and mapped to item using {@link #setLineMapper(LineMapper)}. - * If an exception is thrown during line mapping it is rethrown as {@link FlatFileParseException} adding information - * about the problematic line and its line number. - * + * Restartable {@link ItemReader} that reads lines from input + * {@link #setResource(Resource)}. Line is defined by the + * {@link #setRecordSeparatorPolicy(RecordSeparatorPolicy)} and mapped to item using + * {@link #setLineMapper(LineMapper)}. If an exception is thrown during line mapping it is + * rethrown as {@link FlatFileParseException} adding information about the problematic + * line and its line number. + * * @author Robert Kasanicky * @author Mahmoud Ben Hassine */ -public class FlatFileItemReader extends AbstractItemCountingItemStreamItemReader implements - ResourceAwareItemReaderItemStream, InitializingBean { +public class FlatFileItemReader extends AbstractItemCountingItemStreamItemReader + implements ResourceAwareItemReaderItemStream, InitializingBean { private static final Log logger = LogFactory.getLog(FlatFileItemReader.class); @@ -83,7 +85,8 @@ public class FlatFileItemReader extends AbstractItemCountingItemStreamItemRea /** * In strict mode the reader will throw an exception on - * {@link #open(org.springframework.batch.item.ExecutionContext)} if the input resource does not exist. + * {@link #open(org.springframework.batch.item.ExecutionContext)} if the input + * resource does not exist. * @param strict true by default */ public void setStrict(boolean strict) { @@ -91,16 +94,17 @@ public class FlatFileItemReader extends AbstractItemCountingItemStreamItemRea } /** - * @param skippedLinesCallback will be called for each one of the initial skipped lines before any items are read. + * @param skippedLinesCallback will be called for each one of the initial skipped + * lines before any items are read. */ public void setSkippedLinesCallback(LineCallbackHandler skippedLinesCallback) { this.skippedLinesCallback = skippedLinesCallback; } /** - * Public setter for the number of lines to skip at the start of a file. Can be used if the file contains a header - * without useful (column name) information, and without a comment delimiter at the beginning of the lines. - * + * Public setter for the number of lines to skip at the start of a file. Can be used + * if the file contains a header without useful (column name) information, and without + * a comment delimiter at the beginning of the lines. * @param linesToSkip the number of lines to skip */ public void setLinesToSkip(int linesToSkip) { @@ -116,19 +120,19 @@ public class FlatFileItemReader extends AbstractItemCountingItemStreamItemRea } /** - * Setter for the encoding for this input source. Default value is {@link #DEFAULT_CHARSET}. - * - * @param encoding a properties object which possibly contains the encoding for this input file; + * Setter for the encoding for this input source. Default value is + * {@link #DEFAULT_CHARSET}. + * @param encoding a properties object which possibly contains the encoding for this + * input file; */ public void setEncoding(String encoding) { this.encoding = encoding; } /** - * Factory for the {@link BufferedReader} that will be used to extract lines from the file. The default is fine for - * plain text files, but this is a useful strategy for binary files where the standard BufferedReader from java.io - * is limiting. - * + * Factory for the {@link BufferedReader} that will be used to extract lines from the + * file. The default is fine for plain text files, but this is a useful strategy for + * binary files where the standard BufferedReader from java.io is limiting. * @param bufferedReaderFactory the bufferedReaderFactory to set */ public void setBufferedReaderFactory(BufferedReaderFactory bufferedReaderFactory) { @@ -136,9 +140,9 @@ public class FlatFileItemReader extends AbstractItemCountingItemStreamItemRea } /** - * Setter for comment prefixes. Can be used to ignore header lines as well by using e.g. the first couple of column - * names as a prefix. Defaults to {@link #DEFAULT_COMMENT_PREFIXES}. - * + * Setter for comment prefixes. Can be used to ignore header lines as well by using + * e.g. the first couple of column names as a prefix. Defaults to + * {@link #DEFAULT_COMMENT_PREFIXES}. * @param comments an array of comment line prefixes. */ public void setComments(String[] comments) { @@ -149,15 +153,15 @@ public class FlatFileItemReader extends AbstractItemCountingItemStreamItemRea /** * Public setter for the input resource. */ - @Override + @Override public void setResource(Resource resource) { this.resource = resource; } /** - * Public setter for the recordSeparatorPolicy. Used to determine where the line endings are and do things like - * continue over a line ending if inside a quoted string. - * + * Public setter for the recordSeparatorPolicy. Used to determine where the line + * endings are and do things like continue over a line ending if inside a quoted + * string. * @param recordSeparatorPolicy the recordSeparatorPolicy to set */ public void setRecordSeparatorPolicy(RecordSeparatorPolicy recordSeparatorPolicy) { @@ -166,7 +170,8 @@ public class FlatFileItemReader extends AbstractItemCountingItemStreamItemRea /** * @return string corresponding to logical record according to - * {@link #setRecordSeparatorPolicy(RecordSeparatorPolicy)} (might span multiple lines in file). + * {@link #setRecordSeparatorPolicy(RecordSeparatorPolicy)} (might span multiple lines + * in file). */ @Nullable @Override @@ -262,8 +267,8 @@ public class FlatFileItemReader extends AbstractItemCountingItemStreamItemRea if (!resource.isReadable()) { if (strict) { - throw new IllegalStateException("Input resource must be readable (reader is in 'strict' mode): " - + resource); + throw new IllegalStateException( + "Input resource must be readable (reader is in 'strict' mode): " + resource); } logger.warn("Input resource is not readable " + resource.getDescription()); return; @@ -279,7 +284,7 @@ public class FlatFileItemReader extends AbstractItemCountingItemStreamItemRea noInput = false; } - @Override + @Override public void afterPropertiesSet() throws Exception { Assert.notNull(lineMapper, "LineMapper is required"); } @@ -300,7 +305,8 @@ public class FlatFileItemReader extends AbstractItemCountingItemStreamItemRea if (StringUtils.hasText(record)) { // A record was partially complete since it hasn't ended but // the line is null - throw new FlatFileParseException("Unexpected end of file before record complete", record, lineCount); + throw new FlatFileParseException("Unexpected end of file before record complete", record, + lineCount); } else { // Record has no text but it might still be post processed diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FlatFileItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FlatFileItemWriter.java index 244390842..2202d52af 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FlatFileItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FlatFileItemWriter.java @@ -25,14 +25,14 @@ import org.springframework.util.Assert; import org.springframework.util.ClassUtils; /** - * This class is an item writer that writes data to a file or stream. The writer - * also provides restart. The location of the output file is defined by a - * {@link Resource} and must represent a writable file.
      - * + * This class is an item writer that writes data to a file or stream. The writer also + * provides restart. The location of the output file is defined by a {@link Resource} and + * must represent a writable file.
      + * * Uses buffered writer to improve performance.
      - * + * * The implementation is not thread-safe. - * + * * @author Waseem Malik * @author Tomas Slanina * @author Robert Kasanicky @@ -50,7 +50,7 @@ public class FlatFileItemWriter extends AbstractFileItemWriter { /** * Assert that mandatory properties (lineAggregator) are set. - * + * * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() */ @Override @@ -62,9 +62,8 @@ public class FlatFileItemWriter extends AbstractFileItemWriter { } /** - * Public setter for the {@link LineAggregator}. This will be used to - * translate the item into a line for output. - * + * Public setter for the {@link LineAggregator}. This will be used to translate the + * item into a line for output. * @param lineAggregator the {@link LineAggregator} to set */ public void setLineAggregator(LineAggregator lineAggregator) { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FlatFileParseException.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FlatFileParseException.java index f3b2f65d3..7e7eb720d 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FlatFileParseException.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FlatFileParseException.java @@ -18,11 +18,9 @@ package org.springframework.batch.item.file; import org.springframework.batch.item.ParseException; /** - * Exception thrown when errors are encountered - * parsing flat files. The original input, typically - * a line, can be passed in, so that latter catches - * can write out the original input to a log, or - * an error table. + * Exception thrown when errors are encountered parsing flat files. The original input, + * typically a line, can be passed in, so that latter catches can write out the original + * input to a log, or an error table. * * @author Lucas Ward * @author Ben Hale @@ -31,7 +29,7 @@ import org.springframework.batch.item.ParseException; public class FlatFileParseException extends ParseException { private String input; - + private int lineNumber; public FlatFileParseException(String message, String input) { @@ -57,5 +55,6 @@ public class FlatFileParseException extends ParseException { public int getLineNumber() { return lineNumber; - } + } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/LineCallbackHandler.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/LineCallbackHandler.java index f6f6a5170..a323a188d 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/LineCallbackHandler.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/LineCallbackHandler.java @@ -17,12 +17,12 @@ package org.springframework.batch.item.file; /** - * Callback interface for handling a line from file. Useful e.g. for header - * processing. - * + * Callback interface for handling a line from file. Useful e.g. for header processing. + * * @author Robert Kasanicky */ public interface LineCallbackHandler { void handleLine(String line); + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/LineMapper.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/LineMapper.java index ddf0efe3f..748f798d7 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/LineMapper.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/LineMapper.java @@ -19,13 +19,12 @@ package org.springframework.batch.item.file; import org.springframework.batch.item.file.mapping.FieldSetMapper; import org.springframework.batch.item.file.transform.LineTokenizer; - /** - * Interface for mapping lines (strings) to domain objects typically used to map lines read from a file to domain objects - * on a per line basis. Implementations of this interface perform the actual - * work of parsing a line without having to deal with how the line was - * obtained. - * + * Interface for mapping lines (strings) to domain objects typically used to map lines + * read from a file to domain objects on a per line basis. Implementations of this + * interface perform the actual work of parsing a line without having to deal with how the + * line was obtained. + * * @author Robert Kasanicky * @param type of the domain object * @see FieldSetMapper @@ -35,14 +34,14 @@ import org.springframework.batch.item.file.transform.LineTokenizer; public interface LineMapper { /** - * Implementations must implement this method to map the provided line to - * the parameter type T. The line number represents the number of lines - * into a file the current line resides. - * + * Implementations must implement this method to map the provided line to the + * parameter type T. The line number represents the number of lines into a file the + * current line resides. * @param line to be mapped * @param lineNumber of the current line * @return mapped object of type T * @throws Exception if error occurred while parsing. */ T mapLine(String line, int lineNumber) throws Exception; + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/MultiResourceItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/MultiResourceItemReader.java index f8870fe85..913d1e80e 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/MultiResourceItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/MultiResourceItemReader.java @@ -34,13 +34,13 @@ import org.springframework.util.Assert; import org.springframework.util.ClassUtils; /** - * Reads items from multiple resources sequentially - resource list is given by {@link #setResources(Resource[])}, the - * actual reading is delegated to {@link #setDelegate(ResourceAwareItemReaderItemStream)}. - * - * Input resources are ordered using {@link #setComparator(Comparator)} to make sure resource ordering is preserved - * between job runs in restart scenario. - * - * + * Reads items from multiple resources sequentially - resource list is given by + * {@link #setResources(Resource[])}, the actual reading is delegated to + * {@link #setDelegate(ResourceAwareItemReaderItemStream)}. + * + * Input resources are ordered using {@link #setComparator(Comparator)} to make sure + * resource ordering is preserved between job runs in restart scenario. + * * @author Robert Kasanicky * @author Lucas Ward * @author Mahmoud Ben Hassine @@ -66,7 +66,8 @@ public class MultiResourceItemReader extends AbstractItemStreamItemReader /** * In strict mode the reader will throw an exception on - * {@link #open(org.springframework.batch.item.ExecutionContext)} if there are no resources to read. + * {@link #open(org.springframework.batch.item.ExecutionContext)} if there are no + * resources to read. * @param strict false by default */ public void setStrict(boolean strict) { @@ -112,9 +113,8 @@ public class MultiResourceItemReader extends AbstractItemStreamItemReader } /** - * Use the delegate to read the next item, jump to next resource if current one is exhausted. Items are appended to - * the buffer. - * + * Use the delegate to read the next item, jump to next resource if current one is + * exhausted. Items are appended to the buffer. * @return next item from input */ private T readNextItem() throws Exception { @@ -141,20 +141,21 @@ public class MultiResourceItemReader extends AbstractItemStreamItemReader private T readFromDelegate() throws Exception { T item = delegate.read(); - if(item instanceof ResourceAware){ + if (item instanceof ResourceAware) { ((ResourceAware) item).setResource(resources[currentResource]); } return item; } /** - * Close the {@link #setDelegate(ResourceAwareItemReaderItemStream)} reader and reset instance variable values. + * Close the {@link #setDelegate(ResourceAwareItemReaderItemStream)} reader and reset + * instance variable values. */ @Override public void close() throws ItemStreamException { super.close(); - if(!this.noInput) { + if (!this.noInput) { delegate.close(); } @@ -162,8 +163,8 @@ public class MultiResourceItemReader extends AbstractItemStreamItemReader } /** - * Figure out which resource to start with in case of restart, open the delegate and restore delegate's position in - * the resource. + * Figure out which resource to start with in case of restart, open the delegate and + * restore delegate's position in the resource. */ @Override public void open(ExecutionContext executionContext) throws ItemStreamException { @@ -221,9 +222,8 @@ public class MultiResourceItemReader extends AbstractItemStreamItemReader } /** - * Set the boolean indicating whether or not state should be saved in the provided {@link ExecutionContext} during - * the {@link ItemStream} call to update. - * + * Set the boolean indicating whether or not state should be saved in the provided + * {@link ExecutionContext} during the {@link ItemStream} call to update. * @param saveState true to update ExecutionContext. False do not update * ExecutionContext. */ @@ -232,8 +232,8 @@ public class MultiResourceItemReader extends AbstractItemStreamItemReader } /** - * @param comparator used to order the injected resources, by default compares {@link Resource#getFilename()} - * values. + * @param comparator used to order the injected resources, by default compares + * {@link Resource#getFilename()} values. */ public void setComparator(Comparator comparator) { this.comparator = comparator; diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/MultiResourceItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/MultiResourceItemWriter.java index 0c32631a5..776dd217b 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/MultiResourceItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/MultiResourceItemWriter.java @@ -28,17 +28,16 @@ import org.springframework.util.Assert; import org.springframework.util.ClassUtils; /** - * Wraps a {@link ResourceAwareItemWriterItemStream} and creates a new output - * resource when the count of items written in current resource exceeds - * {@link #setItemCountLimitPerResource(int)}. Suffix creation can be customized - * with {@link #setResourceSuffixCreator(ResourceSuffixCreator)}. - * - * Note that new resources are created only at chunk boundaries i.e. the number - * of items written into one resource is between the limit set by + * Wraps a {@link ResourceAwareItemWriterItemStream} and creates a new output resource + * when the count of items written in current resource exceeds + * {@link #setItemCountLimitPerResource(int)}. Suffix creation can be customized with + * {@link #setResourceSuffixCreator(ResourceSuffixCreator)}. + * + * Note that new resources are created only at chunk boundaries i.e. the number of items + * written into one resource is between the limit set by * {@link #setItemCountLimitPerResource(int)} and (limit + chunk size). - * + * * @param item type - * * @author Robert Kasanicky */ public class MultiResourceItemWriter extends AbstractItemStreamItemWriter { @@ -67,7 +66,7 @@ public class MultiResourceItemWriter extends AbstractItemStreamItemWriter this.setExecutionContextName(ClassUtils.getShortName(MultiResourceItemWriter.class)); } - @Override + @Override public void write(List items) throws Exception { if (!opened) { File file = setResourceToDelegate(); @@ -89,9 +88,7 @@ public class MultiResourceItemWriter extends AbstractItemStreamItemWriter } /** - * Allows customization of the suffix of the created resources based on the - * index. - * + * Allows customization of the suffix of the created resources based on the index. * @param suffixCreator {@link ResourceSuffixCreator} to be used by the writer. */ public void setResourceSuffixCreator(ResourceSuffixCreator suffixCreator) { @@ -99,9 +96,8 @@ public class MultiResourceItemWriter extends AbstractItemStreamItemWriter } /** - * After this limit is exceeded the next chunk will be written into newly - * created resource. - * + * After this limit is exceeded the next chunk will be written into newly created + * resource. * @param itemCountLimitPerResource int item threshold used to determine when a new * resource should be created. */ @@ -111,37 +107,32 @@ public class MultiResourceItemWriter extends AbstractItemStreamItemWriter /** * Delegate used for actual writing of the output. - * - * @param delegate {@link ResourceAwareItemWriterItemStream} that will be used - * to write the output. + * @param delegate {@link ResourceAwareItemWriterItemStream} that will be used to + * write the output. */ public void setDelegate(ResourceAwareItemWriterItemStream delegate) { this.delegate = delegate; } /** - * Prototype for output resources. Actual output files will be created in - * the same directory and use the same name as this prototype with appended - * suffix (according to - * {@link #setResourceSuffixCreator(ResourceSuffixCreator)}. - * + * Prototype for output resources. Actual output files will be created in the same + * directory and use the same name as this prototype with appended suffix (according + * to {@link #setResourceSuffixCreator(ResourceSuffixCreator)}. * @param resource The prototype resource. */ public void setResource(Resource resource) { this.resource = resource; } - /** * Indicates that the state of the reader will be saved after each commit. - * * @param saveState true the state is saved. */ public void setSaveState(boolean saveState) { this.saveState = saveState; } - @Override + @Override public void close() throws ItemStreamException { super.close(); resourceIndex = 1; @@ -151,7 +142,7 @@ public class MultiResourceItemWriter extends AbstractItemStreamItemWriter } } - @Override + @Override public void open(ExecutionContext executionContext) throws ItemStreamException { super.open(executionContext); resourceIndex = executionContext.getInt(getExecutionContextKey(RESOURCE_INDEX_KEY), 1); @@ -174,7 +165,7 @@ public class MultiResourceItemWriter extends AbstractItemStreamItemWriter } } - @Override + @Override public void update(ExecutionContext executionContext) throws ItemStreamException { super.update(executionContext); if (saveState) { @@ -195,4 +186,5 @@ public class MultiResourceItemWriter extends AbstractItemStreamItemWriter delegate.setResource(new FileSystemResource(file)); return file; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/NonTransientFlatFileException.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/NonTransientFlatFileException.java index 9aa5b074b..8a98ab53d 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/NonTransientFlatFileException.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/NonTransientFlatFileException.java @@ -19,7 +19,7 @@ import org.springframework.batch.item.NonTransientResourceException; /** * Exception thrown when errors are encountered with the underlying resource. - * + * * @author Dave Syer */ @SuppressWarnings("serial") @@ -53,4 +53,5 @@ public class NonTransientFlatFileException extends NonTransientResourceException public int getLineNumber() { return lineNumber; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/ResourceAwareItemReaderItemStream.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/ResourceAwareItemReaderItemStream.java index 3a4261ad6..4b7747fd8 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/ResourceAwareItemReaderItemStream.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/ResourceAwareItemReaderItemStream.java @@ -22,12 +22,13 @@ import org.springframework.batch.item.ItemStreamReader; import org.springframework.core.io.Resource; /** - * Interface for {@link ItemReader}s that implement {@link ItemStream} and read - * input from {@link Resource}. - * + * Interface for {@link ItemReader}s that implement {@link ItemStream} and read input from + * {@link Resource}. + * * @author Robert Kasanicky */ public interface ResourceAwareItemReaderItemStream extends ItemStreamReader { void setResource(Resource resource); + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/ResourceAwareItemWriterItemStream.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/ResourceAwareItemWriterItemStream.java index e8592ce90..2ff301cfb 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/ResourceAwareItemWriterItemStream.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/ResourceAwareItemWriterItemStream.java @@ -22,12 +22,13 @@ import org.springframework.batch.item.ItemWriter; import org.springframework.core.io.WritableResource; /** - * Interface for {@link ItemWriter}s that implement {@link ItemStream} and write - * output to {@link WritableResource}. - * + * Interface for {@link ItemWriter}s that implement {@link ItemStream} and write output to + * {@link WritableResource}. + * * @author Robert Kasanicky */ public interface ResourceAwareItemWriterItemStream extends ItemStreamWriter { void setResource(WritableResource resource); + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/ResourceSuffixCreator.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/ResourceSuffixCreator.java index d9581bf09..1952e0c3a 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/ResourceSuffixCreator.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/ResourceSuffixCreator.java @@ -17,15 +17,14 @@ package org.springframework.batch.item.file; /** - * Strategy interface for translating resource index into unique filename - * suffix. + * Strategy interface for translating resource index into unique filename suffix. * * @see MultiResourceItemWriter - * @see SimpleResourceSuffixCreator - * + * @see SimpleResourceSuffixCreator * @author Robert Kasanicky */ public interface ResourceSuffixCreator { String getSuffix(int index); + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/ResourcesItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/ResourcesItemReader.java index 372c8b90b..d101ecf77 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/ResourcesItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/ResourcesItemReader.java @@ -1,99 +1,96 @@ -/* - * Copyright 2009-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.file; - -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.ItemStreamException; -import org.springframework.batch.item.support.AbstractItemStreamItemReader; -import org.springframework.core.io.Resource; -import org.springframework.core.io.support.ResourceArrayPropertyEditor; -import org.springframework.lang.Nullable; - -import java.util.Arrays; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * {@link ItemReader} which produces {@link Resource} instances from an array. - * This can be used conveniently with a configuration entry that injects a - * pattern (e.g. mydir/*.txt, which can then be converted by Spring - * to an array of Resources by the ApplicationContext. - * - *
      - *
      - * - * Thread-safe between calls to {@link #open(ExecutionContext)}. The - * {@link ExecutionContext} is not accurate in a multi-threaded environment, so - * do not rely on that data for restart (i.e. always open with a fresh context). - * - * @author Dave Syer - * @author Mahmoud Ben Hassine - * - * @see ResourceArrayPropertyEditor - * - * @since 2.1 - */ -public class ResourcesItemReader extends AbstractItemStreamItemReader { - - private static final String COUNT_KEY = "COUNT"; - - private Resource[] resources = new Resource[0]; - - private AtomicInteger counter = new AtomicInteger(0); - - public ResourcesItemReader() { - /* - * Initialize the name for the key in the execution context. - */ - this.setExecutionContextName(getClass().getName()); - } - - /** - * The resources to serve up as items. Hint: use a pattern to configure. - * - * @param resources the resources - */ - public void setResources(Resource[] resources) { - this.resources = Arrays.asList(resources).toArray(new Resource[resources.length]); - } - - /** - * Increments a counter and returns the next {@link Resource} instance from - * the input, or {@code null} if none remain. - */ - @Override - @Nullable - public synchronized Resource read() throws Exception { - int index = counter.incrementAndGet() - 1; - if (index >= resources.length) { - return null; - } - return resources[index]; - } - - @Override - public void open(ExecutionContext executionContext) throws ItemStreamException { - super.open(executionContext); - counter.set(executionContext.getInt(getExecutionContextKey(COUNT_KEY), 0)); - } - - @Override - public void update(ExecutionContext executionContext) throws ItemStreamException { - super.update(executionContext); - executionContext.putInt(getExecutionContextKey(COUNT_KEY), counter.get()); - } - -} +/* + * Copyright 2009-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item.file; + +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemStreamException; +import org.springframework.batch.item.support.AbstractItemStreamItemReader; +import org.springframework.core.io.Resource; +import org.springframework.core.io.support.ResourceArrayPropertyEditor; +import org.springframework.lang.Nullable; + +import java.util.Arrays; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * {@link ItemReader} which produces {@link Resource} instances from an array. This can be + * used conveniently with a configuration entry that injects a pattern (e.g. + * mydir/*.txt, which can then be converted by Spring to an array of + * Resources by the ApplicationContext. + * + *
      + *
      + * + * Thread-safe between calls to {@link #open(ExecutionContext)}. The + * {@link ExecutionContext} is not accurate in a multi-threaded environment, so do not + * rely on that data for restart (i.e. always open with a fresh context). + * + * @author Dave Syer + * @author Mahmoud Ben Hassine + * @see ResourceArrayPropertyEditor + * @since 2.1 + */ +public class ResourcesItemReader extends AbstractItemStreamItemReader { + + private static final String COUNT_KEY = "COUNT"; + + private Resource[] resources = new Resource[0]; + + private AtomicInteger counter = new AtomicInteger(0); + + public ResourcesItemReader() { + /* + * Initialize the name for the key in the execution context. + */ + this.setExecutionContextName(getClass().getName()); + } + + /** + * The resources to serve up as items. Hint: use a pattern to configure. + * @param resources the resources + */ + public void setResources(Resource[] resources) { + this.resources = Arrays.asList(resources).toArray(new Resource[resources.length]); + } + + /** + * Increments a counter and returns the next {@link Resource} instance from the input, + * or {@code null} if none remain. + */ + @Override + @Nullable + public synchronized Resource read() throws Exception { + int index = counter.incrementAndGet() - 1; + if (index >= resources.length) { + return null; + } + return resources[index]; + } + + @Override + public void open(ExecutionContext executionContext) throws ItemStreamException { + super.open(executionContext); + counter.set(executionContext.getInt(getExecutionContextKey(COUNT_KEY), 0)); + } + + @Override + public void update(ExecutionContext executionContext) throws ItemStreamException { + super.update(executionContext); + executionContext.putInt(getExecutionContextKey(COUNT_KEY), counter.get()); + } + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/SimpleBinaryBufferedReaderFactory.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/SimpleBinaryBufferedReaderFactory.java index b6a747368..4ccbd2b2d 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/SimpleBinaryBufferedReaderFactory.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/SimpleBinaryBufferedReaderFactory.java @@ -24,14 +24,13 @@ import java.io.UnsupportedEncodingException; import org.springframework.core.io.Resource; /** - * A {@link BufferedReaderFactory} useful for reading simple binary (or text) - * files with no line endings, such as those produced by mainframe copy books. - * The reader splits a stream up across fixed line endings (rather than the - * usual convention based on plain text). The line endings are discarded, just - * as with the default plain text implementation. - * + * A {@link BufferedReaderFactory} useful for reading simple binary (or text) files with + * no line endings, such as those produced by mainframe copy books. The reader splits a + * stream up across fixed line endings (rather than the usual convention based on plain + * text). The line endings are discarded, just as with the default plain text + * implementation. + * * @author Dave Syer - * * @since 2.1 */ public class SimpleBinaryBufferedReaderFactory implements BufferedReaderFactory { @@ -50,17 +49,17 @@ public class SimpleBinaryBufferedReaderFactory implements BufferedReaderFactory this.lineEnding = lineEnding; } - @Override + @Override public BufferedReader create(Resource resource, String encoding) throws UnsupportedEncodingException, IOException { return new BinaryBufferedReader(new InputStreamReader(resource.getInputStream(), encoding), lineEnding); } /** - * BufferedReader extension that splits lines based on a line ending, rather - * than the usual plain text conventions. - * + * BufferedReader extension that splits lines based on a line ending, rather than the + * usual plain text conventions. + * * @author Dave Syer - * + * */ private final class BinaryBufferedReader extends BufferedReader { @@ -105,7 +104,6 @@ public class SimpleBinaryBufferedReaderFactory implements BufferedReaderFactory /** * Check for end of line and accumulate a buffer for next time. - * * @param buffer the current line excluding the candidate ending * @param candidate a buffer containing accumulated state * @param next the next character (or -1 for end of file) @@ -139,6 +137,7 @@ public class SimpleBinaryBufferedReaderFactory implements BufferedReaderFactory return end; } + } } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/SimpleResourceSuffixCreator.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/SimpleResourceSuffixCreator.java index 74641814f..d53277c02 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/SimpleResourceSuffixCreator.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/SimpleResourceSuffixCreator.java @@ -17,14 +17,14 @@ package org.springframework.batch.item.file; /** - * Trivial implementation of {@link ResourceSuffixCreator} that uses the index - * itself as suffix, separated by dot. - * + * Trivial implementation of {@link ResourceSuffixCreator} that uses the index itself as + * suffix, separated by dot. + * * @author Robert Kasanicky */ public class SimpleResourceSuffixCreator implements ResourceSuffixCreator { - @Override + @Override public String getSuffix(int index) { return "." + index; } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/builder/FlatFileItemReaderBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/builder/FlatFileItemReaderBuilder.java index d3222779b..ec9d4b180 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/builder/FlatFileItemReaderBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/builder/FlatFileItemReaderBuilder.java @@ -68,16 +68,13 @@ public class FlatFileItemReaderBuilder { private String encoding = FlatFileItemReader.DEFAULT_CHARSET; - private RecordSeparatorPolicy recordSeparatorPolicy = - new SimpleRecordSeparatorPolicy(); + private RecordSeparatorPolicy recordSeparatorPolicy = new SimpleRecordSeparatorPolicy(); - private BufferedReaderFactory bufferedReaderFactory = - new DefaultBufferedReaderFactory(); + private BufferedReaderFactory bufferedReaderFactory = new DefaultBufferedReaderFactory(); private Resource resource; - private List comments = - new ArrayList<>(Arrays.asList(FlatFileItemReader.DEFAULT_COMMENT_PREFIXES)); + private List comments = new ArrayList<>(Arrays.asList(FlatFileItemReader.DEFAULT_COMMENT_PREFIXES)); private int linesToSkip = 0; @@ -116,10 +113,9 @@ public class FlatFileItemReaderBuilder { private int currentItemCount; /** - * Configure if the state of the {@link org.springframework.batch.item.ItemStreamSupport} - * should be persisted within the {@link org.springframework.batch.item.ExecutionContext} - * for restart purposes. - * + * Configure if the state of the + * {@link org.springframework.batch.item.ItemStreamSupport} should be persisted within + * the {@link org.springframework.batch.item.ExecutionContext} for restart purposes. * @param saveState defaults to true * @return The current instance of the builder. */ @@ -133,7 +129,6 @@ public class FlatFileItemReaderBuilder { * The name used to calculate the key within the * {@link org.springframework.batch.item.ExecutionContext}. Required if * {@link #saveState(boolean)} is set to true. - * * @param name name of the reader instance * @return The current instance of the builder. * @see org.springframework.batch.item.ItemStreamSupport#setName(String) @@ -146,7 +141,6 @@ public class FlatFileItemReaderBuilder { /** * Configure the max number of items to be read. - * * @param maxItemCount the max items to be read * @return The current instance of the builder. * @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setMaxItemCount(int) @@ -159,7 +153,6 @@ public class FlatFileItemReaderBuilder { /** * Index for the current item. Used on restarts to indicate where to start from. - * * @param currentItemCount current index * @return this instance for method chaining * @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setCurrentItemCount(int) @@ -171,9 +164,8 @@ public class FlatFileItemReaderBuilder { } /** - * Add a string to the list of Strings that indicate commented lines. - * Defaults to {@link FlatFileItemReader#DEFAULT_COMMENT_PREFIXES}. - * + * Add a string to the list of Strings that indicate commented lines. Defaults to + * {@link FlatFileItemReader#DEFAULT_COMMENT_PREFIXES}. * @param comment the string to define a commented line. * @return The current instance of the builder. * @see FlatFileItemReader#setComments(String[]) @@ -184,10 +176,9 @@ public class FlatFileItemReaderBuilder { } /** - * Set an array of Strings that indicate lines that are comments (and therefore skipped by - * the reader). This method overrides the default comment prefixes which are - * {@link FlatFileItemReader#DEFAULT_COMMENT_PREFIXES}. - * + * Set an array of Strings that indicate lines that are comments (and therefore + * skipped by the reader). This method overrides the default comment prefixes which + * are {@link FlatFileItemReader#DEFAULT_COMMENT_PREFIXES}. * @param comments an array of strings to identify comments. * @return The current instance of the builder. * @see FlatFileItemReader#setComments(String[]) @@ -199,7 +190,6 @@ public class FlatFileItemReaderBuilder { /** * Configure a custom {@link RecordSeparatorPolicy} for the reader. - * * @param policy custom policy * @return The current instance of the builder. * @see FlatFileItemReader#setRecordSeparatorPolicy(RecordSeparatorPolicy) @@ -211,7 +201,6 @@ public class FlatFileItemReaderBuilder { /** * Configure a custom {@link BufferedReaderFactory} for the reader. - * * @param factory custom factory * @return The current instance of the builder. * @see FlatFileItemReader#setBufferedReaderFactory(BufferedReaderFactory) @@ -221,10 +210,8 @@ public class FlatFileItemReaderBuilder { return this; } - /** * The {@link Resource} to be used as input. - * * @param resource the input to the reader. * @return The current instance of the builder. * @see FlatFileItemReader#setResource(Resource) @@ -235,9 +222,8 @@ public class FlatFileItemReaderBuilder { } /** - * Configure if the reader should be in strict mode (require the input {@link Resource} - * to exist). - * + * Configure if the reader should be in strict mode (require the input + * {@link Resource} to exist). * @param strict true if the input file is required to exist. * @return The current instance of the builder. * @see FlatFileItemReader#setStrict(boolean) @@ -248,9 +234,8 @@ public class FlatFileItemReaderBuilder { } /** - * Configure the encoding used by the reader to read the input source. - * Default value is {@link FlatFileItemReader#DEFAULT_CHARSET}. - * + * Configure the encoding used by the reader to read the input source. Default value + * is {@link FlatFileItemReader#DEFAULT_CHARSET}. * @param encoding to use to read the input source. * @return The current instance of the builder. * @see FlatFileItemReader#setEncoding(String) @@ -262,7 +247,6 @@ public class FlatFileItemReaderBuilder { /** * The number of lines to skip at the beginning of reading the file. - * * @param linesToSkip number of lines to be skipped. * @return The current instance of the builder. * @see FlatFileItemReader#setLinesToSkip(int) @@ -274,7 +258,6 @@ public class FlatFileItemReaderBuilder { /** * A callback to be called for each line that is skipped. - * * @param callback the callback * @return The current instance of the builder. * @see FlatFileItemReader#setSkippedLinesCallback(LineCallbackHandler) @@ -286,7 +269,6 @@ public class FlatFileItemReaderBuilder { /** * A {@link LineMapper} implementation to be used. - * * @param lineMapper {@link LineMapper} * @return The current instance of the builder. * @see FlatFileItemReader#setLineMapper(LineMapper) @@ -298,7 +280,6 @@ public class FlatFileItemReaderBuilder { /** * A {@link FieldSetMapper} implementation to be used. - * * @param mapper a {@link FieldSetMapper} * @return The current instance of the builder. * @see DefaultLineMapper#setFieldSetMapper(FieldSetMapper) @@ -310,7 +291,6 @@ public class FlatFileItemReaderBuilder { /** * A {@link LineTokenizer} implementation to be used. - * * @param tokenizer a {@link LineTokenizer} * @return The current instance of the builder. * @see DefaultLineMapper#setLineTokenizer(LineTokenizer) @@ -324,10 +304,9 @@ public class FlatFileItemReaderBuilder { /** * Returns an instance of a {@link DelimitedBuilder} for building a - * {@link DelimitedLineTokenizer}. The {@link DelimitedLineTokenizer} configured by + * {@link DelimitedLineTokenizer}. The {@link DelimitedLineTokenizer} configured by * this builder will only be used if one is not explicitly configured via * {@link FlatFileItemReaderBuilder#lineTokenizer} - * * @return a {@link DelimitedBuilder} * */ @@ -339,10 +318,9 @@ public class FlatFileItemReaderBuilder { /** * Returns an instance of a {@link FixedLengthBuilder} for building a - * {@link FixedLengthTokenizer}. The {@link FixedLengthTokenizer} configured by this + * {@link FixedLengthTokenizer}. The {@link FixedLengthTokenizer} configured by this * builder will only be used if the {@link FlatFileItemReaderBuilder#lineTokenizer} * has not been configured. - * * @return a {@link FixedLengthBuilder} */ public FixedLengthBuilder fixedLength() { @@ -352,11 +330,10 @@ public class FlatFileItemReaderBuilder { } /** - * The class that will represent the "item" to be returned from the reader. This - * class is used via the {@link BeanWrapperFieldSetMapper}. If more complex logic is + * The class that will represent the "item" to be returned from the reader. This class + * is used via the {@link BeanWrapperFieldSetMapper}. If more complex logic is * required, providing your own {@link FieldSetMapper} via * {@link FlatFileItemReaderBuilder#fieldSetMapper} is required. - * * @param targetType The class to map to * @return The current instance of the builder. * @see BeanWrapperFieldSetMapper#setTargetType(Class) @@ -369,7 +346,6 @@ public class FlatFileItemReaderBuilder { /** * Configures the id of a prototype scoped bean to be used as the item returned by the * reader. - * * @param prototypeBeanName the name of a prototype scoped bean * @return The current instance of the builder. * @see BeanWrapperFieldSetMapper#setPrototypeBeanName(String) @@ -382,7 +358,6 @@ public class FlatFileItemReaderBuilder { /** * Configures the {@link BeanFactory} used to create the beans that are returned as * items. - * * @param beanFactory a {@link BeanFactory} * @return The current instance of the builder. * @see BeanWrapperFieldSetMapper#setBeanFactory(BeanFactory) @@ -394,13 +369,12 @@ public class FlatFileItemReaderBuilder { /** * Register custom type converters for beans being mapped. - * * @param customEditors a {@link Map} of editors * @return The current instance of the builder. * @see BeanWrapperFieldSetMapper#setCustomEditors(Map) */ public FlatFileItemReaderBuilder customEditors(Map, PropertyEditor> customEditors) { - if(customEditors != null) { + if (customEditors != null) { this.customEditors.putAll(customEditors); } @@ -410,7 +384,6 @@ public class FlatFileItemReaderBuilder { /** * Configures the maximum tolerance between the actual spelling of a field's name and * the property's name. - * * @param distanceLimit distance limit to set * @return The current instance of the builder. * @see BeanWrapperFieldSetMapper#setDistanceLimit(int) @@ -421,9 +394,9 @@ public class FlatFileItemReaderBuilder { } /** - * If set to true, mapping will fail if the {@link org.springframework.batch.item.file.transform.FieldSet} - * contains fields that cannot be mapped to the bean. - * + * If set to true, mapping will fail if the + * {@link org.springframework.batch.item.file.transform.FieldSet} contains fields that + * cannot be mapped to the bean. * @param beanMapperStrict defaults to false * @return The current instance of the builder. * @see BeanWrapperFieldSetMapper#setStrict(boolean) @@ -435,18 +408,16 @@ public class FlatFileItemReaderBuilder { /** * Builds the {@link FlatFileItemReader}. - * * @return a {@link FlatFileItemReader} */ public FlatFileItemReader build() { - if(this.saveState) { - Assert.state(StringUtils.hasText(this.name), - "A name is required when saveState is set to true."); + if (this.saveState) { + Assert.state(StringUtils.hasText(this.name), "A name is required when saveState is set to true."); } - if(this.resource == null) { - logger.debug("The resource is null. This is only a valid scenario when " + - "injecting it later as in when using the MultiResourceItemReader"); + if (this.resource == null) { + logger.debug("The resource is null. This is only a valid scenario when " + + "injecting it later as in when using the MultiResourceItemReader"); } Assert.notNull(this.recordSeparatorPolicy, "A RecordSeparatorPolicy is required."); @@ -455,17 +426,17 @@ public class FlatFileItemReaderBuilder { FlatFileItemReader reader = new FlatFileItemReader<>(); - if(StringUtils.hasText(this.name)) { + if (StringUtils.hasText(this.name)) { reader.setName(this.name); } - if(StringUtils.hasText(this.encoding)) { + if (StringUtils.hasText(this.encoding)) { reader.setEncoding(this.encoding); } reader.setResource(this.resource); - if(this.lineMapper != null) { + if (this.lineMapper != null) { reader.setLineMapper(this.lineMapper); } else { @@ -474,20 +445,20 @@ public class FlatFileItemReaderBuilder { DefaultLineMapper lineMapper = new DefaultLineMapper<>(); - if(this.lineTokenizer != null) { + if (this.lineTokenizer != null) { lineMapper.setLineTokenizer(this.lineTokenizer); } - else if(this.fixedLengthBuilder != null) { + else if (this.fixedLengthBuilder != null) { lineMapper.setLineTokenizer(this.fixedLengthBuilder.build()); } - else if(this.delimitedBuilder != null) { + else if (this.delimitedBuilder != null) { lineMapper.setLineTokenizer(this.delimitedBuilder.build()); } else { throw new IllegalStateException("No LineTokenizer implementation was provided."); } - if(this.targetType != null || StringUtils.hasText(this.prototypeBeanName)) { + if (this.targetType != null || StringUtils.hasText(this.prototypeBeanName)) { BeanWrapperFieldSetMapper mapper = new BeanWrapperFieldSetMapper<>(); mapper.setTargetType(this.targetType); mapper.setPrototypeBeanName(this.prototypeBeanName); @@ -504,7 +475,7 @@ public class FlatFileItemReaderBuilder { lineMapper.setFieldSetMapper(mapper); } - else if(this.fieldSetMapper != null) { + else if (this.fieldSetMapper != null) { lineMapper.setFieldSetMapper(this.fieldSetMapper); } else { @@ -529,7 +500,7 @@ public class FlatFileItemReaderBuilder { } private void updateTokenizerValidation(Object tokenizer, int index) { - if(tokenizer != null) { + if (tokenizer != null) { this.tokenizerValidator = this.tokenizerValidator.flipBit(index); } else { @@ -543,6 +514,7 @@ public class FlatFileItemReaderBuilder { * @param the type of the parent {@link FlatFileItemReaderBuilder} */ public static class DelimitedBuilder { + private FlatFileItemReaderBuilder parent; private List names = new ArrayList<>(); @@ -563,7 +535,6 @@ public class FlatFileItemReaderBuilder { /** * Define the delimiter for the file. - * * @param delimiter String used as a delimiter between fields. * @return The instance of the builder for chaining. * @see DelimitedLineTokenizer#setDelimiter(String) @@ -575,7 +546,6 @@ public class FlatFileItemReaderBuilder { /** * Define the character used to quote fields. - * * @param quoteCharacter char used to define quoted fields * @return The instance of the builder for chaining. * @see DelimitedLineTokenizer#setQuoteCharacter(char) @@ -587,7 +557,6 @@ public class FlatFileItemReaderBuilder { /** * A list of indices of the fields within a delimited file to be included - * * @param fields indices of the fields * @return The instance of the builder for chaining. * @see DelimitedLineTokenizer#setIncludedFields(int[]) @@ -599,7 +568,6 @@ public class FlatFileItemReaderBuilder { /** * Add an index to the list of fields to be included from the file - * * @param field the index to be included * @return The instance of the builder for chaining. * @see DelimitedLineTokenizer#setIncludedFields(int[]) @@ -611,10 +579,10 @@ public class FlatFileItemReaderBuilder { /** * A factory for creating the resulting - * {@link org.springframework.batch.item.file.transform.FieldSet}. Defaults to + * {@link org.springframework.batch.item.file.transform.FieldSet}. Defaults to * {@link DefaultFieldSetFactory}. - * - * @param fieldSetFactory Factory for creating {@link org.springframework.batch.item.file.transform.FieldSet} + * @param fieldSetFactory Factory for creating + * {@link org.springframework.batch.item.file.transform.FieldSet} * @return The instance of the builder for chaining. * @see DelimitedLineTokenizer#setFieldSetFactory(FieldSetFactory) */ @@ -625,8 +593,7 @@ public class FlatFileItemReaderBuilder { /** * Names of each of the fields within the fields that are returned in the order - * they occur within the delimited file. Required. - * + * they occur within the delimited file. Required. * @param names names of each field * @return The parent {@link FlatFileItemReaderBuilder} * @see DelimitedLineTokenizer#setNames(String[]) @@ -638,7 +605,6 @@ public class FlatFileItemReaderBuilder { /** * Returns a {@link DelimitedLineTokenizer} - * * @return {@link DelimitedLineTokenizer} */ public DelimitedLineTokenizer build() { @@ -649,22 +615,22 @@ public class FlatFileItemReaderBuilder { tokenizer.setNames(this.names.toArray(new String[this.names.size()])); - if(StringUtils.hasLength(this.delimiter)) { + if (StringUtils.hasLength(this.delimiter)) { tokenizer.setDelimiter(this.delimiter); } - if(this.quoteCharacter != null) { + if (this.quoteCharacter != null) { tokenizer.setQuoteCharacter(this.quoteCharacter); } - if(!this.includedFields.isEmpty()) { + if (!this.includedFields.isEmpty()) { Set deDupedFields = new HashSet<>(this.includedFields.size()); deDupedFields.addAll(this.includedFields); deDupedFields.remove(null); - int [] fields = new int[deDupedFields.size()]; + int[] fields = new int[deDupedFields.size()]; Iterator iterator = deDupedFields.iterator(); - for(int i = 0; i < fields.length; i++) { + for (int i = 0; i < fields.length; i++) { fields[i] = iterator.next(); } @@ -683,6 +649,7 @@ public class FlatFileItemReaderBuilder { return tokenizer; } + } /** @@ -691,6 +658,7 @@ public class FlatFileItemReaderBuilder { * @param the type of the parent {@link FlatFileItemReaderBuilder} */ public static class FixedLengthBuilder { + private FlatFileItemReaderBuilder parent; private List ranges = new ArrayList<>(); @@ -707,7 +675,6 @@ public class FlatFileItemReaderBuilder { /** * The column ranges for each field - * * @param ranges column ranges * @return This instance for chaining * @see FixedLengthTokenizer#setColumns(Range[]) @@ -719,7 +686,6 @@ public class FlatFileItemReaderBuilder { /** * Add a column range to the existing list - * * @param range a new column range * @return This instance for chaining * @see FixedLengthTokenizer#setColumns(Range[]) @@ -731,7 +697,6 @@ public class FlatFileItemReaderBuilder { /** * Insert a column range to the existing list - * * @param range a new column range * @param index index to add it at * @return This instance for chaining @@ -743,8 +708,7 @@ public class FlatFileItemReaderBuilder { } /** - * The names of the fields to be parsed from the file. Required. - * + * The names of the fields to be parsed from the file. Required. * @param names names of fields * @return The parent builder * @see FixedLengthTokenizer#setNames(String[]) @@ -756,8 +720,7 @@ public class FlatFileItemReaderBuilder { /** * Boolean indicating if the number of tokens in a line must match the number of - * fields (ranges) configured. Defaults to true. - * + * fields (ranges) configured. Defaults to true. * @param strict defaults to true * @return This instance for chaining * @see FixedLengthTokenizer#setStrict(boolean) @@ -769,9 +732,10 @@ public class FlatFileItemReaderBuilder { /** * A factory for creating the resulting - * {@link org.springframework.batch.item.file.transform.FieldSet}. Defaults to + * {@link org.springframework.batch.item.file.transform.FieldSet}. Defaults to * {@link DefaultFieldSetFactory}. - * @param fieldSetFactory Factory for creating {@link org.springframework.batch.item.file.transform.FieldSet} + * @param fieldSetFactory Factory for creating + * {@link org.springframework.batch.item.file.transform.FieldSet} * @return The instance of the builder for chaining. * @see FixedLengthTokenizer#setFieldSetFactory(FieldSetFactory) */ @@ -782,7 +746,6 @@ public class FlatFileItemReaderBuilder { /** * Returns a {@link FixedLengthTokenizer} - * * @return a {@link FixedLengthTokenizer} */ public FixedLengthTokenizer build() { @@ -799,5 +762,7 @@ public class FlatFileItemReaderBuilder { return tokenizer; } + } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/builder/FlatFileItemWriterBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/builder/FlatFileItemWriterBuilder.java index 6dc0b0cbd..428936840 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/builder/FlatFileItemWriterBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/builder/FlatFileItemWriterBuilder.java @@ -79,10 +79,9 @@ public class FlatFileItemWriterBuilder { private FormattedBuilder formattedBuilder; /** - * Configure if the state of the {@link org.springframework.batch.item.ItemStreamSupport} - * should be persisted within the {@link org.springframework.batch.item.ExecutionContext} - * for restart purposes. - * + * Configure if the state of the + * {@link org.springframework.batch.item.ItemStreamSupport} should be persisted within + * the {@link org.springframework.batch.item.ExecutionContext} for restart purposes. * @param saveState defaults to true * @return The current instance of the builder. */ @@ -96,7 +95,6 @@ public class FlatFileItemWriterBuilder { * The name used to calculate the key within the * {@link org.springframework.batch.item.ExecutionContext}. Required if * {@link #saveState(boolean)} is set to true. - * * @param name name of the reader instance * @return The current instance of the builder. * @see org.springframework.batch.item.ItemStreamSupport#setName(String) @@ -109,7 +107,6 @@ public class FlatFileItemWriterBuilder { /** * The {@link WritableResource} to be used as output. - * * @param resource the output of the writer. * @return The current instance of the builder. * @see FlatFileItemWriter#setResource(WritableResource) @@ -121,9 +118,8 @@ public class FlatFileItemWriterBuilder { } /** - * A flag indicating that changes should be force-synced to disk on flush. Defaults - * to false. - * + * A flag indicating that changes should be force-synced to disk on flush. Defaults to + * false. * @param forceSync value to set the flag to * @return The current instance of the builder. * @see FlatFileItemWriter#setForceSync(boolean) @@ -135,9 +131,8 @@ public class FlatFileItemWriterBuilder { } /** - * String used to separate lines in output. Defaults to the System property + * String used to separate lines in output. Defaults to the System property * line.separator. - * * @param lineSeparator value to use for a line separator * @return The current instance of the builder. * @see FlatFileItemWriter#setLineSeparator(String) @@ -150,7 +145,6 @@ public class FlatFileItemWriterBuilder { /** * Line aggregator used to build the String version of each item. - * * @param lineAggregator {@link LineAggregator} implementation * @return The current instance of the builder. * @see FlatFileItemWriter#setLineAggregator(LineAggregator) @@ -163,7 +157,6 @@ public class FlatFileItemWriterBuilder { /** * Encoding used for output. - * * @param encoding encoding type. * @return The current instance of the builder. * @see FlatFileItemWriter#setEncoding(String) @@ -177,7 +170,6 @@ public class FlatFileItemWriterBuilder { /** * If set to true, once the step is complete, if the resource previously provided is * empty, it will be deleted. - * * @param shouldDelete defaults to false * @return The current instance of the builder * @see FlatFileItemWriter#setShouldDeleteIfEmpty(boolean) @@ -191,7 +183,6 @@ public class FlatFileItemWriterBuilder { /** * If set to true, upon the start of the step, if the resource already exists, it will * be deleted and recreated. - * * @param shouldDelete defaults to true * @return The current instance of the builder * @see FlatFileItemWriter#setShouldDeleteIfExists(boolean) @@ -205,7 +196,6 @@ public class FlatFileItemWriterBuilder { /** * If set to true and the file exists, the output will be appended to the existing * file. - * * @param append defaults to false * @return The current instance of the builder * @see FlatFileItemWriter#setAppendAllowed(boolean) @@ -218,7 +208,6 @@ public class FlatFileItemWriterBuilder { /** * A callback for header processing. - * * @param callback {@link FlatFileHeaderCallback} impl * @return The current instance of the builder * @see FlatFileItemWriter#setHeaderCallback(FlatFileHeaderCallback) @@ -242,8 +231,8 @@ public class FlatFileItemWriterBuilder { } /** - * If set to true, the flushing of the buffer is delayed while a transaction is active. - * + * If set to true, the flushing of the buffer is delayed while a transaction is + * active. * @param transactional defaults to true * @return The current instance of the builder * @see FlatFileItemWriter#setTransactional(boolean) @@ -259,7 +248,6 @@ public class FlatFileItemWriterBuilder { * {@link DelimitedLineAggregator}. The {@link DelimitedLineAggregator} configured by * this builder will only be used if one is not explicitly configured via * {@link FlatFileItemWriterBuilder#lineAggregator} - * * @return a {@link DelimitedBuilder} * */ @@ -273,7 +261,6 @@ public class FlatFileItemWriterBuilder { * {@link FormatterLineAggregator}. The {@link FormatterLineAggregator} configured by * this builder will only be used if one is not explicitly configured via * {@link FlatFileItemWriterBuilder#lineAggregator} - * * @return a {@link FormattedBuilder} * */ @@ -328,8 +315,8 @@ public class FlatFileItemWriterBuilder { } /** - * Set the minimum length of the formatted string. If this is not set - * the default is to allow any length. + * Set the minimum length of the formatted string. If this is not set the default + * is to allow any length. * @param minimumLength of the formatted string * @return The instance of the builder for chaining. */ @@ -339,8 +326,8 @@ public class FlatFileItemWriterBuilder { } /** - * Set the maximum length of the formatted string. If this is not set - * the default is to allow any length. + * Set the maximum length of the formatted string. If this is not set the default + * is to allow any length. * @param maximumLength of the formatted string * @return The instance of the builder for chaining. */ @@ -361,10 +348,9 @@ public class FlatFileItemWriterBuilder { /** * Names of each of the fields within the fields that are returned in the order - * they occur within the formatted file. These names will be used to create - * a {@link BeanWrapperFieldExtractor} only if no explicit field extractor - * is set via {@link FormattedBuilder#fieldExtractor(FieldExtractor)}. - * + * they occur within the formatted file. These names will be used to create a + * {@link BeanWrapperFieldExtractor} only if no explicit field extractor is set + * via {@link FormattedBuilder#fieldExtractor(FieldExtractor)}. * @param names names of each field * @return The parent {@link FlatFileItemWriterBuilder} * @see BeanWrapperFieldExtractor#setNames(String[]) @@ -400,6 +386,7 @@ public class FlatFileItemWriterBuilder { formatterLineAggregator.setFieldExtractor(this.fieldExtractor); return formatterLineAggregator; } + } /** @@ -423,7 +410,6 @@ public class FlatFileItemWriterBuilder { /** * Define the delimiter for the file. - * * @param delimiter String used as a delimiter between fields. * @return The instance of the builder for chaining. * @see DelimitedLineAggregator#setDelimiter(String) @@ -435,10 +421,9 @@ public class FlatFileItemWriterBuilder { /** * Names of each of the fields within the fields that are returned in the order - * they occur within the delimited file. These names will be used to create - * a {@link BeanWrapperFieldExtractor} only if no explicit field extractor - * is set via {@link DelimitedBuilder#fieldExtractor(FieldExtractor)}. - * + * they occur within the delimited file. These names will be used to create a + * {@link BeanWrapperFieldExtractor} only if no explicit field extractor is set + * via {@link DelimitedBuilder#fieldExtractor(FieldExtractor)}. * @param names names of each field * @return The parent {@link FlatFileItemWriterBuilder} * @see BeanWrapperFieldExtractor#setNames(String[]) @@ -482,11 +467,11 @@ public class FlatFileItemWriterBuilder { delimitedLineAggregator.setFieldExtractor(this.fieldExtractor); return delimitedLineAggregator; } + } /** * Validates and builds a {@link FlatFileItemWriter}. - * * @return a {@link FlatFileItemWriter} */ public FlatFileItemWriter build() { @@ -494,13 +479,13 @@ public class FlatFileItemWriterBuilder { Assert.isTrue(this.lineAggregator != null || this.delimitedBuilder != null || this.formattedBuilder != null, "A LineAggregator or a DelimitedBuilder or a FormattedBuilder is required"); - if(this.saveState) { + if (this.saveState) { Assert.hasText(this.name, "A name is required when saveState is true"); } - if(this.resource == null) { - logger.debug("The resource is null. This is only a valid scenario when " + - "injecting it later as in when using the MultiResourceItemWriter"); + if (this.resource == null) { + logger.debug("The resource is null. This is only a valid scenario when " + + "injecting it later as in when using the MultiResourceItemWriter"); } FlatFileItemWriter writer = new FlatFileItemWriter<>(); @@ -531,4 +516,5 @@ public class FlatFileItemWriterBuilder { return writer; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/builder/MultiResourceItemReaderBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/builder/MultiResourceItemReaderBuilder.java index 7dffefd26..bfb692751 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/builder/MultiResourceItemReaderBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/builder/MultiResourceItemReaderBuilder.java @@ -47,10 +47,9 @@ public class MultiResourceItemReaderBuilder { private String name; /** - * Configure if the state of the {@link org.springframework.batch.item.ItemStreamSupport} - * should be persisted within the {@link org.springframework.batch.item.ExecutionContext} - * for restart purposes. - * + * Configure if the state of the + * {@link org.springframework.batch.item.ItemStreamSupport} should be persisted within + * the {@link org.springframework.batch.item.ExecutionContext} for restart purposes. * @param saveState defaults to true * @return The current instance of the builder. */ @@ -64,7 +63,6 @@ public class MultiResourceItemReaderBuilder { * The name used to calculate the key within the * {@link org.springframework.batch.item.ExecutionContext}. Required if * {@link #saveState(boolean)} is set to true. - * * @param name name of the reader instance * @return The current instance of the builder. * @see org.springframework.batch.item.ItemStreamSupport#setName(String) @@ -78,7 +76,6 @@ public class MultiResourceItemReaderBuilder { /** * The array of resources that the {@link MultiResourceItemReader} will use to * retrieve items. - * * @param resources the array of resources to use. * @return this instance for method chaining. * @@ -92,7 +89,6 @@ public class MultiResourceItemReaderBuilder { /** * Establishes the delegate to use for reading the resources provided. - * * @param delegate reads items from single {@link Resource}. * @return this instance for method chaining. * @@ -108,7 +104,6 @@ public class MultiResourceItemReaderBuilder { * In strict mode the reader will throw an exception on * {@link MultiResourceItemReader#open(org.springframework.batch.item.ExecutionContext)} * if there are no resources to read. - * * @param strict false by default. * @return this instance for method chaining. * @see MultiResourceItemReader#setStrict(boolean) @@ -122,7 +117,6 @@ public class MultiResourceItemReaderBuilder { /** * Used to order the injected resources, by default compares * {@link Resource#getFilename()} values. - * * @param comparator the comparator to use for ordering resources. * @return this instance for method chaining. * @see MultiResourceItemReader#setComparator(Comparator) @@ -135,7 +129,6 @@ public class MultiResourceItemReaderBuilder { /** * Builds the {@link MultiResourceItemReader}. - * * @return a {@link MultiResourceItemReader} */ public MultiResourceItemReader build() { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/builder/MultiResourceItemWriterBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/builder/MultiResourceItemWriterBuilder.java index ebaccf770..101d283a7 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/builder/MultiResourceItemWriterBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/builder/MultiResourceItemWriterBuilder.java @@ -45,10 +45,9 @@ public class MultiResourceItemWriterBuilder { private String name; /** - * Configure if the state of the {@link org.springframework.batch.item.ItemStreamSupport} - * should be persisted within the {@link org.springframework.batch.item.ExecutionContext} - * for restart purposes. - * + * Configure if the state of the + * {@link org.springframework.batch.item.ItemStreamSupport} should be persisted within + * the {@link org.springframework.batch.item.ExecutionContext} for restart purposes. * @param saveState defaults to true * @return The current instance of the builder. */ @@ -62,7 +61,6 @@ public class MultiResourceItemWriterBuilder { * The name used to calculate the key within the * {@link org.springframework.batch.item.ExecutionContext}. Required if * {@link #saveState(boolean)} is set to true. - * * @param name name of the reader instance * @return The current instance of the builder. * @see org.springframework.batch.item.ItemStreamSupport#setName(String) @@ -75,7 +73,6 @@ public class MultiResourceItemWriterBuilder { /** * Allows customization of the suffix of the created resources based on the index. - * * @param suffixCreator the customizable ResourceSuffixCreator to use. * @return The current instance of the builder. * @see MultiResourceItemWriter#setResourceSuffixCreator(ResourceSuffixCreator) @@ -89,7 +86,6 @@ public class MultiResourceItemWriterBuilder { /** * After this limit is exceeded the next chunk will be written into newly created * resource. - * * @param itemCountLimitPerResource the max numbers of items to be written per chunk. * @return The current instance of the builder. * @see MultiResourceItemWriter#setItemCountLimitPerResource(int) @@ -116,7 +112,6 @@ public class MultiResourceItemWriterBuilder { * Prototype for output resources. Actual output files will be created in the same * directory and use the same name as this prototype with appended suffix (according * to {@link MultiResourceItemWriter#setResourceSuffixCreator(ResourceSuffixCreator)}. - * * @param resource the prototype resource to use as the basis for creating resources. * @return The current instance of the builder. * @see MultiResourceItemWriter#setResource(Resource) @@ -129,14 +124,13 @@ public class MultiResourceItemWriterBuilder { /** * Builds the {@link MultiResourceItemWriter}. - * * @return a {@link MultiResourceItemWriter} */ public MultiResourceItemWriter build() { Assert.notNull(this.resource, "resource is required."); Assert.notNull(this.delegate, "delegate is required."); - if(this.saveState) { + if (this.saveState) { org.springframework.util.Assert.hasText(this.name, "A name is required when saveState is true."); } @@ -144,7 +138,7 @@ public class MultiResourceItemWriterBuilder { writer.setResource(this.resource); writer.setDelegate(this.delegate); writer.setItemCountLimitPerResource(this.itemCountLimitPerResource); - if(this.suffixCreator != null) { + if (this.suffixCreator != null) { writer.setResourceSuffixCreator(this.suffixCreator); } writer.setSaveState(this.saveState); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/ArrayFieldSetMapper.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/ArrayFieldSetMapper.java index 6d6dbb38d..6f866900e 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/ArrayFieldSetMapper.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/ArrayFieldSetMapper.java @@ -1,12 +1,12 @@ /* * Copyright 2011-2012 the original author or authors. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * https://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -19,16 +19,17 @@ import org.springframework.batch.item.file.transform.FieldSet; import org.springframework.validation.BindException; /** - * A basic array mapper, returning the values backing a fieldset. - * Useful for reading the Strings resulting from the line tokenizer without having to - * deal with a {@link FieldSet} object. - * + * A basic array mapper, returning the values backing a fieldset. Useful for reading the + * Strings resulting from the line tokenizer without having to deal with a + * {@link FieldSet} object. + * * @author Costin Leau */ public class ArrayFieldSetMapper implements FieldSetMapper { - @Override + @Override public String[] mapFieldSet(FieldSet fieldSet) throws BindException { return fieldSet.getValues(); } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/BeanWrapperFieldSetMapper.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/BeanWrapperFieldSetMapper.java index ebf2f8706..107bab83a 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/BeanWrapperFieldSetMapper.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/BeanWrapperFieldSetMapper.java @@ -46,57 +46,52 @@ import org.springframework.validation.DataBinder; /** * {@link FieldSetMapper} implementation based on bean property paths. The - * {@link FieldSet} to be mapped should have field name meta data corresponding - * to bean property paths in an instance of the desired type. The instance is - * created and initialized either by referring to a prototype object by bean - * name in the enclosing BeanFactory, or by providing a class to instantiate - * reflectively.
      + * {@link FieldSet} to be mapped should have field name meta data corresponding to bean + * property paths in an instance of the desired type. The instance is created and + * initialized either by referring to a prototype object by bean name in the enclosing + * BeanFactory, or by providing a class to instantiate reflectively.
      *
      - * - * Nested property paths, including indexed properties in maps and collections, - * can be referenced by the {@link FieldSet} names. They will be converted to - * nested bean properties inside the prototype. The {@link FieldSet} and the - * prototype are thus tightly coupled by the fields that are available and those - * that can be initialized. If some of the nested properties are optional (e.g. - * collection members) they need to be removed by a post processor.
      + * + * Nested property paths, including indexed properties in maps and collections, can be + * referenced by the {@link FieldSet} names. They will be converted to nested bean + * properties inside the prototype. The {@link FieldSet} and the prototype are thus + * tightly coupled by the fields that are available and those that can be initialized. If + * some of the nested properties are optional (e.g. collection members) they need to be + * removed by a post processor.
      *
      - * - * To customize the way that {@link FieldSet} values are converted to the - * desired type for injecting into the prototype there are several choices. You - * can inject {@link PropertyEditor} instances directly through the - * {@link #setCustomEditors(Map) customEditors} property, or you can override - * the {@link #createBinder(Object)} and {@link #initBinder(DataBinder)} - * methods, or you can provide a custom {@link FieldSet} implementation. - * You can also use a {@link ConversionService} to convert to the desired type - * through the {@link #setConversionService(ConversionService) conversionService} - * property. + * + * To customize the way that {@link FieldSet} values are converted to the desired type for + * injecting into the prototype there are several choices. You can inject + * {@link PropertyEditor} instances directly through the {@link #setCustomEditors(Map) + * customEditors} property, or you can override the {@link #createBinder(Object)} and + * {@link #initBinder(DataBinder)} methods, or you can provide a custom {@link FieldSet} + * implementation. You can also use a {@link ConversionService} to convert to the desired + * type through the {@link #setConversionService(ConversionService) conversionService} + * property.
      *
      - *
      - * - * Property name matching is "fuzzy" in the sense that it tolerates close - * matches, as long as the match is unique. For instance: - * + * + * Property name matching is "fuzzy" in the sense that it tolerates close matches, as long + * as the match is unique. For instance: + * *
        *
      • Quantity = quantity (field names can be capitalised)
      • - *
      • ISIN = isin (acronyms can be lower case bean property names, as per Java - * Beans recommendations)
      • + *
      • ISIN = isin (acronyms can be lower case bean property names, as per Java Beans + * recommendations)
      • *
      • DuckPate = duckPate (capitalisation including camel casing)
      • - *
      • ITEM_ID = itemId (capitalisation and replacing word boundary with - * underscore)
      • - *
      • ORDER.CUSTOMER_ID = order.customerId (nested paths are recursively - * checked)
      • + *
      • ITEM_ID = itemId (capitalisation and replacing word boundary with underscore)
      • + *
      • ORDER.CUSTOMER_ID = order.customerId (nested paths are recursively checked)
      • *
      - * - * The algorithm used to match a property name is to start with an exact match - * and then search successively through more distant matches until precisely one - * match is found. If more than one match is found there will be an error. - * + * + * The algorithm used to match a property name is to start with an exact match and then + * search successively through more distant matches until precisely one match is found. If + * more than one match is found there will be an error. + * * @author Dave Syer * @author Mahmoud Ben Hassine - * + * */ -public class BeanWrapperFieldSetMapper extends DefaultPropertyEditorRegistrar implements FieldSetMapper, - BeanFactoryAware, InitializingBean { +public class BeanWrapperFieldSetMapper extends DefaultPropertyEditorRegistrar + implements FieldSetMapper, BeanFactoryAware, InitializingBean { private String name; @@ -116,21 +111,19 @@ public class BeanWrapperFieldSetMapper extends DefaultPropertyEditorRegistrar /* * (non-Javadoc) - * - * @see - * org.springframework.beans.factory.BeanFactoryAware#setBeanFactory(org + * + * @see org.springframework.beans.factory.BeanFactoryAware#setBeanFactory(org * .springframework.beans.factory.BeanFactory) */ - @Override + @Override public void setBeanFactory(BeanFactory beanFactory) { this.beanFactory = beanFactory; } /** - * The maximum difference that can be tolerated in spelling between input - * key names and bean property names. Defaults to 5, but could be set lower - * if the field names match the bean names. - * + * The maximum difference that can be tolerated in spelling between input key names + * and bean property names. Defaults to 5, but could be set lower if the field names + * match the bean names. * @param distanceLimit the distance limit to set */ public void setDistanceLimit(int distanceLimit) { @@ -138,14 +131,11 @@ public class BeanWrapperFieldSetMapper extends DefaultPropertyEditorRegistrar } /** - * The bean name (id) for an object that can be populated from the field set - * that will be passed into {@link #mapFieldSet(FieldSet)}. Typically a - * prototype scoped bean so that a new instance is returned for each field - * set mapped. - * - * Either this property or the type property must be specified, but not - * both. - * + * The bean name (id) for an object that can be populated from the field set that will + * be passed into {@link #mapFieldSet(FieldSet)}. Typically a prototype scoped bean so + * that a new instance is returned for each field set mapped. + * + * Either this property or the type property must be specified, but not both. * @param name the name of a prototype bean in the enclosing BeanFactory */ public void setPrototypeBeanName(String name) { @@ -153,13 +143,11 @@ public class BeanWrapperFieldSetMapper extends DefaultPropertyEditorRegistrar } /** - * Public setter for the type of bean to create instead of using a prototype - * bean. An object of this type will be created from its default constructor - * for every call to {@link #mapFieldSet(FieldSet)}.
      - * - * Either this property or the prototype bean name must be specified, but - * not both. - * + * Public setter for the type of bean to create instead of using a prototype bean. An + * object of this type will be created from its default constructor for every call to + * {@link #mapFieldSet(FieldSet)}.
      + * + * Either this property or the prototype bean name must be specified, but not both. * @param type the type to set */ public void setTargetType(Class type) { @@ -168,32 +156,28 @@ public class BeanWrapperFieldSetMapper extends DefaultPropertyEditorRegistrar /** * Check that precisely one of type or prototype bean name is specified. - * - * @throws IllegalStateException if neither is set or both properties are - * set. - * + * @throws IllegalStateException if neither is set or both properties are set. + * * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() */ - @Override + @Override public void afterPropertiesSet() throws Exception { Assert.state(name != null || type != null, "Either name or type must be provided."); Assert.state(name == null || type == null, "Both name and type cannot be specified together."); - Assert.state(!this.isCustomEditorsSet || this.conversionService == null, "Both customEditor and conversionService cannot be specified together."); + Assert.state(!this.isCustomEditorsSet || this.conversionService == null, + "Both customEditor and conversionService cannot be specified together."); } /** - * Map the {@link FieldSet} to an object retrieved from the enclosing Spring - * context, or to a new instance of the required type if no prototype is - * available. - * @throws BindException if there is a type conversion or other error (if - * the {@link DataBinder} from {@link #createBinder(Object)} has errors - * after binding). - * - * @throws NotWritablePropertyException if the {@link FieldSet} contains a - * field that cannot be mapped to a bean property. + * Map the {@link FieldSet} to an object retrieved from the enclosing Spring context, + * or to a new instance of the required type if no prototype is available. + * @throws BindException if there is a type conversion or other error (if the + * {@link DataBinder} from {@link #createBinder(Object)} has errors after binding). + * @throws NotWritablePropertyException if the {@link FieldSet} contains a field that + * cannot be mapped to a bean property. * @see org.springframework.batch.item.file.mapping.FieldSetMapper#mapFieldSet(FieldSet) */ - @Override + @Override public T mapFieldSet(FieldSet fs) throws BindException { T copy = getBean(); DataBinder binder = createBinder(copy); @@ -205,31 +189,28 @@ public class BeanWrapperFieldSetMapper extends DefaultPropertyEditorRegistrar } /** - * Create a binder for the target object. The binder will then be used to - * bind the properties form a field set into the target object. This - * implementation creates a new {@link DataBinder} and calls out to - * {@link #initBinder(DataBinder)} and + * Create a binder for the target object. The binder will then be used to bind the + * properties form a field set into the target object. This implementation creates a + * new {@link DataBinder} and calls out to {@link #initBinder(DataBinder)} and * {@link #registerCustomEditors(PropertyEditorRegistry)}. - * * @param target Object to bind to - * @return a {@link DataBinder} that can be used to bind properties to the - * target. + * @return a {@link DataBinder} that can be used to bind properties to the target. */ protected DataBinder createBinder(Object target) { DataBinder binder = new DataBinder(target); binder.setIgnoreUnknownFields(!this.strict); initBinder(binder); registerCustomEditors(binder); - if(this.conversionService != null) { + if (this.conversionService != null) { binder.setConversionService(this.conversionService); } return binder; } /** - * Initialize a new binder instance. This hook allows customization of - * binder settings such as the {@link DataBinder#initDirectFieldAccess() - * direct field access}. Called by {@link #createBinder(Object)}. + * Initialize a new binder instance. This hook allows customization of binder settings + * such as the {@link DataBinder#initDirectFieldAccess() direct field access}. Called + * by {@link #createBinder(Object)}. *

      * Note that registration of custom property editors can be done in * {@link #registerCustomEditors(PropertyEditorRegistry)}. @@ -287,14 +268,9 @@ public class BeanWrapperFieldSetMapper extends DefaultPropertyEditorRegistrar if (name != null) { if (matches.containsValue(name)) { - throw new NotWritablePropertyException( - cls, - name, - "Duplicate match with distance <= " - + distanceLimit - + " found for this property in input keys: " - + keys - + ". (Consider reducing the distance limit or changing the input key names to get a closer match.)"); + throw new NotWritablePropertyException(cls, name, "Duplicate match with distance <= " + + distanceLimit + " found for this property in input keys: " + keys + + ". (Consider reducing the distance limit or changing the input key names to get a closer match.)"); } matches.put(key, name); switchPropertyNames(properties, key, name); @@ -373,7 +349,8 @@ public class BeanWrapperFieldSetMapper extends DefaultPropertyEditorRegistrar nestedValue = wrapper.getPropertyType(nestedName).getDeclaredConstructor().newInstance(); wrapper.setPropertyValue(nestedName, nestedValue); } - catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { + catch (InstantiationException | IllegalAccessException | NoSuchMethodException + | InvocationTargetException e) { ReflectionUtils.handleReflectionException(e); } } @@ -388,20 +365,17 @@ public class BeanWrapperFieldSetMapper extends DefaultPropertyEditorRegistrar /** * Public setter for the 'strict' property. If true, then - * {@link #mapFieldSet(FieldSet)} will fail of the FieldSet contains fields - * that cannot be mapped to the bean. - * + * {@link #mapFieldSet(FieldSet)} will fail of the FieldSet contains fields that + * cannot be mapped to the bean. * @param strict indicator */ public void setStrict(boolean strict) { this.strict = strict; } - /** - * Public setter for the 'conversionService' property. - * {@link #createBinder(Object)} will use it if not null. - * + * Public setter for the 'conversionService' property. {@link #createBinder(Object)} + * will use it if not null. * @param conversionService {@link ConversionService} to be used for type conversions */ public void setConversionService(ConversionService conversionService) { @@ -410,8 +384,6 @@ public class BeanWrapperFieldSetMapper extends DefaultPropertyEditorRegistrar /** * Specify the {@link PropertyEditor custom editors} to register. - * - * * @param customEditors a map of Class to PropertyEditor (or class name to * PropertyEditor). * @see CustomEditorConfigurer#setCustomEditors(Map) @@ -423,6 +395,7 @@ public class BeanWrapperFieldSetMapper extends DefaultPropertyEditorRegistrar } private static class DistanceHolder { + private final Class cls; private final int distance; @@ -461,6 +434,7 @@ public class BeanWrapperFieldSetMapper extends DefaultPropertyEditorRegistrar return false; return true; } + } } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/DefaultLineMapper.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/DefaultLineMapper.java index 27357ed1a..b47ad613e 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/DefaultLineMapper.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/DefaultLineMapper.java @@ -23,13 +23,12 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; /** - * Two-phase {@link LineMapper} implementation consisting of tokenization of the line into {@link FieldSet} followed by - * mapping to item. If finer grained control of exceptions is needed, the {@link LineMapper} interface should be - * implemented directly. - * + * Two-phase {@link LineMapper} implementation consisting of tokenization of the line into + * {@link FieldSet} followed by mapping to item. If finer grained control of exceptions is + * needed, the {@link LineMapper} interface should be implemented directly. + * * @author Robert Kasanicky * @author Lucas Ward - * * @param type of the item */ public class DefaultLineMapper implements LineMapper, InitializingBean { @@ -38,7 +37,7 @@ public class DefaultLineMapper implements LineMapper, InitializingBean { private FieldSetMapper fieldSetMapper; - @Override + @Override public T mapLine(String line, int lineNumber) throws Exception { return fieldSetMapper.mapFieldSet(tokenizer.tokenize(line)); } @@ -51,7 +50,7 @@ public class DefaultLineMapper implements LineMapper, InitializingBean { this.fieldSetMapper = fieldSetMapper; } - @Override + @Override public void afterPropertiesSet() { Assert.notNull(tokenizer, "The LineTokenizer must be set"); Assert.notNull(fieldSetMapper, "The FieldSetMapper must be set"); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/FieldSetMapper.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/FieldSetMapper.java index ba3327ab2..7f51d9826 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/FieldSetMapper.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/FieldSetMapper.java @@ -19,24 +19,21 @@ package org.springframework.batch.item.file.mapping; import org.springframework.batch.item.file.transform.FieldSet; import org.springframework.validation.BindException; - - /** - * Interface that is used to map data obtained from a {@link FieldSet} into an - * object. - * + * Interface that is used to map data obtained from a {@link FieldSet} into an object. + * * @author Tomas Slanina * @author Dave Syer - * + * */ public interface FieldSetMapper { - + /** * Method used to map data obtained from a {@link FieldSet} into an object. - * * @param fieldSet the {@link FieldSet} to map * @return the populated object * @throws BindException if there is a problem with the binding */ T mapFieldSet(FieldSet fieldSet) throws BindException; + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/JsonLineMapper.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/JsonLineMapper.java index 861c5f46d..127be9102 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/JsonLineMapper.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/JsonLineMapper.java @@ -1,62 +1,62 @@ -/* - * Copyright 2009-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.file.mapping; - -import java.util.Map; - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.MappingJsonFactory; - -import org.springframework.batch.item.file.LineMapper; - -/** - * Interpret a line as a JSON object and parse it up to a Map. The line should be a standard JSON object, starting with - * "{" and ending with "}" and composed of name:value pairs separated by commas. Whitespace is ignored, - * e.g. - * - *

      - * { "foo" : "bar", "value" : 123 }
      - * 
      - * - * The values can also be JSON objects (which are converted to maps): - * - *
      - * { "foo": "bar", "map": { "one": 1, "two": 2}}
      - * 
      - * - * @author Dave Syer - * - */ -public class JsonLineMapper implements LineMapper> { - - private MappingJsonFactory factory = new MappingJsonFactory(); - - /** - * Interpret the line as a Json object and create a Map from it. - * - * @see LineMapper#mapLine(String, int) - */ - @Override - public Map mapLine(String line, int lineNumber) throws Exception { - Map result; - JsonParser parser = factory.createParser(line); - @SuppressWarnings("unchecked") - Map token = parser.readValueAs(Map.class); - result = token; - return result; - } - -} +/* + * Copyright 2009-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item.file.mapping; + +import java.util.Map; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.MappingJsonFactory; + +import org.springframework.batch.item.file.LineMapper; + +/** + * Interpret a line as a JSON object and parse it up to a Map. The line should be a + * standard JSON object, starting with "{" and ending with "}" and composed of + * name:value pairs separated by commas. Whitespace is ignored, e.g. + * + *
      + * { "foo" : "bar", "value" : 123 }
      + * 
      + * + * The values can also be JSON objects (which are converted to maps): + * + *
      + * { "foo": "bar", "map": { "one": 1, "two": 2}}
      + * 
      + * + * @author Dave Syer + * + */ +public class JsonLineMapper implements LineMapper> { + + private MappingJsonFactory factory = new MappingJsonFactory(); + + /** + * Interpret the line as a Json object and create a Map from it. + * + * @see LineMapper#mapLine(String, int) + */ + @Override + public Map mapLine(String line, int lineNumber) throws Exception { + Map result; + JsonParser parser = factory.createParser(line); + @SuppressWarnings("unchecked") + Map token = parser.readValueAs(Map.class); + result = token; + return result; + } + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/PassThroughFieldSetMapper.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/PassThroughFieldSetMapper.java index 254259918..816e5bc9e 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/PassThroughFieldSetMapper.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/PassThroughFieldSetMapper.java @@ -18,22 +18,21 @@ package org.springframework.batch.item.file.mapping; import org.springframework.batch.item.file.transform.FieldSet; /** - * Pass through {@link FieldSetMapper} useful for passing a {@link FieldSet} - * back directly rather than a mapped object. - * + * Pass through {@link FieldSetMapper} useful for passing a {@link FieldSet} back directly + * rather than a mapped object. + * * @author Lucas Ward - * + * */ public class PassThroughFieldSetMapper implements FieldSetMapper
      { /* * (non-Javadoc) - * - * @see - * org.springframework.batch.item.file.FieldSetMapper#mapLine(org.springframework + * + * @see org.springframework.batch.item.file.FieldSetMapper#mapLine(org.springframework * .batch.io.file.FieldSet) */ - @Override + @Override public FieldSet mapFieldSet(FieldSet fs) { return fs; } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/PassThroughLineMapper.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/PassThroughLineMapper.java index 1c3f99fdb..0c04103de 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/PassThroughLineMapper.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/PassThroughLineMapper.java @@ -1,33 +1,33 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.item.file.mapping; - -import org.springframework.batch.item.file.LineMapper; - -/** - * Pass through {@link LineMapper} useful for passing the original - * {@link String} back directly rather than a mapped object. - * - */ -public class PassThroughLineMapper implements LineMapper{ - - @Override - public String mapLine(String line, int lineNumber) throws Exception { - return line; - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.item.file.mapping; + +import org.springframework.batch.item.file.LineMapper; + +/** + * Pass through {@link LineMapper} useful for passing the original {@link String} back + * directly rather than a mapped object. + * + */ +public class PassThroughLineMapper implements LineMapper { + + @Override + public String mapLine(String line, int lineNumber) throws Exception { + return line; + } + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/PatternMatchingCompositeLineMapper.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/PatternMatchingCompositeLineMapper.java index 32ed9e1f1..9d26e6fd8 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/PatternMatchingCompositeLineMapper.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/PatternMatchingCompositeLineMapper.java @@ -27,19 +27,18 @@ import org.springframework.util.Assert; /** *

      - * A {@link LineMapper} implementation that stores a mapping of String patterns - * to delegate {@link LineTokenizer}s as well as a mapping of String patterns to - * delegate {@link FieldSetMapper}s. Each line received will be tokenized and - * then mapped to a field set. - * + * A {@link LineMapper} implementation that stores a mapping of String patterns to + * delegate {@link LineTokenizer}s as well as a mapping of String patterns to delegate + * {@link FieldSetMapper}s. Each line received will be tokenized and then mapped to a + * field set. + * *

      - * Both the tokenizing and the mapping work in a similar way. The line will be - * checked for its matching pattern. If the key matches a pattern in the map of - * delegates, then the corresponding delegate will be used. Patterns are sorted - * starting with the most specific, and the first match succeeds. - * + * Both the tokenizing and the mapping work in a similar way. The line will be checked for + * its matching pattern. If the key matches a pattern in the map of delegates, then the + * corresponding delegate will be used. Patterns are sorted starting with the most + * specific, and the first match succeeds. + * * @see PatternMatchingCompositeLineTokenizer - * * @author Dan Garrette * @author Dave Syer * @since 2.0 @@ -52,23 +51,21 @@ public class PatternMatchingCompositeLineMapper implements LineMapper, Ini /* * (non-Javadoc) - * - * @see - * org.springframework.batch.item.file.mapping.LineMapper#mapLine(java.lang + * + * @see org.springframework.batch.item.file.mapping.LineMapper#mapLine(java.lang * .String, int) */ - @Override + @Override public T mapLine(String line, int lineNumber) throws Exception { return patternMatcher.match(line).mapFieldSet(this.tokenizer.tokenize(line)); } /* * (non-Javadoc) - * - * @see - * org.springframework.beans.factory.InitializingBean#afterPropertiesSet() + * + * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() */ - @Override + @Override public void afterPropertiesSet() throws Exception { this.tokenizer.afterPropertiesSet(); Assert.isTrue(this.patternMatcher != null, "The 'patternMatcher' property must be non-null"); @@ -82,4 +79,5 @@ public class PatternMatchingCompositeLineMapper implements LineMapper, Ini Assert.isTrue(!fieldSetMappers.isEmpty(), "The 'fieldSetMappers' property must be non-empty"); this.patternMatcher = new PatternMatcher<>(fieldSetMappers); } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/PropertyMatches.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/PropertyMatches.java index e39176e45..24420f9b5 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/PropertyMatches.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/PropertyMatches.java @@ -26,29 +26,27 @@ import java.util.Collections; import java.util.List; /** - * Helper class for calculating bean property matches, according to. - * Used by BeanWrapperImpl to suggest alternatives for an invalid property name.
      - * + * Helper class for calculating bean property matches, according to. Used by + * BeanWrapperImpl to suggest alternatives for an invalid property name.
      + * * Copied and slightly modified from Spring core, * * @author Alef Arendsen * @author Arjen Poutsma * @author Juergen Hoeller * @author Dave Syer - * * @since 1.0 * @see #forProperty(String, Class) */ final class PropertyMatches { - //--------------------------------------------------------------------- + // --------------------------------------------------------------------- // Static section - //--------------------------------------------------------------------- + // --------------------------------------------------------------------- /** Default maximum property distance: 2 */ public static final int DEFAULT_MAX_DISTANCE = 2; - /** * Create PropertyMatches for the given bean property. * @param propertyName the name of the property to find possible matches for @@ -68,16 +66,14 @@ final class PropertyMatches { return new PropertyMatches(propertyName, beanClass, maxDistance); } - - //--------------------------------------------------------------------- + // --------------------------------------------------------------------- // Instance section - //--------------------------------------------------------------------- + // --------------------------------------------------------------------- private final String propertyName; private String[] possibleMatches; - /** * Create a new PropertyMatches instance for the given property. */ @@ -86,7 +82,6 @@ final class PropertyMatches { this.possibleMatches = calculateMatches(BeanUtils.getPropertyDescriptors(beanClass), maxDistance); } - /** * Return the calculated possible matches. */ @@ -95,8 +90,8 @@ final class PropertyMatches { } /** - * Build an error message for the given invalid property name, - * indicating the possible property matches. + * Build an error message for the given invalid property name, indicating the possible + * property matches. */ public String buildErrorMessage() { StringBuilder buf = new StringBuilder(128); @@ -115,21 +110,19 @@ final class PropertyMatches { if (i < this.possibleMatches.length - 2) { buf.append("', "); } - else if (i == this.possibleMatches.length - 2){ + else if (i == this.possibleMatches.length - 2) { buf.append("', or "); } - } + } buf.append("'?"); } return buf.toString(); } - /** - * Generate possible property alternatives for the given property and - * class. Internally uses the getStringDistance method, which - * in turn uses the Levenshtein algorithm to determine the distance between - * two Strings. + * Generate possible property alternatives for the given property and class. + * Internally uses the getStringDistance method, which in turn uses the + * Levenshtein algorithm to determine the distance between two Strings. * @param propertyDescriptors the JavaBeans property descriptors to search * @param maxDistance the maximum distance to accept */ @@ -149,8 +142,8 @@ final class PropertyMatches { } /** - * Calculate the distance between the given two Strings - * according to the Levenshtein algorithm. + * Calculate the distance between the given two Strings according to the Levenshtein + * algorithm. * @param s1 the first String * @param s2 the second String * @return the distance value @@ -178,14 +171,15 @@ final class PropertyMatches { char t_j = s2.charAt(j - 1); if (Character.toLowerCase(s_i) == Character.toLowerCase(t_j)) { cost = 0; - } else { + } + else { cost = 1; } - d[i][j] = Math.min(Math.min(d[i - 1][j] + 1, d[i][j - 1] + 1), - d[i - 1][j - 1] + cost); + d[i][j] = Math.min(Math.min(d[i - 1][j] + 1, d[i][j - 1] + 1), d[i - 1][j - 1] + cost); } } return d[s1.length()][s2.length()]; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/RecordFieldSetMapper.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/RecordFieldSetMapper.java index 9e2500745..860a4a660 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/RecordFieldSetMapper.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/RecordFieldSetMapper.java @@ -25,10 +25,10 @@ import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.util.Assert; /** - * This is a {@link FieldSetMapper} that supports Java records mapping - * (requires JKD 14 or higher). It uses the record's canonical constructor - * to map components with the same name as tokens in the {@link FieldSet}. - * + * This is a {@link FieldSetMapper} that supports Java records mapping (requires JKD 14 or + * higher). It uses the record's canonical constructor to map components with the same + * name as tokens in the {@link FieldSet}. + * * @param type of mapped items * @author Mahmoud Ben Hassine * @since 4.3 @@ -36,13 +36,15 @@ import org.springframework.util.Assert; public class RecordFieldSetMapper implements FieldSetMapper { private final SimpleTypeConverter typeConverter = new SimpleTypeConverter(); + private final Constructor mappedConstructor; + private String[] constructorParameterNames; + private Class[] constructorParameterTypes; /** * Create a new {@link RecordFieldSetMapper}. - * * @param targetType type of mapped items */ public RecordFieldSetMapper(Class targetType) { @@ -51,11 +53,10 @@ public class RecordFieldSetMapper implements FieldSetMapper { /** * Create a new {@link RecordFieldSetMapper}. - * * @param targetType type of mapped items * @param conversionService service to use to convert raw data to typed fields */ - public RecordFieldSetMapper(Class< T> targetType, ConversionService conversionService) { + public RecordFieldSetMapper(Class targetType, ConversionService conversionService) { this.typeConverter.setConversionService(conversionService); this.mappedConstructor = BeanUtils.getResolvableConstructor(targetType); if (this.mappedConstructor.getParameterCount() > 0) { @@ -80,4 +81,5 @@ public class RecordFieldSetMapper implements FieldSetMapper { } return BeanUtils.instantiateClass(this.mappedConstructor, args); } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/separator/DefaultRecordSeparatorPolicy.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/separator/DefaultRecordSeparatorPolicy.java index 7f8d4cd5a..fb86c78c1 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/separator/DefaultRecordSeparatorPolicy.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/separator/DefaultRecordSeparatorPolicy.java @@ -19,12 +19,11 @@ package org.springframework.batch.item.file.separator; import org.springframework.util.StringUtils; /** - * A {@link RecordSeparatorPolicy} that treats all lines as record endings, as - * long as they do not have unterminated quotes, and do not end in a - * continuation marker. - * + * A {@link RecordSeparatorPolicy} that treats all lines as record endings, as long as + * they do not have unterminated quotes, and do not end in a continuation marker. + * * @author Dave Syer - * + * */ public class DefaultRecordSeparatorPolicy extends SimpleRecordSeparatorPolicy { @@ -45,7 +44,6 @@ public class DefaultRecordSeparatorPolicy extends SimpleRecordSeparatorPolicy { /** * Convenient constructor with quote character as parameter. - * * @param quoteCharacter value used to indicate a quoted string */ public DefaultRecordSeparatorPolicy(String quoteCharacter) { @@ -53,9 +51,7 @@ public class DefaultRecordSeparatorPolicy extends SimpleRecordSeparatorPolicy { } /** - * Convenient constructor with quote character and continuation marker as - * parameters. - * + * Convenient constructor with quote character and continuation marker as parameters. * @param quoteCharacter value used to indicate a quoted string * @param continuation value used to indicate a line continuation */ @@ -67,7 +63,6 @@ public class DefaultRecordSeparatorPolicy extends SimpleRecordSeparatorPolicy { /** * Public setter for the quoteCharacter. Defaults to double quote mark. - * * @param quoteCharacter the quoteCharacter to set */ public void setQuoteCharacter(String quoteCharacter) { @@ -76,7 +71,6 @@ public class DefaultRecordSeparatorPolicy extends SimpleRecordSeparatorPolicy { /** * Public setter for the continuation. Defaults to back slash. - * * @param continuation the continuation to set */ public void setContinuation(String continuation) { @@ -84,25 +78,24 @@ public class DefaultRecordSeparatorPolicy extends SimpleRecordSeparatorPolicy { } /** - * Return true if the line does not have unterminated quotes (delimited by - * "), and does not end with a continuation marker ('\'). The test for the - * continuation marker ignores whitespace at the end of the line. - * + * Return true if the line does not have unterminated quotes (delimited by "), and + * does not end with a continuation marker ('\'). The test for the continuation marker + * ignores whitespace at the end of the line. + * * @see org.springframework.batch.item.file.separator.RecordSeparatorPolicy#isEndOfRecord(java.lang.String) */ - @Override + @Override public boolean isEndOfRecord(String line) { return !isQuoteUnterminated(line) && !isContinued(line); } /** - * If we are in an unterminated quote, add a line separator. Otherwise - * remove the continuation marker (plus whitespace at the end) if it is - * there. - * + * If we are in an unterminated quote, add a line separator. Otherwise remove the + * continuation marker (plus whitespace at the end) if it is there. + * * @see org.springframework.batch.item.file.separator.SimpleRecordSeparatorPolicy#preProcess(java.lang.String) */ - @Override + @Override public String preProcess(String line) { if (isQuoteUnterminated(line)) { return line + "\n"; @@ -114,10 +107,8 @@ public class DefaultRecordSeparatorPolicy extends SimpleRecordSeparatorPolicy { } /** - * Determine if the current line (or buffered concatenation of lines) - * contains an unterminated quote, indicating that the record is continuing - * onto the next line. - * + * Determine if the current line (or buffered concatenation of lines) contains an + * unterminated quote, indicating that the record is continuing onto the next line. * @param line * @return */ @@ -126,10 +117,8 @@ public class DefaultRecordSeparatorPolicy extends SimpleRecordSeparatorPolicy { } /** - * Determine if the current line (or buffered concatenation of lines) ends - * with the continuation marker, indicating that the record is continuing - * onto the next line. - * + * Determine if the current line (or buffered concatenation of lines) ends with the + * continuation marker, indicating that the record is continuing onto the next line. * @param line * @return */ @@ -139,4 +128,5 @@ public class DefaultRecordSeparatorPolicy extends SimpleRecordSeparatorPolicy { } return line.trim().endsWith(continuation); } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/separator/JsonRecordSeparatorPolicy.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/separator/JsonRecordSeparatorPolicy.java index 0d92b3b9c..157168539 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/separator/JsonRecordSeparatorPolicy.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/separator/JsonRecordSeparatorPolicy.java @@ -19,29 +19,29 @@ package org.springframework.batch.item.file.separator; import org.springframework.util.StringUtils; /** - * JSON-based record separator. Waits for a valid JSON object before returning a - * complete line. A valid object has balanced braces ({}), possibly nested, and - * ends with a closing brace. This separator can be used to split a stream into - * JSON objects, even if those objects are spread over multiple lines, e.g. - * + * JSON-based record separator. Waits for a valid JSON object before returning a complete + * line. A valid object has balanced braces ({}), possibly nested, and ends with a closing + * brace. This separator can be used to split a stream into JSON objects, even if those + * objects are spread over multiple lines, e.g. + * *

        * {"foo": "bar",
        *  "value": { "spam": 2 }}
        *  {"foo": "rab",
        *  "value": { "spam": 3, "foo": "bar" }}
        * 
      - * + * * @author Dave Syer - * + * */ public class JsonRecordSeparatorPolicy extends SimpleRecordSeparatorPolicy { /** * True if the line can be parsed to a JSON object. - * + * * @see RecordSeparatorPolicy#isEndOfRecord(String) */ - @Override + @Override public boolean isEndOfRecord(String line) { return StringUtils.countOccurrencesOf(line, "{") == StringUtils.countOccurrencesOf(line, "}") && line.trim().endsWith("}"); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/separator/RecordSeparatorPolicy.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/separator/RecordSeparatorPolicy.java index 01320c5ac..db1135d2c 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/separator/RecordSeparatorPolicy.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/separator/RecordSeparatorPolicy.java @@ -19,9 +19,8 @@ package org.springframework.batch.item.file.separator; import java.io.BufferedReader; /** - * Policy for text file-based input sources to determine the end of a record, - * e.g. a record might be a single line, or it might be multiple lines - * terminated by a semicolon. + * Policy for text file-based input sources to determine the end of a record, e.g. a + * record might be a single line, or it might be multiple lines terminated by a semicolon. * * @author Dave Syer * @@ -29,33 +28,27 @@ import java.io.BufferedReader; public interface RecordSeparatorPolicy { /** - * Signal the end of a record based on the content of the current record. - * During the course of processing, each time this method returns false, - * the next line read is appended onto it (building the record). The input - * is what you would expect from {@link BufferedReader#readLine()} - i.e. - * no line separator character at the end. But it might have line separators - * embedded in it. - * + * Signal the end of a record based on the content of the current record. During the + * course of processing, each time this method returns false, the next line read is + * appended onto it (building the record). The input is what you would expect from + * {@link BufferedReader#readLine()} - i.e. no line separator character at the end. + * But it might have line separators embedded in it. * @param record a String without a newline character at the end. * @return true if this line is a complete record. */ boolean isEndOfRecord(String record); /** - * Give the policy a chance to post-process a complete record, e.g. remove a - * suffix. - * + * Give the policy a chance to post-process a complete record, e.g. remove a suffix. * @param record the complete record. * @return a modified version of the record if desired. */ String postProcess(String record); /** - * Pre-process a record before another line is appended, in the case of a - * multi-line record. Can be used to remove a prefix or line-continuation - * marker. If a record is a single line this callback is not used (but - * {@link #postProcess(String)} will be). - * + * Pre-process a record before another line is appended, in the case of a multi-line + * record. Can be used to remove a prefix or line-continuation marker. If a record is + * a single line this callback is not used (but {@link #postProcess(String)} will be). * @param record the current record. * @return the line as it should be appended to a record. */ diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/separator/SimpleRecordSeparatorPolicy.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/separator/SimpleRecordSeparatorPolicy.java index 3e50164a4..b26e32e55 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/separator/SimpleRecordSeparatorPolicy.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/separator/SimpleRecordSeparatorPolicy.java @@ -16,22 +16,20 @@ package org.springframework.batch.item.file.separator; - /** - * Simplest possible {@link RecordSeparatorPolicy} - treats all lines as record - * endings. - * + * Simplest possible {@link RecordSeparatorPolicy} - treats all lines as record endings. + * * @author Dave Syer - * + * */ public class SimpleRecordSeparatorPolicy implements RecordSeparatorPolicy { /** * Always returns true. - * + * * @see org.springframework.batch.item.file.separator.RecordSeparatorPolicy#isEndOfRecord(java.lang.String) */ - @Override + @Override public boolean isEndOfRecord(String line) { return true; } @@ -40,16 +38,16 @@ public class SimpleRecordSeparatorPolicy implements RecordSeparatorPolicy { * Pass the record through. Do nothing. * @see org.springframework.batch.item.file.separator.RecordSeparatorPolicy#postProcess(java.lang.String) */ - @Override + @Override public String postProcess(String record) { return record; } - + /** - * Pass the line through. Do nothing. + * Pass the line through. Do nothing. * @see org.springframework.batch.item.file.separator.RecordSeparatorPolicy#preProcess(java.lang.String) */ - @Override + @Override public String preProcess(String line) { return line; } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/separator/SuffixRecordSeparatorPolicy.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/separator/SuffixRecordSeparatorPolicy.java index 5b7be98a0..d8c1bb227 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/separator/SuffixRecordSeparatorPolicy.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/separator/SuffixRecordSeparatorPolicy.java @@ -16,13 +16,12 @@ package org.springframework.batch.item.file.separator; - /** - * A {@link RecordSeparatorPolicy} that looks for an exact match for a String at - * the end of a line (e.g. a semicolon). - * + * A {@link RecordSeparatorPolicy} that looks for an exact match for a String at the end + * of a line (e.g. a semicolon). + * * @author Dave Syer - * + * */ public class SuffixRecordSeparatorPolicy extends DefaultRecordSeparatorPolicy { @@ -37,7 +36,6 @@ public class SuffixRecordSeparatorPolicy extends DefaultRecordSeparatorPolicy { /** * Lines ending in this terminator String signal the end of a record. - * * @param suffix suffix to indicate the end of a record */ public void setSuffix(String suffix) { @@ -45,9 +43,8 @@ public class SuffixRecordSeparatorPolicy extends DefaultRecordSeparatorPolicy { } /** - * Flag to indicate that the decision to terminate a record should ignore - * whitespace at the end of the line. - * + * Flag to indicate that the decision to terminate a record should ignore whitespace + * at the end of the line. * @param ignoreWhitespace indicator */ public void setIgnoreWhitespace(boolean ignoreWhitespace) { @@ -55,13 +52,13 @@ public class SuffixRecordSeparatorPolicy extends DefaultRecordSeparatorPolicy { } /** - * Return true if the line ends with the specified substring. By default - * whitespace is trimmed before the comparison. Also returns true if the - * line is null, but not if it is empty. - * + * Return true if the line ends with the specified substring. By default whitespace is + * trimmed before the comparison. Also returns true if the line is null, but not if it + * is empty. + * * @see org.springframework.batch.item.file.separator.RecordSeparatorPolicy#isEndOfRecord(java.lang.String) */ - @Override + @Override public boolean isEndOfRecord(String line) { if (line == null) { return true; @@ -69,15 +66,15 @@ public class SuffixRecordSeparatorPolicy extends DefaultRecordSeparatorPolicy { String trimmed = ignoreWhitespace ? line.trim() : line; return trimmed.endsWith(suffix); } - + /** * Remove the suffix from the end of the record. - * + * * @see org.springframework.batch.item.file.separator.SimpleRecordSeparatorPolicy#postProcess(java.lang.String) */ - @Override + @Override public String postProcess(String record) { - if (record==null) { + if (record == null) { return null; } return record.substring(0, record.lastIndexOf(suffix)); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/AbstractLineTokenizer.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/AbstractLineTokenizer.java index 394ef73c8..2ee581d87 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/AbstractLineTokenizer.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/AbstractLineTokenizer.java @@ -25,9 +25,8 @@ import org.springframework.util.StringUtils; /** * Abstract class handling common concerns of various {@link LineTokenizer} - * implementations such as dealing with names and actual construction of - * {@link FieldSet} - * + * implementations such as dealing with names and actual construction of {@link FieldSet} + * * @author Dave Syer * @author Robert Kasanicky * @author Lucas Ward @@ -38,38 +37,33 @@ public abstract class AbstractLineTokenizer implements LineTokenizer { protected String[] names = new String[0]; private boolean strict = true; - + private String emptyToken = ""; private FieldSetFactory fieldSetFactory = new DefaultFieldSetFactory(); /** - * Public setter for the strict flag. If true (the default) then number of - * tokens in line must match the number of tokens defined - * (by {@link Range}, columns, etc.) in {@link LineTokenizer}. - * If false then lines with less tokens will be tolerated and padded with - * empty columns, and lines with more tokens will - * simply be truncated. - * + * Public setter for the strict flag. If true (the default) then number of tokens in + * line must match the number of tokens defined (by {@link Range}, columns, etc.) in + * {@link LineTokenizer}. If false then lines with less tokens will be tolerated and + * padded with empty columns, and lines with more tokens will simply be truncated. * @param strict the strict flag to set */ public void setStrict(boolean strict) { this.strict = strict; } - + /** * Provides access to the strict flag for subclasses if needed. - * * @return the strict flag value */ protected boolean isStrict() { return strict; } - + /** - * Factory for {@link FieldSet} instances. Can be injected by clients to - * customize the default number and date formats. - * + * Factory for {@link FieldSet} instances. Can be injected by clients to customize the + * default number and date formats. * @param fieldSetFactory the {@link FieldSetFactory} to set */ public void setFieldSetFactory(FieldSetFactory fieldSetFactory) { @@ -77,25 +71,24 @@ public abstract class AbstractLineTokenizer implements LineTokenizer { } /** - * Setter for column names. Optional, but if set, then all lines must have - * as many or fewer tokens. - * + * Setter for column names. Optional, but if set, then all lines must have as many or + * fewer tokens. * @param names names of each column */ public void setNames(String... names) { - if(names == null) { + if (names == null) { this.names = null; } else { boolean valid = false; for (String name : names) { - if(StringUtils.hasText(name)) { + if (StringUtils.hasText(name)) { valid = true; break; } } - if(valid) { + if (valid) { this.names = Arrays.asList(names).toArray(new String[names.length]); } } @@ -113,14 +106,11 @@ public abstract class AbstractLineTokenizer implements LineTokenizer { } /** - * Yields the tokens resulting from the splitting of the supplied - * line. - * + * Yields the tokens resulting from the splitting of the supplied line. * @param line the line to be tokenized (can be null) - * * @return the resulting tokens */ - @Override + @Override public FieldSet tokenize(@Nullable String line) { if (line == null) { @@ -128,12 +118,12 @@ public abstract class AbstractLineTokenizer implements LineTokenizer { } List tokens = new ArrayList<>(doTokenize(line)); - + // if names are set and strict flag is false - if ( ( names.length != 0 ) && ( ! strict ) ) { - adjustTokenCountIfNecessary( tokens ); + if ((names.length != 0) && (!strict)) { + adjustTokenCountIfNecessary(tokens); } - + String[] values = tokens.toArray(new String[tokens.size()]); if (names.length == 0) { @@ -146,36 +136,37 @@ public abstract class AbstractLineTokenizer implements LineTokenizer { } protected abstract List doTokenize(String line); - + /** - * Adds empty tokens or truncates existing token list to match expected - * (configured) number of tokens in {@link LineTokenizer}. - * + * Adds empty tokens or truncates existing token list to match expected (configured) + * number of tokens in {@link LineTokenizer}. * @param tokens - list of tokens */ - private void adjustTokenCountIfNecessary( List tokens ) { - + private void adjustTokenCountIfNecessary(List tokens) { + int nameLength = names.length; int tokensSize = tokens.size(); - + // if the number of tokens is not what expected - if ( nameLength != tokensSize ) { - - if ( nameLength > tokensSize ) { + if (nameLength != tokensSize) { + + if (nameLength > tokensSize) { // add empty tokens until the token list size matches // the expected number of tokens - for ( int i = 0; i < ( nameLength - tokensSize ); i++ ) { - tokens.add( emptyToken ); + for (int i = 0; i < (nameLength - tokensSize); i++) { + tokens.add(emptyToken); } - } else { + } + else { // truncate token list to match the number of expected tokens - for ( int i = tokensSize - 1; i >= nameLength; i-- ) { + for (int i = tokensSize - 1; i >= nameLength; i--) { tokens.remove(i); } } - + } } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/BeanWrapperFieldExtractor.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/BeanWrapperFieldExtractor.java index d7d082202..6bf43d6ab 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/BeanWrapperFieldExtractor.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/BeanWrapperFieldExtractor.java @@ -26,10 +26,9 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; /** - * This is a field extractor for a java bean. Given an array of property names, - * it will reflectively call getters on the item and return an array of all the - * values. - * + * This is a field extractor for a java bean. Given an array of property names, it will + * reflectively call getters on the item and return an array of all the values. + * * @author Dan Garrette * @since 2.0 */ @@ -48,7 +47,7 @@ public class BeanWrapperFieldExtractor implements FieldExtractor, Initiali /** * @see org.springframework.batch.item.file.transform.FieldExtractor#extract(java.lang.Object) */ - @Override + @Override public Object[] extract(T item) { List values = new ArrayList<>(); @@ -59,8 +58,9 @@ public class BeanWrapperFieldExtractor implements FieldExtractor, Initiali return values.toArray(); } - @Override + @Override public void afterPropertiesSet() { Assert.notNull(names, "The 'names' property must be set."); } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/DefaultFieldSet.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/DefaultFieldSet.java index 178ec9aa1..dc161d691 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/DefaultFieldSet.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/DefaultFieldSet.java @@ -32,10 +32,10 @@ import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** - * Default implementation of {@link FieldSet} using Java using Java primitive - * and standard types and utilities. Strings are trimmed before parsing by - * default, and so are plain String values. - * + * Default implementation of {@link FieldSet} using Java using Java primitive and standard + * types and utilities. Strings are trimmed before parsing by default, and so are plain + * String values. + * * @author Rob Harrop * @author Dave Syer */ @@ -44,6 +44,7 @@ public class DefaultFieldSet implements FieldSet { private final static String DEFAULT_DATE_PATTERN = "yyyy-MM-dd"; private DateFormat dateFormat = new SimpleDateFormat(DEFAULT_DATE_PATTERN); + { dateFormat.setLenient(false); } @@ -62,8 +63,8 @@ public class DefaultFieldSet implements FieldSet { private List names; /** - * The {@link NumberFormat} to use for parsing numbers. If unset the US - * locale will be used ('.' as decimal place). + * The {@link NumberFormat} to use for parsing numbers. If unset the US locale will be + * used ('.' as decimal place). * @param numberFormat the {@link NumberFormat} to use for number parsing */ public final void setNumberFormat(NumberFormat numberFormat) { @@ -75,8 +76,8 @@ public class DefaultFieldSet implements FieldSet { } /** - * The {@link DateFormat} to use for parsing numbers. If unset the default - * pattern is ISO standard yyyy/MM/dd. + * The {@link DateFormat} to use for parsing numbers. If unset the default pattern is + * ISO standard yyyy/MM/dd. * @param dateFormat the {@link DateFormat} to use for date parsing */ public void setDateFormat(DateFormat dateFormat) { @@ -84,8 +85,8 @@ public class DefaultFieldSet implements FieldSet { } /** - * Create a FieldSet with anonymous tokens. They can only be retrieved by - * column number. + * Create a FieldSet with anonymous tokens. They can only be retrieved by column + * number. * @param tokens the token values * @see FieldSet#readString(int) */ @@ -95,8 +96,8 @@ public class DefaultFieldSet implements FieldSet { } /** - * Create a FieldSet with named tokens. The token values can then be - * retrieved either by name or by column number. + * Create a FieldSet with named tokens. The token values can then be retrieved either + * by name or by column number. * @param tokens the token values * @param names the names of the tokens * @see FieldSet#readString(String) @@ -115,10 +116,10 @@ public class DefaultFieldSet implements FieldSet { /* * (non-Javadoc) - * + * * @see org.springframework.batch.item.file.mapping.IFieldSet#getNames() */ - @Override + @Override public String[] getNames() { if (names == null) { throw new IllegalStateException("Field names are not known"); @@ -128,101 +129,94 @@ public class DefaultFieldSet implements FieldSet { /* * (non-Javadoc) - * + * * @see org.springframework.batch.item.file.mapping.FieldSet#hasNames() */ - @Override + @Override public boolean hasNames() { return names != null; } /* * (non-Javadoc) - * + * * @see org.springframework.batch.item.file.mapping.IFieldSet#getValues() */ - @Override + @Override public String[] getValues() { return tokens.clone(); } /* * (non-Javadoc) - * - * @see - * org.springframework.batch.item.file.mapping.IFieldSet#readString(int) + * + * @see org.springframework.batch.item.file.mapping.IFieldSet#readString(int) */ - @Override + @Override public String readString(int index) { return readAndTrim(index); } /* * (non-Javadoc) - * - * @see - * org.springframework.batch.item.file.mapping.IFieldSet#readString(java + * + * @see org.springframework.batch.item.file.mapping.IFieldSet#readString(java * .lang.String) */ - @Override + @Override public String readString(String name) { return readString(indexOf(name)); } /* * (non-Javadoc) - * - * @see - * org.springframework.batch.item.file.mapping.IFieldSet#readRawString(int) + * + * @see org.springframework.batch.item.file.mapping.IFieldSet#readRawString(int) */ - @Override + @Override public String readRawString(int index) { return tokens[index]; } /* * (non-Javadoc) - * - * @see - * org.springframework.batch.item.file.mapping.IFieldSet#readRawString(java + * + * @see org.springframework.batch.item.file.mapping.IFieldSet#readRawString(java * .lang.String) */ - @Override + @Override public String readRawString(String name) { return readRawString(indexOf(name)); } /* * (non-Javadoc) - * - * @see - * org.springframework.batch.item.file.mapping.IFieldSet#readBoolean(int) + * + * @see org.springframework.batch.item.file.mapping.IFieldSet#readBoolean(int) */ - @Override + @Override public boolean readBoolean(int index) { return readBoolean(index, "true"); } /* * (non-Javadoc) - * - * @see - * org.springframework.batch.item.file.mapping.IFieldSet#readBoolean(java + * + * @see org.springframework.batch.item.file.mapping.IFieldSet#readBoolean(java * .lang.String) */ - @Override + @Override public boolean readBoolean(String name) { return readBoolean(indexOf(name)); } /* * (non-Javadoc) - * - * @see - * org.springframework.batch.item.file.mapping.IFieldSet#readBoolean(int, + * + * @see org.springframework.batch.item.file.mapping.IFieldSet#readBoolean(int, * java.lang.String) */ - @Override + @Override public boolean readBoolean(int index, String trueValue) { Assert.notNull(trueValue, "'trueValue' cannot be null."); @@ -233,22 +227,21 @@ public class DefaultFieldSet implements FieldSet { /* * (non-Javadoc) - * - * @see - * org.springframework.batch.item.file.mapping.IFieldSet#readBoolean(java + * + * @see org.springframework.batch.item.file.mapping.IFieldSet#readBoolean(java * .lang.String, java.lang.String) */ - @Override + @Override public boolean readBoolean(String name, String trueValue) { return readBoolean(indexOf(name), trueValue); } /* * (non-Javadoc) - * + * * @see org.springframework.batch.item.file.mapping.IFieldSet#readChar(int) */ - @Override + @Override public char readChar(int index) { String value = readAndTrim(index); @@ -259,89 +252,84 @@ public class DefaultFieldSet implements FieldSet { /* * (non-Javadoc) - * - * @see - * org.springframework.batch.item.file.mapping.IFieldSet#readChar(java.lang + * + * @see org.springframework.batch.item.file.mapping.IFieldSet#readChar(java.lang * .String) */ - @Override + @Override public char readChar(String name) { return readChar(indexOf(name)); } /* * (non-Javadoc) - * + * * @see org.springframework.batch.item.file.mapping.IFieldSet#readByte(int) */ - @Override + @Override public byte readByte(int index) { return Byte.parseByte(readAndTrim(index)); } /* * (non-Javadoc) - * - * @see - * org.springframework.batch.item.file.mapping.IFieldSet#readByte(java.lang + * + * @see org.springframework.batch.item.file.mapping.IFieldSet#readByte(java.lang * .String) */ - @Override + @Override public byte readByte(String name) { return readByte(indexOf(name)); } /* * (non-Javadoc) - * + * * @see org.springframework.batch.item.file.mapping.IFieldSet#readShort(int) */ - @Override + @Override public short readShort(int index) { return Short.parseShort(readAndTrim(index)); } /* * (non-Javadoc) - * - * @see - * org.springframework.batch.item.file.mapping.IFieldSet#readShort(java. + * + * @see org.springframework.batch.item.file.mapping.IFieldSet#readShort(java. * lang.String) */ - @Override + @Override public short readShort(String name) { return readShort(indexOf(name)); } /* * (non-Javadoc) - * + * * @see org.springframework.batch.item.file.mapping.IFieldSet#readInt(int) */ - @Override + @Override public int readInt(int index) { return parseNumber(readAndTrim(index)).intValue(); } /* * (non-Javadoc) - * - * @see - * org.springframework.batch.item.file.mapping.IFieldSet#readInt(java.lang + * + * @see org.springframework.batch.item.file.mapping.IFieldSet#readInt(java.lang * .String) */ - @Override + @Override public int readInt(String name) { return readInt(indexOf(name)); } /* * (non-Javadoc) - * - * @see org.springframework.batch.item.file.mapping.IFieldSet#readInt(int, - * int) + * + * @see org.springframework.batch.item.file.mapping.IFieldSet#readInt(int, int) */ - @Override + @Override public int readInt(int index, int defaultValue) { String value = readAndTrim(index); @@ -350,45 +338,42 @@ public class DefaultFieldSet implements FieldSet { /* * (non-Javadoc) - * - * @see - * org.springframework.batch.item.file.mapping.IFieldSet#readInt(java.lang + * + * @see org.springframework.batch.item.file.mapping.IFieldSet#readInt(java.lang * .String, int) */ - @Override + @Override public int readInt(String name, int defaultValue) { return readInt(indexOf(name), defaultValue); } /* * (non-Javadoc) - * + * * @see org.springframework.batch.item.file.mapping.IFieldSet#readLong(int) */ - @Override + @Override public long readLong(int index) { return parseNumber(readAndTrim(index)).longValue(); } /* * (non-Javadoc) - * - * @see - * org.springframework.batch.item.file.mapping.IFieldSet#readLong(java.lang + * + * @see org.springframework.batch.item.file.mapping.IFieldSet#readLong(java.lang * .String) */ - @Override + @Override public long readLong(String name) { return readLong(indexOf(name)); } /* * (non-Javadoc) - * - * @see org.springframework.batch.item.file.mapping.IFieldSet#readLong(int, - * long) + * + * @see org.springframework.batch.item.file.mapping.IFieldSet#readLong(int, long) */ - @Override + @Override public long readLong(int index, long defaultValue) { String value = readAndTrim(index); @@ -397,92 +382,85 @@ public class DefaultFieldSet implements FieldSet { /* * (non-Javadoc) - * - * @see - * org.springframework.batch.item.file.mapping.IFieldSet#readLong(java.lang + * + * @see org.springframework.batch.item.file.mapping.IFieldSet#readLong(java.lang * .String, long) */ - @Override + @Override public long readLong(String name, long defaultValue) { return readLong(indexOf(name), defaultValue); } /* * (non-Javadoc) - * + * * @see org.springframework.batch.item.file.mapping.IFieldSet#readFloat(int) */ - @Override + @Override public float readFloat(int index) { return parseNumber(readAndTrim(index)).floatValue(); } /* * (non-Javadoc) - * - * @see - * org.springframework.batch.item.file.mapping.IFieldSet#readFloat(java. + * + * @see org.springframework.batch.item.file.mapping.IFieldSet#readFloat(java. * lang.String) */ - @Override + @Override public float readFloat(String name) { return readFloat(indexOf(name)); } /* * (non-Javadoc) - * - * @see - * org.springframework.batch.item.file.mapping.IFieldSet#readDouble(int) + * + * @see org.springframework.batch.item.file.mapping.IFieldSet#readDouble(int) */ - @Override + @Override public double readDouble(int index) { return parseNumber(readAndTrim(index)).doubleValue(); } /* * (non-Javadoc) - * - * @see - * org.springframework.batch.item.file.mapping.IFieldSet#readDouble(java + * + * @see org.springframework.batch.item.file.mapping.IFieldSet#readDouble(java * .lang.String) */ - @Override + @Override public double readDouble(String name) { return readDouble(indexOf(name)); } /* * (non-Javadoc) - * - * @see - * org.springframework.batch.item.file.mapping.IFieldSet#readBigDecimal(int) + * + * @see org.springframework.batch.item.file.mapping.IFieldSet#readBigDecimal(int) */ - @Override + @Override public BigDecimal readBigDecimal(int index) { return readBigDecimal(index, null); } /* * (non-Javadoc) - * - * @see - * org.springframework.batch.item.file.mapping.IFieldSet#readBigDecimal( + * + * @see org.springframework.batch.item.file.mapping.IFieldSet#readBigDecimal( * java.lang.String) */ - @Override + @Override public BigDecimal readBigDecimal(String name) { return readBigDecimal(name, null); } /* * (non-Javadoc) - * - * @see - * org.springframework.batch.item.file.mapping.IFieldSet#readBigDecimal(int, + * + * @see org.springframework.batch.item.file.mapping.IFieldSet#readBigDecimal(int, * java.math.BigDecimal) */ - @Override + @Override public BigDecimal readBigDecimal(int index, BigDecimal defaultValue) { String candidate = readAndTrim(index); @@ -505,12 +483,11 @@ public class DefaultFieldSet implements FieldSet { /* * (non-Javadoc) - * - * @see - * org.springframework.batch.item.file.mapping.IFieldSet#readBigDecimal( + * + * @see org.springframework.batch.item.file.mapping.IFieldSet#readBigDecimal( * java.lang.String, java.math.BigDecimal) */ - @Override + @Override public BigDecimal readBigDecimal(String name, BigDecimal defaultValue) { try { return readBigDecimal(indexOf(name), defaultValue); @@ -525,21 +502,21 @@ public class DefaultFieldSet implements FieldSet { /* * (non-Javadoc) - * + * * @see org.springframework.batch.item.file.mapping.IFieldSet#readDate(int) */ - @Override + @Override public Date readDate(int index) { return parseDate(readAndTrim(index), dateFormat); } /* * (non-Javadoc) - * + * * @see org.springframework.batch.item.file.transform.FieldSet#readDate(int, * java.util.Date) */ - @Override + @Override public Date readDate(int index, Date defaultValue) { String candidate = readAndTrim(index); return StringUtils.hasText(candidate) ? parseDate(candidate, dateFormat) : defaultValue; @@ -547,12 +524,11 @@ public class DefaultFieldSet implements FieldSet { /* * (non-Javadoc) - * - * @see - * org.springframework.batch.item.file.mapping.IFieldSet#readDate(java.lang + * + * @see org.springframework.batch.item.file.mapping.IFieldSet#readDate(java.lang * .String) */ - @Override + @Override public Date readDate(String name) { try { return readDate(indexOf(name)); @@ -564,11 +540,11 @@ public class DefaultFieldSet implements FieldSet { /* * (non-Javadoc) - * + * * @see org.springframework.batch.item.file.transform.FieldSet#readDate(int, * java.util.Date) */ - @Override + @Override public Date readDate(String name, Date defaultValue) { try { return readDate(indexOf(name), defaultValue); @@ -580,11 +556,11 @@ public class DefaultFieldSet implements FieldSet { /* * (non-Javadoc) - * + * * @see org.springframework.batch.item.file.mapping.IFieldSet#readDate(int, * java.lang.String) */ - @Override + @Override public Date readDate(int index, String pattern) { SimpleDateFormat sdf = new SimpleDateFormat(pattern); sdf.setLenient(false); @@ -593,11 +569,11 @@ public class DefaultFieldSet implements FieldSet { /* * (non-Javadoc) - * + * * @see org.springframework.batch.item.file.mapping.IFieldSet#readDate(int, * java.lang.String) */ - @Override + @Override public Date readDate(int index, String pattern, Date defaultValue) { String candidate = readAndTrim(index); return StringUtils.hasText(candidate) ? readDate(index, pattern) : defaultValue; @@ -605,12 +581,11 @@ public class DefaultFieldSet implements FieldSet { /* * (non-Javadoc) - * - * @see - * org.springframework.batch.item.file.mapping.IFieldSet#readDate(java.lang + * + * @see org.springframework.batch.item.file.mapping.IFieldSet#readDate(java.lang * .String, java.lang.String) */ - @Override + @Override public Date readDate(String name, String pattern) { try { return readDate(indexOf(name), pattern); @@ -622,11 +597,11 @@ public class DefaultFieldSet implements FieldSet { /* * (non-Javadoc) - * + * * @see org.springframework.batch.item.file.mapping.IFieldSet#readDate(int, * java.lang.String) */ - @Override + @Override public Date readDate(String name, String pattern, Date defaultValue) { try { return readDate(indexOf(name), pattern, defaultValue); @@ -638,20 +613,17 @@ public class DefaultFieldSet implements FieldSet { /* * (non-Javadoc) - * - * @see - * org.springframework.batch.item.file.mapping.IFieldSet#getFieldCount() + * + * @see org.springframework.batch.item.file.mapping.IFieldSet#getFieldCount() */ - @Override + @Override public int getFieldCount() { return tokens.length; } /** * Read and trim the {@link String} value at 'index'. - * * @param index the offset in the token array to obtain the value to be trimmed. - * * @return null if the field value is null. */ protected String readAndTrim(int index) { @@ -666,14 +638,11 @@ public class DefaultFieldSet implements FieldSet { } /** - * Retrieve the index of where a specified column is located based on the - * {@code name} parameter. - * + * Retrieve the index of where a specified column is located based on the {@code name} + * parameter. * @param name the value to search in the {@link List} of names. * @return the index in the {@link List} of names where the name was found. - * - * @throws IllegalArgumentException if a column with given name is not - * defined. + * @throws IllegalArgumentException if a column with given name is not defined. */ protected int indexOf(String name) { if (names == null) { @@ -686,7 +655,7 @@ public class DefaultFieldSet implements FieldSet { throw new IllegalArgumentException("Cannot access column [" + name + "] from " + names); } - @Override + @Override public String toString() { if (names != null) { return getProperties().toString(); @@ -698,7 +667,7 @@ public class DefaultFieldSet implements FieldSet { /** * @see java.lang.Object#equals(java.lang.Object) */ - @Override + @Override public boolean equals(Object object) { if (object instanceof DefaultFieldSet) { DefaultFieldSet fs = (DefaultFieldSet) object; @@ -714,7 +683,7 @@ public class DefaultFieldSet implements FieldSet { return false; } - @Override + @Override public int hashCode() { // this algorithm was taken from java 1.5 jdk Arrays.hashCode(Object[]) if (tokens == null) { @@ -732,11 +701,10 @@ public class DefaultFieldSet implements FieldSet { /* * (non-Javadoc) - * - * @see - * org.springframework.batch.item.file.mapping.IFieldSet#getProperties() + * + * @see org.springframework.batch.item.file.mapping.IFieldSet#getProperties() */ - @Override + @Override public Properties getProperties() { if (names == null) { throw new IllegalStateException("Cannot create properties without meta data"); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/DefaultFieldSetFactory.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/DefaultFieldSetFactory.java index 5e723baba..7ef0fca1b 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/DefaultFieldSetFactory.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/DefaultFieldSetFactory.java @@ -19,12 +19,11 @@ import java.text.DateFormat; import java.text.NumberFormat; /** - * Default implementation of {@link FieldSetFactory} with no special knowledge - * of the {@link FieldSet} required. Returns a {@link DefaultFieldSet} from both - * factory methods. - * + * Default implementation of {@link FieldSetFactory} with no special knowledge of the + * {@link FieldSet} required. Returns a {@link DefaultFieldSet} from both factory methods. + * * @author Dave Syer - * + * */ public class DefaultFieldSetFactory implements FieldSetFactory { @@ -33,8 +32,8 @@ public class DefaultFieldSetFactory implements FieldSetFactory { private NumberFormat numberFormat; /** - * The {@link NumberFormat} to use for parsing numbers. If unset the default - * locale will be used. + * The {@link NumberFormat} to use for parsing numbers. If unset the default locale + * will be used. * @param numberFormat the {@link NumberFormat} to use for number parsing */ public void setNumberFormat(NumberFormat numberFormat) { @@ -42,8 +41,8 @@ public class DefaultFieldSetFactory implements FieldSetFactory { } /** - * The {@link DateFormat} to use for parsing numbers. If unset the default - * pattern is ISO standard yyyy/MM/dd. + * The {@link DateFormat} to use for parsing numbers. If unset the default pattern is + * ISO standard yyyy/MM/dd. * @param dateFormat the {@link DateFormat} to use for date parsing */ public void setDateFormat(DateFormat dateFormat) { @@ -53,7 +52,7 @@ public class DefaultFieldSetFactory implements FieldSetFactory { /** * {@inheritDoc} */ - @Override + @Override public FieldSet create(String[] values, String[] names) { DefaultFieldSet fieldSet = new DefaultFieldSet(values, names); return enhance(fieldSet); @@ -62,19 +61,19 @@ public class DefaultFieldSetFactory implements FieldSetFactory { /** * {@inheritDoc} */ - @Override + @Override public FieldSet create(String[] values) { DefaultFieldSet fieldSet = new DefaultFieldSet(values); return enhance(fieldSet); } private FieldSet enhance(DefaultFieldSet fieldSet) { - if (dateFormat!=null) { + if (dateFormat != null) { fieldSet.setDateFormat(dateFormat); } - if (numberFormat!=null) { + if (numberFormat != null) { fieldSet.setNumberFormat(numberFormat); - } + } return fieldSet; } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/DelimitedLineAggregator.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/DelimitedLineAggregator.java index 6433ba6e7..8e841bed4 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/DelimitedLineAggregator.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/DelimitedLineAggregator.java @@ -1,44 +1,44 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.file.transform; - -import org.springframework.util.StringUtils; - -/** - * A {@link LineAggregator} implementation that converts an object into a - * delimited list of strings. The default delimiter is a comma. - * - * @author Dave Syer - * - */ -public class DelimitedLineAggregator extends ExtractorLineAggregator { - - private String delimiter = ","; - - /** - * Public setter for the delimiter. - * @param delimiter the delimiter to set - */ - public void setDelimiter(String delimiter) { - this.delimiter = delimiter; - } - - @Override - public String doAggregate(Object[] fields) { - return StringUtils.arrayToDelimitedString(fields, this.delimiter); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item.file.transform; + +import org.springframework.util.StringUtils; + +/** + * A {@link LineAggregator} implementation that converts an object into a delimited list + * of strings. The default delimiter is a comma. + * + * @author Dave Syer + * + */ +public class DelimitedLineAggregator extends ExtractorLineAggregator { + + private String delimiter = ","; + + /** + * Public setter for the delimiter. + * @param delimiter the delimiter to set + */ + public void setDelimiter(String delimiter) { + this.delimiter = delimiter; + } + + @Override + public String doAggregate(Object[] fields) { + return StringUtils.arrayToDelimitedString(fields, this.delimiter); + } + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/DelimitedLineTokenizer.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/DelimitedLineTokenizer.java index 02973ac59..74181a735 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/DelimitedLineTokenizer.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/DelimitedLineTokenizer.java @@ -26,17 +26,17 @@ import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** - * A {@link LineTokenizer} implementation that splits the input String on a - * configurable delimiter. This implementation also supports the use of an - * escape character to escape delimiters and line endings. + * A {@link LineTokenizer} implementation that splits the input String on a configurable + * delimiter. This implementation also supports the use of an escape character to escape + * delimiters and line endings. * * @author Rob Harrop * @author Dave Syer * @author Michael Minella * @author Olivier Bourgain */ -public class DelimitedLineTokenizer extends AbstractLineTokenizer - implements InitializingBean { +public class DelimitedLineTokenizer extends AbstractLineTokenizer implements InitializingBean { + /** * Convenient constant for the common case of a tab delimiter. */ @@ -48,8 +48,8 @@ public class DelimitedLineTokenizer extends AbstractLineTokenizer public static final String DELIMITER_COMMA = ","; /** - * Convenient constant for the common case of a " character used to escape - * delimiters or line endings. + * Convenient constant for the common case of a " character used to escape delimiters + * or line endings. */ public static final char DEFAULT_QUOTE_CHARACTER = '"'; @@ -60,13 +60,13 @@ public class DelimitedLineTokenizer extends AbstractLineTokenizer private String quoteString; - private String escapedQuoteString; + private String escapedQuoteString; private Collection includedFields = null; /** - * Create a new instance of the {@link DelimitedLineTokenizer} class for the - * common case where the delimiter is a {@link #DELIMITER_COMMA comma}. + * Create a new instance of the {@link DelimitedLineTokenizer} class for the common + * case where the delimiter is a {@link #DELIMITER_COMMA comma}. * * @see #DelimitedLineTokenizer(String) * @see #DELIMITER_COMMA @@ -77,13 +77,12 @@ public class DelimitedLineTokenizer extends AbstractLineTokenizer /** * Create a new instance of the {@link DelimitedLineTokenizer} class. - * - * @param delimiter the desired delimiter. This is required + * @param delimiter the desired delimiter. This is required */ public DelimitedLineTokenizer(String delimiter) { Assert.notNull(delimiter, "A delimiter is required"); - Assert.state(!delimiter.equals(String.valueOf(DEFAULT_QUOTE_CHARACTER)), "[" + DEFAULT_QUOTE_CHARACTER - + "] is not allowed as delimiter for tokenizers."); + Assert.state(!delimiter.equals(String.valueOf(DEFAULT_QUOTE_CHARACTER)), + "[" + DEFAULT_QUOTE_CHARACTER + "] is not allowed as delimiter for tokenizers."); this.delimiter = delimiter; setQuoteCharacter(DEFAULT_QUOTE_CHARACTER); @@ -91,7 +90,6 @@ public class DelimitedLineTokenizer extends AbstractLineTokenizer /** * Setter for the delimiter character. - * * @param delimiter the String used as a delimiter */ public void setDelimiter(String delimiter) { @@ -99,11 +97,10 @@ public class DelimitedLineTokenizer extends AbstractLineTokenizer } /** - * The fields to include in the output by position (starting at 0). By - * default all fields are included, but this property can be set to pick out - * only a few fields from a larger set. Note that if field names are - * provided, their number must match the number of included fields. - * + * The fields to include in the output by position (starting at 0). By default all + * fields are included, but this property can be set to pick out only a few fields + * from a larger set. Note that if field names are provided, their number must match + * the number of included fields. * @param includedFields the included fields to set */ public void setIncludedFields(int... includedFields) { @@ -114,11 +111,10 @@ public class DelimitedLineTokenizer extends AbstractLineTokenizer } /** - * Public setter for the quoteCharacter. The quote character can be used to - * extend a field across line endings or to enclose a String which contains - * the delimiter. Inside a quoted token the quote character can be used to - * escape itself, thus "a""b""c" is tokenized to a"b"c. - * + * Public setter for the quoteCharacter. The quote character can be used to extend a + * field across line endings or to enclose a String which contains the delimiter. + * Inside a quoted token the quote character can be used to escape itself, thus + * "a""b""c" is tokenized to a"b"c. * @param quoteCharacter the quoteCharacter to set * * @see #DEFAULT_QUOTE_CHARACTER @@ -126,15 +122,12 @@ public class DelimitedLineTokenizer extends AbstractLineTokenizer public void setQuoteCharacter(char quoteCharacter) { this.quoteCharacter = quoteCharacter; this.quoteString = "" + quoteCharacter; - this.escapedQuoteString = "" + quoteCharacter + quoteCharacter; + this.escapedQuoteString = "" + quoteCharacter + quoteCharacter; } /** - * Yields the tokens resulting from the splitting of the supplied - * line. - * + * Yields the tokens resulting from the splitting of the supplied line. * @param line the line to be tokenized - * * @return the resulting tokens */ @Override @@ -154,7 +147,7 @@ public class DelimitedLineTokenizer extends AbstractLineTokenizer char currentChar = line.charAt(i); boolean isEnd = (i == (length - 1)); - boolean isDelimiter = endsWithDelimiter(line, i, endIndexLastDelimiter); + boolean isDelimiter = endsWithDelimiter(line, i, endIndexLastDelimiter); if ((isDelimiter && !inQuoted) || isEnd) { endIndexLastDelimiter = i; @@ -163,13 +156,12 @@ public class DelimitedLineTokenizer extends AbstractLineTokenizer if (isEnd && isDelimiter) { endPosition = endPosition - delimiter.length(); } - else if (!isEnd){ + else if (!isEnd) { endPosition = (endPosition - delimiter.length()) + 1; } if (includedFields == null || includedFields.contains(fieldCount)) { - String value = - substringWithTrimmedWhitespaceAndQuotesIfQuotesPresent(line, lastCut, endPosition); + String value = substringWithTrimmedWhitespaceAndQuotesIfQuotesPresent(line, lastCut, endPosition); tokens.add(value); } @@ -193,86 +185,85 @@ public class DelimitedLineTokenizer extends AbstractLineTokenizer return tokens; } - /** - * Trim any leading or trailing quotes (and any leading or trailing - * whitespace before or after the quotes) from within the specified character - * array beginning at the specified offset index for the specified count. - *

      - * Quotes are escaped with double instances of the quote character. - * - * @param line the string - * @param offset index from which to begin extracting substring - * @param count length of substring - * @return a substring from the specified offset within the character array - * with any leading or trailing whitespace trimmed. - * @see String#trim() - */ - private String substringWithTrimmedWhitespaceAndQuotesIfQuotesPresent(String line, int offset, int count) { - int start = offset; - int len = count; + /** + * Trim any leading or trailing quotes (and any leading or trailing whitespace before + * or after the quotes) from within the specified character array beginning at the + * specified offset index for the specified count. + *

      + * Quotes are escaped with double instances of the quote character. + * @param line the string + * @param offset index from which to begin extracting substring + * @param count length of substring + * @return a substring from the specified offset within the character array with any + * leading or trailing whitespace trimmed. + * @see String#trim() + */ + private String substringWithTrimmedWhitespaceAndQuotesIfQuotesPresent(String line, int offset, int count) { + int start = offset; + int len = count; - while ((start < (start + len - 1)) && (line.charAt(start) <= ' ')) { - start++; - len--; - } + while ((start < (start + len - 1)) && (line.charAt(start) <= ' ')) { + start++; + len--; + } - while ((start < (start + len)) && ((start + len - 1 < line.length()) && (line.charAt(start + len - 1) <= ' '))) { - len--; - } + while ((start < (start + len)) + && ((start + len - 1 < line.length()) && (line.charAt(start + len - 1) <= ' '))) { + len--; + } - String value; + String value; - if ((line.length() >= 2) && isQuoteCharacter(line.charAt(start)) && isQuoteCharacter(line.charAt(start + len - 1))) { + if ((line.length() >= 2) && isQuoteCharacter(line.charAt(start)) + && isQuoteCharacter(line.charAt(start + len - 1))) { int beginIndex = start + 1; int endIndex = len - 2; value = line.substring(beginIndex, beginIndex + endIndex); - if (value.contains(escapedQuoteString)) { - value = StringUtils.replace(value, escapedQuoteString, quoteString); - } - } - else { - value = line.substring(offset, offset + count); - } + if (value.contains(escapedQuoteString)) { + value = StringUtils.replace(value, escapedQuoteString, quoteString); + } + } + else { + value = line.substring(offset, offset + count); + } - return value; - } + return value; + } - /** - * Do the character(s) in the specified array end, at the specified end - * index, with the delimiter character(s)? - *

      - * Checks that the specified end index is sufficiently greater than the - * specified previous delimiter end index to warrant trying to match - * another delimiter. Also checks that the specified end index is - * sufficiently large to be able to match the length of a delimiter. - * - * @param line the string - * @param end the index in up to which the delimiter should be matched - * @param previous the index of the end of the last delimiter - * @return true if the character(s) from the specified end - * match the delimiter character(s), otherwise false - * @see DelimitedLineTokenizer#DelimitedLineTokenizer(String) - */ - private boolean endsWithDelimiter(String line, int end, int previous) { - boolean result = false; + /** + * Do the character(s) in the specified array end, at the specified end index, with + * the delimiter character(s)? + *

      + * Checks that the specified end index is sufficiently greater than the specified + * previous delimiter end index to warrant trying to match another delimiter. Also + * checks that the specified end index is sufficiently large to be able to match the + * length of a delimiter. + * @param line the string + * @param end the index in up to which the delimiter should be matched + * @param previous the index of the end of the last delimiter + * @return true if the character(s) from the specified end match the + * delimiter character(s), otherwise false + * @see DelimitedLineTokenizer#DelimitedLineTokenizer(String) + */ + private boolean endsWithDelimiter(String line, int end, int previous) { + boolean result = false; - if (end - previous >= delimiter.length()) { - if (end >= delimiter.length() - 1) { - result = true; - for (int j = 0; j < delimiter.length() && (((end - delimiter.length() + 1) + j) < line.length()); j++) { - if (delimiter.charAt(j) != line.charAt((end - delimiter.length() + 1) + j)) { - result = false; - } - } - } - } + if (end - previous >= delimiter.length()) { + if (end >= delimiter.length() - 1) { + result = true; + for (int j = 0; j < delimiter.length() && (((end - delimiter.length() + 1) + j) < line.length()); j++) { + if (delimiter.charAt(j) != line.charAt((end - delimiter.length() + 1) + j)) { + result = false; + } + } + } + } - return result; - } + return result; + } /** * Is the supplied character a quote character? - * * @param c the character to be checked * @return true if the supplied character is an quote character * @see #setQuoteCharacter(char) @@ -285,4 +276,5 @@ public class DelimitedLineTokenizer extends AbstractLineTokenizer public void afterPropertiesSet() throws Exception { Assert.hasLength(this.delimiter, "A delimiter is required"); } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/ExtractorLineAggregator.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/ExtractorLineAggregator.java index dfc0c9cbf..af132dbdc 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/ExtractorLineAggregator.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/ExtractorLineAggregator.java @@ -1,79 +1,76 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.file.transform; - -import org.springframework.util.Assert; - -/** - * An abstract {@link LineAggregator} implementation that utilizes a - * {@link FieldExtractor} to convert the incoming object to an array of its - * parts. Extending classes must decide how those parts will be aggregated - * together. - * - * @author Dan Garrette - * @since 2.0 - */ -public abstract class ExtractorLineAggregator implements LineAggregator { - - private FieldExtractor fieldExtractor = new PassThroughFieldExtractor<>(); - - /** - * Public setter for the field extractor responsible for splitting an input - * object up into an array of objects. Defaults to - * {@link PassThroughFieldExtractor}. - * - * @param fieldExtractor The field extractor to set - */ - public void setFieldExtractor(FieldExtractor fieldExtractor) { - this.fieldExtractor = fieldExtractor; - } - - /** - * Extract fields from the given item using the {@link FieldExtractor} and - * then aggregate them. Any null field returned by the extractor will be - * replaced by an empty String. Null items are not allowed. - * - * @see org.springframework.batch.item.file.transform.LineAggregator#aggregate(java.lang.Object) - */ - @Override - public String aggregate(T item) { - Assert.notNull(item, "Item is required"); - Object[] fields = this.fieldExtractor.extract(item); - - // - // Replace nulls with empty strings - // - Object[] args = new Object[fields.length]; - for (int i = 0; i < fields.length; i++) { - if (fields[i] == null) { - args[i] = ""; - } - else { - args[i] = fields[i]; - } - } - - return this.doAggregate(args); - } - - /** - * Aggregate provided fields into single String. - * - * @param fields An array of the fields that must be aggregated - * @return aggregated string - */ - protected abstract String doAggregate(Object[] fields); -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item.file.transform; + +import org.springframework.util.Assert; + +/** + * An abstract {@link LineAggregator} implementation that utilizes a + * {@link FieldExtractor} to convert the incoming object to an array of its parts. + * Extending classes must decide how those parts will be aggregated together. + * + * @author Dan Garrette + * @since 2.0 + */ +public abstract class ExtractorLineAggregator implements LineAggregator { + + private FieldExtractor fieldExtractor = new PassThroughFieldExtractor<>(); + + /** + * Public setter for the field extractor responsible for splitting an input object up + * into an array of objects. Defaults to {@link PassThroughFieldExtractor}. + * @param fieldExtractor The field extractor to set + */ + public void setFieldExtractor(FieldExtractor fieldExtractor) { + this.fieldExtractor = fieldExtractor; + } + + /** + * Extract fields from the given item using the {@link FieldExtractor} and then + * aggregate them. Any null field returned by the extractor will be replaced by an + * empty String. Null items are not allowed. + * + * @see org.springframework.batch.item.file.transform.LineAggregator#aggregate(java.lang.Object) + */ + @Override + public String aggregate(T item) { + Assert.notNull(item, "Item is required"); + Object[] fields = this.fieldExtractor.extract(item); + + // + // Replace nulls with empty strings + // + Object[] args = new Object[fields.length]; + for (int i = 0; i < fields.length; i++) { + if (fields[i] == null) { + args[i] = ""; + } + else { + args[i] = fields[i]; + } + } + + return this.doAggregate(args); + } + + /** + * Aggregate provided fields into single String. + * @param fields An array of the fields that must be aggregated + * @return aggregated string + */ + protected abstract String doAggregate(Object[] fields); + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/FieldExtractor.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/FieldExtractor.java index 8a23934e9..b9c48ce0f 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/FieldExtractor.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/FieldExtractor.java @@ -1,33 +1,33 @@ -/* - * Copyright 2006-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.file.transform; - -/** - * This class will convert an object to an array of its parts. - * - * @author Dave Syer - * @author Mahmoud Ben Hassine - * - */ -public interface FieldExtractor { - - /** - * @param item the object that contains the information to be extracted. - * @return an array containing item's parts - */ - Object[] extract(T item); - -} +/* + * Copyright 2006-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item.file.transform; + +/** + * This class will convert an object to an array of its parts. + * + * @author Dave Syer + * @author Mahmoud Ben Hassine + * + */ +public interface FieldExtractor { + + /** + * @param item the object that contains the information to be extracted. + * @return an array containing item's parts + */ + Object[] extract(T item); + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/FieldSet.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/FieldSet.java index 4b57676fb..42c9153f5 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/FieldSet.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/FieldSet.java @@ -1,18 +1,18 @@ - /* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +/* +* Copyright 2006-2007 the original author or authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ package org.springframework.batch.item.file.transform; import java.math.BigDecimal; @@ -21,71 +21,61 @@ import java.util.Date; import java.util.Properties; /** - * Interface used by flat file input sources to encapsulate concerns of - * converting an array of Strings to Java native types. A bit like the role - * played by {@link ResultSet} in JDBC, clients will know the name or position - * of strongly typed fields that they want to extract. - * + * Interface used by flat file input sources to encapsulate concerns of converting an + * array of Strings to Java native types. A bit like the role played by {@link ResultSet} + * in JDBC, clients will know the name or position of strongly typed fields that they want + * to extract. + * * @author Dave Syer - * + * */ public interface FieldSet { /** * Accessor for the names of the fields. - * * @return the names - * * @throws IllegalStateException if the names are not defined */ String[] getNames(); /** * Check if there are names defined for the fields. - * * @return true if there are names for the fields */ boolean hasNames(); /** - * @return fields wrapped by this 'FieldSet' instance as - * String values. + * @return fields wrapped by this 'FieldSet' instance as String values. */ String[] getValues(); /** * Read the {@link String} value at index 'index'. - * * @param index the field index. * @return {@link String} containing the value at the index. - * * @throws IndexOutOfBoundsException if the {@code index} is out of bounds. */ String readString(int index); /** * Read the {@link String} value from column with given 'name'. - * * @param name the field {@code name}. * @return {@link String} containing the value from the specified {@code name}. */ String readString(String name); /** - * Read the {@link String} value at index 'index' including - * trailing whitespace (don't trim). - * + * Read the {@link String} value at index 'index' including trailing + * whitespace (don't trim). * @param index the field index. * @return {@link String} containing the value from the specified {@code index}. - * * @throws IndexOutOfBoundsException if the {@code index} is out of bounds. */ String readRawString(int index); /** - * Read the {@link String} value from column with given 'name' - * including trailing whitespace (don't trim). - * + * Read the {@link String} value from column with given 'name' including + * trailing whitespace (don't trim). * @param name the field {@code name}. * @return {@link String} containing the value from the specified {@code name}. */ @@ -93,20 +83,16 @@ public interface FieldSet { /** * Read the 'boolean' value at index 'index'. - * * @param index the field index. * @return boolean containing the value from the specified {@code index}. - * * @throws IndexOutOfBoundsException if the {@code index} is out of bounds. */ boolean readBoolean(int index); /** * Read the 'boolean' value from column with given 'name'. - * * @param name the field {@code name}. * @return boolean containing the value from the specified {@code name}. - * * @throws IllegalArgumentException if a column with given {@code name} is not * defined. */ @@ -114,25 +100,21 @@ public interface FieldSet { /** * Read the 'boolean' value at index 'index'. - * * @param index the field index. * @param trueValue the value that signifies {@link Boolean#TRUE true}; * case-sensitive. * @return boolean containing the value from the specified {@code index}. - * - * @throws IndexOutOfBoundsException if the index is out of bounds, or if - * the supplied trueValue is null. + * @throws IndexOutOfBoundsException if the index is out of bounds, or if the supplied + * trueValue is null. */ boolean readBoolean(int index, String trueValue); /** * Read the 'boolean' value from column with given 'name'. - * * @param name the field {@code name}. * @param trueValue the value that signifies {@link Boolean#TRUE true}; * case-sensitive. * @return boolean containing the value from the specified {@code name}. - * * @throws IllegalArgumentException if a column with given {@code name} is not * defined, or if the supplied trueValue is null. */ @@ -140,20 +122,16 @@ public interface FieldSet { /** * Read the 'char' value at index 'index'. - * * @param index the field index. * @return char containing the value from the specified {@code index}. - * * @throws IndexOutOfBoundsException if the index is out of bounds. */ char readChar(int index); /** * Read the 'char' value from column with given 'name'. - * * @param name the field {@code name}. * @return char containing the value from the specified {@code name}. - * * @throws IllegalArgumentException if a column with given {@code name} is not * defined. */ @@ -161,17 +139,14 @@ public interface FieldSet { /** * Read the 'byte' value at index 'index'. - * * @param index the field index. * @return byte containing the value from the specified {@code index}. - * * @throws IndexOutOfBoundsException if the index is out of bounds. */ byte readByte(int index); /** * Read the 'byte' value from column with given 'name'. - * * @param name the field {@code name}. * @return byte containing the value from the specified {@code name}. */ @@ -179,20 +154,16 @@ public interface FieldSet { /** * Read the 'short' value at index 'index'. - * * @param index the field {@code index}. * @return short containing the value from the specified index. - * * @throws IndexOutOfBoundsException if the index is out of bounds. */ short readShort(int index); /** * Read the 'short' value from column with given 'name'. - * * @param name the field {@code name}. * @return short containing the value from the specified {@code name}. - * * @throws IllegalArgumentException if a column with given {@code name} is not * defined. */ @@ -200,47 +171,37 @@ public interface FieldSet { /** * Read the 'int' value at index 'index'. - * * @param index the field index. * @return int containing the value from the specified index. - * * @throws IndexOutOfBoundsException if the index is out of bounds. */ int readInt(int index); /** * Read the 'int' value from column with given 'name'. - * * @param name the field {@code name}. * @return int containing the value from the specified {@code name}. - * * @throws IllegalArgumentException if a column with given {@code name} is not * defined. */ int readInt(String name); /** - * Read the 'int' value at index 'index', - * using the supplied defaultValue if the field value is - * blank. - * + * Read the 'int' value at index 'index', using the supplied + * defaultValue if the field value is blank. * @param index the field index. * @param defaultValue the value to use if the field value is blank. * @return int containing the value from the specified index. - * * @throws IndexOutOfBoundsException if the index is out of bounds. */ int readInt(int index, int defaultValue); /** - * Read the 'int' value from column with given 'name', - * using the supplied defaultValue if the field value is - * blank. - * + * Read the 'int' value from column with given 'name', using + * the supplied defaultValue if the field value is blank. * @param name the field {@code name}. * @param defaultValue the value to use if the field value is blank. * @return int containing the value from the specified {@code name}. - * * @throws IllegalArgumentException if a column with given {@code name} is not * defined. */ @@ -248,47 +209,37 @@ public interface FieldSet { /** * Read the 'long' value at index 'index'. - * * @param index the field index. * @return long containing the value from the specified index. - * * @throws IndexOutOfBoundsException if the index is out of bounds. */ long readLong(int index); /** * Read the 'long' value from column with given 'name'. - * * @param name the field {@code name}. * @return long containing the value from the specified {@code name}. - * * @throws IllegalArgumentException if a column with given {@code name} is not * defined. */ long readLong(String name); /** - * Read the 'long' value at index 'index', - * using the supplied defaultValue if the field value is - * blank. - * + * Read the 'long' value at index 'index', using the + * supplied defaultValue if the field value is blank. * @param index the field index. * @param defaultValue the value to use if the field value is blank. * @return long containing the value from the specified index. - * * @throws IndexOutOfBoundsException if the index is out of bounds. */ long readLong(int index, long defaultValue); /** * Read the 'long' value from column with given 'name', - * using the supplied defaultValue if the field value is - * blank. - * + * using the supplied defaultValue if the field value is blank. * @param name the field {@code name}. * @param defaultValue the value to use if the field value is blank. * @return long containing the value from the specified {@code name}. - * * @throws IllegalArgumentException if a column with given {@code name} is not * defined. */ @@ -296,20 +247,16 @@ public interface FieldSet { /** * Read the 'float' value at index 'index'. - * * @param index the field index. * @return float containing the value from the specified index. - * * @throws IndexOutOfBoundsException if the index is out of bounds. */ float readFloat(int index); /** * Read the 'float' value from column with given 'name. - * * @param name the field {@code name}. * @return float containing the value from the specified {@code name}. - * * @throws IllegalArgumentException if a column with given {@code name} is not * defined. */ @@ -317,20 +264,16 @@ public interface FieldSet { /** * Read the 'double' value at index 'index'. - * * @param index the field index. * @return double containing the value from the specified index. - * * @throws IndexOutOfBoundsException if the index is out of bounds. */ double readDouble(int index); /** * Read the 'double' value from column with given 'name. - * * @param name the field {@code name}. * @return double containing the value from the specified {@code name}. - * * @throws IllegalArgumentException if a column with given {@code name} is not * defined. */ @@ -338,59 +281,50 @@ public interface FieldSet { /** * Read the {@link java.math.BigDecimal} value at index 'index'. - * * @param index the field index. * @return {@link BigDecimal} containing the value from the specified index. - * * @throws IndexOutOfBoundsException if the index is out of bounds. */ BigDecimal readBigDecimal(int index); /** - * Read the {@link java.math.BigDecimal} value from column with given 'name. - * + * Read the {@link java.math.BigDecimal} value from column with given + * 'name. * @param name the field {@code name}. * @return {@link BigDecimal} containing the value from the specified {@code name}. - * * @throws IllegalArgumentException if a column with given {@code name} is not * defined. */ BigDecimal readBigDecimal(String name); /** - * Read the {@link BigDecimal} value at index 'index', - * returning the supplied defaultValue if the trimmed string - * value at index 'index' is blank. - * + * Read the {@link BigDecimal} value at index 'index', returning the + * supplied defaultValue if the trimmed string value at index + * 'index' is blank. * @param index the field index. * @param defaultValue the value to use if the field value is blank. * @return {@link BigDecimal} containing the value from the specified index. - * * @throws IndexOutOfBoundsException if the index is out of bounds. */ BigDecimal readBigDecimal(int index, BigDecimal defaultValue); /** * Read the {@link BigDecimal} value from column with given 'name, - * returning the supplied defaultValue if the trimmed string - * value at index 'index' is blank. - * + * returning the supplied defaultValue if the trimmed string value at + * index 'index' is blank. * @param name the field {@code name}. * @param defaultValue the default value to use if the field is blank * @return {@link BigDecimal} containing the value from the specified {@code name}. - * * @throws IllegalArgumentException if a column with given {@code name} is not * defined. */ BigDecimal readBigDecimal(String name, BigDecimal defaultValue); /** - * Read the java.util.Date value in default format at - * designated column index. - * + * Read the java.util.Date value in default format at designated column + * index. * @param index the field index. * @return {@link Date} containing the value from the specified index. - * * @throws IndexOutOfBoundsException if the index is out of bounds. * @throws IllegalArgumentException if the value is not parseable * @throws NullPointerException if the value is empty @@ -398,26 +332,22 @@ public interface FieldSet { Date readDate(int index); /** - * Read the java.sql.Date value in given format from column - * with given name. - * + * Read the java.sql.Date value in given format from column with given + * name. * @param name the field {@code name}. * @return {@link Date} containing the value from the specified {@code name}. - * - * @throws IllegalArgumentException if a column with given {@code name} is not - * defined or if the value is not parseable + * @throws IllegalArgumentException if a column with given {@code name} is not defined + * or if the value is not parseable * @throws NullPointerException if the value is empty */ Date readDate(String name); /** - * Read the java.util.Date value in default format at - * designated column index. - * + * Read the java.util.Date value in default format at designated column + * index. * @param index the field index. * @param defaultValue the default value to use if the field is blank * @return {@link Date} containing the value from the specified index. - * * @throws IndexOutOfBoundsException if the index is out of bounds. * @throws IllegalArgumentException if the value is not parseable * @throws NullPointerException if the value is empty @@ -425,91 +355,77 @@ public interface FieldSet { Date readDate(int index, Date defaultValue); /** - * Read the java.sql.Date value in given format from column - * with given name. - * + * Read the java.sql.Date value in given format from column with given + * name. * @param name the field {@code name}. * @param defaultValue the default value to use if the field is blank * @return {@link Date} containing the value from the specified {@code name}. - * * @throws IllegalArgumentException if a column with given {@code name} is not * defined. */ Date readDate(String name, Date defaultValue); /** - * Read the java.util.Date value in default format at - * designated column index. - * + * Read the java.util.Date value in default format at designated column + * index. * @param index the field index. * @param pattern the pattern describing the date and time format * @return {@link Date} containing the value from the specified index. - * * @throws IndexOutOfBoundsException if the index is out of bounds. * @throws IllegalArgumentException if the date cannot be parsed. - * + * */ Date readDate(int index, String pattern); /** - * Read the java.sql.Date value in given format from column - * with given name. - * + * Read the java.sql.Date value in given format from column with given + * name. * @param name the field {@code name}. * @param pattern the pattern describing the date and time format * @return {@link Date} containing the value from the specified {@code name}. + * @throws IllegalArgumentException if a column with given {@code name} is not defined + * or if the specified field cannot be parsed * - * @throws IllegalArgumentException if a column with given {@code name} is not - * defined or if the specified field cannot be parsed - * */ Date readDate(String name, String pattern); /** - * Read the java.util.Date value in default format at - * designated column index. - * + * Read the java.util.Date value in default format at designated column + * index. * @param index the field index. * @param pattern the pattern describing the date and time format * @param defaultValue the default value to use if the field is blank * @return {@link Date} containing the value from the specified index. - * * @throws IndexOutOfBoundsException if the index is out of bounds. * @throws IllegalArgumentException if the date cannot be parsed. - * + * */ Date readDate(int index, String pattern, Date defaultValue); /** - * Read the java.sql.Date value in given format from column - * with given name. - * + * Read the java.sql.Date value in given format from column with given + * name. * @param name the field {@code name}. * @param pattern the pattern describing the date and time format * @param defaultValue the default value to use if the field is blank * @return {@link Date} containing the value from the specified {@code name}. + * @throws IllegalArgumentException if a column with given {@code name} is not defined + * or if the specified field cannot be parsed * - * @throws IllegalArgumentException if a column with given {@code name} is not - * defined or if the specified field cannot be parsed - * */ Date readDate(String name, String pattern, Date defaultValue); /** * Return the number of fields in this 'FieldSet'. - * * @return int containing the number of fields in this field set. */ int getFieldCount(); /** - * Construct name-value pairs from the field names and string values. Null - * values are omitted. - * + * Construct name-value pairs from the field names and string values. Null values are + * omitted. * @return some properties representing the field set. - * - * @throws IllegalStateException if the field name meta data is not - * available. + * @throws IllegalStateException if the field name meta data is not available. */ Properties getProperties(); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/FieldSetFactory.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/FieldSetFactory.java index 26d42ae67..898ee40bc 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/FieldSetFactory.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/FieldSetFactory.java @@ -17,16 +17,15 @@ package org.springframework.batch.item.file.transform; /** * Factory interface for creating {@link FieldSet} instances. - * + * * @author Dave Syer * */ public interface FieldSetFactory { - + /** - * Create a FieldSet with named tokens. The token values can then be - * retrieved either by name or by column number. - * + * Create a FieldSet with named tokens. The token values can then be retrieved either + * by name or by column number. * @param values the token values * @param names the names of the tokens * @return an instance of {@link FieldSet}. @@ -36,9 +35,8 @@ public interface FieldSetFactory { FieldSet create(String[] values, String[] names); /** - * Create a FieldSet with anonymous tokens. They can only be retrieved by - * column number. - * + * Create a FieldSet with anonymous tokens. They can only be retrieved by column + * number. * @param values the token values * @return an instance of {@link FieldSet}. * diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/FixedLengthTokenizer.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/FixedLengthTokenizer.java index f2d83769d..47c703af0 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/FixedLengthTokenizer.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/FixedLengthTokenizer.java @@ -21,10 +21,9 @@ import java.util.Arrays; import java.util.List; /** - * Tokenizer used to process data obtained from files with fixed-length format. - * Columns are specified by array of Range objects ({@link #setColumns(Range[])} - * ). - * + * Tokenizer used to process data obtained from files with fixed-length format. Columns + * are specified by array of Range objects ({@link #setColumns(Range[])} ). + * * @author tomas.slanina * @author peter.zozom * @author Dave Syer @@ -41,13 +40,12 @@ public class FixedLengthTokenizer extends AbstractLineTokenizer { /** * Set the column ranges. Used in conjunction with the - * {@link RangeArrayPropertyEditor} this property can be set in the form of - * a String describing the range boundaries, e.g. "1,4,7" or "1-3,4-6,7" or - * "1-2,4-5,7-10". If the last range is open then the rest of the line is - * read into that column (irrespective of the strict flag setting). - * + * {@link RangeArrayPropertyEditor} this property can be set in the form of a String + * describing the range boundaries, e.g. "1,4,7" or "1-3,4-6,7" or "1-2,4-5,7-10". If + * the last range is open then the rest of the line is read into that column + * (irrespective of the strict flag setting). + * * @see #setStrict(boolean) - * * @param ranges the column ranges expected in the input */ public void setColumns(Range... ranges) { @@ -57,8 +55,8 @@ public class FixedLengthTokenizer extends AbstractLineTokenizer { /* * Calculate the highest value within an array of ranges. The ranges aren't - * necessarily in order. For example: "5-10, 1-4,11-15". Furthermore, there - * isn't always a min and max, such as: "1,4-20, 22" + * necessarily in order. For example: "5-10, 1-4,11-15". Furthermore, there isn't + * always a min and max, such as: "1,4-20, 22" */ private void calculateMaxRange(Range[] ranges) { if (ranges == null || ranges.length == 0) { @@ -88,16 +86,13 @@ public class FixedLengthTokenizer extends AbstractLineTokenizer { } /** - * Yields the tokens resulting from the splitting of the supplied - * line. - * + * Yields the tokens resulting from the splitting of the supplied line. * @param line the line to be tokenized (can be null) - * * @return the resulting tokens (empty if the line is null) - * @throws IncorrectLineLengthException if line length is greater than or - * less than the max range set. + * @throws IncorrectLineLengthException if line length is greater than or less than + * the max range set. */ - @Override + @Override protected List doTokenize(String line) { List tokens = new ArrayList<>(ranges.length); int lineLength; @@ -106,11 +101,13 @@ public class FixedLengthTokenizer extends AbstractLineTokenizer { lineLength = line.length(); if (lineLength < maxRange && isStrict()) { - throw new IncorrectLineLengthException("Line is shorter than max range " + maxRange, maxRange, lineLength, line); + throw new IncorrectLineLengthException("Line is shorter than max range " + maxRange, maxRange, lineLength, + line); } if (!open && lineLength > maxRange && isStrict()) { - throw new IncorrectLineLengthException("Line is longer than max range " + maxRange, maxRange, lineLength, line); + throw new IncorrectLineLengthException("Line is longer than max range " + maxRange, maxRange, lineLength, + line); } for (int i = 0; i < ranges.length; i++) { @@ -133,4 +130,5 @@ public class FixedLengthTokenizer extends AbstractLineTokenizer { return tokens; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/FlatFileFormatException.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/FlatFileFormatException.java index 1f5a08426..55d5f2455 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/FlatFileFormatException.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/FlatFileFormatException.java @@ -15,12 +15,10 @@ */ package org.springframework.batch.item.file.transform; - - /** - * Exception indicating that some type of error has occurred while - * attempting to parse a line of input into tokens. - * + * Exception indicating that some type of error has occurred while attempting to parse a + * line of input into tokens. + * * @author Lucas Ward * @author Michael Minella * @@ -32,27 +30,26 @@ public class FlatFileFormatException extends RuntimeException { /** * Create a new {@link FlatFileFormatException} based on a message. - * * @param message the message for this exception - * @param input {@link String} containing the input for that caused this - * exception to be thrown. + * @param input {@link String} containing the input for that caused this exception to + * be thrown. */ public FlatFileFormatException(String message, String input) { super(message); this.input = input; } + /** * Create a new {@link FlatFileFormatException} based on a message. - * * @param message the message for this exception */ public FlatFileFormatException(String message) { super(message); } - + /** - * Create a new {@link FlatFileFormatException} based on a message and another exception. - * + * Create a new {@link FlatFileFormatException} based on a message and another + * exception. * @param message the message for this exception * @param cause the other exception */ @@ -62,8 +59,10 @@ public class FlatFileFormatException extends RuntimeException { /** * Retrieve the input that caused this exception. - * * @return String containing the input. */ - public String getInput() { return input; } + public String getInput() { + return input; + } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/FormatterLineAggregator.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/FormatterLineAggregator.java index c3129f82d..99c7997ff 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/FormatterLineAggregator.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/FormatterLineAggregator.java @@ -22,11 +22,10 @@ import java.util.Locale; import org.springframework.util.Assert; /** - * A {@link LineAggregator} implementation which produces a String by - * aggregating the provided item via the {@link Formatter} syntax.
      - * + * A {@link LineAggregator} implementation which produces a String by aggregating the + * provided item via the {@link Formatter} syntax.
      + * * @see Formatter - * * @author Dave Syer */ public class FormatterLineAggregator extends ExtractorLineAggregator { @@ -40,9 +39,8 @@ public class FormatterLineAggregator extends ExtractorLineAggregator { private int minimumLength = 0; /** - * Public setter for the minimum length of the formatted string. If this is - * not set the default is to allow any length. - * + * Public setter for the minimum length of the formatted string. If this is not set + * the default is to allow any length. * @param minimumLength the minimum length to set */ public void setMinimumLength(int minimumLength) { @@ -50,8 +48,8 @@ public class FormatterLineAggregator extends ExtractorLineAggregator { } /** - * Public setter for the maximum length of the formatted string. If this is - * not set the default is to allow any length. + * Public setter for the maximum length of the formatted string. If this is not set + * the default is to allow any length. * @param maximumLength the maximum length to set */ public void setMaximumLength(int maximumLength) { @@ -60,7 +58,6 @@ public class FormatterLineAggregator extends ExtractorLineAggregator { /** * Set the format string used to aggregate items. - * * @param format {@link String} containing the format to use. * * @see Formatter @@ -85,15 +82,16 @@ public class FormatterLineAggregator extends ExtractorLineAggregator { String value = String.format(locale, format, fields); if (maximumLength > 0) { - Assert.state(value.length() <= maximumLength, String.format("String overflowed in formatter -" - + " longer than %d characters: [%s", maximumLength, value)); + Assert.state(value.length() <= maximumLength, String.format( + "String overflowed in formatter -" + " longer than %d characters: [%s", maximumLength, value)); } if (minimumLength > 0) { - Assert.state(value.length() >= minimumLength, String.format("String underflowed in formatter -" - + " shorter than %d characters: [%s", minimumLength, value)); + Assert.state(value.length() >= minimumLength, String.format( + "String underflowed in formatter -" + " shorter than %d characters: [%s", minimumLength, value)); } return value; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/IncorrectLineLengthException.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/IncorrectLineLengthException.java index 201ca632c..72feb1433 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/IncorrectLineLengthException.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/IncorrectLineLengthException.java @@ -16,9 +16,8 @@ package org.springframework.batch.item.file.transform; /** - * Exception indicating that the line size expected is different from what - * is expected. - * + * Exception indicating that the line size expected is different from what is expected. + * * @author Lucas Ward * @author Michael Minella * @since 1.1 @@ -27,14 +26,15 @@ package org.springframework.batch.item.file.transform; public class IncorrectLineLengthException extends FlatFileFormatException { private int actualLength; + private int expectedLength; /** * @param message the message for this exception. * @param expectedLength int containing the length that was expected. * @param actualLength int containing the actual length. - * @param input the {@link String} that contained the contents that caused - * the exception to be thrown. + * @param input the {@link String} that contained the contents that caused the + * exception to be thrown. * * @since 2.2.6 */ @@ -58,9 +58,9 @@ public class IncorrectLineLengthException extends FlatFileFormatException { /** * @param expectedLength int containing the length that was expected. * @param actualLength int containing the actual length. - * @param input the {@link String} that contained the contents that caused - * the exception to be thrown. - + * @param input the {@link String} that contained the contents that caused the + * exception to be thrown. + * * @since 2.2.6 */ public IncorrectLineLengthException(int expectedLength, int actualLength, String input) { @@ -81,7 +81,6 @@ public class IncorrectLineLengthException extends FlatFileFormatException { /** * Retrieves the actual length that was recorded for this exception. - * * @return int containing the actual length. */ public int getActualLength() { @@ -90,10 +89,10 @@ public class IncorrectLineLengthException extends FlatFileFormatException { /** * Retrieves the expected length that was recorded for this exception. - * * @return int containing the expected length. */ public int getExpectedLength() { return expectedLength; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/IncorrectTokenCountException.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/IncorrectTokenCountException.java index 960b1b7bd..bf5d9ee9b 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/IncorrectTokenCountException.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/IncorrectTokenCountException.java @@ -16,9 +16,9 @@ package org.springframework.batch.item.file.transform; /** - * Exception indicating that an incorrect number of tokens have been found - * while parsing a file. - * + * Exception indicating that an incorrect number of tokens have been found while parsing a + * file. + * * @author Lucas Ward * @author "Michael Minella" * @since 1.1 @@ -27,7 +27,9 @@ package org.springframework.batch.item.file.transform; public class IncorrectTokenCountException extends FlatFileFormatException { private int actualCount; + private int expectedCount; + private String input; public IncorrectTokenCountException(String message, int expectedCount, int actualCount, String input) { @@ -55,11 +57,11 @@ public class IncorrectTokenCountException extends FlatFileFormatException { this.actualCount = actualCount; this.expectedCount = expectedCount; } - + public int getActualCount() { return actualCount; } - + public int getExpectedCount() { return expectedCount; } @@ -68,5 +70,8 @@ public class IncorrectTokenCountException extends FlatFileFormatException { * @return the line that caused the exception * @since 2.2.6 */ - public String getInput() { return input; } + public String getInput() { + return input; + } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/LineAggregator.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/LineAggregator.java index 5fac28302..4514b55ee 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/LineAggregator.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/LineAggregator.java @@ -18,16 +18,16 @@ package org.springframework.batch.item.file.transform; /** * Interface used to create string representing object. - * + * * @author Dave Syer */ public interface LineAggregator { - + /** * Create a string from the value provided. - * * @param item values to be converted * @return string */ String aggregate(T item); + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/LineTokenizer.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/LineTokenizer.java index b87cb4959..7157876c3 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/LineTokenizer.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/LineTokenizer.java @@ -19,22 +19,20 @@ package org.springframework.batch.item.file.transform; import org.springframework.lang.Nullable; /** - * Interface that is used by framework to split string obtained typically from a - * file into tokens. - * + * Interface that is used by framework to split string obtained typically from a file into + * tokens. + * * @author tomas.slanina * @author Mahmoud Ben Hassine - * + * */ public interface LineTokenizer { - + /** - * Yields the tokens resulting from the splitting of the supplied - * line. - * + * Yields the tokens resulting from the splitting of the supplied line. * @param line the line to be tokenized (can be null) - * * @return the resulting tokens */ FieldSet tokenize(@Nullable String line); + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/PassThroughFieldExtractor.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/PassThroughFieldExtractor.java index 977397542..98630c021 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/PassThroughFieldExtractor.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/PassThroughFieldExtractor.java @@ -19,34 +19,32 @@ import java.util.Collection; import java.util.Map; /** - * {@link FieldExtractor} that just returns the original item. If the item is an - * array or collection it will be returned as is, otherwise it is wrapped in a - * single element array. - * + * {@link FieldExtractor} that just returns the original item. If the item is an array or + * collection it will be returned as is, otherwise it is wrapped in a single element + * array. + * * @author Dave Syer - * + * */ public class PassThroughFieldExtractor implements FieldExtractor { /** - * Get an array of fields as close as possible to the input. The result - * depends on the type of the input: + * Get an array of fields as close as possible to the input. The result depends on the + * type of the input: *

        *
      • A {@link FieldSet} or array will be returned as is
      • *
      • For a Collection the toArray() method will be used
      • *
      • For a Map the values() will be returned as an array
      • *
      • Otherwise it is wrapped in a single element array.
      • *
      - * Note that no attempt is made to sort the values, so passing in an - * unordered collection or map is probably a bad idea. Spring often gives - * you an ordered Map (e.g. if extracting data from a generic query using - * JDBC), so check the documentation for whatever is being used to generate - * the input. - * + * Note that no attempt is made to sort the values, so passing in an unordered + * collection or map is probably a bad idea. Spring often gives you an ordered Map + * (e.g. if extracting data from a generic query using JDBC), so check the + * documentation for whatever is being used to generate the input. * @param item the object to convert * @return an array of objects as close as possible to the original item */ - @Override + @Override public Object[] extract(T item) { if (item.getClass().isArray()) { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/PassThroughLineAggregator.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/PassThroughLineAggregator.java index 038a76e5f..6299b674a 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/PassThroughLineAggregator.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/PassThroughLineAggregator.java @@ -1,36 +1,36 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.item.file.transform; - -/** - * A {@link LineAggregator} implementation that simply calls - * {@link Object#toString()} on the given object - * - */ -public class PassThroughLineAggregator implements LineAggregator { - - /** - * Simply convert to a String with toString(). - * - * @see org.springframework.batch.item.file.transform.LineAggregator#aggregate(java.lang.Object) - */ - @Override - public String aggregate(T item) { - return item.toString(); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.item.file.transform; + +/** + * A {@link LineAggregator} implementation that simply calls {@link Object#toString()} on + * the given object + * + */ +public class PassThroughLineAggregator implements LineAggregator { + + /** + * Simply convert to a String with toString(). + * + * @see org.springframework.batch.item.file.transform.LineAggregator#aggregate(java.lang.Object) + */ + @Override + public String aggregate(T item) { + return item.toString(); + } + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/PatternMatchingCompositeLineTokenizer.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/PatternMatchingCompositeLineTokenizer.java index 35075f904..25cdd507e 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/PatternMatchingCompositeLineTokenizer.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/PatternMatchingCompositeLineTokenizer.java @@ -24,13 +24,12 @@ import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** - * A {@link LineTokenizer} implementation that stores a mapping of String - * patterns to delegate {@link LineTokenizer}s. Each line tokenized will be - * checked to see if it matches a pattern. If the line matches a key in the map - * of delegates, then the corresponding delegate {@link LineTokenizer} will be - * used. Patterns are sorted starting with the most specific, and the first - * match succeeds. - * + * A {@link LineTokenizer} implementation that stores a mapping of String patterns to + * delegate {@link LineTokenizer}s. Each line tokenized will be checked to see if it + * matches a pattern. If the line matches a key in the map of delegates, then the + * corresponding delegate {@link LineTokenizer} will be used. Patterns are sorted starting + * with the most specific, and the first match succeeds. + * * @author Ben Hale * @author Dan Garrette * @author Dave Syer @@ -41,23 +40,21 @@ public class PatternMatchingCompositeLineTokenizer implements LineTokenizer, Ini /* * (non-Javadoc) - * - * @see - * org.springframework.batch.item.file.transform.LineTokenizer#tokenize( + * + * @see org.springframework.batch.item.file.transform.LineTokenizer#tokenize( * java.lang.String) */ - @Override + @Override public FieldSet tokenize(@Nullable String line) { return tokenizers.match(line).tokenize(line); } /* * (non-Javadoc) - * - * @see - * org.springframework.beans.factory.InitializingBean#afterPropertiesSet() + * + * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() */ - @Override + @Override public void afterPropertiesSet() throws Exception { Assert.isTrue(this.tokenizers != null, "The 'tokenizers' property must be non-empty"); } @@ -66,4 +63,5 @@ public class PatternMatchingCompositeLineTokenizer implements LineTokenizer, Ini Assert.isTrue(!tokenizers.isEmpty(), "The 'tokenizers' property must be non-empty"); this.tokenizers = new PatternMatcher<>(tokenizers); } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/Range.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/Range.java index 11e4c48bc..869b3abbb 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/Range.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/Range.java @@ -19,31 +19,32 @@ package org.springframework.batch.item.file.transform; import org.springframework.util.Assert; /** - * A class to represent ranges. A Range can have minimum/maximum values from - * interval <1,Integer.MAX_VALUE-1> A Range can be unbounded at maximum - * side. This can be specified by passing {@link Range#UPPER_BORDER_NOT_DEFINED}} as max - * value or using constructor {@link #Range(int)}. - * + * A class to represent ranges. A Range can have minimum/maximum values from interval + * <1,Integer.MAX_VALUE-1> A Range can be unbounded at maximum side. This can be + * specified by passing {@link Range#UPPER_BORDER_NOT_DEFINED}} as max value or using + * constructor {@link #Range(int)}. + * * @author peter.zozom */ public class Range { public final static int UPPER_BORDER_NOT_DEFINED = Integer.MAX_VALUE; - - final private int min; + + final private int min; + final private int max; - + public Range(int min) { - this(min,UPPER_BORDER_NOT_DEFINED); + this(min, UPPER_BORDER_NOT_DEFINED); } - + public Range(int min, int max) { checkMinMaxValues(min, max); this.min = min; this.max = max; } - public int getMax() { + public int getMax() { return max; } @@ -54,14 +55,15 @@ public class Range { public boolean hasMaxValue() { return max != UPPER_BORDER_NOT_DEFINED; } - - @Override + + @Override public String toString() { return hasMaxValue() ? min + "-" + max : String.valueOf(min); } - + private void checkMinMaxValues(int min, int max) { - Assert.isTrue(min>0, "Min value must be higher than zero"); - Assert.isTrue(min<=max, "Min value should be lower or equal to max value"); + Assert.isTrue(min > 0, "Min value must be higher than zero"); + Assert.isTrue(min <= max, "Min value should be lower or equal to max value"); } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/RangeArrayPropertyEditor.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/RangeArrayPropertyEditor.java index 37eec4934..51b0a0961 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/RangeArrayPropertyEditor.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/RangeArrayPropertyEditor.java @@ -24,16 +24,16 @@ import java.util.Arrays; import java.util.Comparator; /** - * Property editor implementation which parses string and creates array of - * ranges. Ranges can be provided in any order.
      Input string should be - * provided in following format: 'range1, range2, range3,...' where range is - * specified as: + * Property editor implementation which parses string and creates array of ranges. Ranges + * can be provided in any order.
      + * Input string should be provided in following format: 'range1, range2, range3,...' where + * range is specified as: *
        - *
      • 'X-Y', where X is minimum value and Y is maximum value (condition X<=Y - * is verified)
      • - *
      • or 'Z', where Z is minimum and maximum is calculated as (minimum of - * adjacent range - 1). Maximum of the last range is never calculated. Range - * stays unbound at maximum side if maximum value is not provided.
      • + *
      • 'X-Y', where X is minimum value and Y is maximum value (condition X<=Y is + * verified)
      • + *
      • or 'Z', where Z is minimum and maximum is calculated as (minimum of adjacent range + * - 1). Maximum of the last range is never calculated. Range stays unbound at maximum + * side if maximum value is not provided.
      • *
      * Minimum and maximum values can be from interval <1, Integer.MAX_VALUE-1> *

      @@ -41,111 +41,110 @@ import java.util.Comparator; * '1, 15, 25, 38, 55-60' is equal to '1-14, 15-24, 25-37, 38-54, 55-60'
      * '36, 14, 1-10, 15, 49-57' is equal to '36-48, 14-14, 1-10, 15-35, 49-57' *

      - * Property editor also allows to validate whether ranges are disjoint. Validation - * can be turned on/off by using {@link #setForceDisjointRanges(boolean)}. By default - * validation is turned off. - * + * Property editor also allows to validate whether ranges are disjoint. Validation can be + * turned on/off by using {@link #setForceDisjointRanges(boolean)}. By default validation + * is turned off. + * * @author peter.zozom */ public class RangeArrayPropertyEditor extends PropertyEditorSupport { - + private boolean forceDisjointRanges = false; - + /** - * Set force disjoint ranges. If set to TRUE, ranges are validated to be disjoint. - * For example: defining ranges '1-10, 5-15' will cause IllegalArgumentException in - * case of forceDisjointRanges=TRUE. - * @param forceDisjointRanges true to force disjoint ranges. + * Set force disjoint ranges. If set to TRUE, ranges are validated to be disjoint. For + * example: defining ranges '1-10, 5-15' will cause IllegalArgumentException in case + * of forceDisjointRanges=TRUE. + * @param forceDisjointRanges true to force disjoint ranges. */ public void setForceDisjointRanges(boolean forceDisjointRanges) { this.forceDisjointRanges = forceDisjointRanges; } - @Override + @Override public void setAsText(String text) throws IllegalArgumentException { - - //split text into ranges + + // split text into ranges String[] strRanges = text.split(","); Range[] ranges = new Range[strRanges.length]; - - //parse ranges and create array of Range objects - for (int i = 0; i < strRanges.length; i++) { + + // parse ranges and create array of Range objects + for (int i = 0; i < strRanges.length; i++) { String[] range = strRanges[i].split("-"); - + int min; int max; - + if ((range.length == 1) && (StringUtils.hasText(range[0]))) { min = Integer.parseInt(range[0].trim()); // correct max value will be assigned later ranges[i] = new Range(min); - } else if ((range.length == 2) && (StringUtils.hasText(range[0])) - && (StringUtils.hasText(range[1]))) { + } + else if ((range.length == 2) && (StringUtils.hasText(range[0])) && (StringUtils.hasText(range[1]))) { min = Integer.parseInt(range[0].trim()); max = Integer.parseInt(range[1].trim()); - ranges[i] = new Range(min,max); - } else { + ranges[i] = new Range(min, max); + } + else { throw new IllegalArgumentException("Range[" + i + "]: range (" + strRanges[i] + ") is invalid"); - } - + } + } - + setMaxValues(ranges); setValue(ranges); } - - @Override + + @Override public String getAsText() { - Range[] ranges = (Range[])getValue(); - + Range[] ranges = (Range[]) getValue(); + StringBuilder sb = new StringBuilder(); for (int i = 0; i < ranges.length; i++) { - if(i>0) { + if (i > 0) { sb.append(", "); } sb.append(ranges[i]); } return sb.toString(); } - + private void setMaxValues(final Range[] ranges) { - + // Array of integers to track range values by index Integer[] c = new Integer[ranges.length]; - for (int i=0; i() { - @Override - public int compare(Integer r1, Integer r2) { - return ranges[r1].getMin()-ranges[r2].getMin(); - } + @Override + public int compare(Integer r1, Integer r2) { + return ranges[r1].getMin() - ranges[r2].getMin(); } - ); - - //set max values for all unbound ranges (except last range) + }); + + // set max values for all unbound ranges (except last range) for (int i = 0; i < c.length - 1; i++) { if (!ranges[c[i]].hasMaxValue()) { - //set max value to (min value - 1) of the next range - ranges[c[i]] = new Range(ranges[c[i]].getMin(),ranges[c[i+1]].getMin() - 1); + // set max value to (min value - 1) of the next range + ranges[c[i]] = new Range(ranges[c[i]].getMin(), ranges[c[i + 1]].getMin() - 1); } } - + if (forceDisjointRanges) { verifyRanges(ranges); } } - - + private void verifyRanges(Range[] ranges) { - //verify that ranges are disjoint - for(int i = 1; i < ranges.length;i++) { - Assert.isTrue(ranges[i-1].getMax() < ranges[i].getMin(), - "Ranges must be disjoint. Range[" + (i-1) + "]: (" + ranges[i-1] + - ") Range[" + i +"]: (" + ranges[i] + ")"); + // verify that ranges are disjoint + for (int i = 1; i < ranges.length; i++) { + Assert.isTrue(ranges[i - 1].getMax() < ranges[i].getMin(), "Ranges must be disjoint. Range[" + (i - 1) + + "]: (" + ranges[i - 1] + ") Range[" + i + "]: (" + ranges[i] + ")"); } } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/RecursiveCollectionLineAggregator.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/RecursiveCollectionLineAggregator.java index b4c528994..8918e736e 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/RecursiveCollectionLineAggregator.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/RecursiveCollectionLineAggregator.java @@ -18,13 +18,12 @@ package org.springframework.batch.item.file.transform; import java.util.Collection; - /** - * An implementation of {@link LineAggregator} that concatenates a collection of - * items of a common type with the system line separator. - * + * An implementation of {@link LineAggregator} that concatenates a collection of items of + * a common type with the system line separator. + * * @author Dave Syer - * + * */ public class RecursiveCollectionLineAggregator implements LineAggregator> { @@ -33,10 +32,9 @@ public class RecursiveCollectionLineAggregator implements LineAggregator delegate = new PassThroughLineAggregator<>(); /** - * Public setter for the {@link LineAggregator} to use on single items, that - * are not Strings. This can be used to strategise the conversion of - * collection and array elements to a String.
      - * + * Public setter for the {@link LineAggregator} to use on single items, that are not + * Strings. This can be used to strategise the conversion of collection and array + * elements to a String.
      * @param delegate the line aggregator to set. Defaults to a pass through. */ public void setDelegate(LineAggregator delegate) { @@ -45,7 +43,10 @@ public class RecursiveCollectionLineAggregator implements LineAggregator items) { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/RegexLineTokenizer.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/RegexLineTokenizer.java index 76e37d07c..6128c84de 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/RegexLineTokenizer.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/RegexLineTokenizer.java @@ -1,12 +1,12 @@ /* * Copyright 2006-2012 the original author or authors. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * https://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -24,27 +24,26 @@ import java.util.regex.Pattern; import org.springframework.util.Assert; /** - * Line-tokenizer using a regular expression to filter out data (by using matching and non-matching groups). - * Consider the following regex which picks only the first and last name (notice the non-matching group in the middle): - *

      - * (.*?)(?: .*)* (.*) 
      - * 
      - * For the names: - *
        - *
      • "Graham James Edward Miller"
      • - *
      • "Andrew Gregory Macintyre"
      • - *
      • "No MiddleName"
      • - *
      - * + * Line-tokenizer using a regular expression to filter out data (by using matching and + * non-matching groups). Consider the following regex which picks only the first and last + * name (notice the non-matching group in the middle):
      + * (.*?)(?: .*)* (.*)
      + * 
      For the names: + *
        + *
      • "Graham James Edward Miller"
      • + *
      • "Andrew Gregory Macintyre"
      • + *
      • "No MiddleName"
      • + *
      + * * the output will be: *
        *
      • "Miller", "Graham"
      • *
      • "Macintyre", "Andrew"
      • *
      • "MiddleName", "No"
      • *
      - * + * * An empty list is returned, in case of a non-match. - * + * * @see Matcher#group(int) * @author Costin Leau */ @@ -69,7 +68,6 @@ public class RegexLineTokenizer extends AbstractLineTokenizer { /** * Sets the regex pattern to use. - * * @param pattern Regular Expression pattern */ public void setPattern(Pattern pattern) { @@ -78,12 +76,12 @@ public class RegexLineTokenizer extends AbstractLineTokenizer { } /** - * Sets the regular expression to use. - * + * Sets the regular expression to use. * @param regex regular expression (as a String) */ public void setRegex(String regex) { Assert.hasText(regex, "a valid regex is required"); this.pattern = Pattern.compile(regex); } + } \ No newline at end of file diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/function/FunctionItemProcessor.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/function/FunctionItemProcessor.java index 7de337a05..07b5c1f5e 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/function/FunctionItemProcessor.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/function/FunctionItemProcessor.java @@ -27,12 +27,12 @@ import org.springframework.util.Assert; * @author Michael Minella * @since 4.0 */ -public class FunctionItemProcessor implements ItemProcessor{ +public class FunctionItemProcessor implements ItemProcessor { private final Function function; /** - * @param function the delegate. Must not be null + * @param function the delegate. Must not be null */ public FunctionItemProcessor(Function function) { Assert.notNull(function, "A function is required"); @@ -44,4 +44,5 @@ public class FunctionItemProcessor implements ItemProcessor{ public O process(I item) throws Exception { return this.function.apply(item); } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/jms/JmsItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/jms/JmsItemReader.java index bd1c94e95..b55728378 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/jms/JmsItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/jms/JmsItemReader.java @@ -28,17 +28,16 @@ import org.springframework.util.Assert; import jakarta.jms.Message; /** - * An {@link ItemReader} for JMS using a {@link JmsTemplate}. The template - * should have a default destination, which will be used to provide items in - * {@link #read()}.
      + * An {@link ItemReader} for JMS using a {@link JmsTemplate}. The template should have a + * default destination, which will be used to provide items in {@link #read()}.
      *
      - * - * The implementation is thread-safe after its properties are set (normal - * singleton behavior). - * + * + * The implementation is thread-safe after its properties are set (normal singleton + * behavior). + * * @author Dave Syer * @author Mahmoud Ben Hassine - * + * */ public class JmsItemReader implements ItemReader, InitializingBean { @@ -50,7 +49,6 @@ public class JmsItemReader implements ItemReader, InitializingBean { /** * Setter for JMS template. - * * @param jmsTemplate a {@link JmsOperations} instance */ public void setJmsTemplate(JmsOperations jmsTemplate) { @@ -65,20 +63,17 @@ public class JmsItemReader implements ItemReader, InitializingBean { } /** - * Set the expected type of incoming message payloads. Set this to - * {@link Message} to receive the raw underlying message. - * - * @param itemType the java class of the items to be delivered. Typically - * the same as the class parameter - * - * @throws IllegalStateException if the message payload is of the wrong - * type. + * Set the expected type of incoming message payloads. Set this to {@link Message} to + * receive the raw underlying message. + * @param itemType the java class of the items to be delivered. Typically the same as + * the class parameter + * @throws IllegalStateException if the message payload is of the wrong type. */ public void setItemType(Class itemType) { this.itemType = itemType; } - @Nullable + @Nullable @Override @SuppressWarnings("unchecked") public T read() { @@ -93,8 +88,9 @@ public class JmsItemReader implements ItemReader, InitializingBean { return (T) result; } - @Override + @Override public void afterPropertiesSet() throws Exception { Assert.notNull(this.jmsTemplate, "The 'jmsTemplate' is required."); } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/jms/JmsItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/jms/JmsItemWriter.java index 2ea054447..934963e95 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/jms/JmsItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/jms/JmsItemWriter.java @@ -26,16 +26,15 @@ import org.springframework.util.Assert; import java.util.List; /** - * An {@link ItemWriter} for JMS using a {@link JmsTemplate}. The template - * should have a default destination, which will be used to send items in - * {@link #write(List)}.
      + * An {@link ItemWriter} for JMS using a {@link JmsTemplate}. The template should have a + * default destination, which will be used to send items in {@link #write(List)}.
      *
      - * - * The implementation is thread-safe after its properties are set (normal - * singleton behavior). - * + * + * The implementation is thread-safe after its properties are set (normal singleton + * behavior). + * * @author Dave Syer - * + * */ public class JmsItemWriter implements ItemWriter { @@ -45,27 +44,23 @@ public class JmsItemWriter implements ItemWriter { /** * Setter for JMS template. - * - * @param jmsTemplate - * a {@link JmsOperations} instance + * @param jmsTemplate a {@link JmsOperations} instance */ public void setJmsTemplate(JmsOperations jmsTemplate) { this.jmsTemplate = jmsTemplate; if (jmsTemplate instanceof JmsTemplate) { JmsTemplate template = (JmsTemplate) jmsTemplate; - Assert - .isTrue(template.getDefaultDestination() != null - || template.getDefaultDestinationName() != null, - "JmsTemplate must have a defaultDestination or defaultDestinationName!"); + Assert.isTrue(template.getDefaultDestination() != null || template.getDefaultDestinationName() != null, + "JmsTemplate must have a defaultDestination or defaultDestinationName!"); } } /** * Send the items one-by-one to the default destination of the JMS template. - * + * * @see org.springframework.batch.item.ItemWriter#write(java.util.List) */ - @Override + @Override public void write(List items) throws Exception { if (logger.isDebugEnabled()) { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/jms/JmsMethodArgumentsKeyGenerator.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/jms/JmsMethodArgumentsKeyGenerator.java index 6da0ce9e4..7cd35de36 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/jms/JmsMethodArgumentsKeyGenerator.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/jms/JmsMethodArgumentsKeyGenerator.java @@ -23,25 +23,24 @@ import org.springframework.batch.item.UnexpectedInputException; import org.springframework.retry.interceptor.MethodArgumentsKeyGenerator; /** - * A {@link MethodArgumentsKeyGenerator} for JMS - * + * A {@link MethodArgumentsKeyGenerator} for JMS + * * @author Dave Syer * @author Mahmoud Ben Hassine - * + * */ public class JmsMethodArgumentsKeyGenerator implements MethodArgumentsKeyGenerator { /** - * If the message is a {@link Message} then returns the JMS message ID. - * Otherwise just return the first argument. - * + * If the message is a {@link Message} then returns the JMS message ID. Otherwise just + * return the first argument. + * * @see org.springframework.retry.interceptor.MethodArgumentsKeyGenerator#getKey(Object[]) - * - * @throws UnexpectedInputException if the JMS id cannot be determined from - * a JMS Message + * @throws UnexpectedInputException if the JMS id cannot be determined from a JMS + * Message * @throws IllegalArgumentException if the arguments are empty */ - @Override + @Override public Object getKey(Object[] items) { for (Object item : items) { if (item instanceof Message) { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/jms/JmsMethodInvocationRecoverer.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/jms/JmsMethodInvocationRecoverer.java index 55d8416bf..2afb4399e 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/jms/JmsMethodInvocationRecoverer.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/jms/JmsMethodInvocationRecoverer.java @@ -26,7 +26,7 @@ import org.springframework.jms.core.JmsOperations; /** * @author Dave Syer * @author Mahmoud Ben Hassine - * + * */ public class JmsMethodInvocationRecoverer implements MethodInvocationRecoverer { @@ -36,7 +36,6 @@ public class JmsMethodInvocationRecoverer implements MethodInvocationRecovere /** * Setter for jms template. - * * @param jmsTemplate a {@link JmsOperations} instance */ public void setJmsTemplate(JmsOperations jmsTemplate) { @@ -46,11 +45,11 @@ public class JmsMethodInvocationRecoverer implements MethodInvocationRecovere /** * Send one message per item in the arguments list using the default destination of * the jms template. If the recovery is successful {@code null} is returned. - * + * * @see org.springframework.retry.interceptor.MethodInvocationRecoverer#recover(Object[], * Throwable) */ - @Override + @Override @Nullable public T recover(Object[] items, Throwable cause) { try { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/jms/JmsNewMethodArgumentsIdentifier.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/jms/JmsNewMethodArgumentsIdentifier.java index 55d526d31..d5090673a 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/jms/JmsNewMethodArgumentsIdentifier.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/jms/JmsNewMethodArgumentsIdentifier.java @@ -23,22 +23,22 @@ import org.springframework.batch.item.UnexpectedInputException; import org.springframework.retry.interceptor.NewMethodArgumentsIdentifier; /** - * A {@link NewMethodArgumentsIdentifier} for JMS that looks for a message in - * the arguments and checks its delivery status. - * + * A {@link NewMethodArgumentsIdentifier} for JMS that looks for a message in the + * arguments and checks its delivery status. + * * @author Dave Syer * @author Mahmoud Ben Hassine - * + * */ public class JmsNewMethodArgumentsIdentifier implements NewMethodArgumentsIdentifier { /** - * If any of the arguments is a message, check the JMS re-delivered flag and - * return it, otherwise return false to be on the safe side. - * + * If any of the arguments is a message, check the JMS re-delivered flag and return + * it, otherwise return false to be on the safe side. + * * @see org.springframework.retry.interceptor.NewMethodArgumentsIdentifier#isNew(java.lang.Object[]) */ - @Override + @Override public boolean isNew(Object[] args) { for (Object item : args) { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/jms/builder/JmsItemReaderBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/jms/builder/JmsItemReaderBuilder.java index 1278c15a8..bec28d06c 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/jms/builder/JmsItemReaderBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/jms/builder/JmsItemReaderBuilder.java @@ -27,7 +27,6 @@ import org.springframework.util.Assert; * * @author Glenn Renfro * @author Mahmoud Ben Hassine - * * @since 4.0 */ public class JmsItemReaderBuilder { @@ -38,7 +37,6 @@ public class JmsItemReaderBuilder { /** * Establish the JMS template that will be used by the JmsItemReader. - * * @param jmsTemplate a {@link JmsOperations} instance * @return this instance for method chaining. * @see JmsItemReader#setJmsTemplate(JmsOperations) @@ -52,11 +50,9 @@ public class JmsItemReaderBuilder { /** * Set the expected type of incoming message payloads. Set this to {@link Message} to * receive the raw underlying message. - * * @param itemType the java class of the items to be delivered. Typically the same as * the class parameter * @return this instance for method chaining. - * * @throws IllegalStateException if the message payload is of the wrong type. * @see JmsItemReader#setItemType(Class) */ @@ -68,7 +64,6 @@ public class JmsItemReaderBuilder { /** * Returns a fully constructed {@link JmsItemReader}. - * * @return a new {@link JmsItemReader} */ public JmsItemReader build() { @@ -79,4 +74,5 @@ public class JmsItemReaderBuilder { jmsItemReader.setJmsTemplate(this.jmsTemplate); return jmsItemReader; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/jms/builder/JmsItemWriterBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/jms/builder/JmsItemWriterBuilder.java index 82e1d29c2..de6ca5739 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/jms/builder/JmsItemWriterBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/jms/builder/JmsItemWriterBuilder.java @@ -24,7 +24,6 @@ import org.springframework.util.Assert; * Creates a fully qualified JmsItemWriter. * * @author Glenn Renfro - * * @since 4.0 */ public class JmsItemWriterBuilder { @@ -33,7 +32,6 @@ public class JmsItemWriterBuilder { /** * Establish the JMS template that will be used by the {@link JmsItemWriter}. - * * @param jmsTemplate a {@link JmsOperations} instance * @return this instance for method chaining. * @see JmsItemWriter#setJmsTemplate(JmsOperations) @@ -46,7 +44,6 @@ public class JmsItemWriterBuilder { /** * Returns a fully constructed {@link JmsItemWriter}. - * * @return a new {@link JmsItemWriter} */ public JmsItemWriter build() { @@ -56,4 +53,5 @@ public class JmsItemWriterBuilder { jmsItemWriter.setJmsTemplate(this.jmsTemplate); return jmsItemWriter; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/GsonJsonObjectMarshaller.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/GsonJsonObjectMarshaller.java index c4c982d62..9e2485544 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/GsonJsonObjectMarshaller.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/GsonJsonObjectMarshaller.java @@ -19,8 +19,8 @@ package org.springframework.batch.item.json; import com.google.gson.Gson; /** - * A json object marshaller that uses Google Gson - * to marshal an object into a json representation. + * A json object marshaller that uses Google + * Gson to marshal an object into a json representation. * * @param type of objects to marshal * @author Mahmoud Ben Hassine @@ -33,15 +33,15 @@ public class GsonJsonObjectMarshaller implements JsonObjectMarshaller { public GsonJsonObjectMarshaller() { this(new Gson()); } - + public GsonJsonObjectMarshaller(Gson gson) { this.gson = gson; } - + /** * Set the {@link Gson} object to use. * @param gson object to use - * @see #GsonJsonObjectMarshaller(Gson) + * @see #GsonJsonObjectMarshaller(Gson) */ public void setGson(Gson gson) { this.gson = gson; @@ -51,4 +51,5 @@ public class GsonJsonObjectMarshaller implements JsonObjectMarshaller { public String marshal(T item) { return gson.toJson(item); } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/GsonJsonObjectReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/GsonJsonObjectReader.java index da493a1a1..48787430f 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/GsonJsonObjectReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/GsonJsonObjectReader.java @@ -36,7 +36,6 @@ import org.springframework.util.Assert; * Google Gson. * * @param type of the target object - * * @author Mahmoud Ben Hassine * @since 4.1 */ @@ -90,7 +89,8 @@ public class GsonJsonObjectReader implements JsonObjectReader { if (this.jsonReader.hasNext()) { return this.mapper.fromJson(this.jsonReader, this.itemType); } - } catch (IOException |JsonIOException | JsonSyntaxException e) { + } + catch (IOException | JsonIOException | JsonSyntaxException e) { throw new ParseException("Unable to read next JSON object", e); } return null; diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/JacksonJsonObjectMarshaller.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/JacksonJsonObjectMarshaller.java index dab06b215..f032549f0 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/JacksonJsonObjectMarshaller.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/JacksonJsonObjectMarshaller.java @@ -22,8 +22,9 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.batch.item.ItemStreamException; /** - * A json object marshaller that uses Jackson - * to marshal an object into a json representation. + * A json object marshaller that uses + * Jackson to marshal an object into a + * json representation. * * @param type of objects to marshal * @author Mahmoud Ben Hassine @@ -51,11 +52,13 @@ public class JacksonJsonObjectMarshaller implements JsonObjectMarshaller { } @Override - public String marshal(T item) { + public String marshal(T item) { try { return objectMapper.writeValueAsString(item); - } catch (JsonProcessingException e) { + } + catch (JsonProcessingException e) { throw new ItemStreamException("Unable to marshal object " + item + " to Json", e); } } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/JacksonJsonObjectReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/JacksonJsonObjectReader.java index 141446f6c..04d7a7b97 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/JacksonJsonObjectReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/JacksonJsonObjectReader.java @@ -33,7 +33,6 @@ import org.springframework.util.Assert; * Jackson. * * @param type of the target object - * * @author Mahmoud Ben Hassine * @since 4.1 */ @@ -86,7 +85,8 @@ public class JacksonJsonObjectReader implements JsonObjectReader { if (this.jsonParser.nextToken() == JsonToken.START_OBJECT) { return this.mapper.readValue(this.jsonParser, this.itemType); } - } catch (IOException e) { + } + catch (IOException e) { throw new ParseException("Unable to read next JSON object", e); } return null; diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/JsonFileItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/JsonFileItemWriter.java index c4f8eae1f..d41e8d015 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/JsonFileItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/JsonFileItemWriter.java @@ -25,10 +25,10 @@ import org.springframework.util.Assert; import org.springframework.util.ClassUtils; /** - * Item writer that writes data in json format to an output file. The location - * of the output file is defined by a {@link WritableResource} and must represent a - * writable file. Items are transformed to json format using a - * {@link JsonObjectMarshaller}. Items will be enclosed in a json array as follows: + * Item writer that writes data in json format to an output file. The location of the + * output file is defined by a {@link WritableResource} and must represent a writable + * file. Items are transformed to json format using a {@link JsonObjectMarshaller}. Items + * will be enclosed in a json array as follows: * *

      * @@ -51,7 +51,9 @@ import org.springframework.util.ClassUtils; public class JsonFileItemWriter extends AbstractFileItemWriter { private static final char JSON_OBJECT_SEPARATOR = ','; + private static final char JSON_ARRAY_START = '['; + private static final char JSON_ARRAY_STOP = ']'; private JsonObjectMarshaller jsonObjectMarshaller; diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/JsonItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/JsonItemReader.java index 9980d3e35..c39f9886e 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/JsonItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/JsonItemReader.java @@ -28,8 +28,8 @@ import org.springframework.util.Assert; import org.springframework.util.ClassUtils; /** - * {@link ItemStreamReader} implementation that reads Json objects from a - * {@link Resource} having the following format: + * {@link ItemStreamReader} implementation that reads Json objects from a {@link Resource} + * having the following format: *

      * * [ @@ -46,12 +46,11 @@ import org.springframework.util.ClassUtils; * The implementation is not thread-safe. * * @param the type of json objects to read - * * @author Mahmoud Ben Hassine * @since 4.1 */ -public class JsonItemReader extends AbstractItemCountingItemStreamItemReader implements - ResourceAwareItemReaderItemStream { +public class JsonItemReader extends AbstractItemCountingItemStreamItemReader + implements ResourceAwareItemReaderItemStream { private static final Log LOGGER = LogFactory.getLog(JsonItemReader.class); @@ -77,12 +76,13 @@ public class JsonItemReader extends AbstractItemCountingItemStreamItemReader< /** * Create a new {@link JsonItemReader} instance. */ - public JsonItemReader(){ + public JsonItemReader() { setExecutionContextName(ClassUtils.getShortName(JsonItemReader.class)); } /** - * Set the {@link JsonObjectReader} to use to read and map Json fragments to domain objects. + * Set the {@link JsonObjectReader} to use to read and map Json fragments to domain + * objects. * @param jsonObjectReader the json object reader to use */ public void setJsonObjectReader(JsonObjectReader jsonObjectReader) { @@ -91,8 +91,8 @@ public class JsonItemReader extends AbstractItemCountingItemStreamItemReader< /** * In strict mode the reader will throw an exception on - * {@link #open(org.springframework.batch.item.ExecutionContext)} if the - * input resource does not exist. + * {@link #open(org.springframework.batch.item.ExecutionContext)} if the input + * resource does not exist. * @param strict true by default */ public void setStrict(boolean strict) { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/JsonObjectMarshaller.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/JsonObjectMarshaller.java index 457926cf5..d052e4db6 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/JsonObjectMarshaller.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/JsonObjectMarshaller.java @@ -17,8 +17,8 @@ package org.springframework.batch.item.json; /** - * Strategy interface to marshal an object into a json representation. - * Implementations are required to return a valid json object. + * Strategy interface to marshal an object into a json representation. Implementations are + * required to return a valid json object. * * @param type of objects to marshal * @author Mahmoud Ben Hassine diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/JsonObjectReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/JsonObjectReader.java index a83b2ea93..5793d2e09 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/JsonObjectReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/JsonObjectReader.java @@ -20,11 +20,10 @@ import org.springframework.core.io.Resource; import org.springframework.lang.Nullable; /** - * Strategy interface for Json readers. Implementations are expected to use - * a streaming API in order to read Json objects one at a time. + * Strategy interface for Json readers. Implementations are expected to use a streaming + * API in order to read Json objects one at a time. * * @param type of the target object - * * @author Mahmoud Ben Hassine * @since 4.1 */ @@ -54,4 +53,5 @@ public interface JsonObjectReader { default void close() throws Exception { } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/builder/JsonFileItemWriterBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/builder/JsonFileItemWriterBuilder.java index c618b84d0..e92dec952 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/builder/JsonFileItemWriterBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/builder/JsonFileItemWriterBuilder.java @@ -33,26 +33,35 @@ import org.springframework.util.Assert; public class JsonFileItemWriterBuilder { private WritableResource resource; + private JsonObjectMarshaller jsonObjectMarshaller; + private FlatFileHeaderCallback headerCallback; + private FlatFileFooterCallback footerCallback; private String name; + private String encoding = JsonFileItemWriter.DEFAULT_CHARSET; + private String lineSeparator = JsonFileItemWriter.DEFAULT_LINE_SEPARATOR; private boolean append = false; + private boolean forceSync = false; + private boolean saveState = true; + private boolean shouldDeleteIfExists = true; + private boolean shouldDeleteIfEmpty = false; + private boolean transactional = JsonFileItemWriter.DEFAULT_TRANSACTIONAL; /** - * Configure if the state of the {@link org.springframework.batch.item.ItemStreamSupport} - * should be persisted within the {@link org.springframework.batch.item.ExecutionContext} - * for restart purposes. - * + * Configure if the state of the + * {@link org.springframework.batch.item.ItemStreamSupport} should be persisted within + * the {@link org.springframework.batch.item.ExecutionContext} for restart purposes. * @param saveState defaults to true * @return The current instance of the builder. */ @@ -66,7 +75,6 @@ public class JsonFileItemWriterBuilder { * The name used to calculate the key within the * {@link org.springframework.batch.item.ExecutionContext}. Required if * {@link #saveState(boolean)} is set to true. - * * @param name name of the reader instance * @return The current instance of the builder. * @see org.springframework.batch.item.ItemStreamSupport#setName(String) @@ -78,9 +86,8 @@ public class JsonFileItemWriterBuilder { } /** - * A flag indicating that changes should be force-synced to disk on flush. Defaults - * to false. - * + * A flag indicating that changes should be force-synced to disk on flush. Defaults to + * false. * @param forceSync value to set the flag to * @return The current instance of the builder. * @see JsonFileItemWriter#setForceSync(boolean) @@ -92,9 +99,8 @@ public class JsonFileItemWriterBuilder { } /** - * String used to separate lines in output. Defaults to the System property + * String used to separate lines in output. Defaults to the System property * line.separator. - * * @param lineSeparator value to use for a line separator * @return The current instance of the builder. * @see JsonFileItemWriter#setLineSeparator(String) @@ -107,7 +113,6 @@ public class JsonFileItemWriterBuilder { /** * Set the {@link JsonObjectMarshaller} to use to marshal objects to json. - * * @param jsonObjectMarshaller to use * @return The current instance of the builder. * @see JsonFileItemWriter#setJsonObjectMarshaller(JsonObjectMarshaller) @@ -120,7 +125,6 @@ public class JsonFileItemWriterBuilder { /** * The {@link WritableResource} to be used as output. - * * @param resource the output of the writer. * @return The current instance of the builder. * @see JsonFileItemWriter#setResource(WritableResource) @@ -133,7 +137,6 @@ public class JsonFileItemWriterBuilder { /** * Encoding used for output. - * * @param encoding encoding type. * @return The current instance of the builder. * @see JsonFileItemWriter#setEncoding(String) @@ -147,7 +150,6 @@ public class JsonFileItemWriterBuilder { /** * If set to true, once the step is complete, if the resource previously provided is * empty, it will be deleted. - * * @param shouldDelete defaults to false * @return The current instance of the builder * @see JsonFileItemWriter#setShouldDeleteIfEmpty(boolean) @@ -161,7 +163,6 @@ public class JsonFileItemWriterBuilder { /** * If set to true, upon the start of the step, if the resource already exists, it will * be deleted and recreated. - * * @param shouldDelete defaults to true * @return The current instance of the builder * @see JsonFileItemWriter#setShouldDeleteIfExists(boolean) @@ -175,7 +176,6 @@ public class JsonFileItemWriterBuilder { /** * If set to true and the file exists, the output will be appended to the existing * file. - * * @param append defaults to false * @return The current instance of the builder * @see JsonFileItemWriter#setAppendAllowed(boolean) @@ -188,7 +188,6 @@ public class JsonFileItemWriterBuilder { /** * A callback for header processing. - * * @param callback {@link FlatFileHeaderCallback} implementation * @return The current instance of the builder * @see JsonFileItemWriter#setHeaderCallback(FlatFileHeaderCallback) @@ -201,7 +200,6 @@ public class JsonFileItemWriterBuilder { /** * A callback for footer processing. - * * @param callback {@link FlatFileFooterCallback} implementation * @return The current instance of the builder * @see JsonFileItemWriter#setFooterCallback(FlatFileFooterCallback) @@ -213,8 +211,8 @@ public class JsonFileItemWriterBuilder { } /** - * If set to true, the flushing of the buffer is delayed while a transaction is active. - * + * If set to true, the flushing of the buffer is delayed while a transaction is + * active. * @param transactional defaults to true * @return The current instance of the builder * @see JsonFileItemWriter#setTransactional(boolean) @@ -227,7 +225,6 @@ public class JsonFileItemWriterBuilder { /** * Validate the configuration and build a new {@link JsonFileItemWriter}. - * * @return a new instance of the {@link JsonFileItemWriter} */ public JsonFileItemWriter build() { @@ -258,4 +255,5 @@ public class JsonFileItemWriterBuilder { return jsonFileItemWriter; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/builder/JsonItemReaderBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/builder/JsonItemReaderBuilder.java index ba752462f..9c1e7c6bc 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/builder/JsonItemReaderBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/json/builder/JsonItemReaderBuilder.java @@ -29,7 +29,6 @@ import org.springframework.util.StringUtils; * A builder for {@link JsonItemReader}. * * @param type of the target item - * * @author Mahmoud Ben Hassine * @since 4.1 */ @@ -52,7 +51,8 @@ public class JsonItemReaderBuilder { private int currentItemCount; /** - * Set the {@link JsonObjectReader} to use to read and map Json objects to domain objects. + * Set the {@link JsonObjectReader} to use to read and map Json objects to domain + * objects. * @param jsonObjectReader to use * @return The current instance of the builder. * @see JsonItemReader#setJsonObjectReader(JsonObjectReader) @@ -90,8 +90,8 @@ public class JsonItemReaderBuilder { } /** - * Setting this value to true indicates that it is an error if the input - * does not exist and an exception will be thrown. Defaults to true. + * Setting this value to true indicates that it is an error if the input does not + * exist and an exception will be thrown. Defaults to true. * @param strict indicates the input resource must exist * @return The current instance of the builder. * @see JsonItemReader#setStrict(boolean) @@ -103,9 +103,9 @@ public class JsonItemReaderBuilder { } /** - * Configure if the state of the {@link org.springframework.batch.item.ItemStreamSupport} - * should be persisted within the {@link org.springframework.batch.item.ExecutionContext} - * for restart purposes. + * Configure if the state of the + * {@link org.springframework.batch.item.ItemStreamSupport} should be persisted within + * the {@link org.springframework.batch.item.ExecutionContext} for restart purposes. * @param saveState defaults to true * @return The current instance of the builder. */ @@ -150,8 +150,8 @@ public class JsonItemReaderBuilder { } if (this.resource == null) { - logger.debug("The resource is null. This is only a valid scenario when " + - "injecting it later as in when using the MultiResourceItemReader"); + logger.debug("The resource is null. This is only a valid scenario when " + + "injecting it later as in when using the MultiResourceItemReader"); } JsonItemReader reader = new JsonItemReader<>(); @@ -165,4 +165,5 @@ public class JsonItemReaderBuilder { return reader; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/kafka/KafkaItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/kafka/KafkaItemReader.java index e5c2a477c..8a60d00e2 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/kafka/KafkaItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/kafka/KafkaItemReader.java @@ -38,8 +38,8 @@ import org.springframework.util.Assert; /** *

      * An {@link org.springframework.batch.item.ItemReader} implementation for Apache Kafka. - * Uses a {@link KafkaConsumer} to read data from a given topic. - * Multiple partitions within the same topic can be assigned to this reader. + * Uses a {@link KafkaConsumer} to read data from a given topic. Multiple partitions + * within the same topic can be assigned to this reader. *

      * *

      @@ -72,8 +72,12 @@ public class KafkaItemReader extends AbstractItemStreamItemReader { /** * Create a new {@link KafkaItemReader}. - *

      {@code consumerProperties} must contain the following keys: - * 'bootstrap.servers', 'group.id', 'key.deserializer' and 'value.deserializer'

      . + *

      + * {@code consumerProperties} must contain the following keys: + * 'bootstrap.servers', 'group.id', 'key.deserializer' and 'value.deserializer' + * + *

      + * . * @param consumerProperties properties of the consumer * @param topicName name of the topic to read data from * @param partitions list of partitions to read data from @@ -84,8 +88,12 @@ public class KafkaItemReader extends AbstractItemStreamItemReader { /** * Create a new {@link KafkaItemReader}. - *

      {@code consumerProperties} must contain the following keys: - * 'bootstrap.servers', 'group.id', 'key.deserializer' and 'value.deserializer'

      . + *

      + * {@code consumerProperties} must contain the following keys: + * 'bootstrap.servers', 'group.id', 'key.deserializer' and 'value.deserializer' + * + *

      + * . * @param consumerProperties properties of the consumer * @param topicName name of the topic to read data from * @param partitions list of partitions to read data from @@ -122,10 +130,9 @@ public class KafkaItemReader extends AbstractItemStreamItemReader { /** * Set the flag that determines whether to save internal data for - * {@link ExecutionContext}. Only switch this to false if you don't want to - * save any state from this stream, and you don't need it to be restartable. - * Always set it to false if the reader is being used in a concurrent - * environment. + * {@link ExecutionContext}. Only switch this to false if you don't want to save any + * state from this stream, and you don't need it to be restartable. Always set it to + * false if the reader is being used in a concurrent environment. * @param saveState flag value (default true). */ public void setSaveState(boolean saveState) { @@ -142,13 +149,14 @@ public class KafkaItemReader extends AbstractItemStreamItemReader { /** * Setter for partition offsets. This mapping tells the reader the offset to start - * reading from in each partition. This is optional, defaults to starting from - * offset 0 in each partition. Passing an empty map makes the reader start - * from the offset stored in Kafka for the consumer group ID. - * - *

      In case of a restart, offsets stored in the execution context - * will take precedence.

      - * + * reading from in each partition. This is optional, defaults to starting from offset + * 0 in each partition. Passing an empty map makes the reader start from the offset + * stored in Kafka for the consumer group ID. + * + *

      + * In case of a restart, offsets stored in the execution context will take + * precedence. + *

      * @param partitionOffsets mapping of starting offset in each partition */ public void setPartitionOffsets(Map partitionOffsets) { @@ -165,7 +173,8 @@ public class KafkaItemReader extends AbstractItemStreamItemReader { } } if (this.saveState && executionContext.containsKey(TOPIC_PARTITION_OFFSETS)) { - Map offsets = (Map) executionContext.get(TOPIC_PARTITION_OFFSETS); + Map offsets = (Map) executionContext + .get(TOPIC_PARTITION_OFFSETS); for (Map.Entry entry : offsets.entrySet()) { this.partitionOffsets.put(entry.getKey(), entry.getValue() == 0 ? 0 : entry.getValue() + 1); } @@ -204,4 +213,5 @@ public class KafkaItemReader extends AbstractItemStreamItemReader { this.kafkaConsumer.close(); } } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/kafka/KafkaItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/kafka/KafkaItemWriter.java index 52f67785c..0fcdb63a1 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/kafka/KafkaItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/kafka/KafkaItemWriter.java @@ -29,8 +29,8 @@ import java.util.concurrent.TimeUnit; /** *

      - * An {@link ItemWriter} implementation for Apache Kafka using a - * {@link KafkaTemplate} with default topic configured. + * An {@link ItemWriter} implementation for Apache Kafka using a {@link KafkaTemplate} + * with default topic configured. *

      * * @author Mathieu Ouellet @@ -41,7 +41,9 @@ import java.util.concurrent.TimeUnit; public class KafkaItemWriter extends KeyValueItemWriter { protected KafkaTemplate kafkaTemplate; + private final List>> listenableFutures = new ArrayList<>(); + private long timeout = -1; @Override @@ -55,9 +57,9 @@ public class KafkaItemWriter extends KeyValueItemWriter { } @Override - protected void flush() throws Exception{ + protected void flush() throws Exception { this.kafkaTemplate.flush(); - for(ListenableFuture> future: this.listenableFutures){ + for (ListenableFuture> future : this.listenableFutures) { if (this.timeout >= 0) { future.get(this.timeout, TimeUnit.MILLISECONDS); } @@ -84,7 +86,6 @@ public class KafkaItemWriter extends KeyValueItemWriter { /** * The time limit to wait when flushing items to Kafka. - * * @param timeout milliseconds to wait, defaults to -1 (no timeout). * @since 4.3.2 */ diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/kafka/builder/KafkaItemReaderBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/kafka/builder/KafkaItemReaderBuilder.java index 24c37c9ee..ae8c7fb35 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/kafka/builder/KafkaItemReaderBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/kafka/builder/KafkaItemReaderBuilder.java @@ -54,9 +54,9 @@ public class KafkaItemReaderBuilder { private String name; /** - * Configure if the state of the {@link org.springframework.batch.item.ItemStreamSupport} - * should be persisted within the {@link org.springframework.batch.item.ExecutionContext} - * for restart purposes. + * Configure if the state of the + * {@link org.springframework.batch.item.ItemStreamSupport} should be persisted within + * the {@link org.springframework.batch.item.ExecutionContext} for restart purposes. * @param saveState defaults to true * @return The current instance of the builder. */ @@ -66,8 +66,9 @@ public class KafkaItemReaderBuilder { } /** - * The name used to calculate the key within the {@link org.springframework.batch.item.ExecutionContext}. - * Required if {@link #saveState(boolean)} is set to true. + * The name used to calculate the key within the + * {@link org.springframework.batch.item.ExecutionContext}. Required if + * {@link #saveState(boolean)} is set to true. * @param name name of the reader instance * @return The current instance of the builder. * @see org.springframework.batch.item.ItemStreamSupport#setName(String) @@ -79,8 +80,12 @@ public class KafkaItemReaderBuilder { /** * Configure the underlying consumer properties. - *

      {@code consumerProperties} must contain the following keys: - * 'bootstrap.servers', 'group.id', 'key.deserializer' and 'value.deserializer'

      . + *

      + * {@code consumerProperties} must contain the following keys: + * 'bootstrap.servers', 'group.id', 'key.deserializer' and 'value.deserializer' + * + *

      + * . * @param consumerProperties properties of the consumer * @return The current instance of the builder. */ @@ -110,13 +115,14 @@ public class KafkaItemReaderBuilder { /** * Setter for partition offsets. This mapping tells the reader the offset to start - * reading from in each partition. This is optional, defaults to starting from - * offset 0 in each partition. Passing an empty map makes the reader start - * from the offset stored in Kafka for the consumer group ID. - * - *

      In case of a restart, offsets stored in the execution context - * will take precedence.

      + * reading from in each partition. This is optional, defaults to starting from offset + * 0 in each partition. Passing an empty map makes the reader start from the offset + * stored in Kafka for the consumer group ID. * + *

      + * In case of a restart, offsets stored in the execution context will take + * precedence. + *

      * @param partitionOffsets mapping of starting offset in each partition * @return The current instance of the builder. */ @@ -172,4 +178,5 @@ public class KafkaItemReaderBuilder { reader.setPartitionOffsets(this.partitionOffsets); return reader; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/kafka/builder/KafkaItemWriterBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/kafka/builder/KafkaItemWriterBuilder.java index 09df94027..adc6dc37b 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/kafka/builder/KafkaItemWriterBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/kafka/builder/KafkaItemWriterBuilder.java @@ -61,10 +61,11 @@ public class KafkaItemWriterBuilder { } /** - * Indicate if the items being passed to the writer are all to be sent as delete events to the topic. A delete - * event is made of a key with a null value. If set to false (default), the items will be sent with provided value - * and key converter by the itemKeyMapper. If set to true, the items will be sent with the key converter from the - * value by the itemKeyMapper and a null value. + * Indicate if the items being passed to the writer are all to be sent as delete + * events to the topic. A delete event is made of a key with a null value. If set to + * false (default), the items will be sent with provided value and key converter by + * the itemKeyMapper. If set to true, the items will be sent with the key converter + * from the value by the itemKeyMapper and a null value. * @param delete removal indicator. * @return The current instance of the builder. * @see KafkaItemWriter#setDelete(boolean) @@ -76,7 +77,6 @@ public class KafkaItemWriterBuilder { /** * The time limit to wait when flushing items to Kafka. - * * @param timeout milliseconds to wait, defaults to -1 (no timeout). * @return The current instance of the builder. * @see KafkaItemWriter#setTimeout(long) @@ -102,4 +102,5 @@ public class KafkaItemWriterBuilder { writer.setTimeout(this.timeout); return writer; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ldif/LdifReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ldif/LdifReader.java index 6572dd9fa..7e8035f14 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ldif/LdifReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ldif/LdifReader.java @@ -29,23 +29,31 @@ import org.springframework.util.Assert; import org.springframework.util.ClassUtils; /** - * The {@link LdifReader LdifReader} is an adaptation of the {@link org.springframework.batch.item.file.FlatFileItemReader FlatFileItemReader} - * built around an {@link LdifParser LdifParser}. + * The {@link LdifReader LdifReader} is an adaptation of the + * {@link org.springframework.batch.item.file.FlatFileItemReader FlatFileItemReader} built + * around an {@link LdifParser LdifParser}. *

      - * Unlike the {@link org.springframework.batch.item.file.FlatFileItemReader FlatFileItemReader}, the {@link LdifReader LdifReader} - * does not require a mapper. Instead, this version of the {@link LdifReader LdifReader} simply returns an {@link LdapAttributes LdapAttributes} - * object which can be consumed and manipulated as necessary by {@link org.springframework.batch.item.ItemProcessor ItemProcessor} or any - * output service. Alternatively, the {@link RecordMapper RecordMapper} interface can be implemented and set in a - * {@link MappingLdifReader MappingLdifReader} to map records to objects for return. + * Unlike the {@link org.springframework.batch.item.file.FlatFileItemReader + * FlatFileItemReader}, the {@link LdifReader LdifReader} does not require a mapper. + * Instead, this version of the {@link LdifReader LdifReader} simply returns an + * {@link LdapAttributes LdapAttributes} object which can be consumed and manipulated as + * necessary by {@link org.springframework.batch.item.ItemProcessor ItemProcessor} or any + * output service. Alternatively, the {@link RecordMapper RecordMapper} interface can be + * implemented and set in a {@link MappingLdifReader MappingLdifReader} to map records to + * objects for return. *

      - * {@link LdifReader LdifReader} usage is mimics that of the {@link org.springframework.batch.item.file.FlatFileItemReader FlatFileItemReader} - * for all intensive purposes. Adjustments have been made to process records instead of lines, however. As such, the - * {@link #recordsToSkip recordsToSkip} attribute indicates the number of records from the top of the file that should not be processed. - * Implementations of the {@link RecordCallbackHandler RecordCallbackHandler} interface can be used to execute operations on those skipped records. + * {@link LdifReader LdifReader} usage is mimics that of the + * {@link org.springframework.batch.item.file.FlatFileItemReader FlatFileItemReader} for + * all intensive purposes. Adjustments have been made to process records instead of lines, + * however. As such, the {@link #recordsToSkip recordsToSkip} attribute indicates the + * number of records from the top of the file that should not be processed. + * Implementations of the {@link RecordCallbackHandler RecordCallbackHandler} interface + * can be used to execute operations on those skipped records. *

      - * As with the {@link org.springframework.batch.item.file.FlatFileItemReader FlatFileItemReader}, the {@link #strict strict} option differentiates - * between whether or not to require the resource to exist before processing. In the case of a value set to false, a warning is logged instead of - * an exception being thrown. + * As with the {@link org.springframework.batch.item.file.FlatFileItemReader + * FlatFileItemReader}, the {@link #strict strict} option differentiates between whether + * or not to require the resource to exist before processing. In the case of a value set + * to false, a warning is logged instead of an exception being thrown. * * @author Keith Barlow * @@ -73,8 +81,8 @@ public class LdifReader extends AbstractItemCountingItemStreamItemReader - * The {@link MappingLdifReader MappingLdifReader} requires an {@link RecordMapper RecordMapper} implementation. If mapping - * is not required, the {@link LdifReader LdifReader} should be used instead. It simply returns an {@link LdapAttributes LdapAttributes} - * object which can be consumed and manipulated as necessary by {@link org.springframework.batch.item.ItemProcessor ItemProcessor} or any - * output service. + * The {@link MappingLdifReader MappingLdifReader} requires an {@link RecordMapper + * RecordMapper} implementation. If mapping is not required, the {@link LdifReader + * LdifReader} should be used instead. It simply returns an {@link LdapAttributes + * LdapAttributes} object which can be consumed and manipulated as necessary by + * {@link org.springframework.batch.item.ItemProcessor ItemProcessor} or any output + * service. *

      - * As with the {@link org.springframework.batch.item.file.FlatFileItemReader FlatFileItemReader}, the {@link #strict strict} option - * differentiates between whether or not to require the resource to exist before processing. In the case of a value set to false, a warning - * is logged instead of an exception being thrown. + * As with the {@link org.springframework.batch.item.file.FlatFileItemReader + * FlatFileItemReader}, the {@link #strict strict} option differentiates between whether + * or not to require the resource to exist before processing. In the case of a value set + * to false, a warning is logged instead of an exception being thrown. * * @author Keith Barlow * @@ -69,8 +74,8 @@ public class MappingLdifReader extends AbstractItemCountingItemStreamItemRead /** * In strict mode the reader will throw an exception on - * {@link #open(org.springframework.batch.item.ExecutionContext)} if the - * input resource does not exist. + * {@link #open(org.springframework.batch.item.ExecutionContext)} if the input + * resource does not exist. * @param strict false by default */ public void setStrict(boolean strict) { @@ -78,21 +83,19 @@ public class MappingLdifReader extends AbstractItemCountingItemStreamItemRead } /** - * {@link RecordCallbackHandler RecordCallbackHandler} implementations can be used to take action on skipped records. - * - * @param skippedRecordsCallback will be called for each one of the initial - * skipped lines before any items are read. + * {@link RecordCallbackHandler RecordCallbackHandler} implementations can be used to + * take action on skipped records. + * @param skippedRecordsCallback will be called for each one of the initial skipped + * lines before any items are read. */ public void setSkippedRecordsCallback(RecordCallbackHandler skippedRecordsCallback) { this.skippedRecordsCallback = skippedRecordsCallback; } /** - * Public setter for the number of lines to skip at the start of a file. Can - * be used if the file contains a header without useful (column name) - * information, and without a comment delimiter at the beginning of the - * lines. - * + * Public setter for the number of lines to skip at the start of a file. Can be used + * if the file contains a header without useful (column name) information, and without + * a comment delimiter at the beginning of the lines. * @param recordsToSkip the number of lines to skip */ public void setRecordsToSkip(int recordsToSkip) { @@ -122,8 +125,9 @@ public class MappingLdifReader extends AbstractItemCountingItemStreamItemRead if (!resource.exists()) { if (strict) { - throw new IllegalStateException("Input resource must exist (reader is in 'strict' mode): "+resource); - } else { + throw new IllegalStateException("Input resource must exist (reader is in 'strict' mode): " + resource); + } + else { LOG.warn("Input resource does not exist " + resource.getDescription()); return; } @@ -154,9 +158,10 @@ public class MappingLdifReader extends AbstractItemCountingItemStreamItemRead } return null; - } catch(Exception ex){ - LOG.error("Parsing error at record " + recordCount + " in resource=" + - resource.getDescription() + ", input=[" + attributes + "]", ex); + } + catch (Exception ex) { + LOG.error("Parsing error at record " + recordCount + " in resource=" + resource.getDescription() + + ", input=[" + attributes + "]", ex); throw ex; } } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ldif/RecordCallbackHandler.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ldif/RecordCallbackHandler.java index 3b6fdcf20..3bb3c4226 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ldif/RecordCallbackHandler.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ldif/RecordCallbackHandler.java @@ -18,8 +18,8 @@ package org.springframework.batch.item.ldif; import org.springframework.ldap.core.LdapAttributes; /** - * This interface can be used to operate on skipped records during open in the {@link LdifReader LdifReader} and the - * {@link MappingLdifReader MappingLdifReader}. + * This interface can be used to operate on skipped records during open in the + * {@link LdifReader LdifReader} and the {@link MappingLdifReader MappingLdifReader}. * * @author Keith Barlow * @@ -28,7 +28,6 @@ public interface RecordCallbackHandler { /** * Execute operations on the supplied record. - * * @param attributes represents the record */ void handleRecord(LdapAttributes attributes); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ldif/RecordMapper.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ldif/RecordMapper.java index c60d53617..3d824e1c9 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ldif/RecordMapper.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ldif/RecordMapper.java @@ -19,22 +19,20 @@ import org.springframework.lang.Nullable; import org.springframework.ldap.core.LdapAttributes; /** - * This interface should be implemented to map {@link LdapAttributes LdapAttributes} objects to POJOs. The resulting - * implementations can be used in the {@link MappingLdifReader MappingLdifReader}. + * This interface should be implemented to map {@link LdapAttributes LdapAttributes} + * objects to POJOs. The resulting implementations can be used in the + * {@link MappingLdifReader MappingLdifReader}. * * @author Keith Barlow * @author Mahmoud Ben Hassine - * * @param type the record will be mapped to */ public interface RecordMapper { /** * Maps an {@link LdapAttributes LdapAttributes} object to the specified type. - * * @param attributes attributes - * @return object of type T or {@code null} if unable to map the record to - * an object. + * @return object of type T or {@code null} if unable to map the record to an object. */ @Nullable T mapRecord(LdapAttributes attributes); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ldif/builder/LdifReaderBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ldif/builder/LdifReaderBuilder.java index e0172506d..5bda30d64 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ldif/builder/LdifReaderBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ldif/builder/LdifReaderBuilder.java @@ -25,10 +25,10 @@ import org.springframework.util.Assert; * Creates a fully qualified LdifReader. * * @author Glenn Renfro - * * @since 4.0 */ -public class LdifReaderBuilder { +public class LdifReaderBuilder { + private Resource resource; private int recordsToSkip = 0; @@ -46,10 +46,9 @@ public class LdifReaderBuilder { private int currentItemCount; /** - * Configure if the state of the {@link org.springframework.batch.item.ItemStreamSupport} - * should be persisted within the {@link org.springframework.batch.item.ExecutionContext} - * for restart purposes. - * + * Configure if the state of the + * {@link org.springframework.batch.item.ItemStreamSupport} should be persisted within + * the {@link org.springframework.batch.item.ExecutionContext} for restart purposes. * @param saveState defaults to true * @return The current instance of the builder. */ @@ -63,7 +62,6 @@ public class LdifReaderBuilder { * The name used to calculate the key within the * {@link org.springframework.batch.item.ExecutionContext}. Required if * {@link #saveState(boolean)} is set to true. - * * @param name name of the reader instance * @return The current instance of the builder. * @see org.springframework.batch.item.ItemStreamSupport#setName(String) @@ -76,7 +74,6 @@ public class LdifReaderBuilder { /** * Configure the max number of items to be read. - * * @param maxItemCount the max items to be read * @return The current instance of the builder. * @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setMaxItemCount(int) @@ -89,7 +86,6 @@ public class LdifReaderBuilder { /** * Index for the current item. Used on restarts to indicate where to start from. - * * @param currentItemCount current index * @return this instance for method chaining * @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setCurrentItemCount(int) @@ -104,7 +100,6 @@ public class LdifReaderBuilder { * In strict mode the reader will throw an exception on * {@link LdifReader#open(org.springframework.batch.item.ExecutionContext)} if the * input resource does not exist. - * * @param strict true by default * @return this instance for method chaining. * @see LdifReader#setStrict(boolean) @@ -118,7 +113,6 @@ public class LdifReaderBuilder { /** * {@link RecordCallbackHandler RecordCallbackHandler} implementations can be used to * take action on skipped records. - * * @param skippedRecordsCallback will be called for each one of the initial skipped * lines before any items are read. * @return this instance for method chaining. @@ -134,7 +128,6 @@ public class LdifReaderBuilder { * Public setter for the number of lines to skip at the start of a file. Can be used * if the file contains a header without useful (column name) information, and without * a comment delimiter at the beginning of the lines. - * * @param recordsToSkip the number of lines to skip * @return this instance for method chaining. * @see LdifReader#setRecordsToSkip(int) @@ -147,7 +140,6 @@ public class LdifReaderBuilder { /** * Establishes the resource that will be used as the input for the LdifReader. - * * @param resource the resource that will be read. * @return this instance for method chaining. * @see LdifReader#setResource(Resource) @@ -160,7 +152,6 @@ public class LdifReaderBuilder { /** * Returns a fully constructed {@link LdifReader}. - * * @return a new {@link org.springframework.batch.item.ldif.LdifReader} */ public LdifReader build() { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ldif/builder/MappingLdifReaderBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ldif/builder/MappingLdifReaderBuilder.java index 66405d308..e56a723a7 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ldif/builder/MappingLdifReaderBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ldif/builder/MappingLdifReaderBuilder.java @@ -26,10 +26,10 @@ import org.springframework.util.Assert; * Creates a fully qualified MappingLdifReader. * * @author Glenn Renfro - * * @since 4.0 */ -public class MappingLdifReaderBuilder { +public class MappingLdifReaderBuilder { + private Resource resource; private int recordsToSkip = 0; @@ -49,10 +49,9 @@ public class MappingLdifReaderBuilder { private int currentItemCount; /** - * Configure if the state of the {@link org.springframework.batch.item.ItemStreamSupport} - * should be persisted within the {@link org.springframework.batch.item.ExecutionContext} - * for restart purposes. - * + * Configure if the state of the + * {@link org.springframework.batch.item.ItemStreamSupport} should be persisted within + * the {@link org.springframework.batch.item.ExecutionContext} for restart purposes. * @param saveState defaults to true * @return The current instance of the builder. */ @@ -66,7 +65,6 @@ public class MappingLdifReaderBuilder { * The name used to calculate the key within the * {@link org.springframework.batch.item.ExecutionContext}. Required if * {@link #saveState(boolean)} is set to true. - * * @param name name of the reader instance * @return The current instance of the builder. * @see org.springframework.batch.item.ItemStreamSupport#setName(String) @@ -79,7 +77,6 @@ public class MappingLdifReaderBuilder { /** * Configure the max number of items to be read. - * * @param maxItemCount the max items to be read * @return The current instance of the builder. * @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setMaxItemCount(int) @@ -92,7 +89,6 @@ public class MappingLdifReaderBuilder { /** * Index for the current item. Used on restarts to indicate where to start from. - * * @param currentItemCount current index * @return this instance for method chaining * @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setCurrentItemCount(int) @@ -107,7 +103,6 @@ public class MappingLdifReaderBuilder { * In strict mode the reader will throw an exception on * {@link MappingLdifReader#open(org.springframework.batch.item.ExecutionContext)} if * the input resource does not exist. - * * @param strict true by default * @return this instance for method chaining. * @see MappingLdifReader#setStrict(boolean) @@ -121,7 +116,6 @@ public class MappingLdifReaderBuilder { /** * {@link RecordCallbackHandler RecordCallbackHandler} implementations can be used to * take action on skipped records. - * * @param skippedRecordsCallback will be called for each one of the initial skipped * lines before any items are read. * @return this instance for method chaining. @@ -137,7 +131,6 @@ public class MappingLdifReaderBuilder { * Public setter for the number of lines to skip at the start of a file. Can be used * if the file contains a header without useful (column name) information, and without * a comment delimiter at the beginning of the lines. - * * @param recordsToSkip the number of lines to skip * @return this instance for method chaining. * @see MappingLdifReader#setRecordsToSkip(int) @@ -150,7 +143,6 @@ public class MappingLdifReaderBuilder { /** * Establishes the resource that will be used as the input for the MappingLdifReader. - * * @param resource the resource that will be read. * @return this instance for method chaining. * @see MappingLdifReader#setResource(Resource) @@ -163,7 +155,6 @@ public class MappingLdifReaderBuilder { /** * Setter for object mapper. This property is required to be set. - * * @param recordMapper maps record to an object * @return this instance for method chaining. */ @@ -175,7 +166,6 @@ public class MappingLdifReaderBuilder { /** * Returns a fully constructed {@link MappingLdifReader}. - * * @return a new {@link org.springframework.batch.item.ldif.MappingLdifReader} */ public MappingLdifReader build() { @@ -199,4 +189,5 @@ public class MappingLdifReaderBuilder { return reader; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ldif/package-info.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ldif/package-info.java index de9ae6f8f..f50cc0e79 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ldif/package-info.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ldif/package-info.java @@ -1,5 +1,7 @@ /** - *

      This package contains the classes required for using the LdifParser in Spring LDAP.

      + *

      + * This package contains the classes required for using the LdifParser in Spring LDAP. + *

      * * @author Michael Minella * @author Mahmoud Ben Hassine diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/mail/DefaultMailErrorHandler.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/mail/DefaultMailErrorHandler.java index 004765f73..e4cf4a503 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/mail/DefaultMailErrorHandler.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/mail/DefaultMailErrorHandler.java @@ -20,12 +20,10 @@ import org.springframework.mail.MailMessage; import org.springframework.mail.MailSendException; /** - * This {@link MailErrorHandler} implementation simply rethrows the exception it - * receives. - * + * This {@link MailErrorHandler} implementation simply rethrows the exception it receives. + * * @author Dan Garrette * @author Dave Syer - * * @since 2.1 */ public class DefaultMailErrorHandler implements MailErrorHandler { @@ -35,9 +33,8 @@ public class DefaultMailErrorHandler implements MailErrorHandler { private int maxMessageLength = DEFAULT_MAX_MESSAGE_LENGTH; /** - * The limit for the size of message that will be copied to the exception - * message. Output will be truncated beyond that. Default value is 1024. - * + * The limit for the size of message that will be copied to the exception message. + * Output will be truncated beyond that. Default value is 1024. * @param maxMessageLength the maximum message length */ public void setMaxMessageLength(int maxMessageLength) { @@ -45,18 +42,18 @@ public class DefaultMailErrorHandler implements MailErrorHandler { } /** - * Wraps the input exception with a runtime {@link MailException}. The - * exception message will contain the failed message (using toString). - * + * Wraps the input exception with a runtime {@link MailException}. The exception + * message will contain the failed message (using toString). * @param message a failed message * @param exception a MessagingException * @throws MailException a translation of the Exception * @see MailErrorHandler#handle(MailMessage, Exception) */ - @Override + @Override public void handle(MailMessage message, Exception exception) throws MailException { String msg = message.toString(); - throw new MailSendException("Mail server send failed: " - + msg.substring(0, Math.min(maxMessageLength, msg.length())), exception); + throw new MailSendException( + "Mail server send failed: " + msg.substring(0, Math.min(maxMessageLength, msg.length())), exception); } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/mail/MailErrorHandler.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/mail/MailErrorHandler.java index d3eed538d..b27cc841d 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/mail/MailErrorHandler.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/mail/MailErrorHandler.java @@ -19,22 +19,20 @@ import org.springframework.mail.MailException; import org.springframework.mail.MailMessage; /** - * This class is used to handle errors that occur when email messages are unable - * to be sent. - * + * This class is used to handle errors that occur when email messages are unable to be + * sent. + * * @author Dan Garrette * @author Dave Syer - * * @since 2.1 */ public interface MailErrorHandler { /** - * This method will be called for each message that failed sending in the - * chunk. If the failed message is needed by the handler it will need to be - * downcast according to its runtime type. If an exception is thrown from - * this method, then it will propagate to the caller. - * + * This method will be called for each message that failed sending in the chunk. If + * the failed message is needed by the handler it will need to be downcast according + * to its runtime type. If an exception is thrown from this method, then it will + * propagate to the caller. * @param message the failed message * @param exception the exception that caused the failure * @throws MailException if the exception cannot be handled diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/mail/SimpleMailMessageItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/mail/SimpleMailMessageItemWriter.java index 08130d752..b9df93a2c 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/mail/SimpleMailMessageItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/mail/SimpleMailMessageItemWriter.java @@ -29,30 +29,29 @@ import org.springframework.util.Assert; /** *

      - * A simple {@link ItemWriter} that can send mail messages. If it fails there is - * no guarantee about which of the messages were sent, but the ones that failed - * can be picked up in the error handler. Because the mail protocol is not - * transactional, failures should be dealt with here if possible rather than - * allowing them to be rethrown (which is the default). + * A simple {@link ItemWriter} that can send mail messages. If it fails there is no + * guarantee about which of the messages were sent, but the ones that failed can be picked + * up in the error handler. Because the mail protocol is not transactional, failures + * should be dealt with here if possible rather than allowing them to be rethrown (which + * is the default). *

      - * + * *

      - * Delegates the actual sending of messages to a {@link MailSender}, using the - * batch method {@link MailSender#send(SimpleMailMessage[])}, which normally - * uses a single server connection for the whole batch (depending on the - * implementation). The efficiency of for large volumes of messages (repeated - * calls to the item writer) might be improved by the use of a special - * {@link MailSender} that caches connections to the server in between calls. + * Delegates the actual sending of messages to a {@link MailSender}, using the batch + * method {@link MailSender#send(SimpleMailMessage[])}, which normally uses a single + * server connection for the whole batch (depending on the implementation). The efficiency + * of for large volumes of messages (repeated calls to the item writer) might be improved + * by the use of a special {@link MailSender} that caches connections to the server in + * between calls. *

      - * + * *

      * Stateless, so automatically restartable. *

      - * + * * @author Dave Syer - * * @since 2.1 - * + * */ public class SimpleMailMessageItemWriter implements ItemWriter, InitializingBean { @@ -62,7 +61,6 @@ public class SimpleMailMessageItemWriter implements ItemWriter items) throws MailException { try { mailSender.send(items.toArray(new SimpleMailMessage[items.size()])); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/mail/builder/SimpleMailMessageItemWriterBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/mail/builder/SimpleMailMessageItemWriterBuilder.java index 46f12aec7..d8e1fee7f 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/mail/builder/SimpleMailMessageItemWriterBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/mail/builder/SimpleMailMessageItemWriterBuilder.java @@ -28,7 +28,6 @@ import org.springframework.util.Assert; * Creates a fully qualified SimpleMailMessageItemWriter. * * @author Glenn Renfro - * * @since 4.0 */ @@ -41,7 +40,6 @@ public class SimpleMailMessageItemWriterBuilder { /** * A {@link MailSender} to be used to send messages in * {@link SimpleMailMessageItemWriter#write(List)}. - * * @param mailSender strategy for sending simple mails. * @return this instance for method chaining. * @see SimpleMailMessageItemWriter#setMailSender(MailSender) @@ -53,7 +51,6 @@ public class SimpleMailMessageItemWriterBuilder { /** * The handler for failed messages. Defaults to a {@link DefaultMailErrorHandler}. - * * @param mailErrorHandler the mail error handler to set. * @return this instance for method chaining. * @see SimpleMailMessageItemWriter#setMailErrorHandler(MailErrorHandler) @@ -65,7 +62,6 @@ public class SimpleMailMessageItemWriterBuilder { /** * Returns a fully constructed {@link SimpleMailMessageItemWriter}. - * * @return a new {@link SimpleMailMessageItemWriter} */ public SimpleMailMessageItemWriter build() { @@ -79,4 +75,5 @@ public class SimpleMailMessageItemWriterBuilder { return writer; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/mail/javamail/MimeMessageItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/mail/javamail/MimeMessageItemWriter.java index 7d4f88993..ae3d2f955 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/mail/javamail/MimeMessageItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/mail/javamail/MimeMessageItemWriter.java @@ -32,32 +32,30 @@ import java.util.Map.Entry; /** *

      - * A simple {@link ItemWriter} that can send mail messages. If it fails there is - * no guarantee about which of the messages were sent, but the ones that failed - * can be picked up in the error handler. Because the mail protocol is not - * transactional, failures should be dealt with here if possible rather than - * allowing them to be rethrown (which is the default). + * A simple {@link ItemWriter} that can send mail messages. If it fails there is no + * guarantee about which of the messages were sent, but the ones that failed can be picked + * up in the error handler. Because the mail protocol is not transactional, failures + * should be dealt with here if possible rather than allowing them to be rethrown (which + * is the default). *

      - * + * *

      - * Delegates the actual sending of messages to a {@link JavaMailSender}, using the - * batch method {@link JavaMailSender#send(MimeMessage[])}, which normally uses - * a single server connection for the whole batch (depending on the - * implementation). The efficiency of for large volumes of messages (repeated - * calls to the item writer) might be improved by the use of a special - * {@link JavaMailSender} that caches connections to the server in between - * calls. + * Delegates the actual sending of messages to a {@link JavaMailSender}, using the batch + * method {@link JavaMailSender#send(MimeMessage[])}, which normally uses a single server + * connection for the whole batch (depending on the implementation). The efficiency of for + * large volumes of messages (repeated calls to the item writer) might be improved by the + * use of a special {@link JavaMailSender} that caches connections to the server in + * between calls. *

      - * + * *

      * Stateless, so automatically restartable. *

      - * + * * @author Dave Syer * @author Mahmoud Ben Hassine - * * @since 2.1 - * + * */ public class MimeMessageItemWriter implements ItemWriter { @@ -67,7 +65,6 @@ public class MimeMessageItemWriter implements ItemWriter { /** * A {@link JavaMailSender} to be used to send messages in {@link #write(List)}. - * * @param mailSender service for doing the work of sending a MIME message */ public void setJavaMailSender(JavaMailSender mailSender) { @@ -75,9 +72,7 @@ public class MimeMessageItemWriter implements ItemWriter { } /** - * The handler for failed messages. Defaults to a - * {@link DefaultMailErrorHandler}. - * + * The handler for failed messages. Defaults to a {@link DefaultMailErrorHandler}. * @param mailErrorHandler the mail error handler to set */ public void setMailErrorHandler(MailErrorHandler mailErrorHandler) { @@ -86,9 +81,8 @@ public class MimeMessageItemWriter implements ItemWriter { /** * Check mandatory properties (mailSender). - * * @throws IllegalStateException if the mandatory properties are not set - * + * * @see InitializingBean#afterPropertiesSet() */ public void afterPropertiesSet() throws IllegalStateException { @@ -99,7 +93,7 @@ public class MimeMessageItemWriter implements ItemWriter { * @param items the items to send * @see ItemWriter#write(List) */ - @Override + @Override public void write(List items) throws MailException { try { mailSender.send(items.toArray(new MimeMessage[items.size()])); @@ -107,7 +101,7 @@ public class MimeMessageItemWriter implements ItemWriter { catch (MailSendException e) { Map failedMessages = e.getFailedMessages(); for (Entry entry : failedMessages.entrySet()) { - mailErrorHandler.handle(new MimeMailMessage((MimeMessage)entry.getKey()), entry.getValue()); + mailErrorHandler.handle(new MimeMailMessage((MimeMessage) entry.getKey()), entry.getValue()); } } } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/AbstractFileItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/AbstractFileItemWriter.java index 069ef3140..dd376307c 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/AbstractFileItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/AbstractFileItemWriter.java @@ -46,15 +46,14 @@ import org.springframework.core.io.WritableResource; import org.springframework.util.Assert; /** - * Base class for item writers that write data to a file or stream. - * This class provides common features like restart, force sync, append etc. - * The location of the output file is defined by a {@link WritableResource} which must - * represent a writable file.
      - * + * Base class for item writers that write data to a file or stream. This class provides + * common features like restart, force sync, append etc. The location of the output file + * is defined by a {@link WritableResource} which must represent a writable file.
      + * * Uses buffered writer to improve performance.
      - * + * * The implementation is not thread-safe. - * + * * @author Waseem Malik * @author Tomas Slanina * @author Robert Kasanicky @@ -63,7 +62,6 @@ import org.springframework.util.Assert; * @author Mahmoud Ben Hassine * @author Glenn Renfro * @author Remi Kaeffer - * * @since 4.1 */ public abstract class AbstractFileItemWriter extends AbstractItemStreamItemWriter @@ -106,12 +104,10 @@ public abstract class AbstractFileItemWriter extends AbstractItemStreamItemWr protected boolean append = false; /** - * Flag to indicate that changes should be force-synced to disk on flush. - * Defaults to false, which means that even with a local disk changes could - * be lost if the OS crashes in between a write and a cache flush. Setting - * to true may result in slower performance for usage patterns involving many - * frequent writes. - * + * Flag to indicate that changes should be force-synced to disk on flush. Defaults to + * false, which means that even with a local disk changes could be lost if the OS + * crashes in between a write and a cache flush. Setting to true may result in slower + * performance for usage patterns involving many frequent writes. * @param forceSync the flag value to set */ public void setForceSync(boolean forceSync) { @@ -129,7 +125,6 @@ public abstract class AbstractFileItemWriter extends AbstractItemStreamItemWr /** * Setter for a writable resource. Represents a file that can be written. - * * @param resource the resource to be written to */ @Override @@ -139,21 +134,19 @@ public abstract class AbstractFileItemWriter extends AbstractItemStreamItemWr /** * Sets encoding for output template. - * - * @param newEncoding {@link String} containing the encoding to be used for - * the writer. + * @param newEncoding {@link String} containing the encoding to be used for the + * writer. */ public void setEncoding(String newEncoding) { this.encoding = newEncoding; } /** - * Flag to indicate that the target file should be deleted if it already - * exists, otherwise it will be created. Defaults to true, so no appending - * except on restart. If set to false and {@link #setAppendAllowed(boolean) - * appendAllowed} is also false then there will be an exception when the - * stream is opened to prevent existing data being potentially corrupted. - * + * Flag to indicate that the target file should be deleted if it already exists, + * otherwise it will be created. Defaults to true, so no appending except on restart. + * If set to false and {@link #setAppendAllowed(boolean) appendAllowed} is also false + * then there will be an exception when the stream is opened to prevent existing data + * being potentially corrupted. * @param shouldDeleteIfExists the flag value to set */ public void setShouldDeleteIfExists(boolean shouldDeleteIfExists) { @@ -161,12 +154,10 @@ public abstract class AbstractFileItemWriter extends AbstractItemStreamItemWr } /** - * Flag to indicate that the target file should be appended if it already - * exists. If this flag is set then the flag - * {@link #setShouldDeleteIfExists(boolean) shouldDeleteIfExists} is - * automatically set to false, so that flag should not be set explicitly. - * Defaults value is false. - * + * Flag to indicate that the target file should be appended if it already exists. If + * this flag is set then the flag {@link #setShouldDeleteIfExists(boolean) + * shouldDeleteIfExists} is automatically set to false, so that flag should not be set + * explicitly. Defaults value is false. * @param append the flag value to set */ public void setAppendAllowed(boolean append) { @@ -174,9 +165,8 @@ public abstract class AbstractFileItemWriter extends AbstractItemStreamItemWr } /** - * Flag to indicate that the target file should be deleted if no lines have - * been written (other than header and footer) on close. Defaults to false. - * + * Flag to indicate that the target file should be deleted if no lines have been + * written (other than header and footer) on close. Defaults to false. * @param shouldDeleteIfEmpty the flag value to set */ public void setShouldDeleteIfEmpty(boolean shouldDeleteIfEmpty) { @@ -184,11 +174,9 @@ public abstract class AbstractFileItemWriter extends AbstractItemStreamItemWr } /** - * Set the flag indicating whether or not state should be saved in the - * provided {@link ExecutionContext} during the {@link ItemStream} call to - * update. Setting this to false means that it will always start at the - * beginning on a restart. - * + * Set the flag indicating whether or not state should be saved in the provided + * {@link ExecutionContext} during the {@link ItemStream} call to update. Setting this + * to false means that it will always start at the beginning on a restart. * @param saveState if true, state will be persisted */ public void setSaveState(boolean saveState) { @@ -196,9 +184,8 @@ public abstract class AbstractFileItemWriter extends AbstractItemStreamItemWr } /** - * headerCallback will be called before writing the first item to file. - * Newline will be automatically appended after the header is written. - * + * headerCallback will be called before writing the first item to file. Newline will + * be automatically appended after the header is written. * @param headerCallback {@link FlatFileHeaderCallback} to generate the header * */ @@ -207,9 +194,8 @@ public abstract class AbstractFileItemWriter extends AbstractItemStreamItemWr } /** - * footerCallback will be called after writing the last item to file, but - * before the file is closed. - * + * footerCallback will be called after writing the last item to file, but before the + * file is closed. * @param footerCallback {@link FlatFileFooterCallback} to generate the footer * */ @@ -218,9 +204,8 @@ public abstract class AbstractFileItemWriter extends AbstractItemStreamItemWr } /** - * Flag to indicate that writing to the buffer should be delayed if a - * transaction is active. Defaults to true. - * + * Flag to indicate that writing to the buffer should be delayed if a transaction is + * active. Defaults to true. * @param transactional true if writing to buffer should be delayed. * */ @@ -229,9 +214,8 @@ public abstract class AbstractFileItemWriter extends AbstractItemStreamItemWr } /** - * Writes out a string followed by a "new line", where the format of the new - * line separator is determined by the underlying operating system. - * + * Writes out a string followed by a "new line", where the format of the new line + * separator is determined by the underlying operating system. * @param items list of items to be written to output stream * @throws Exception if an error occurs while writing items to the output stream */ @@ -297,9 +281,9 @@ public abstract class AbstractFileItemWriter extends AbstractItemStreamItemWr } /** - * Initialize the reader. This method may be called multiple times before - * close is called. - * + * Initialize the reader. This method may be called multiple times before close is + * called. + * * @see ItemStream#open(ExecutionContext) */ @Override @@ -382,8 +366,8 @@ public abstract class AbstractFileItemWriter extends AbstractItemStreamItemWr } /** - * Encapsulates the runtime state of the writer. All state changing - * operations on the writer go through this class. + * Encapsulates the runtime state of the writer. All state changing operations on the + * writer go through this class. */ protected class OutputState { @@ -413,8 +397,8 @@ public abstract class AbstractFileItemWriter extends AbstractItemStreamItemWr private boolean appending = false; /** - * Return the byte offset position of the cursor in the output file as a - * long integer. + * Return the byte offset position of the cursor in the output file as a long + * integer. * @return the byte offset position of the cursor in the output file * @throws IOException If unable to get the offset position */ @@ -449,10 +433,12 @@ public abstract class AbstractFileItemWriter extends AbstractItemStreamItemWr lastMarkedByteOffsetPosition = executionContext.getLong(getExecutionContextKey(RESTART_DATA_NAME)); linesWritten = executionContext.getLong(getExecutionContextKey(WRITTEN_STATISTICS_NAME)); if (shouldDeleteIfEmpty && linesWritten == 0) { - // previous execution deleted the output file because no items were written + // previous execution deleted the output file because no items were + // written restarted = false; lastMarkedByteOffsetPosition = 0; - } else { + } + else { restarted = true; } } @@ -537,7 +523,6 @@ public abstract class AbstractFileItemWriter extends AbstractItemStreamItemWr /** * Truncate the output at the last known good point. - * * @throws IOException if unable to work with file */ public void truncate() throws IOException { @@ -546,8 +531,8 @@ public abstract class AbstractFileItemWriter extends AbstractItemStreamItemWr } /** - * Creates the buffered writer for the output file channel based on - * configuration information. + * Creates the buffered writer for the output file channel based on configuration + * information. * @throws IOException if unable to initialize buffer */ private void initializeBufferedWriter() throws IOException { @@ -570,8 +555,7 @@ public abstract class AbstractFileItemWriter extends AbstractItemStreamItemWr } } - Assert.state(outputBufferedWriter != null, - "Unable to initialize buffered writer"); + Assert.state(outputBufferedWriter != null, "Unable to initialize buffered writer"); // in case of restarting reset position to last committed point if (restarted) { checkFileSize(); @@ -586,14 +570,15 @@ public abstract class AbstractFileItemWriter extends AbstractItemStreamItemWr } /** - * Returns the buffered writer opened to the beginning of the file - * specified by the absolute path name contained in absoluteFileName. + * Returns the buffered writer opened to the beginning of the file specified by + * the absolute path name contained in absoluteFileName. */ private Writer getBufferedWriter(FileChannel fileChannel, String encoding) { try { final FileChannel channel = fileChannel; if (transactional) { - TransactionAwareBufferedWriter writer = new TransactionAwareBufferedWriter(channel, () -> closeStream()); + TransactionAwareBufferedWriter writer = new TransactionAwareBufferedWriter(channel, + () -> closeStream()); writer.setEncoding(encoding); writer.setForceSync(forceSync); @@ -619,10 +604,10 @@ public abstract class AbstractFileItemWriter extends AbstractItemStreamItemWr } /** - * Checks (on setState) to make sure that the current output file's size - * is not smaller than the last saved commit point. If it is, then the - * file has been damaged in some way and whole task must be started over - * again from the beginning. + * Checks (on setState) to make sure that the current output file's size is not + * smaller than the last saved commit point. If it is, then the file has been + * damaged in some way and whole task must be started over again from the + * beginning. * @throws IOException if there is an IO problem */ private void checkFileSize() throws IOException { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/AbstractItemCountingItemStreamItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/AbstractItemCountingItemStreamItemReader.java index 3c2d6963a..23034eb7c 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/AbstractItemCountingItemStreamItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/AbstractItemCountingItemStreamItemReader.java @@ -26,12 +26,12 @@ import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** - * Abstract superclass for {@link ItemReader}s that supports restart by storing - * item count in the {@link ExecutionContext} (therefore requires item ordering - * to be preserved between runs). - * + * Abstract superclass for {@link ItemReader}s that supports restart by storing item count + * in the {@link ExecutionContext} (therefore requires item ordering to be preserved + * between runs). + * * Subclasses are inherently not thread-safe. - * + * * @author Robert Kasanicky * @author Glenn Renfro * @author Mahmoud Ben Hassine @@ -50,32 +50,34 @@ public abstract class AbstractItemCountingItemStreamItemReader extends Abstra /** * Read next item from input. - * * @return an item or {@code null} if the data source is exhausted - * @throws Exception Allows subclasses to throw checked exceptions for interpretation by the framework + * @throws Exception Allows subclasses to throw checked exceptions for interpretation + * by the framework */ @Nullable protected abstract T doRead() throws Exception; /** * Open resources necessary to start reading input. - * @throws Exception Allows subclasses to throw checked exceptions for interpretation by the framework + * @throws Exception Allows subclasses to throw checked exceptions for interpretation + * by the framework */ protected abstract void doOpen() throws Exception; /** * Close the resources opened in {@link #doOpen()}. - * @throws Exception Allows subclasses to throw checked exceptions for interpretation by the framework + * @throws Exception Allows subclasses to throw checked exceptions for interpretation + * by the framework */ protected abstract void doClose() throws Exception; /** - * Move to the given item index. Subclasses should override this method if - * there is a more efficient way of moving to given index than re-reading - * the input using {@link #doRead()}. - * + * Move to the given item index. Subclasses should override this method if there is a + * more efficient way of moving to given index than re-reading the input using + * {@link #doRead()}. * @param itemIndex index of item (0 based) to jump to. - * @throws Exception Allows subclasses to throw checked exceptions for interpretation by the framework + * @throws Exception Allows subclasses to throw checked exceptions for interpretation + * by the framework */ protected void jumpToItem(int itemIndex) throws Exception { for (int i = 0; i < itemIndex; i++) { @@ -91,7 +93,7 @@ public abstract class AbstractItemCountingItemStreamItemReader extends Abstra } currentItemCount++; T item = doRead(); - if(item instanceof ItemCountAware) { + if (item instanceof ItemCountAware) { ((ItemCountAware) item).setItemCount(currentItemCount); } return item; @@ -102,13 +104,12 @@ public abstract class AbstractItemCountingItemStreamItemReader extends Abstra } /** - * The index of the item to start reading from. If the - * {@link ExecutionContext} contains a key [name].read.count - * (where [name] is the name of this component) the value from - * the {@link ExecutionContext} will be used in preference. - * + * The index of the item to start reading from. If the {@link ExecutionContext} + * contains a key [name].read.count (where [name] is the + * name of this component) the value from the {@link ExecutionContext} will be used in + * preference. + * * @see #setName(String) - * * @param count the value of the current item count */ public void setCurrentItemCount(int count) { @@ -116,15 +117,13 @@ public abstract class AbstractItemCountingItemStreamItemReader extends Abstra } /** - * The maximum index of the items to be read. If the - * {@link ExecutionContext} contains a key - * [name].read.count.max (where [name] is the name - * of this component) the value from the {@link ExecutionContext} will be - * used in preference. - * + * The maximum index of the items to be read. If the {@link ExecutionContext} contains + * a key [name].read.count.max (where [name] is the name of + * this component) the value from the {@link ExecutionContext} will be used in + * preference. + * * @see #setName(String) - * - * @param count the value of the maximum item count. count must be greater than zero. + * @param count the value of the maximum item count. count must be greater than zero. */ public void setMaxItemCount(int count) { Assert.isTrue(count > 0, "count must be greater than zero"); @@ -164,7 +163,7 @@ public abstract class AbstractItemCountingItemStreamItemReader extends Abstra if (executionContext.containsKey(getExecutionContextKey(READ_COUNT))) { itemCount = executionContext.getInt(getExecutionContextKey(READ_COUNT)); } - else if(currentItemCount > 0) { + else if (currentItemCount > 0) { itemCount = currentItemCount; } @@ -194,14 +193,11 @@ public abstract class AbstractItemCountingItemStreamItemReader extends Abstra } - /** * Set the flag that determines whether to save internal data for - * {@link ExecutionContext}. Only switch this to false if you don't want to - * save any state from this stream, and you don't need it to be restartable. - * Always set it to false if the reader is being used in a concurrent - * environment. - * + * {@link ExecutionContext}. Only switch this to false if you don't want to save any + * state from this stream, and you don't need it to be restartable. Always set it to + * false if the reader is being used in a concurrent environment. * @param saveState flag value (default true). */ public void setSaveState(boolean saveState) { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/AbstractItemStreamItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/AbstractItemStreamItemReader.java index b3567a2a9..2a77922d9 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/AbstractItemStreamItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/AbstractItemStreamItemReader.java @@ -20,9 +20,9 @@ import org.springframework.batch.item.ItemReader; import org.springframework.batch.item.ItemStreamReader; import org.springframework.batch.item.ItemStreamSupport; - /** * Base class for {@link ItemReader} implementations. + * * @author Dave Syer * */ diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/AbstractItemStreamItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/AbstractItemStreamItemWriter.java index 07a3538f0..7ad22838d 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/AbstractItemStreamItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/AbstractItemStreamItemWriter.java @@ -20,9 +20,9 @@ import org.springframework.batch.item.ItemStreamSupport; import org.springframework.batch.item.ItemStreamWriter; import org.springframework.batch.item.ItemWriter; - /** * Base class for {@link ItemWriter} implementations. + * * @author Dave Syer * */ diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/ClassifierCompositeItemProcessor.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/ClassifierCompositeItemProcessor.java index 482798485..c06e911f2 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/ClassifierCompositeItemProcessor.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/ClassifierCompositeItemProcessor.java @@ -22,19 +22,18 @@ import org.springframework.classify.ClassifierSupport; import org.springframework.lang.Nullable; /** - * Calls one of a collection of ItemProcessors, based on a router - * pattern implemented through the provided {@link Classifier}. - * - * Note the user is responsible for injecting a {@link Classifier} - * that returns an ItemProcessor that conforms to the declared input and output types. - * + * Calls one of a collection of ItemProcessors, based on a router pattern implemented + * through the provided {@link Classifier}. + * + * Note the user is responsible for injecting a {@link Classifier} that returns an + * ItemProcessor that conforms to the declared input and output types. + * * @author Jimmy Praet * @since 3.0 */ -public class ClassifierCompositeItemProcessor implements ItemProcessor { +public class ClassifierCompositeItemProcessor implements ItemProcessor { - private Classifier> classifier = - new ClassifierSupport<> (null); + private Classifier> classifier = new ClassifierSupport<>(null); /** * Establishes the classifier that will determine which {@link ItemProcessor} to use. @@ -43,7 +42,7 @@ public class ClassifierCompositeItemProcessor implements ItemProcessor> classifier) { this.classifier = classifier; } - + /** * Delegates to injected {@link ItemProcessor} instances according to the * classification by the {@link Classifier}. @@ -53,14 +52,16 @@ public class ClassifierCompositeItemProcessor implements ItemProcessor is not applicable for the arguments (I) - */ - @SuppressWarnings("unchecked") + + /* + * Helper method to work around wildcard capture compiler error: see + * https://docs.oracle.com/javase/tutorial/java/generics/capture.html The method + * process(capture#4-of ?) in the type ItemProcessor is not applicable for the arguments (I) + */ + @SuppressWarnings("unchecked") private O processItem(ItemProcessor processor, I input) throws Exception { - return processor.process((T) input); - } + return processor.process((T) input); + } } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/ClassifierCompositeItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/ClassifierCompositeItemWriter.java index 9eafc2aad..4b3f243fa 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/ClassifierCompositeItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/ClassifierCompositeItemWriter.java @@ -27,11 +27,11 @@ import org.springframework.batch.item.ItemWriter; import org.springframework.util.Assert; /** - * Calls one of a collection of ItemWriters for each item, based on a router - * pattern implemented through the provided {@link Classifier}. - * + * Calls one of a collection of ItemWriters for each item, based on a router pattern + * implemented through the provided {@link Classifier}. + * * The implementation is thread-safe if all delegates are thread-safe. - * + * * @author Dave Syer * @author Glenn Renfro * @since 2.0 @@ -52,7 +52,7 @@ public class ClassifierCompositeItemWriter implements ItemWriter { * Delegates to injected {@link ItemWriter} instances according to their * classification by the {@link Classifier}. */ - @Override + @Override public void write(List items) throws Exception { Map, List> map = new LinkedHashMap<>(); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/CompositeItemProcessor.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/CompositeItemProcessor.java index ebea1dbf1..c210bb63d 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/CompositeItemProcessor.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/CompositeItemProcessor.java @@ -25,14 +25,14 @@ import java.util.Arrays; import java.util.List; /** - * Composite {@link ItemProcessor} that passes the item through a sequence of - * injected ItemTransformers (return value of previous - * transformation is the entry value of the next).
      + * Composite {@link ItemProcessor} that passes the item through a sequence of injected + * ItemTransformers (return value of previous transformation is the entry + * value of the next).
      *
      - * - * Note the user is responsible for injecting a chain of {@link ItemProcessor}s - * that conforms to declared input and output types. - * + * + * Note the user is responsible for injecting a chain of {@link ItemProcessor}s that + * conforms to declared input and output types. + * * @author Robert Kasanicky */ public class CompositeItemProcessor implements ItemProcessor, InitializingBean { @@ -48,7 +48,6 @@ public class CompositeItemProcessor implements ItemProcessor, Initia /** * Convenience constructor for setting the delegates. - * * @param delegates array of {@link ItemProcessor} delegates that will work on the * item. */ @@ -58,7 +57,6 @@ public class CompositeItemProcessor implements ItemProcessor, Initia /** * Convenience constructor for setting the delegates. - * * @param delegates list of {@link ItemProcessor} delegates that will work on the * item. */ @@ -81,15 +79,17 @@ public class CompositeItemProcessor implements ItemProcessor, Initia } return (O) result; } - - /* - * Helper method to work around wildcard capture compiler error: see https://docs.oracle.com/javase/tutorial/java/generics/capture.html - * The method process(capture#1-of ?) in the type ItemProcessor is not applicable for the arguments (Object) - */ - @SuppressWarnings("unchecked") + + /* + * Helper method to work around wildcard capture compiler error: see + * https://docs.oracle.com/javase/tutorial/java/generics/capture.html The method + * process(capture#1-of ?) in the type ItemProcessor is + * not applicable for the arguments (Object) + */ + @SuppressWarnings("unchecked") private Object processItem(ItemProcessor processor, Object input) throws Exception { - return processor.process((T) input); - } + return processor.process((T) input); + } @Override public void afterPropertiesSet() throws Exception { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/CompositeItemStream.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/CompositeItemStream.java index 331cdf672..61fbf3f4e 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/CompositeItemStream.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/CompositeItemStream.java @@ -25,10 +25,10 @@ import org.springframework.batch.item.ItemStreamException; /** * Simple {@link ItemStream} that delegates to a list of other streams. - * + * * @author Dave Syer * @author Mahmoud Ben Hassine - * + * */ public class CompositeItemStream implements ItemStream { @@ -36,7 +36,6 @@ public class CompositeItemStream implements ItemStream { /** * Public setter for the {@link ItemStream}s. - * * @param streams {@link List} of {@link ItemStream}. */ public void setStreams(List streams) { @@ -45,7 +44,6 @@ public class CompositeItemStream implements ItemStream { /** * Public setter for the {@link ItemStream}s. - * * @param streams array of {@link ItemStream}. */ public void setStreams(ItemStream[] streams) { @@ -53,9 +51,8 @@ public class CompositeItemStream implements ItemStream { } /** - * Register a {@link ItemStream} as one of the interesting providers under - * the provided key. - * + * Register a {@link ItemStream} as one of the interesting providers under the + * provided key. * @param stream an instance of {@link ItemStream} to be added to the list of streams. */ public void register(ItemStream stream) { @@ -75,7 +72,6 @@ public class CompositeItemStream implements ItemStream { /** * Convenience constructor for setting the {@link ItemStream}s. - * * @param streams {@link List} of {@link ItemStream}. */ public CompositeItemStream(List streams) { @@ -84,7 +80,6 @@ public class CompositeItemStream implements ItemStream { /** * Convenience constructor for setting the {@link ItemStream}s. - * * @param streams array of {@link ItemStream}. */ public CompositeItemStream(ItemStream... streams) { @@ -92,12 +87,12 @@ public class CompositeItemStream implements ItemStream { } /** - * Simple aggregate {@link ExecutionContext} provider for the contributions - * registered under the given key. - * + * Simple aggregate {@link ExecutionContext} provider for the contributions registered + * under the given key. + * * @see org.springframework.batch.item.ItemStream#update(ExecutionContext) */ - @Override + @Override public void update(ExecutionContext executionContext) { for (ItemStream itemStream : streams) { itemStream.update(executionContext); @@ -106,12 +101,11 @@ public class CompositeItemStream implements ItemStream { /** * Broadcast the call to close. - - * @throws ItemStreamException thrown if one of the {@link ItemStream}s in - * the list fails to close. This is a sequential operation so all itemStreams - * in the list after the one that failed to close will remain open. + * @throws ItemStreamException thrown if one of the {@link ItemStream}s in the list + * fails to close. This is a sequential operation so all itemStreams in the list after + * the one that failed to close will remain open. */ - @Override + @Override public void close() throws ItemStreamException { for (ItemStream itemStream : streams) { itemStream.close(); @@ -120,12 +114,11 @@ public class CompositeItemStream implements ItemStream { /** * Broadcast the call to open. - * - * @throws ItemStreamException thrown if one of the {@link ItemStream}s in - * the list fails to open. This is a sequential operation so all itemStreams - * in the list after the one that failed to open will not be opened. + * @throws ItemStreamException thrown if one of the {@link ItemStream}s in the list + * fails to open. This is a sequential operation so all itemStreams in the list after + * the one that failed to open will not be opened. */ - @Override + @Override public void open(ExecutionContext executionContext) throws ItemStreamException { for (ItemStream itemStream : streams) { itemStream.open(executionContext); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/CompositeItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/CompositeItemWriter.java index 7357c1ede..73051efe7 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/CompositeItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/CompositeItemWriter.java @@ -30,9 +30,9 @@ import java.util.List; /** * Calls a collection of {@link ItemWriter}s in fixed-order sequence.
      *
      - * + * * The implementation is thread-safe if all delegates are thread-safe. - * + * * @author Robert Kasanicky * @author Dave Syer */ @@ -51,7 +51,6 @@ public class CompositeItemWriter implements ItemStreamWriter, Initializing /** * Convenience constructor for setting the delegates. - * * @param delegates the list of delegates to use. */ public CompositeItemWriter(List> delegates) { @@ -60,7 +59,6 @@ public class CompositeItemWriter implements ItemStreamWriter, Initializing /** * Convenience constructor for setting the delegates. - * * @param delegates the array of delegates to use. */ public CompositeItemWriter(ItemWriter... delegates) { @@ -70,23 +68,23 @@ public class CompositeItemWriter implements ItemStreamWriter, Initializing /** * Establishes the policy whether to call the open, close, or update methods for the * item writer delegates associated with the CompositeItemWriter. - * * @param ignoreItemStream if false the delegates' open, close, or update methods will * be called when the corresponding methods on the CompositeItemWriter are called. If - * true the delegates' open, close, nor update methods will not be called (default is false). + * true the delegates' open, close, nor update methods will not be called (default is + * false). */ public void setIgnoreItemStream(boolean ignoreItemStream) { this.ignoreItemStream = ignoreItemStream; } - @Override + @Override public void write(List item) throws Exception { for (ItemWriter writer : delegates) { writer.write(item); } } - @Override + @Override public void afterPropertiesSet() throws Exception { Assert.notNull(delegates, "The 'delegates' may not be null"); Assert.notEmpty(delegates, "The 'delegates' may not be empty"); @@ -95,14 +93,14 @@ public class CompositeItemWriter implements ItemStreamWriter, Initializing /** * The list of item writers to use as delegates. Items are written to each of the * delegates. - * - * @param delegates the list of delegates to use. The delegates list must not be null nor be empty. + * @param delegates the list of delegates to use. The delegates list must not be null + * nor be empty. */ public void setDelegates(List> delegates) { this.delegates = delegates; } - @Override + @Override public void close() throws ItemStreamException { for (ItemWriter writer : delegates) { if (!ignoreItemStream && (writer instanceof ItemStream)) { @@ -111,7 +109,7 @@ public class CompositeItemWriter implements ItemStreamWriter, Initializing } } - @Override + @Override public void open(ExecutionContext executionContext) throws ItemStreamException { for (ItemWriter writer : delegates) { if (!ignoreItemStream && (writer instanceof ItemStream)) { @@ -120,7 +118,7 @@ public class CompositeItemWriter implements ItemStreamWriter, Initializing } } - @Override + @Override public void update(ExecutionContext executionContext) throws ItemStreamException { for (ItemWriter writer : delegates) { if (!ignoreItemStream && (writer instanceof ItemStream)) { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/IteratorItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/IteratorItemReader.java index 54d1536e3..95cb7d3fe 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/IteratorItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/IteratorItemReader.java @@ -23,9 +23,9 @@ import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** - * An {@link ItemReader} that pulls data from a {@link Iterator} or - * {@link Iterable} using the constructors. - * + * An {@link ItemReader} that pulls data from a {@link Iterator} or {@link Iterable} using + * the constructors. + * * @author Juliusz Brzostek * @author Dave Syer * @author Mahmoud Ben Hassine @@ -38,11 +38,10 @@ public class IteratorItemReader implements ItemReader { private final Iterator iterator; /** - * Construct a new reader from this iterable (could be a collection), by - * extracting an instance of {@link Iterator} from it. - * + * Construct a new reader from this iterable (could be a collection), by extracting an + * instance of {@link Iterator} from it. * @param iterable in instance of {@link Iterable} - * + * * @see Iterable#iterator() */ public IteratorItemReader(Iterable iterable) { @@ -60,10 +59,10 @@ public class IteratorItemReader implements ItemReader { } /** - * Implementation of {@link ItemReader#read()} that just iterates over the - * iterator provided. + * Implementation of {@link ItemReader#read()} that just iterates over the iterator + * provided. */ - @Nullable + @Nullable @Override public T read() { if (iterator.hasNext()) diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/ListItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/ListItemReader.java index 0fcd98b7f..9262757b8 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/ListItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/ListItemReader.java @@ -25,7 +25,7 @@ import org.springframework.lang.Nullable; /** * An {@link ItemReader} that pulls data from a list. Useful for testing. - * + * * @author Dave Syer * @author jojoldu * @@ -45,7 +45,7 @@ public class ListItemReader implements ItemReader { } } - @Nullable + @Nullable @Override public T read() { if (!list.isEmpty()) { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/ListItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/ListItemWriter.java index 1e1a9c1ec..c51e892ed 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/ListItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/ListItemWriter.java @@ -35,4 +35,5 @@ public class ListItemWriter implements ItemWriter { public List getWrittenItems() { return this.writtenItems; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/PassThroughItemProcessor.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/PassThroughItemProcessor.java index 9c9352611..6387ea5d2 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/PassThroughItemProcessor.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/PassThroughItemProcessor.java @@ -20,23 +20,21 @@ import org.springframework.batch.item.ItemProcessor; import org.springframework.lang.Nullable; /** - * Simple {@link ItemProcessor} that does nothing - simply passes its argument - * through to the caller. Useful as a default when the reader and writer in a - * business process deal with items of the same type, and no transformations are - * required. - * + * Simple {@link ItemProcessor} that does nothing - simply passes its argument through to + * the caller. Useful as a default when the reader and writer in a business process deal + * with items of the same type, and no transformations are required. + * * @author Dave Syer - * + * */ public class PassThroughItemProcessor implements ItemProcessor { /** * Just returns the item back to the caller. - * * @return the item * @see ItemProcessor#process(Object) */ - @Nullable + @Nullable @Override public T process(T item) throws Exception { return item; diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/ScriptItemProcessor.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/ScriptItemProcessor.java index cee4e38bf..30315ade9 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/ScriptItemProcessor.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/ScriptItemProcessor.java @@ -32,26 +32,32 @@ import java.util.Map; /** *

      - * {@link org.springframework.batch.item.ItemProcessor} implementation that passes the current - * item to process to the provided script. Exposes the current item for processing via the + * {@link org.springframework.batch.item.ItemProcessor} implementation that passes the + * current item to process to the provided script. Exposes the current item for processing + * via the * {@link org.springframework.batch.item.support.ScriptItemProcessor#ITEM_BINDING_VARIABLE_NAME} * key name ("item"). A custom key name can be set by invoking: * {@link org.springframework.batch.item.support.ScriptItemProcessor#setItemBindingVariableName} - * with the desired key name. The thread safety of this {@link org.springframework.batch.item.ItemProcessor} - * depends on the implementation of the {@link org.springframework.scripting.ScriptEvaluator} used. + * with the desired key name. The thread safety of this + * {@link org.springframework.batch.item.ItemProcessor} depends on the implementation of + * the {@link org.springframework.scripting.ScriptEvaluator} used. *

      * - * * @author Chris Schaefer * @since 3.0 */ public class ScriptItemProcessor implements ItemProcessor, InitializingBean { + private static final String ITEM_BINDING_VARIABLE_NAME = "item"; private String language; + private ScriptSource script; + private ScriptSource scriptSource; + private ScriptEvaluator scriptEvaluator; + private String itemBindingVariableName = ITEM_BINDING_VARIABLE_NAME; @Nullable @@ -66,11 +72,11 @@ public class ScriptItemProcessor implements ItemProcessor, Initializ /** *

      - * Sets the {@link org.springframework.core.io.Resource} location of the script to use. - * The script language will be deduced from the filename extension. + * Sets the {@link org.springframework.core.io.Resource} location of the script to + * use. The script language will be deduced from the filename extension. *

      - * - * @param resource the {@link org.springframework.core.io.Resource} location of the script to use. + * @param resource the {@link org.springframework.core.io.Resource} location of the + * script to use. */ public void setScript(Resource resource) { Assert.notNull(resource, "The script resource cannot be null"); @@ -82,7 +88,6 @@ public class ScriptItemProcessor implements ItemProcessor, Initializ *

      * Sets the provided {@link String} as the script source code to use. *

      - * * @param scriptSource the {@link String} form of the script source code to use. * @param language the language of the script. */ @@ -101,7 +106,6 @@ public class ScriptItemProcessor implements ItemProcessor, Initializ * {@link org.springframework.batch.item.support.ScriptItemProcessor#ITEM_BINDING_VARIABLE_NAME} * is not suitable ("item"). *

      - * * @param itemBindingVariableName the desired binding variable name */ public void setItemBindingVariableName(String itemBindingVariableName) { @@ -110,12 +114,13 @@ public class ScriptItemProcessor implements ItemProcessor, Initializ /** *

      - * Provides the ability to set a custom {@link org.springframework.scripting.ScriptEvaluator} - * implementation. If not set, a {@link org.springframework.scripting.support.StandardScriptEvaluator} - * will be used by default. + * Provides the ability to set a custom + * {@link org.springframework.scripting.ScriptEvaluator} implementation. If not set, a + * {@link org.springframework.scripting.support.StandardScriptEvaluator} will be used + * by default. *

      - * - * @param scriptEvaluator the {@link org.springframework.scripting.ScriptEvaluator} to use + * @param scriptEvaluator the {@link org.springframework.scripting.ScriptEvaluator} to + * use */ public void setScriptEvaluator(ScriptEvaluator scriptEvaluator) { this.scriptEvaluator = scriptEvaluator; @@ -123,7 +128,7 @@ public class ScriptItemProcessor implements ItemProcessor, Initializ @Override public void afterPropertiesSet() throws Exception { - if(scriptEvaluator == null) { + if (scriptEvaluator == null) { scriptEvaluator = new StandardScriptEvaluator(); } @@ -152,4 +157,5 @@ public class ScriptItemProcessor implements ItemProcessor, Initializ throw new IllegalStateException("Either a script source or script needs to be provided."); } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/SingleItemPeekableItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/SingleItemPeekableItemReader.java index d5d1daa4e..b2d550427 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/SingleItemPeekableItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/SingleItemPeekableItemReader.java @@ -29,19 +29,19 @@ import org.springframework.lang.Nullable; /** *

      - * A {@link PeekableItemReader} that allows the user to peek one item ahead. - * Repeated calls to {@link #peek()} will return the same item, and this will be - * the next item returned from {@link #read()}. + * A {@link PeekableItemReader} that allows the user to peek one item ahead. Repeated + * calls to {@link #peek()} will return the same item, and this will be the next item + * returned from {@link #read()}. *

      - * + * *

      * Intentionally not thread-safe: it wouldn't be possible to honour the peek in - * multiple threads because only one of the threads that peeked would get that - * item in the next call to read. + * multiple threads because only one of the threads that peeked would get that item in the + * next call to read. *

      - * + * * @author Dave Syer - * + * */ public class SingleItemPeekableItemReader implements ItemStreamReader, PeekableItemReader { @@ -52,9 +52,8 @@ public class SingleItemPeekableItemReader implements ItemStreamReader, Pee private ExecutionContext executionContext = new ExecutionContext(); /** - * The item reader to use as a delegate. Items are read from the delegate - * and passed to the caller in {@link #read()}. - * + * The item reader to use as a delegate. Items are read from the delegate and passed + * to the caller in {@link #read()}. * @param delegate the delegate to set */ public void setDelegate(ItemReader delegate) { @@ -62,9 +61,8 @@ public class SingleItemPeekableItemReader implements ItemStreamReader, Pee } /** - * Get the next item from the delegate (whether or not it has already been - * peeked at). - * + * Get the next item from the delegate (whether or not it has already been peeked at). + * * @see ItemReader#read() */ @Nullable @@ -80,12 +78,10 @@ public class SingleItemPeekableItemReader implements ItemStreamReader, Pee } /** - * Peek at the next item, ensuring that if the delegate is an - * {@link ItemStream} the state is stored for the next call to - * {@link #update(ExecutionContext)}. - * + * Peek at the next item, ensuring that if the delegate is an {@link ItemStream} the + * state is stored for the next call to {@link #update(ExecutionContext)}. * @return the next item (or null if there is none). - * + * * @see PeekableItemReader#peek() */ @Nullable @@ -99,9 +95,8 @@ public class SingleItemPeekableItemReader implements ItemStreamReader, Pee } /** - * If the delegate is an {@link ItemStream}, just pass the call on, - * otherwise reset the peek cache. - * + * If the delegate is an {@link ItemStream}, just pass the call on, otherwise reset + * the peek cache. * @throws ItemStreamException if there is a problem * @see ItemStream#close() */ @@ -115,9 +110,8 @@ public class SingleItemPeekableItemReader implements ItemStreamReader, Pee } /** - * If the delegate is an {@link ItemStream}, just pass the call on, - * otherwise reset the peek cache. - * + * If the delegate is an {@link ItemStream}, just pass the call on, otherwise reset + * the peek cache. * @param executionContext the current context * @throws ItemStreamException if there is a problem * @see ItemStream#open(ExecutionContext) @@ -132,10 +126,8 @@ public class SingleItemPeekableItemReader implements ItemStreamReader, Pee } /** - * If there is a cached peek, then retrieve the execution context state from - * that point. If there is no peek cached, then call directly to the - * delegate. - * + * If there is a cached peek, then retrieve the execution context state from that + * point. If there is no peek cached, then call directly to the delegate. * @param executionContext the current context * @throws ItemStreamException if there is a problem * @see ItemStream#update(ExecutionContext) diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/SynchronizedItemStreamReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/SynchronizedItemStreamReader.java index 50d200dd5..7f8f75dfb 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/SynchronizedItemStreamReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/SynchronizedItemStreamReader.java @@ -25,20 +25,19 @@ import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** - * - * This is a simple ItemStreamReader decorator with a synchronized ItemReader.read() + * + * This is a simple ItemStreamReader decorator with a synchronized ItemReader.read() * method - which makes a non-thread-safe ItemReader thread-safe. - * + * * However, if reprocessing an item is problematic then using this will make a job not * restartable. - * - * Here are some links about the motivation behind this class: - * - https://projects.spring.io/spring-batch/faq.html#threading-reader} - * - https://stackoverflow.com/a/20002493/2910265} - * + * + * Here are some links about the motivation behind this class: - + * https://projects.spring.io/spring-batch/faq.html#threading-reader} - + * https://stackoverflow.com/a/20002493/2910265} + * * @author Matthew Ouyang * @since 3.0.4 - * * @param type of object being read */ public class SynchronizedItemStreamReader implements ItemStreamReader, InitializingBean { @@ -53,7 +52,8 @@ public class SynchronizedItemStreamReader implements ItemStreamReader, Ini * This delegates to the read method of the delegate */ @Nullable - public synchronized T read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException { + public synchronized T read() + throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException { return this.delegate.read(); } @@ -73,4 +73,5 @@ public class SynchronizedItemStreamReader implements ItemStreamReader, Ini public void afterPropertiesSet() throws Exception { Assert.notNull(this.delegate, "A delegate item reader is required"); } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/SynchronizedItemStreamWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/SynchronizedItemStreamWriter.java index f9d4cd991..e61853a13 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/SynchronizedItemStreamWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/SynchronizedItemStreamWriter.java @@ -26,24 +26,22 @@ import java.util.List; /** * An {@link ItemStreamWriter} decorator with a synchronized * {@link SynchronizedItemStreamWriter#write write()} method. - * - * This decorator is useful when using a non thread-safe item writer - * in a multi-threaded step. Typical delegate examples are the - * {@link org.springframework.batch.item.json.JsonFileItemWriter JsonFileItemWriter} - * and {@link org.springframework.batch.item.xml.StaxEventItemWriter StaxEventItemWriter}. - * + * + * This decorator is useful when using a non thread-safe item writer in a multi-threaded + * step. Typical delegate examples are the + * {@link org.springframework.batch.item.json.JsonFileItemWriter JsonFileItemWriter} and + * {@link org.springframework.batch.item.xml.StaxEventItemWriter StaxEventItemWriter}. + * *

      - * It should be noted that synchronizing writes might introduce - * some performance degradation, so this decorator should be used - * wisely and only when necessary. For example, using a - * {@link org.springframework.batch.item.file.FlatFileItemWriter FlatFileItemWriter} in - * a multi-threaded step does NOT require synchronizing writes, so using - * this decorator in such use case might be counter-productive. + * It should be noted that synchronizing writes might introduce some performance + * degradation, so this decorator should be used wisely and only when necessary. For + * example, using a {@link org.springframework.batch.item.file.FlatFileItemWriter + * FlatFileItemWriter} in a multi-threaded step does NOT require synchronizing writes, so + * using this decorator in such use case might be counter-productive. *

      * * @author Dimitrios Liapis * @author Mahmoud Ben Hassine - * * @param type of object being written */ public class SynchronizedItemStreamWriter implements ItemStreamWriter, InitializingBean { @@ -52,7 +50,6 @@ public class SynchronizedItemStreamWriter implements ItemStreamWriter, Ini /** * Set the delegate {@link ItemStreamWriter}. - * * @param delegate the delegate to set */ public void setDelegate(ItemStreamWriter delegate) { @@ -86,4 +83,5 @@ public class SynchronizedItemStreamWriter implements ItemStreamWriter, Ini public void afterPropertiesSet() throws Exception { Assert.notNull(this.delegate, "A delegate item writer is required"); } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/builder/ClassifierCompositeItemProcessorBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/builder/ClassifierCompositeItemProcessorBuilder.java index 698a4b557..fd5e47f8e 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/builder/ClassifierCompositeItemProcessorBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/builder/ClassifierCompositeItemProcessorBuilder.java @@ -25,7 +25,6 @@ import org.springframework.util.Assert; * Creates a fully qualified {@link ClassifierCompositeItemProcessor}. * * @author Glenn Renfro - * * @since 4.0 */ public class ClassifierCompositeItemProcessorBuilder { @@ -38,7 +37,8 @@ public class ClassifierCompositeItemProcessorBuilder { * @return this instance for method chaining * @see ClassifierCompositeItemProcessor#setClassifier(Classifier) */ - public ClassifierCompositeItemProcessorBuilder classifier(Classifier> classifier) { + public ClassifierCompositeItemProcessorBuilder classifier( + Classifier> classifier) { this.classifier = classifier; return this; @@ -46,7 +46,6 @@ public class ClassifierCompositeItemProcessorBuilder { /** * Returns a fully constructed {@link ClassifierCompositeItemProcessor}. - * * @return a new {@link ClassifierCompositeItemProcessor} */ public ClassifierCompositeItemProcessor build() { @@ -56,4 +55,5 @@ public class ClassifierCompositeItemProcessorBuilder { processor.setClassifier(this.classifier); return processor; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/builder/ClassifierCompositeItemWriterBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/builder/ClassifierCompositeItemWriterBuilder.java index 2f5360d75..dd0bccdaf 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/builder/ClassifierCompositeItemWriterBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/builder/ClassifierCompositeItemWriterBuilder.java @@ -26,7 +26,6 @@ import org.springframework.util.Assert; * * @author Glenn Renfro * @author Mahmoud Ben Hassine - * * @since 4.0 */ public class ClassifierCompositeItemWriterBuilder { @@ -36,7 +35,6 @@ public class ClassifierCompositeItemWriterBuilder { /** * Establish the classifier to be used for the selection of which {@link ItemWriter} * to use. - * * @param classifier the classifier to set * @return this instance for method chaining * @see org.springframework.batch.item.support.ClassifierCompositeItemWriter#setClassifier(Classifier) @@ -49,7 +47,6 @@ public class ClassifierCompositeItemWriterBuilder { /** * Returns a fully constructed {@link ClassifierCompositeItemWriter}. - * * @return a new {@link ClassifierCompositeItemWriter} */ public ClassifierCompositeItemWriter build() { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/builder/CompositeItemProcessorBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/builder/CompositeItemProcessorBuilder.java index 0d8a00958..c4d6291e4 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/builder/CompositeItemProcessorBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/builder/CompositeItemProcessorBuilder.java @@ -31,11 +31,14 @@ import org.springframework.util.Assert; * @since 4.0 */ public class CompositeItemProcessorBuilder { + private List> delegates; /** - * Establishes the {@link ItemProcessor} delegates that will work on the item to be processed. - * @param delegates list of {@link ItemProcessor} delegates that will work on the item. + * Establishes the {@link ItemProcessor} delegates that will work on the item to be + * processed. + * @param delegates list of {@link ItemProcessor} delegates that will work on the + * item. * @return this instance for method chaining. * @see CompositeItemProcessor#setDelegates(List) */ @@ -46,7 +49,8 @@ public class CompositeItemProcessorBuilder { } /** - * Establishes the {@link ItemProcessor} delegates that will work on the item to be processed. + * Establishes the {@link ItemProcessor} delegates that will work on the item to be + * processed. * @param delegates the {@link ItemProcessor} delegates that will work on the item. * @return this instance for method chaining. * @see CompositeItemProcessorBuilder#delegates(List) @@ -57,7 +61,6 @@ public class CompositeItemProcessorBuilder { /** * Returns a fully constructed {@link CompositeItemProcessor}. - * * @return a new {@link CompositeItemProcessor} */ public CompositeItemProcessor build() { @@ -68,4 +71,5 @@ public class CompositeItemProcessorBuilder { processor.setDelegates(this.delegates); return processor; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/builder/CompositeItemWriterBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/builder/CompositeItemWriterBuilder.java index b2ef41c57..adc067de1 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/builder/CompositeItemWriterBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/builder/CompositeItemWriterBuilder.java @@ -32,6 +32,7 @@ import org.springframework.util.Assert; * @since 4.0 */ public class CompositeItemWriterBuilder { + private List> delegates; private boolean ignoreItemStream = false; @@ -39,12 +40,12 @@ public class CompositeItemWriterBuilder { /** * Establishes the policy whether to call the open, close, or update methods for the * item writer delegates associated with the CompositeItemWriter. - * * @param ignoreItemStream if false the delegates' open, close, or update methods will * be called when the corresponding methods on the CompositeItemWriter are called. If - * true the delegates' open, close, nor update methods will not be called (default is false). + * true the delegates' open, close, nor update methods will not be called (default is + * false). * @return this instance for method chaining. - * + * * @see CompositeItemWriter#setIgnoreItemStream(boolean) */ public CompositeItemWriterBuilder ignoreItemStream(boolean ignoreItemStream) { @@ -56,11 +57,10 @@ public class CompositeItemWriterBuilder { /** * The list of item writers to use as delegates. Items are written to each of the * delegates. - * * @param delegates the list of delegates to use. The delegates list must not be null * nor be empty. * @return this instance for method chaining. - * + * * @see CompositeItemWriter#setDelegates(List) */ public CompositeItemWriterBuilder delegates(List> delegates) { @@ -70,9 +70,7 @@ public class CompositeItemWriterBuilder { } /** - * The item writers to use as delegates. Items are written to each of the - * delegates. - * + * The item writers to use as delegates. Items are written to each of the delegates. * @param delegates the delegates to use. * @return this instance for method chaining. * @@ -86,7 +84,6 @@ public class CompositeItemWriterBuilder { /** * Returns a fully constructed {@link CompositeItemWriter}. - * * @return a new {@link CompositeItemWriter} */ public CompositeItemWriter build() { @@ -98,4 +95,5 @@ public class CompositeItemWriterBuilder { writer.setIgnoreItemStream(this.ignoreItemStream); return writer; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/builder/ScriptItemProcessorBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/builder/ScriptItemProcessorBuilder.java index 1653cd55c..7a79f5e80 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/builder/ScriptItemProcessorBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/builder/ScriptItemProcessorBuilder.java @@ -1,10 +1,10 @@ /* * Copyright 2017 the original author or authors. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software @@ -25,7 +25,6 @@ import org.springframework.util.StringUtils; * Creates a fully qualified ScriptItemProcessor. * * @author Glenn Renfro - * * @since 4.0 */ public class ScriptItemProcessorBuilder { @@ -41,12 +40,11 @@ public class ScriptItemProcessorBuilder { /** * Sets the {@link org.springframework.core.io.Resource} location of the script to * use. The script language will be deduced from the filename extension. - * * @param resource the {@link org.springframework.core.io.Resource} location of the * script to use. * @return this instance for method chaining * @see ScriptItemProcessor#setScript(Resource) - * + * */ public ScriptItemProcessorBuilder scriptResource(Resource resource) { this.scriptResource = resource; @@ -56,7 +54,6 @@ public class ScriptItemProcessorBuilder { /** * Establishes the language of the script. - * * @param language the language of the script. * @return this instance for method chaining * @see ScriptItemProcessor#setScriptSource(String, String) @@ -70,7 +67,6 @@ public class ScriptItemProcessorBuilder { /** * Sets the provided {@link String} as the script source code to use. Language must * not be null nor empty when using script. - * * @param scriptSource the {@link String} form of the script source code to use. * @return this instance for method chaining * @see ScriptItemProcessor#setScriptSource(String, String) @@ -84,9 +80,7 @@ public class ScriptItemProcessorBuilder { /** * Provides the ability to change the key name that scripts use to obtain the current * item to process if the variable represented by: - * {@link ScriptItemProcessor#ITEM_BINDING_VARIABLE_NAME} - * is not suitable ("item"). - * + * {@link ScriptItemProcessor#ITEM_BINDING_VARIABLE_NAME} is not suitable ("item"). * @param itemBindingVariableName the desired binding variable name * @return this instance for method chaining * @see ScriptItemProcessor#setItemBindingVariableName(String) @@ -99,7 +93,6 @@ public class ScriptItemProcessorBuilder { /** * Returns a fully constructed {@link ScriptItemProcessor}. - * * @return a new {@link ScriptItemProcessor} */ public ScriptItemProcessor build() { @@ -126,4 +119,5 @@ public class ScriptItemProcessorBuilder { return processor; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/builder/SingleItemPeekableItemReaderBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/builder/SingleItemPeekableItemReaderBuilder.java index 6b95d0531..2b9b5fc94 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/builder/SingleItemPeekableItemReaderBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/builder/SingleItemPeekableItemReaderBuilder.java @@ -24,7 +24,6 @@ import org.springframework.util.Assert; * Creates a fully qualified SingleItemPeekeableItemReader. * * @author Glenn Renfro - * * @since 4.0 */ public class SingleItemPeekableItemReaderBuilder { @@ -35,7 +34,6 @@ public class SingleItemPeekableItemReaderBuilder { * The item reader to use as a delegate. Items are read from the delegate and passed * to the caller in * {@link org.springframework.batch.item.support.SingleItemPeekableItemReader#read()}. - * * @param delegate the delegate to set * @return this instance for method chaining * @see SingleItemPeekableItemReader#setDelegate(ItemReader) @@ -48,7 +46,6 @@ public class SingleItemPeekableItemReaderBuilder { /** * Returns a fully constructed {@link SingleItemPeekableItemReader}. - * * @return a new {@link SingleItemPeekableItemReader} */ public SingleItemPeekableItemReader build() { @@ -58,4 +55,5 @@ public class SingleItemPeekableItemReaderBuilder { reader.setDelegate(this.delegate); return reader; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/builder/SynchronizedItemStreamReaderBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/builder/SynchronizedItemStreamReaderBuilder.java index 560b0c06d..df15272ad 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/builder/SynchronizedItemStreamReaderBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/builder/SynchronizedItemStreamReaderBuilder.java @@ -24,7 +24,6 @@ import org.springframework.util.Assert; * Creates a fully qualified SynchronizedItemStreamReader. * * @author Glenn Renfro - * * @since 4.0 */ public class SynchronizedItemStreamReaderBuilder { @@ -35,7 +34,6 @@ public class SynchronizedItemStreamReaderBuilder { * The item stream reader to use as a delegate. Items are read from the delegate and * passed to the caller in * {@link org.springframework.batch.item.support.SynchronizedItemStreamReader#read()}. - * * @param delegate the delegate to set * @return this instance for method chaining * @see SynchronizedItemStreamReader#setDelegate(ItemStreamReader) @@ -48,7 +46,6 @@ public class SynchronizedItemStreamReaderBuilder { /** * Returns a fully constructed {@link SynchronizedItemStreamReader}. - * * @return a new {@link SynchronizedItemStreamReader} */ public SynchronizedItemStreamReader build() { @@ -58,4 +55,5 @@ public class SynchronizedItemStreamReaderBuilder { reader.setDelegate(this.delegate); return reader; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/builder/SynchronizedItemStreamWriterBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/builder/SynchronizedItemStreamWriterBuilder.java index 18e08dba7..18b89c5c8 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/builder/SynchronizedItemStreamWriterBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/support/builder/SynchronizedItemStreamWriterBuilder.java @@ -31,7 +31,6 @@ public class SynchronizedItemStreamWriterBuilder { /** * Set the delegate {@link ItemStreamWriter}. - * * @param delegate the delegate to set * @return this instance for method chaining */ @@ -43,7 +42,6 @@ public class SynchronizedItemStreamWriterBuilder { /** * Returns a fully constructed {@link SynchronizedItemStreamWriter}. - * * @return a new {@link SynchronizedItemStreamWriter} */ public SynchronizedItemStreamWriter build() { @@ -53,4 +51,5 @@ public class SynchronizedItemStreamWriterBuilder { writer.setDelegate(this.delegate); return writer; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/util/ExecutionContextUserSupport.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/util/ExecutionContextUserSupport.java index 1b3365f4c..389de9fc9 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/util/ExecutionContextUserSupport.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/util/ExecutionContextUserSupport.java @@ -19,9 +19,9 @@ import org.springframework.batch.item.ExecutionContext; import org.springframework.util.Assert; /** - * Facilitates assigning names to objects persisting data in {@link ExecutionContext} and generating keys for - * {@link ExecutionContext} based on the name. - * + * Facilitates assigning names to objects persisting data in {@link ExecutionContext} and + * generating keys for {@link ExecutionContext} based on the name. + * * @author Robert Kasanicky */ public class ExecutionContextUserSupport { @@ -52,9 +52,8 @@ public class ExecutionContextUserSupport { } /** - * Prefix the argument with {@link #getName()} to create a unique key that can be safely used to identify data - * stored in {@link ExecutionContext}. - * + * Prefix the argument with {@link #getName()} to create a unique key that can be + * safely used to identify data stored in {@link ExecutionContext}. * @param suffix {@link String} to be used to generate the key. * @return the key that was generated based on the name and the suffix. */ diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/util/FileUtils.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/util/FileUtils.java index f52ccece6..d7a837072 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/util/FileUtils.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/util/FileUtils.java @@ -24,7 +24,7 @@ import org.springframework.util.Assert; /** * Utility methods for files used in batch processing. - * + * * @author Peter Zozom * @author Mahmoud Ben Hassine */ @@ -35,15 +35,15 @@ public final class FileUtils { } /** - * Set up output file for batch processing. This method implements common logic for handling output files when - * starting or restarting file I/O. When starting output file processing, creates/overwrites new file. When - * restarting output file processing, checks whether file is writable. - * + * Set up output file for batch processing. This method implements common logic for + * handling output files when starting or restarting file I/O. When starting output + * file processing, creates/overwrites new file. When restarting output file + * processing, checks whether file is writable. * @param file file to be set up * @param restarted true signals that we are restarting output file processing * @param append true signals input file may already exist (but doesn't have to) - * @param overwriteOutputFile If set to true, output file will be overwritten (this flag is ignored when processing - * is restart) + * @param overwriteOutputFile If set to true, output file will be overwritten (this + * flag is ignored when processing is restart) */ public static void setUpOutputFile(File file, boolean restarted, boolean append, boolean overwriteOutputFile) { @@ -74,8 +74,8 @@ public final class FileUtils { new File(file.getParent()).mkdirs(); } if (!createNewFile(file)) { - throw new ItemStreamException("Output file was not created: [" + file.getAbsolutePath() - + "]"); + throw new ItemStreamException( + "Output file was not created: [" + file.getAbsolutePath() + "]"); } } } @@ -92,12 +92,10 @@ public final class FileUtils { /** * Create a new file if it doesn't already exist. - * * @param file the file to create on the filesystem * @return true if file was created else false. - * - * @throws IOException is thrown if error occurs during creation and file - * does not exist. + * @throws IOException is thrown if error occurs during creation and file does not + * exist. */ public static boolean createNewFile(File file) throws IOException { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/validator/BeanValidatingItemProcessor.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/validator/BeanValidatingItemProcessor.java index 1b8e10806..4b6ed2da4 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/validator/BeanValidatingItemProcessor.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/validator/BeanValidatingItemProcessor.java @@ -23,8 +23,8 @@ import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; import org.springframework.validation.beanvalidation.SpringValidatorAdapter; /** - * A {@link ValidatingItemProcessor} that uses the Bean Validation API (JSR-303) - * to validate items. + * A {@link ValidatingItemProcessor} that uses the Bean Validation API (JSR-303) to + * validate items. * * @param type of items to validate * @author Mahmoud Ben Hassine @@ -35,8 +35,8 @@ public class BeanValidatingItemProcessor extends ValidatingItemProcessor { private Validator validator; /** - * Create a new instance of {@link BeanValidatingItemProcessor} with the - * default configuration. + * Create a new instance of {@link BeanValidatingItemProcessor} with the default + * configuration. */ public BeanValidatingItemProcessor() { LocalValidatorFactoryBean localValidatorFactoryBean = new LocalValidatorFactoryBean(); @@ -62,4 +62,5 @@ public class BeanValidatingItemProcessor extends ValidatingItemProcessor { setValidator(springValidator); super.afterPropertiesSet(); } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/validator/SpringValidator.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/validator/SpringValidator.java index 42f3ca728..d4b8e5d0a 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/validator/SpringValidator.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/validator/SpringValidator.java @@ -27,7 +27,7 @@ import org.springframework.validation.Errors; /** * Adapts the {@link org.springframework.validation.Validator} interface to * {@link org.springframework.batch.item.validator.Validator}. - * + * * @author Tomas Slanina * @author Robert Kasanicky */ @@ -38,7 +38,7 @@ public class SpringValidator implements Validator, InitializingBean { /** * @see Validator#validate(Object) */ - @Override + @Override public void validate(T item) throws ValidationException { if (!validator.supports(item.getClass())) { @@ -51,7 +51,8 @@ public class SpringValidator implements Validator, InitializingBean { validator.validate(item, errors); if (errors.hasErrors()) { - throw new ValidationException("Validation failed for " + item + ": " + errorsToString(errors), new BindException(errors)); + throw new ValidationException("Validation failed for " + item + ": " + errorsToString(errors), + new BindException(errors)); } } @@ -68,8 +69,8 @@ public class SpringValidator implements Validator, InitializingBean { } /** - * Append the string representation of elements of the collection (separated - * by new lines) to the given StringBuilder. + * Append the string representation of elements of the collection (separated by new + * lines) to the given StringBuilder. */ private void appendCollection(Collection collection, StringBuilder builder) { for (Object value : collection) { @@ -82,9 +83,10 @@ public class SpringValidator implements Validator, InitializingBean { this.validator = validator; } - @Override + @Override public void afterPropertiesSet() throws Exception { Assert.notNull(validator, "validator must be set"); } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/validator/ValidatingItemProcessor.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/validator/ValidatingItemProcessor.java index 156d362e0..d48cd882d 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/validator/ValidatingItemProcessor.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/validator/ValidatingItemProcessor.java @@ -21,13 +21,12 @@ import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** - * Simple implementation of {@link ItemProcessor} that validates input and - * returns it without modifications. Should the given {@link Validator} throw a - * {@link ValidationException} this processor will re-throw it to indicate the - * item should be skipped, unless {@link #setFilter(boolean)} is set to - * true, in which case null will be returned to - * indicate the item should be filtered. - * + * Simple implementation of {@link ItemProcessor} that validates input and returns it + * without modifications. Should the given {@link Validator} throw a + * {@link ValidationException} this processor will re-throw it to indicate the item should + * be skipped, unless {@link #setFilter(boolean)} is set to true, in which + * case null will be returned to indicate the item should be filtered. + * * @author Robert Kasanicky */ public class ValidatingItemProcessor implements ItemProcessor, InitializingBean { @@ -44,7 +43,6 @@ public class ValidatingItemProcessor implements ItemProcessor, Initiali /** * Creates a ValidatingItemProcessor based on the given Validator. - * * @param validator the {@link Validator} instance to be used. */ public ValidatingItemProcessor(Validator validator) { @@ -53,7 +51,6 @@ public class ValidatingItemProcessor implements ItemProcessor, Initiali /** * Set the validator used to validate each item. - * * @param validator the {@link Validator} instance to be used. */ public void setValidator(Validator validator) { @@ -62,9 +59,8 @@ public class ValidatingItemProcessor implements ItemProcessor, Initiali /** * Should the processor filter invalid records instead of skipping them? - * * @param filter if set to {@code true}, items that fail validation are filtered - * ({@code null} is returned). Otherwise, a {@link ValidationException} will be + * ({@code null} is returned). Otherwise, a {@link ValidationException} will be * thrown. */ public void setFilter(boolean filter) { @@ -73,11 +69,10 @@ public class ValidatingItemProcessor implements ItemProcessor, Initiali /** * Validate the item and return it unmodified - * * @return the input item * @throws ValidationException if validation fails */ - @Nullable + @Nullable @Override public T process(T item) throws ValidationException { try { @@ -94,7 +89,7 @@ public class ValidatingItemProcessor implements ItemProcessor, Initiali return item; } - @Override + @Override public void afterPropertiesSet() throws Exception { Assert.notNull(validator, "Validator must not be null."); } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/validator/ValidationException.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/validator/ValidationException.java index e883d38fc..1e0d19387 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/validator/ValidationException.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/validator/ValidationException.java @@ -20,7 +20,7 @@ import org.springframework.batch.item.ItemReaderException; /** * This exception should be thrown when there are validation errors. - * + * * @author Ben Hale */ @SuppressWarnings("serial") @@ -28,7 +28,6 @@ public class ValidationException extends ItemReaderException { /** * Create a new {@link ValidationException} based on a message and another exception. - * * @param message the message for this exception * @param cause the other exception */ @@ -38,7 +37,6 @@ public class ValidationException extends ItemReaderException { /** * Create a new {@link ValidationException} based on a message. - * * @param message the message for this exception */ public ValidationException(String message) { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/validator/Validator.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/validator/Validator.java index 91a0ac2e1..2becc900f 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/validator/Validator.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/validator/Validator.java @@ -16,19 +16,19 @@ package org.springframework.batch.item.validator; - /** * Interface used to validate objects. - * + * * @author tomas.slanina - * + * */ public interface Validator { + /** * Method used to validate if the value is valid. - * * @param value object to be validated * @throws ValidationException if value is not valid. */ void validate(T value) throws ValidationException; + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/StaxEventItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/StaxEventItemReader.java index 4bc56d341..9a91b2876 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/StaxEventItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/StaxEventItemReader.java @@ -50,18 +50,18 @@ import org.springframework.util.xml.StaxUtils; /** * Item reader for reading XML input based on StAX. - * - * It extracts fragments from the input XML document which correspond to records for processing. The fragments are - * wrapped with StartDocument and EndDocument events so that the fragments can be further processed like standalone XML - * documents. - * + * + * It extracts fragments from the input XML document which correspond to records for + * processing. The fragments are wrapped with StartDocument and EndDocument events so that + * the fragments can be further processed like standalone XML documents. + * * The implementation is not thread-safe. - * + * * @author Robert Kasanicky * @author Mahmoud Ben Hassine */ -public class StaxEventItemReader extends AbstractItemCountingItemStreamItemReader implements -ResourceAwareItemReaderItemStream, InitializingBean { +public class StaxEventItemReader extends AbstractItemCountingItemStreamItemReader + implements ResourceAwareItemReaderItemStream, InitializingBean { private static final Log logger = LogFactory.getLog(StaxEventItemReader.class); @@ -93,7 +93,8 @@ ResourceAwareItemReaderItemStream, InitializingBean { /** * In strict mode the reader will throw an exception on - * {@link #open(org.springframework.batch.item.ExecutionContext)} if the input resource does not exist. + * {@link #open(org.springframework.batch.item.ExecutionContext)} if the input + * resource does not exist. * @param strict true by default */ public void setStrict(boolean strict) { @@ -116,11 +117,12 @@ ResourceAwareItemReaderItemStream, InitializingBean { * @param fragmentRootElementName name of the root element of the fragment */ public void setFragmentRootElementName(String fragmentRootElementName) { - setFragmentRootElementNames(new String[] {fragmentRootElementName}); + setFragmentRootElementNames(new String[] { fragmentRootElementName }); } /** - * @param fragmentRootElementNames list of the names of the root element of the fragment + * @param fragmentRootElementNames list of the names of the root element of the + * fragment */ public void setFragmentRootElementNames(String[] fragmentRootElementNames) { this.fragmentRootElementNames = new ArrayList<>(); @@ -140,7 +142,6 @@ ResourceAwareItemReaderItemStream, InitializingBean { /** * Set encoding to be used for the input file. Defaults to {@link #DEFAULT_ENCODING}. - * * @param encoding the encoding to be used */ public void setEncoding(String encoding) { @@ -149,11 +150,12 @@ ResourceAwareItemReaderItemStream, InitializingBean { } /** - * Ensure that all required dependencies for the ItemReader to run are provided after all properties have been set. - * + * Ensure that all required dependencies for the ItemReader to run are provided after + * all properties have been set. + * * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() - * @throws IllegalArgumentException if the Resource, FragmentDeserializer or FragmentRootElementName is null, or if - * the root element is empty. + * @throws IllegalArgumentException if the Resource, FragmentDeserializer or + * FragmentRootElementName is null, or if the root element is empty. * @throws IllegalStateException if the Resource does not exist. */ @Override @@ -161,22 +163,21 @@ ResourceAwareItemReaderItemStream, InitializingBean { Assert.notNull(unmarshaller, "The Unmarshaller must not be null."); Assert.notEmpty(fragmentRootElementNames, "The FragmentRootElementNames must not be empty"); for (QName fragmentRootElementName : fragmentRootElementNames) { - Assert.hasText(fragmentRootElementName.getLocalPart(), "The FragmentRootElementNames must not contain empty elements"); - } + Assert.hasText(fragmentRootElementName.getLocalPart(), + "The FragmentRootElementNames must not contain empty elements"); + } } /** * Responsible for moving the cursor before the StartElement of the fragment root. - * - * This implementation simply looks for the next corresponding element, it does not care about element nesting. You - * will need to override this method to correctly handle composite fragments. * + * This implementation simply looks for the next corresponding element, it does not + * care about element nesting. You will need to override this method to correctly + * handle composite fragments. * @param reader the {@link XMLEventReader} to be used to find next fragment. - * * @return true if next fragment was found, false otherwise. - * - * @throws NonTransientResourceException if the cursor could not be moved. This will be treated as fatal and - * subsequent calls to read will return null. + * @throws NonTransientResourceException if the cursor could not be moved. This will + * be treated as fatal and subsequent calls to read will return null. */ protected boolean moveCursorToNextFragment(XMLEventReader reader) throws NonTransientResourceException { try { @@ -283,8 +284,9 @@ ResourceAwareItemReaderItemStream, InitializingBean { } /* - * jumpToItem is overridden because reading in and attempting to bind an entire fragment is unacceptable in a - * restart scenario, and may cause exceptions to be thrown that were already skipped in previous runs. + * jumpToItem is overridden because reading in and attempting to bind an entire + * fragment is unacceptable in a restart scenario, and may cause exceptions to be + * thrown that were already skipped in previous runs. */ @Override protected void jumpToItem(int itemIndex) throws Exception { @@ -292,12 +294,16 @@ ResourceAwareItemReaderItemStream, InitializingBean { try { QName fragmentName = readToStartFragment(); readToEndFragment(fragmentName); - } catch (NoSuchElementException e) { + } + catch (NoSuchElementException e) { if (itemIndex == (i + 1)) { - // we can presume a NoSuchElementException on the last item means the EOF was reached on the last run + // we can presume a NoSuchElementException on the last item means the + // EOF was reached on the last run return; - } else { - // if NoSuchElementException occurs on an item other than the last one, this indicates a problem + } + else { + // if NoSuchElementException occurs on an item other than the last + // one, this indicates a problem throw e; } } @@ -305,47 +311,47 @@ ResourceAwareItemReaderItemStream, InitializingBean { } /* - * Read until the first StartElement tag that matches any of the provided fragmentRootElementNames. Because there may be any - * number of tags in between where the reader is now and the fragment start, this is done in a loop until the - * element type and name match. + * Read until the first StartElement tag that matches any of the provided + * fragmentRootElementNames. Because there may be any number of tags in between where + * the reader is now and the fragment start, this is done in a loop until the element + * type and name match. */ private QName readToStartFragment() throws XMLStreamException { while (true) { XMLEvent nextEvent = eventReader.nextEvent(); - if (nextEvent.isStartElement() - && isFragmentRootElementName(((StartElement) nextEvent).getName())) { + if (nextEvent.isStartElement() && isFragmentRootElementName(((StartElement) nextEvent).getName())) { return ((StartElement) nextEvent).getName(); } } } /* - * Read until the first EndElement tag that matches the provided fragmentRootElementName. Because there may be any - * number of tags in between where the reader is now and the fragment end tag, this is done in a loop until the + * Read until the first EndElement tag that matches the provided + * fragmentRootElementName. Because there may be any number of tags in between where + * the reader is now and the fragment end tag, this is done in a loop until the * element type and name match */ private void readToEndFragment(QName fragmentRootElementName) throws XMLStreamException { while (true) { XMLEvent nextEvent = eventReader.nextEvent(); - if (nextEvent.isEndElement() - && fragmentRootElementName.equals(((EndElement) nextEvent).getName())) { + if (nextEvent.isEndElement() && fragmentRootElementName.equals(((EndElement) nextEvent).getName())) { return; } } } - + protected boolean isFragmentRootElementName(QName name) { for (QName fragmentRootElementName : fragmentRootElementNames) { if (fragmentRootElementName.getLocalPart().equals(name.getLocalPart())) { if (!StringUtils.hasText(fragmentRootElementName.getNamespaceURI()) - || fragmentRootElementName.getNamespaceURI().equals(name.getNamespaceURI())) { + || fragmentRootElementName.getNamespaceURI().equals(name.getNamespaceURI())) { return true; } } } return false; - } - + } + private QName parseFragmentRootElementName(String fragmentRootElementName) { String name = fragmentRootElementName; String nameSpace = null; @@ -355,5 +361,5 @@ ResourceAwareItemReaderItemStream, InitializingBean { } return new QName(nameSpace, name, ""); } - + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/StaxEventItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/StaxEventItemWriter.java index c012a204c..4af844600 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/StaxEventItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/StaxEventItemWriter.java @@ -62,22 +62,22 @@ import org.springframework.util.StringUtils; import org.springframework.util.xml.StaxUtils; /** - * An implementation of {@link ItemWriter} which uses StAX and - * {@link Marshaller} for serializing object to XML. - * - * This item writer also provides restart, statistics and transaction features - * by implementing corresponding interfaces. - * + * An implementation of {@link ItemWriter} which uses StAX and {@link Marshaller} for + * serializing object to XML. + * + * This item writer also provides restart, statistics and transaction features by + * implementing corresponding interfaces. + * * The implementation is not thread-safe. - * + * * @author Peter Zozom * @author Robert Kasanicky * @author Michael Minella * @author Parikshit Dutta * @author Mahmoud Ben Hassine */ -public class StaxEventItemWriter extends AbstractItemStreamItemWriter implements -ResourceAwareItemWriterItemStream, InitializingBean { +public class StaxEventItemWriter extends AbstractItemStreamItemWriter + implements ResourceAwareItemWriterItemStream, InitializingBean { private static final Log log = LogFactory.getLog(StaxEventItemWriter.class); @@ -98,7 +98,7 @@ ResourceAwareItemWriterItemStream, InitializingBean { // unclosed header callback elements property name private static final String UNCLOSED_HEADER_CALLBACK_ELEMENTS_NAME = "unclosedHeaderCallbackElements"; - + // restart data property name private static final String WRITE_STATISTICS_NAME = "record.count"; @@ -159,12 +159,13 @@ ResourceAwareItemWriterItemStream, InitializingBean { private boolean forceSync; private boolean shouldDeleteIfEmpty = false; - + private boolean restarted = false; private boolean initialized = false; - - // List holding the QName of elements that were opened in the header callback, but not closed + + // List holding the QName of elements that were opened in the header callback, but not + // closed private List unclosedHeaderCallbackElements = Collections.emptyList(); public StaxEventItemWriter() { @@ -173,7 +174,6 @@ ResourceAwareItemWriterItemStream, InitializingBean { /** * Set output file. - * * @param resource the output file */ @Override @@ -183,7 +183,6 @@ ResourceAwareItemWriterItemStream, InitializingBean { /** * Set Object to XML marshaller. - * * @param marshaller the Object to XML marshaller */ public void setMarshaller(Marshaller marshaller) { @@ -192,27 +191,25 @@ ResourceAwareItemWriterItemStream, InitializingBean { /** * headerCallback is called before writing any items. - * - * @param headerCallback the {@link StaxWriterCallback} to be called prior to writing items. + * @param headerCallback the {@link StaxWriterCallback} to be called prior to writing + * items. */ public void setHeaderCallback(StaxWriterCallback headerCallback) { this.headerCallback = headerCallback; } /** - * footerCallback is called after writing all items but before closing the - * file. - * - *@param footerCallback the {@link StaxWriterCallback} to be called after writing items. + * footerCallback is called after writing all items but before closing the file. + * @param footerCallback the {@link StaxWriterCallback} to be called after writing + * items. */ public void setFooterCallback(StaxWriterCallback footerCallback) { this.footerCallback = footerCallback; } /** - * Flag to indicate that writes should be deferred to the end of a - * transaction if present. Defaults to true. - * + * Flag to indicate that writes should be deferred to the end of a transaction if + * present. Defaults to true. * @param transactional the flag to set */ public void setTransactional(boolean transactional) { @@ -220,12 +217,10 @@ ResourceAwareItemWriterItemStream, InitializingBean { } /** - * Flag to indicate that changes should be force-synced to disk on flush. - * Defaults to false, which means that even with a local disk changes could - * be lost if the OS crashes in between a write and a cache flush. Setting - * to true may result in slower performance for usage patterns involving - * many frequent writes. - * + * Flag to indicate that changes should be force-synced to disk on flush. Defaults to + * false, which means that even with a local disk changes could be lost if the OS + * crashes in between a write and a cache flush. Setting to true may result in slower + * performance for usage patterns involving many frequent writes. * @param forceSync the flag value to set */ public void setForceSync(boolean forceSync) { @@ -233,9 +228,8 @@ ResourceAwareItemWriterItemStream, InitializingBean { } /** - * Flag to indicate that the target file should be deleted if no items have - * been written (other than header and footer) on close. Defaults to false. - * + * Flag to indicate that the target file should be deleted if no items have been + * written (other than header and footer) on close. Defaults to false. * @param shouldDeleteIfEmpty the flag value to set */ public void setShouldDeleteIfEmpty(boolean shouldDeleteIfEmpty) { @@ -244,7 +238,6 @@ ResourceAwareItemWriterItemStream, InitializingBean { /** * Get used encoding. - * * @return the encoding used */ public String getEncoding() { @@ -253,7 +246,6 @@ ResourceAwareItemWriterItemStream, InitializingBean { /** * Set encoding to be used for output file. - * * @param encoding the encoding to be used */ public void setEncoding(String encoding) { @@ -262,7 +254,6 @@ ResourceAwareItemWriterItemStream, InitializingBean { /** * Get XML version. - * * @return the XML version used */ public String getVersion() { @@ -271,7 +262,6 @@ ResourceAwareItemWriterItemStream, InitializingBean { /** * Set XML version to be used for output XML. - * * @param version the XML version to be used */ public void setVersion(String version) { @@ -280,7 +270,6 @@ ResourceAwareItemWriterItemStream, InitializingBean { /** * Get used standalone document declaration. - * * @return the standalone document declaration used * * @since 4.3 @@ -292,7 +281,6 @@ ResourceAwareItemWriterItemStream, InitializingBean { /** * Set standalone document declaration to be used for output XML. If not set, * standalone document declaration will be omitted. - * * @param standalone the XML standalone document declaration to be used * * @since 4.3 @@ -303,7 +291,6 @@ ResourceAwareItemWriterItemStream, InitializingBean { /** * Get the tag name of the root element. - * * @return the root element tag name */ public String getRootTagName() { @@ -311,19 +298,16 @@ ResourceAwareItemWriterItemStream, InitializingBean { } /** - * Set the tag name of the root element. If not set, default name is used - * ("root"). Namespace URI and prefix can also be set optionally using the - * notation: - * + * Set the tag name of the root element. If not set, default name is used ("root"). + * Namespace URI and prefix can also be set optionally using the notation: + * *
       	 * {uri}prefix:root
       	 * 
      - * - * The prefix is optional (defaults to empty), but if it is specified then - * the uri must be provided. In addition you might want to declare other - * namespaces using the {@link #setRootElementAttributes(Map) root - * attributes}. - * + * + * The prefix is optional (defaults to empty), but if it is specified then the uri + * must be provided. In addition you might want to declare other namespaces using the + * {@link #setRootElementAttributes(Map) root attributes}. * @param rootTagName the tag name to be used for the root element */ public void setRootTagName(String rootTagName) { @@ -332,7 +316,6 @@ ResourceAwareItemWriterItemStream, InitializingBean { /** * Get the namespace prefix of the root element. Empty by default. - * * @return the rootTagNamespacePrefix */ public String getRootTagNamespacePrefix() { @@ -341,7 +324,6 @@ ResourceAwareItemWriterItemStream, InitializingBean { /** * Get the namespace of the root element. - * * @return the rootTagNamespace */ public String getRootTagNamespace() { @@ -350,7 +332,6 @@ ResourceAwareItemWriterItemStream, InitializingBean { /** * Get attributes of the root element. - * * @return attributes of the root element */ public Map getRootElementAttributes() { @@ -358,9 +339,8 @@ ResourceAwareItemWriterItemStream, InitializingBean { } /** - * Set the root element attributes to be written. If any of the key names - * begin with "xmlns:" then they are treated as namespace declarations. - * + * Set the root element attributes to be written. If any of the key names begin with + * "xmlns:" then they are treated as namespace declarations. * @param rootElementAttributes attributes of the root element */ public void setRootElementAttributes(Map rootElementAttributes) { @@ -368,11 +348,10 @@ ResourceAwareItemWriterItemStream, InitializingBean { } /** - * Set "overwrite" flag for the output file. Flag is ignored when output - * file processing is restarted. - * - * @param overwriteOutput If set to true, output file will be overwritten - * (this flag is ignored when processing is restart). + * Set "overwrite" flag for the output file. Flag is ignored when output file + * processing is restarted. + * @param overwriteOutput If set to true, output file will be overwritten (this flag + * is ignored when processing is restart). */ public void setOverwriteOutput(boolean overwriteOutput) { this.overwriteOutput = overwriteOutput; @@ -401,9 +380,8 @@ ResourceAwareItemWriterItemStream, InitializingBean { /** * Open the output source - * * @param executionContext the batch context. - * + * * @see org.springframework.batch.item.ItemStream#open(ExecutionContext) */ @SuppressWarnings("unchecked") @@ -414,7 +392,7 @@ ResourceAwareItemWriterItemStream, InitializingBean { Assert.notNull(resource, "The resource must be set"); long startAtPosition = 0; - + // if restart data is provided, restart from provided offset // otherwise start from beginning if (executionContext.containsKey(getExecutionContextKey(RESTART_DATA_NAME))) { @@ -424,16 +402,19 @@ ResourceAwareItemWriterItemStream, InitializingBean { unclosedHeaderCallbackElements = (List) executionContext .get(getExecutionContextKey(UNCLOSED_HEADER_CALLBACK_ELEMENTS_NAME)); } - + restarted = true; if (shouldDeleteIfEmpty && currentRecordCount == 0) { - // previous execution deleted the output file because no items were written + // previous execution deleted the output file because no items were + // written restarted = false; startAtPosition = 0; - } else { + } + else { restarted = true; } - } else { + } + else { currentRecordCount = 0; restarted = false; } @@ -443,7 +424,8 @@ ResourceAwareItemWriterItemStream, InitializingBean { if (startAtPosition == 0) { try { if (headerCallback != null) { - UnclosedElementCollectingEventWriter headerCallbackWriter = new UnclosedElementCollectingEventWriter(delegateEventWriter); + UnclosedElementCollectingEventWriter headerCallbackWriter = new UnclosedElementCollectingEventWriter( + delegateEventWriter); headerCallback.write(headerCallbackWriter); unclosedHeaderCallbackElements = headerCallbackWriter.getUnclosedElements(); } @@ -511,7 +493,7 @@ ResourceAwareItemWriterItemStream, InitializingBean { bufferedWriter = writer; } else { - bufferedWriter = new BufferedWriter(new OutputStreamWriter(os, encoding)); + bufferedWriter = new BufferedWriter(new OutputStreamWriter(os, encoding)); } delegateEventWriter = createXmlEventWriter(outputFactory, bufferedWriter); eventWriter = new NoStartEndDocumentStreamWriter(delegateEventWriter); @@ -527,9 +509,9 @@ ResourceAwareItemWriterItemStream, InitializingBean { throw new DataAccessResourceFailureException("Unable to write to file resource: [" + resource + "]", xse); } catch (UnsupportedEncodingException e) { - throw new DataAccessResourceFailureException("Unable to write to file resource: [" + resource - + "] with encoding=[" + encoding + "]", e); - } + throw new DataAccessResourceFailureException( + "Unable to write to file resource: [" + resource + "] with encoding=[" + encoding + "]", e); + } catch (IOException e) { throw new DataAccessResourceFailureException("Unable to write to file resource: [" + resource + "]", e); } @@ -537,12 +519,10 @@ ResourceAwareItemWriterItemStream, InitializingBean { /** * Subclasses can override to customize the writer. - * * @param outputFactory the factory to be used to create an {@link XMLEventWriter}. * @param writer the {@link Writer} to be used by the {@link XMLEventWriter} for * writing to character streams. * @return an xml writer - * * @throws XMLStreamException thrown if error occured creating {@link XMLEventWriter}. */ protected XMLEventWriter createXmlEventWriter(XMLOutputFactory outputFactory, Writer writer) @@ -552,10 +532,9 @@ ResourceAwareItemWriterItemStream, InitializingBean { /** * Subclasses can override to customize the factory. - * * @return a factory for the xml output - * - * @throws FactoryConfigurationError throw if an instance of this factory cannot be loaded. + * @throws FactoryConfigurationError throw if an instance of this factory cannot be + * loaded. */ protected XMLOutputFactory createXmlOutputFactory() throws FactoryConfigurationError { return XMLOutputFactory.newInstance(); @@ -563,10 +542,9 @@ ResourceAwareItemWriterItemStream, InitializingBean { /** * Subclasses can override to customize the event factory. - * * @return a factory for the xml events - * - * @throws FactoryConfigurationError thrown if an instance of this factory cannot be loaded. + * @throws FactoryConfigurationError thrown if an instance of this factory cannot be + * loaded. */ protected XMLEventFactory createXmlEventFactory() throws FactoryConfigurationError { XMLEventFactory factory = XMLEventFactory.newInstance(); @@ -575,7 +553,6 @@ ResourceAwareItemWriterItemStream, InitializingBean { /** * Subclasses can override to customize the STAX result. - * * @return a result for writing to */ protected Result createStaxResult() { @@ -586,19 +563,19 @@ ResourceAwareItemWriterItemStream, InitializingBean { * Inits the namespace context of the XMLEventWriter: *
        *
      • rootTagNamespacePrefix for rootTagName
      • - *
      • any other xmlns namespace prefix declarations in the root element attributes
      • + *
      • any other xmlns namespace prefix declarations in the root element + * attributes
      • *
      - * * @param writer XML event writer - * - * @throws XMLStreamException thrown if error occurs while setting the - * prefix or default name space. + * @throws XMLStreamException thrown if error occurs while setting the prefix or + * default name space. */ protected void initNamespaceContext(XMLEventWriter writer) throws XMLStreamException { if (StringUtils.hasText(getRootTagNamespace())) { - if(StringUtils.hasText(getRootTagNamespacePrefix())) { + if (StringUtils.hasText(getRootTagNamespacePrefix())) { writer.setPrefix(getRootTagNamespacePrefix(), getRootTagNamespace()); - } else { + } + else { writer.setDefaultNamespace(getRootTagNamespace()); } } @@ -611,7 +588,7 @@ ResourceAwareItemWriterItemStream, InitializingBean { prefix = key.substring(key.indexOf(":") + 1); } if (log.isDebugEnabled()) { - log.debug("registering prefix: " +prefix + "=" + entry.getValue()); + log.debug("registering prefix: " + prefix + "=" + entry.getValue()); } writer.setPrefix(prefix, entry.getValue()); } @@ -625,11 +602,9 @@ ResourceAwareItemWriterItemStream, InitializingBean { *
    • xml declaration - defines encoding and XML version
    • *
    • opening tag of the root element and its attributes
    • * - * If this is not sufficient for you, simply override this method. Encoding, - * version and root tag name can be retrieved with corresponding getters. - * + * If this is not sufficient for you, simply override this method. Encoding, version + * and root tag name can be retrieved with corresponding getters. * @param writer XML event writer - * * @throws XMLStreamException thrown if error occurs. */ protected void startDocument(XMLEventWriter writer) throws XMLStreamException { @@ -675,8 +650,8 @@ ResourceAwareItemWriterItemStream, InitializingBean { } /* - * This forces the flush to write the end of the root element and avoids - * an off-by-one error on restart. + * This forces the flush to write the end of the root element and avoids an + * off-by-one error on restart. */ writer.add(factory.createIgnorableSpace("")); writer.flush(); @@ -685,9 +660,7 @@ ResourceAwareItemWriterItemStream, InitializingBean { /** * Writes the EndDocument tag manually. - * * @param writer XML event writer - * * @throws XMLStreamException thrown if error occurs. */ protected void endDocument(XMLEventWriter writer) throws XMLStreamException { @@ -706,7 +679,7 @@ ResourceAwareItemWriterItemStream, InitializingBean { /** * Flush and close the output source. - * + * * @see org.springframework.batch.item.ItemStream#close() */ @Override @@ -725,9 +698,9 @@ ResourceAwareItemWriterItemStream, InitializingBean { if (footerCallback != null) { XMLEventWriter footerCallbackWriter = delegateEventWriter; if (restarted && !unclosedHeaderCallbackElements.isEmpty()) { - footerCallbackWriter = new UnopenedElementClosingEventWriter( - delegateEventWriter, bufferedWriter, unclosedHeaderCallbackElements); - } + footerCallbackWriter = new UnopenedElementClosingEventWriter(delegateEventWriter, bufferedWriter, + unclosedHeaderCallbackElements); + } footerCallback.write(footerCallbackWriter); } delegateEventWriter.flush(); @@ -784,16 +757,14 @@ ResourceAwareItemWriterItemStream, InitializingBean { /** * Write the value objects and flush them to the file. - * * @param items the value object - * * @throws IOException thrown if general error occurs. * @throws XmlMappingException thrown if error occurs during XML Mapping. */ @Override public void write(List items) throws XmlMappingException, IOException { - if(!this.initialized) { + if (!this.initialized) { throw new WriterNotOpenException("Writer must be open before it can be written to"); } @@ -809,18 +780,17 @@ ResourceAwareItemWriterItemStream, InitializingBean { eventWriter.flush(); if (forceSync) { channel.force(false); - } + } } catch (XMLStreamException | IOException e) { throw new WriteFailedException("Failed to flush the events", e); - } + } } /** * Get the restart data. - * * @param executionContext the batch context. - * + * * @see org.springframework.batch.item.ItemStream#update(ExecutionContext) */ @Override @@ -833,14 +803,14 @@ ResourceAwareItemWriterItemStream, InitializingBean { if (!unclosedHeaderCallbackElements.isEmpty()) { executionContext.put(getExecutionContextKey(UNCLOSED_HEADER_CALLBACK_ELEMENTS_NAME), unclosedHeaderCallbackElements); - } + } } } /* - * Get the actual position in file channel. This method flushes any buffered - * data before position is read. - * + * Get the actual position in file channel. This method flushes any buffered data + * before position is read. + * * @return byte offset in file channel */ private long getPosition() { @@ -863,7 +833,6 @@ ResourceAwareItemWriterItemStream, InitializingBean { /** * Set the file channel position. - * * @param newPosition new file channel position */ private void setPosition(long newPosition) { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/StaxWriterCallback.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/StaxWriterCallback.java index 57915f875..9200584ee 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/StaxWriterCallback.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/StaxWriterCallback.java @@ -21,20 +21,19 @@ import java.io.IOException; import javax.xml.stream.XMLEventWriter; /** - * Callback interface for writing to an XML file - useful e.g. for handling headers - * and footers. - * + * Callback interface for writing to an XML file - useful e.g. for handling headers and + * footers. + * * @author Robert Kasanicky */ public interface StaxWriterCallback { /** - * Write contents using the supplied {@link XMLEventWriter}. It is not - * required to flush the writer inside this method. - * + * Write contents using the supplied {@link XMLEventWriter}. It is not required to + * flush the writer inside this method. * @param writer the {@link XMLEventWriter} to be used to write the contents. - * * @throws IOException thrown if an error occurs during writing. */ void write(XMLEventWriter writer) throws IOException; + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/builder/StaxEventItemReaderBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/builder/StaxEventItemReaderBuilder.java index 5f9c7bb36..ea508a3ec 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/builder/StaxEventItemReaderBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/builder/StaxEventItemReaderBuilder.java @@ -65,10 +65,9 @@ public class StaxEventItemReaderBuilder { private String encoding = StaxEventItemReader.DEFAULT_ENCODING; /** - * Configure if the state of the {@link org.springframework.batch.item.ItemStreamSupport} - * should be persisted within the {@link org.springframework.batch.item.ExecutionContext} - * for restart purposes. - * + * Configure if the state of the + * {@link org.springframework.batch.item.ItemStreamSupport} should be persisted within + * the {@link org.springframework.batch.item.ExecutionContext} for restart purposes. * @param saveState defaults to true * @return The current instance of the builder. */ @@ -82,7 +81,6 @@ public class StaxEventItemReaderBuilder { * The name used to calculate the key within the * {@link org.springframework.batch.item.ExecutionContext}. Required if * {@link #saveState(boolean)} is set to true. - * * @param name name of the reader instance * @return The current instance of the builder. * @see org.springframework.batch.item.ItemStreamSupport#setName(String) @@ -95,7 +93,6 @@ public class StaxEventItemReaderBuilder { /** * Configure the max number of items to be read. - * * @param maxItemCount the max items to be read * @return The current instance of the builder. * @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setMaxItemCount(int) @@ -108,7 +105,6 @@ public class StaxEventItemReaderBuilder { /** * Index for the current item. Used on restarts to indicate where to start from. - * * @param currentItemCount current index * @return this instance for method chaining * @see org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader#setCurrentItemCount(int) @@ -121,7 +117,6 @@ public class StaxEventItemReaderBuilder { /** * The {@link Resource} to be used as input. - * * @param resource the input to the reader. * @return The current instance of the builder. * @see StaxEventItemReader#setResource(Resource) @@ -134,7 +129,6 @@ public class StaxEventItemReaderBuilder { /** * An implementation of the {@link Unmarshaller} from Spring's OXM module. - * * @param unmarshaller component responsible for unmarshalling XML chunks * @return The current instance of the builder. * @see StaxEventItemReader#setUnmarshaller @@ -148,7 +142,6 @@ public class StaxEventItemReaderBuilder { /** * Adds the list of fragments to be used as the root of each chunk to the * configuration. - * * @param fragmentRootElements the XML root elements to be used to identify XML * chunks. * @return The current instance of the builder. @@ -163,7 +156,6 @@ public class StaxEventItemReaderBuilder { /** * Adds the list of fragments to be used as the root of each chunk to the * configuration. - * * @param fragmentRootElements the XML root elements to be used to identify XML * chunks. * @return The current instance of the builder. @@ -178,7 +170,6 @@ public class StaxEventItemReaderBuilder { /** * Setting this value to true indicates that it is an error if the input does not * exist and an exception will be thrown. Defaults to true. - * * @param strict indicates the input file must exist * @return The current instance of the builder * @see StaxEventItemReader#setStrict(boolean) @@ -191,7 +182,6 @@ public class StaxEventItemReaderBuilder { /** * Set the {@link XMLInputFactory}. - * * @param xmlInputFactory to use * @return The current instance of the builder * @see StaxEventItemReader#setXmlInputFactory(XMLInputFactory) @@ -203,8 +193,8 @@ public class StaxEventItemReaderBuilder { } /** - * Encoding for the input file. Defaults to {@link StaxEventItemReader#DEFAULT_ENCODING}. - * + * Encoding for the input file. Defaults to + * {@link StaxEventItemReader#DEFAULT_ENCODING}. * @param encoding String encoding algorithm * @return the current instance of the builder * @see StaxEventItemReader#setEncoding(String) @@ -217,15 +207,14 @@ public class StaxEventItemReaderBuilder { /** * Validates the configuration and builds a new {@link StaxEventItemReader} - * * @return a new instance of the {@link StaxEventItemReader} */ public StaxEventItemReader build() { StaxEventItemReader reader = new StaxEventItemReader<>(); if (this.resource == null) { - logger.debug("The resource is null. This is only a valid scenario when " + - "injecting resource later as in when using the MultiResourceItemReader"); + logger.debug("The resource is null. This is only a valid scenario when " + + "injecting resource later as in when using the MultiResourceItemReader"); } if (this.saveState) { @@ -249,4 +238,5 @@ public class StaxEventItemReaderBuilder { return reader; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/builder/StaxEventItemWriterBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/builder/StaxEventItemWriterBuilder.java index 15dc154bc..95ecff3c0 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/builder/StaxEventItemWriterBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/builder/StaxEventItemWriterBuilder.java @@ -66,9 +66,8 @@ public class StaxEventItemWriterBuilder { /** * The name used to calculate the key within the - * {@link org.springframework.batch.item.ExecutionContext}. Required if + * {@link org.springframework.batch.item.ExecutionContext}. Required if * {@link StaxEventItemWriterBuilder#saveState(boolean)} is set to true. - * * @param name name of the reader instance * @return The current instance of the builder. * @see StaxEventItemWriter#setName(String) @@ -81,7 +80,6 @@ public class StaxEventItemWriterBuilder { /** * The {@link WritableResource} to be used as output. - * * @param resource the output from the writer * @return the current instance of the builder. * @see StaxEventItemWriter#setResource(WritableResource) @@ -94,8 +92,7 @@ public class StaxEventItemWriterBuilder { /** * The {@link Marshaller} implementation responsible for the serialization of the - * items to XML. This field is required. - * + * items to XML. This field is required. * @param marshaller the component used to generate XML * @return the current instance of the builder. * @see StaxEventItemWriter#setMarshaller(Marshaller) @@ -108,7 +105,6 @@ public class StaxEventItemWriterBuilder { /** * A {@link StaxWriterCallback} to provide any header elements - * * @param headerCallback a {@link StaxWriterCallback} * @return the current instance of the builder. * @see StaxEventItemWriter#setHeaderCallback(StaxWriterCallback) @@ -121,7 +117,6 @@ public class StaxEventItemWriterBuilder { /** * A {@link StaxWriterCallback} to provide any footer elements - * * @param footerCallback a {@link StaxWriterCallback} * @return the current instance of the builder. * @see StaxEventItemWriter#setFooterCallback(StaxWriterCallback) @@ -135,8 +130,7 @@ public class StaxEventItemWriterBuilder { /** * The resulting writer is participating in a transaction and writes should be delayed * as late as possible. - * - * @param transactional indicates that the writer is transactional. Defaults to false. + * @param transactional indicates that the writer is transactional. Defaults to false. * @return the current instance of the builder * @see StaxEventItemWriter#setTransactional(boolean) */ @@ -148,8 +142,7 @@ public class StaxEventItemWriterBuilder { /** * Flag to indicate that changes should be force-synced to disk on flush. - * - * @param forceSync indicates if force sync should occur. Defaults to false. + * @param forceSync indicates if force sync should occur. Defaults to false. * @return the current instance of the builder * @see StaxEventItemWriter#setForceSync(boolean) */ @@ -161,8 +154,7 @@ public class StaxEventItemWriterBuilder { /** * Flag to indicate that the output file should be deleted if no results were written - * to it. Defaults to false. - * + * to it. Defaults to false. * @param shouldDelete indicator * @return the current instance of the builder * @see StaxEventItemWriter#setShouldDeleteIfEmpty(boolean) @@ -174,8 +166,7 @@ public class StaxEventItemWriterBuilder { } /** - * Encoding for the file. Defaults to UTF-8. - * + * Encoding for the file. Defaults to UTF-8. * @param encoding String encoding algorithm * @return the current instance of the builder * @see StaxEventItemWriter#setEncoding(String) @@ -187,9 +178,8 @@ public class StaxEventItemWriterBuilder { } /** - * Version of XML to be generated. Must be supported by the {@link Marshaller} + * Version of XML to be generated. Must be supported by the {@link Marshaller} * provided. - * * @param version XML version * @return the current instance of the builder * @see StaxEventItemWriter#setVersion(String) @@ -202,7 +192,6 @@ public class StaxEventItemWriterBuilder { /** * Standalone document declaration for the output document. Defaults to {@code null}. - * * @param standalone Boolean standalone document declaration * @return the current instance of the builder * @see StaxEventItemWriter#setStandalone(Boolean) @@ -217,7 +206,6 @@ public class StaxEventItemWriterBuilder { /** * The name of the root tag for the output document. - * * @param rootTagName tag name * @return the current instance of the builder * @see StaxEventItemWriter#setRootTagName(String) @@ -230,7 +218,6 @@ public class StaxEventItemWriterBuilder { /** * A Map of attributes to be included in the document's root element. - * * @param rootElementAttributes map fo attributes * @return the current instance of the builder. * @see StaxEventItemWriter#setRootElementAttributes(Map) @@ -243,7 +230,6 @@ public class StaxEventItemWriterBuilder { /** * Indicates if an existing file should be overwritten if found. Defaults to true. - * * @param overwriteOutput indicator * @return the current instance of the builder. * @see StaxEventItemWriter#setOverwriteOutput(boolean) @@ -256,9 +242,8 @@ public class StaxEventItemWriterBuilder { /** * Indicates if the state of the writer should be saved in the - * {@link org.springframework.batch.item.ExecutionContext}. Setting this to false - * will impact restartability. Defaults to true. - * + * {@link org.springframework.batch.item.ExecutionContext}. Setting this to false will + * impact restartability. Defaults to true. * @param saveState indicator * @return the current instance of the builder * @see StaxEventItemWriter#setSaveState(boolean) @@ -271,13 +256,12 @@ public class StaxEventItemWriterBuilder { /** * Returns a configured {@link StaxEventItemWriter} - * * @return a StaxEventItemWriter */ public StaxEventItemWriter build() { Assert.notNull(this.marshaller, "A marshaller is required"); - if(this.saveState) { + if (this.saveState) { Assert.notNull(this.name, "A name is required"); } @@ -302,4 +286,4 @@ public class StaxEventItemWriterBuilder { return writer; } - } +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/stax/AbstractEventReaderWrapper.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/stax/AbstractEventReaderWrapper.java index b65231409..8f190a788 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/stax/AbstractEventReaderWrapper.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/stax/AbstractEventReaderWrapper.java @@ -21,61 +21,61 @@ import javax.xml.stream.XMLStreamException; import javax.xml.stream.events.XMLEvent; /** - * Delegates all functionality to the wrapped reader allowing - * subclasses to override only the methods they want to change. - * + * Delegates all functionality to the wrapped reader allowing subclasses to override only + * the methods they want to change. + * * @author Robert Kasanicky */ abstract class AbstractEventReaderWrapper implements XMLEventReader { protected XMLEventReader wrappedEventReader; - + public AbstractEventReaderWrapper(XMLEventReader wrappedEventReader) { this.wrappedEventReader = wrappedEventReader; } - - @Override + + @Override public void close() throws XMLStreamException { wrappedEventReader.close(); - + } - @Override + @Override public String getElementText() throws XMLStreamException { return wrappedEventReader.getElementText(); } - @Override + @Override public Object getProperty(String name) throws IllegalArgumentException { return wrappedEventReader.getProperty(name); } - @Override + @Override public boolean hasNext() { return wrappedEventReader.hasNext(); } - @Override + @Override public XMLEvent nextEvent() throws XMLStreamException { return wrappedEventReader.nextEvent(); } - @Override + @Override public XMLEvent nextTag() throws XMLStreamException { return wrappedEventReader.nextTag(); } - @Override + @Override public XMLEvent peek() throws XMLStreamException { return wrappedEventReader.peek(); } - @Override + @Override public Object next() { return wrappedEventReader.next(); } - @Override + @Override public void remove() { wrappedEventReader.remove(); } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/stax/AbstractEventWriterWrapper.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/stax/AbstractEventWriterWrapper.java index 6b945c8b1..254a0872d 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/stax/AbstractEventWriterWrapper.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/stax/AbstractEventWriterWrapper.java @@ -23,61 +23,62 @@ import javax.xml.stream.XMLStreamException; import javax.xml.stream.events.XMLEvent; /** - * Delegates all functionality to the wrapped writer allowing - * subclasses to override only the methods they want to change. - * + * Delegates all functionality to the wrapped writer allowing subclasses to override only + * the methods they want to change. + * * @author Robert Kasanicky */ abstract class AbstractEventWriterWrapper implements XMLEventWriter { - + protected XMLEventWriter wrappedEventWriter; public AbstractEventWriterWrapper(XMLEventWriter wrappedEventWriter) { this.wrappedEventWriter = wrappedEventWriter; } - @Override + @Override public void add(XMLEvent event) throws XMLStreamException { wrappedEventWriter.add(event); } - @Override + @Override public void add(XMLEventReader reader) throws XMLStreamException { wrappedEventWriter.add(reader); } - @Override + @Override public void close() throws XMLStreamException { wrappedEventWriter.close(); } - @Override + @Override public void flush() throws XMLStreamException { wrappedEventWriter.flush(); } - @Override + @Override public NamespaceContext getNamespaceContext() { return wrappedEventWriter.getNamespaceContext(); } - @Override + @Override public String getPrefix(String uri) throws XMLStreamException { return wrappedEventWriter.getPrefix(uri); } - @Override + @Override public void setDefaultNamespace(String uri) throws XMLStreamException { wrappedEventWriter.setDefaultNamespace(uri); } - @Override + @Override public void setNamespaceContext(NamespaceContext context) throws XMLStreamException { wrappedEventWriter.setNamespaceContext(context); } - @Override + @Override public void setPrefix(String prefix, String uri) throws XMLStreamException { wrappedEventWriter.setPrefix(prefix, uri); } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/stax/DefaultFragmentEventReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/stax/DefaultFragmentEventReader.java index 97e7be168..bf35e85d1 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/stax/DefaultFragmentEventReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/stax/DefaultFragmentEventReader.java @@ -32,7 +32,7 @@ import org.springframework.dao.DataAccessResourceFailureException; /** * Default implementation of {@link FragmentEventReader} - * + * * @author Robert Kasanicky */ public class DefaultFragmentEventReader extends AbstractEventReaderWrapper implements FragmentEventReader { @@ -77,13 +77,13 @@ public class DefaultFragmentEventReader extends AbstractEventReaderWrapper imple endDocumentEvent = XMLEventFactory.newInstance().createEndDocument(); } - @Override + @Override public void markStartFragment() { startFragmentFollows = true; fragmentRootName = null; } - @Override + @Override public boolean hasNext() { try { if (peek() != null) { @@ -96,7 +96,7 @@ public class DefaultFragmentEventReader extends AbstractEventReaderWrapper imple return false; } - @Override + @Override public Object next() { try { return nextEvent(); @@ -106,7 +106,7 @@ public class DefaultFragmentEventReader extends AbstractEventReaderWrapper imple } } - @Override + @Override public XMLEvent nextEvent() throws XMLStreamException { if (fakeDocumentEnd) { throw new NoSuchElementException(); @@ -122,8 +122,8 @@ public class DefaultFragmentEventReader extends AbstractEventReaderWrapper imple } /** - * Sets the endFragmentFollows flag to true if next event is the last event - * of the fragment. + * Sets the endFragmentFollows flag to true if next event is the last event of the + * fragment. * @param event peek() from wrapped event reader */ private void checkFragmentEnd(XMLEvent event) { @@ -141,9 +141,8 @@ public class DefaultFragmentEventReader extends AbstractEventReaderWrapper imple /** * @param event peek() from wrapped event reader * @param peek if true do not change the internal state - * @return StartDocument event if peek() points to beginning of fragment - * EndDocument event if cursor is right behind the end of fragment original - * event otherwise + * @return StartDocument event if peek() points to beginning of fragment EndDocument + * event if cursor is right behind the end of fragment original event otherwise */ private XMLEvent alterEvent(XMLEvent event, boolean peek) { if (startFragmentFollows) { @@ -165,7 +164,7 @@ public class DefaultFragmentEventReader extends AbstractEventReaderWrapper imple return event; } - @Override + @Override public XMLEvent peek() throws XMLStreamException { if (fakeDocumentEnd) { return null; @@ -174,12 +173,12 @@ public class DefaultFragmentEventReader extends AbstractEventReaderWrapper imple } /** - * Finishes reading the fragment in case the fragment was processed without - * being read until the end. + * Finishes reading the fragment in case the fragment was processed without being read + * until the end. */ - @Override + @Override public void markFragmentProcessed() { - if (insideFragment|| startFragmentFollows) { + if (insideFragment || startFragmentFollows) { try { while (!(nextEvent() instanceof EndDocument)) { // just read all events until EndDocument @@ -192,7 +191,7 @@ public class DefaultFragmentEventReader extends AbstractEventReaderWrapper imple fakeDocumentEnd = false; } - @Override + @Override public void reset() { insideFragment = false; startFragmentFollows = false; diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/stax/FragmentEventReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/stax/FragmentEventReader.java index 104768322..d4a9f626d 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/stax/FragmentEventReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/stax/FragmentEventReader.java @@ -18,11 +18,10 @@ package org.springframework.batch.item.xml.stax; import javax.xml.stream.XMLEventReader; - /** - * Interface for event readers which support treating XML fragments as standalone XML documents - * by wrapping the fragments with StartDocument and EndDocument events. - * + * Interface for event readers which support treating XML fragments as standalone XML + * documents by wrapping the fragments with StartDocument and EndDocument events. + * * @author Robert Kasanicky */ public interface FragmentEventReader extends XMLEventReader { @@ -31,18 +30,16 @@ public interface FragmentEventReader extends XMLEventReader { * Tells the event reader its cursor position is exactly before the fragment. */ void markStartFragment(); - + /** - * Tells the event reader the current fragment has been processed. - * If the cursor is still inside the fragment it should be moved - * after the end of the fragment. + * Tells the event reader the current fragment has been processed. If the cursor is + * still inside the fragment it should be moved after the end of the fragment. */ void markFragmentProcessed(); - + /** - * Reset the state of the fragment reader - make it forget - * it assumptions about current position of cursor - * (e.g. in case of rollback of the wrapped reader). + * Reset the state of the fragment reader - make it forget it assumptions about + * current position of cursor (e.g. in case of rollback of the wrapped reader). */ void reset(); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/stax/NoStartEndDocumentStreamWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/stax/NoStartEndDocumentStreamWriter.java index 929bcc298..cd44345f0 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/stax/NoStartEndDocumentStreamWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/stax/NoStartEndDocumentStreamWriter.java @@ -21,8 +21,8 @@ import javax.xml.stream.XMLStreamException; import javax.xml.stream.events.XMLEvent; /** - * Delegating XMLEventWriter, which ignores start and end document events, - * but passes through everything else. + * Delegating XMLEventWriter, which ignores start and end document events, but passes + * through everything else. * * @author peter.zozom * @author Robert Kasanicky @@ -33,16 +33,17 @@ public class NoStartEndDocumentStreamWriter extends AbstractEventWriterWrapper { super(wrappedEventWriter); } - @Override + @Override public void add(XMLEvent event) throws XMLStreamException { if ((!event.isStartDocument()) && (!event.isEndDocument())) { wrappedEventWriter.add(event); } } - - // prevents OXM Marshallers from closing the XMLEventWriter - @Override - public void close() throws XMLStreamException { - flush(); - } + + // prevents OXM Marshallers from closing the XMLEventWriter + @Override + public void close() throws XMLStreamException { + flush(); + } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/stax/UnclosedElementCollectingEventWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/stax/UnclosedElementCollectingEventWriter.java index 50deb8200..4adc4c9fe 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/stax/UnclosedElementCollectingEventWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/stax/UnclosedElementCollectingEventWriter.java @@ -1,57 +1,64 @@ -/* - * Copyright 2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.item.xml.stax; - -import java.util.LinkedList; -import java.util.List; - -import javax.xml.namespace.QName; -import javax.xml.stream.XMLEventWriter; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.events.XMLEvent; - -/** - * Delegating XMLEventWriter, which collects the QNames of elements that were opened but not closed. - * - * @author Jimmy Praet - * @since 3.0 - */ -public class UnclosedElementCollectingEventWriter extends AbstractEventWriterWrapper { - - private LinkedList unclosedElements = new LinkedList<>(); - - public UnclosedElementCollectingEventWriter(XMLEventWriter wrappedEventWriter) { - super(wrappedEventWriter); - } - - /* (non-Javadoc) - * @see org.springframework.batch.item.xml.stax.AbstractEventWriterWrapper#add(javax.xml.stream.events.XMLEvent) - */ - @Override - public void add(XMLEvent event) throws XMLStreamException { - if (event.isStartElement()) { - unclosedElements.addLast(event.asStartElement().getName()); - } else if (event.isEndElement()) { - unclosedElements.removeLast(); - } - super.add(event); - } - - public List getUnclosedElements() { - return unclosedElements; - } -} +/* + * Copyright 2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.item.xml.stax; + +import java.util.LinkedList; +import java.util.List; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLEventWriter; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.XMLEvent; + +/** + * Delegating XMLEventWriter, which collects the QNames of elements that were opened but + * not closed. + * + * @author Jimmy Praet + * @since 3.0 + */ +public class UnclosedElementCollectingEventWriter extends AbstractEventWriterWrapper { + + private LinkedList unclosedElements = new LinkedList<>(); + + public UnclosedElementCollectingEventWriter(XMLEventWriter wrappedEventWriter) { + super(wrappedEventWriter); + } + + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.item.xml.stax.AbstractEventWriterWrapper#add(javax.xml. + * stream.events.XMLEvent) + */ + @Override + public void add(XMLEvent event) throws XMLStreamException { + if (event.isStartElement()) { + unclosedElements.addLast(event.asStartElement().getName()); + } + else if (event.isEndElement()) { + unclosedElements.removeLast(); + } + super.add(event); + } + + public List getUnclosedElements() { + return unclosedElements; + } + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/stax/UnopenedElementClosingEventWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/stax/UnopenedElementClosingEventWriter.java index 768c9f20d..96086abdb 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/stax/UnopenedElementClosingEventWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/xml/stax/UnopenedElementClosingEventWriter.java @@ -1,82 +1,91 @@ -/* - * Copyright 2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.item.xml.stax; - -import java.io.IOException; -import java.io.Writer; -import java.util.LinkedList; -import java.util.List; - -import javax.xml.namespace.QName; -import javax.xml.stream.XMLEventWriter; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.events.XMLEvent; - -import org.springframework.dao.DataAccessResourceFailureException; -import org.springframework.util.StringUtils; - -/** - * Delegating XMLEventWriter, which writes EndElement events that match a given collection of QNames directly - * to the underlying java.io.Writer instead of to the delegate XMLEventWriter. - * - * @author Jimmy Praet - * @since 3.0 - */ -public class UnopenedElementClosingEventWriter extends AbstractEventWriterWrapper { - - private LinkedList unopenedElements; - - private Writer ioWriter; - - public UnopenedElementClosingEventWriter(XMLEventWriter wrappedEventWriter, Writer ioWriter, List unopenedElements) { - super(wrappedEventWriter); - this.unopenedElements = new LinkedList<>(unopenedElements); - this.ioWriter = ioWriter; - } - - /* (non-Javadoc) - * @see org.springframework.batch.item.xml.stax.AbstractEventWriterWrapper#add(javax.xml.stream.events.XMLEvent) - */ - @Override - public void add(XMLEvent event) throws XMLStreamException { - if (isUnopenedElementCloseEvent(event)) { - QName element = unopenedElements.removeLast(); - String nsPrefix = !StringUtils.hasText(element.getPrefix()) ? "" : element.getPrefix() + ":"; - try { - super.flush(); - ioWriter.write(""); - ioWriter.flush(); - } - catch (IOException ioe) { - throw new DataAccessResourceFailureException("Unable to close tag: " + element, ioe); - } - } else { - super.add(event); - } - } - - private boolean isUnopenedElementCloseEvent(XMLEvent event) { - if (unopenedElements.isEmpty()) { - return false; - } else if (!event.isEndElement()) { - return false; - } else { - return unopenedElements.getLast().equals(event.asEndElement().getName()); - } - } - -} +/* + * Copyright 2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.item.xml.stax; + +import java.io.IOException; +import java.io.Writer; +import java.util.LinkedList; +import java.util.List; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLEventWriter; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.XMLEvent; + +import org.springframework.dao.DataAccessResourceFailureException; +import org.springframework.util.StringUtils; + +/** + * Delegating XMLEventWriter, which writes EndElement events that match a given collection + * of QNames directly to the underlying java.io.Writer instead of to the delegate + * XMLEventWriter. + * + * @author Jimmy Praet + * @since 3.0 + */ +public class UnopenedElementClosingEventWriter extends AbstractEventWriterWrapper { + + private LinkedList unopenedElements; + + private Writer ioWriter; + + public UnopenedElementClosingEventWriter(XMLEventWriter wrappedEventWriter, Writer ioWriter, + List unopenedElements) { + super(wrappedEventWriter); + this.unopenedElements = new LinkedList<>(unopenedElements); + this.ioWriter = ioWriter; + } + + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.item.xml.stax.AbstractEventWriterWrapper#add(javax.xml. + * stream.events.XMLEvent) + */ + @Override + public void add(XMLEvent event) throws XMLStreamException { + if (isUnopenedElementCloseEvent(event)) { + QName element = unopenedElements.removeLast(); + String nsPrefix = !StringUtils.hasText(element.getPrefix()) ? "" : element.getPrefix() + ":"; + try { + super.flush(); + ioWriter.write(""); + ioWriter.flush(); + } + catch (IOException ioe) { + throw new DataAccessResourceFailureException("Unable to close tag: " + element, ioe); + } + } + else { + super.add(event); + } + } + + private boolean isUnopenedElementCloseEvent(XMLEvent event) { + if (unopenedElements.isEmpty()) { + return false; + } + else if (!event.isEndElement()) { + return false; + } + else { + return unopenedElements.getLast().equals(event.asEndElement().getName()); + } + } + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/poller/DirectPoller.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/poller/DirectPoller.java index 3e93b015c..bd214a22b 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/poller/DirectPoller.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/poller/DirectPoller.java @@ -22,13 +22,12 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; /** - * A {@link Poller} that uses the callers thread to poll for a result as soon as - * it is asked for. This is often appropriate if you expect a result relatively - * quickly, or if there is only one such result expected (otherwise it is more - * efficient to use a background thread to do the polling). - * + * A {@link Poller} that uses the callers thread to poll for a result as soon as it is + * asked for. This is often appropriate if you expect a result relatively quickly, or if + * there is only one such result expected (otherwise it is more efficient to use a + * background thread to do the polling). + * * @author Dave Syer - * * @param the type of the result */ public class DirectPoller implements Poller { @@ -40,13 +39,13 @@ public class DirectPoller implements Poller { } /** - * Get a future for a non-null result from the callback. Only when the - * result is asked for (using {@link Future#get()} or - * {@link Future#get(long, TimeUnit)} will the polling actually start. - * + * Get a future for a non-null result from the callback. Only when the result is asked + * for (using {@link Future#get()} or {@link Future#get(long, TimeUnit)} will the + * polling actually start. + * * @see Poller#poll(Callable) */ - @Override + @Override public Future poll(Callable callable) throws Exception { return new DirectPollingFuture<>(interval, callable); } @@ -68,13 +67,13 @@ public class DirectPoller implements Poller { this.callable = callable; } - @Override + @Override public boolean cancel(boolean mayInterruptIfRunning) { cancelled = true; return true; } - @Override + @Override public S get() throws InterruptedException, ExecutionException { try { return get(-1, TimeUnit.MILLISECONDS); @@ -84,7 +83,7 @@ public class DirectPoller implements Poller { } } - @Override + @Override public S get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { try { @@ -125,12 +124,12 @@ public class DirectPoller implements Poller { } - @Override + @Override public boolean isCancelled() { return cancelled; } - @Override + @Override public boolean isDone() { return cancelled || result != null; } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/poller/Poller.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/poller/Poller.java index 55e9df8b0..870b6ad63 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/poller/Poller.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/poller/Poller.java @@ -19,36 +19,35 @@ import java.util.concurrent.Callable; import java.util.concurrent.Future; /** - * Interface for polling a {@link Callable} instance provided by the user. Use - * when you need to put something in the background (e.g. a remote invocation) - * and wait for the result, e.g. - * + * Interface for polling a {@link Callable} instance provided by the user. Use when you + * need to put something in the background (e.g. a remote invocation) and wait for the + * result, e.g. + * *
        * Poller<Result> poller = ...
      - * 
      + *
        * final long id = remoteService.execute(); // do something remotely
      - * 
      + *
        * Future<Result> future = poller.poll(new Callable<Result> {
        *     public Object call() {
        *     	   // Look for the result (null if not ready)
        *     	   return remoteService.get(id);
        *     }
        * });
      - * 
      + *
        * Result result = future.get(1000L, TimeUnit.MILLISECONDS);
        * 
      - * + * * @author Dave Syer * @author Mahmoud Ben Hassine - * + * */ public interface Poller { /** - * Use the callable provided to poll for a non-null result. The callable - * might be executed multiple times searching for a result, but once either - * a result or an exception has been observed the polling stops. - * + * Use the callable provided to poll for a non-null result. The callable might be + * executed multiple times searching for a result, but once either a result or an + * exception has been observed the polling stops. * @param callable a {@link Callable} to use to retrieve a result * @return a future which itself can be used to get the result * @throws java.lang.Exception allows for checked exceptions diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/CompletionPolicy.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/CompletionPolicy.java index 2095c59d6..da0167cf6 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/CompletionPolicy.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/CompletionPolicy.java @@ -16,63 +16,53 @@ package org.springframework.batch.repeat; - /** - * Interface for batch completion policies, to enable batch operations to - * strategise normal completion conditions. Stateful implementations of batch - * iterators should only update state using the update method. If you - * need custom behaviour consider extending an existing implementation or using - * the composite provided. - * + * Interface for batch completion policies, to enable batch operations to strategise + * normal completion conditions. Stateful implementations of batch iterators should + * only update state using the update method. If you need custom behaviour + * consider extending an existing implementation or using the composite provided. + * * @author Dave Syer - * + * */ public interface CompletionPolicy { /** - * Determine whether a batch is complete given the latest result from the - * callback. If this method returns true then - * {@link #isComplete(RepeatContext)} should also (but not necessarily vice - * versa, since the answer here depends on the result). - * + * Determine whether a batch is complete given the latest result from the callback. If + * this method returns true then {@link #isComplete(RepeatContext)} should also (but + * not necessarily vice versa, since the answer here depends on the result). * @param context the current batch context. * @param result the result of the latest batch item processing. - * * @return true if the batch should terminate. - * + * * @see #isComplete(RepeatContext) */ boolean isComplete(RepeatContext context, RepeatStatus result); /** - * Allow policy to signal completion according to internal state, without - * having to wait for the callback to complete. - * + * Allow policy to signal completion according to internal state, without having to + * wait for the callback to complete. * @param context the current batch context. - * * @return true if the batch should terminate. */ boolean isComplete(RepeatContext context); /** - * Create a new context for the execution of a batch. N.B. implementations - * should not return the parent from this method - they must - * create a new context to meet the specific needs of the policy. The best - * way to do this might be to override an existing implementation and use - * the {@link RepeatContext} to store state in its attributes. - * + * Create a new context for the execution of a batch. N.B. implementations should + * not return the parent from this method - they must create a new context to + * meet the specific needs of the policy. The best way to do this might be to override + * an existing implementation and use the {@link RepeatContext} to store state in its + * attributes. * @param parent the current context if one is already in progress. - * @return a context object that can be used by the implementation to store - * internal state for a batch. + * @return a context object that can be used by the implementation to store internal + * state for a batch. */ RepeatContext start(RepeatContext parent); /** - * Give implementations the opportunity to update the state of the current - * batch. Will be called once per callback, after it has been - * launched, but not necessarily after it completes (if the batch is - * asynchronous). - * + * Give implementations the opportunity to update the state of the current batch. Will + * be called once per callback, after it has been launched, but not + * necessarily after it completes (if the batch is asynchronous). * @param context the value returned by start. */ void update(RepeatContext context); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/RepeatCallback.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/RepeatCallback.java index 085a83fa3..f6c70337b 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/RepeatCallback.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/RepeatCallback.java @@ -16,29 +16,27 @@ package org.springframework.batch.repeat; - /** - * Callback interface for batch operations. Many simple processes will be able - * to use off-the-shelf implementations of this interface, enabling the - * application developer to concentrate on business logic. - * + * Callback interface for batch operations. Many simple processes will be able to use + * off-the-shelf implementations of this interface, enabling the application developer to + * concentrate on business logic. + * * @see RepeatOperations - * * @author Dave Syer - * + * */ public interface RepeatCallback { /** - * Implementations return true if they can continue processing - e.g. there - * is a data source that is not yet exhausted. Exceptions are not necessarily - * fatal - processing might continue depending on the Exception type and the - * implementation of the caller. - * + * Implementations return true if they can continue processing - e.g. there is a data + * source that is not yet exhausted. Exceptions are not necessarily fatal - processing + * might continue depending on the Exception type and the implementation of the + * caller. * @param context the current context passed in by the caller. - * @return an {@link RepeatStatus} which is continuable if there is (or may - * be) more data to process. + * @return an {@link RepeatStatus} which is continuable if there is (or may be) more + * data to process. * @throws Exception if there is a problem with the processing. */ RepeatStatus doInIteration(RepeatContext context) throws Exception; + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/RepeatContext.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/RepeatContext.java index 93d7c9ac8..7ca05e82f 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/RepeatContext.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/RepeatContext.java @@ -19,29 +19,26 @@ package org.springframework.batch.repeat; import org.springframework.core.AttributeAccessor; /** - * Base interface for context which controls the state and completion / - * termination of a batch step. A new context is created for each call to the - * {@link RepeatOperations}. Within a batch callback code can communicate via - * the {@link AttributeAccessor} interface. - * + * Base interface for context which controls the state and completion / termination of a + * batch step. A new context is created for each call to the {@link RepeatOperations}. + * Within a batch callback code can communicate via the {@link AttributeAccessor} + * interface. + * * @author Dave Syer - * * @see RepeatOperations#iterate(RepeatCallback) - * + * */ public interface RepeatContext extends AttributeAccessor { /** - * If batches are nested, then the inner batch will be created with the - * outer one as a parent. This is an accessor for the parent if it exists. - * + * If batches are nested, then the inner batch will be created with the outer one as a + * parent. This is an accessor for the parent if it exists. * @return the parent context or null if there is none */ RepeatContext getParent(); /** * Public access to a counter for the number of operations attempted. - * * @return the number of batch operations started. */ int getStartedCount(); @@ -54,41 +51,36 @@ public interface RepeatContext extends AttributeAccessor { /** * Public accessor for the complete flag. - * * @return indicator if the repeat is complete */ boolean isCompleteOnly(); /** - * Signal to the framework that the current batch should complete - * abnormally, independent of the current {@link CompletionPolicy}. + * Signal to the framework that the current batch should complete abnormally, + * independent of the current {@link CompletionPolicy}. */ void setTerminateOnly(); /** - * Public accessor for the termination flag. If this flag is set then the - * complete flag will also be. - * + * Public accessor for the termination flag. If this flag is set then the complete + * flag will also be. * @return indicates if the repeat should terminate */ boolean isTerminateOnly(); /** - * Register a callback to be executed on close, associated with the - * attribute having the given name. The {@link Runnable} callback should not - * throw any exceptions. - * - * @param name the name of the attribute to associated this callback with. - * If this attribute is removed the callback should never be called. + * Register a callback to be executed on close, associated with the attribute having + * the given name. The {@link Runnable} callback should not throw any exceptions. + * @param name the name of the attribute to associated this callback with. If this + * attribute is removed the callback should never be called. * @param callback a {@link Runnable} to execute when the context is closed. */ void registerDestructionCallback(String name, Runnable callback); /** - * Allow resources to be cleared, especially in destruction callbacks. - * Implementations should ensure that any registered destruction callbacks - * are executed here, as long as the corresponding attribute is still - * available. + * Allow resources to be cleared, especially in destruction callbacks. Implementations + * should ensure that any registered destruction callbacks are executed here, as long + * as the corresponding attribute is still available. */ void close(); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/RepeatListener.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/RepeatListener.java index a5555f148..51afffa06 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/RepeatListener.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/RepeatListener.java @@ -16,31 +16,29 @@ package org.springframework.batch.repeat; - /** - * Interface for listeners to the batch process. Implementers can provide - * enhance the behaviour of a batch in small cross-cutting modules. The - * framework provides callbacks at key points in the processing. - * + * Interface for listeners to the batch process. Implementers can provide enhance the + * behaviour of a batch in small cross-cutting modules. The framework provides callbacks + * at key points in the processing. + * * @author Dave Syer * @author Mahmoud Ben Hassine - * + * */ public interface RepeatListener { + /** - * Called by the framework before each batch item. Implementers can halt a - * batch by setting the complete flag on the context. - * + * Called by the framework before each batch item. Implementers can halt a batch by + * setting the complete flag on the context. * @param context the current batch context. */ default void before(RepeatContext context) { } /** - * Called by the framework after each item has been processed, unless the - * item processing results in an exception. This method is called as soon as - * the result is known. - * + * Called by the framework after each item has been processed, unless the item + * processing results in an exception. This method is called as soon as the result is + * known. * @param context the current batch context * @param result the result of the callback */ @@ -48,26 +46,23 @@ public interface RepeatListener { } /** - * Called once at the start of a complete batch, before any items are - * processed. Implementers can use this method to acquire any resources that - * might be needed during processing. Implementers can halt the current - * operation by setting the complete flag on the context. To halt all - * enclosing batches (the whole job), the would need to use the parent - * context (recursively). - * + * Called once at the start of a complete batch, before any items are processed. + * Implementers can use this method to acquire any resources that might be needed + * during processing. Implementers can halt the current operation by setting the + * complete flag on the context. To halt all enclosing batches (the whole job), the + * would need to use the parent context (recursively). * @param context the current batch context */ default void open(RepeatContext context) { } /** - * Called when a repeat callback fails by throwing an exception. There will - * be one call to this method for each exception thrown during a repeat - * operation (e.g. a chunk).
      - * - * There is no need to re-throw the exception here - that will be done by - * the enclosing framework. - * + * Called when a repeat callback fails by throwing an exception. There will be one + * call to this method for each exception thrown during a repeat operation (e.g. a + * chunk).
      + * + * There is no need to re-throw the exception here - that will be done by the + * enclosing framework. * @param context the current batch context * @param e the error that was encountered in an item callback. */ @@ -75,12 +70,12 @@ public interface RepeatListener { } /** - * Called once at the end of a complete batch, after normal or abnormal - * completion (i.e. even after an exception). Implementers can use this - * method to clean up any resources. - * + * Called once at the end of a complete batch, after normal or abnormal completion + * (i.e. even after an exception). Implementers can use this method to clean up any + * resources. * @param context the current batch context. */ default void close(RepeatContext context) { } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/RepeatOperations.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/RepeatOperations.java index 77ab5e403..b09646c71 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/RepeatOperations.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/RepeatOperations.java @@ -16,31 +16,27 @@ package org.springframework.batch.repeat; - /** - * The main interface providing access to batch operations. The batch client is - * the {@link RepeatCallback}, where a single item or record is processed. The - * batch behaviour, boundary conditions, transactions etc, are dealt with by the - * {@link RepeatOperations} in such as way that the client does not need to know - * about them. The client may have access to framework abstractions, like - * template data sources, but these should work the same whether they are in a - * batch or not. - * + * The main interface providing access to batch operations. The batch client is the + * {@link RepeatCallback}, where a single item or record is processed. The batch + * behaviour, boundary conditions, transactions etc, are dealt with by the + * {@link RepeatOperations} in such as way that the client does not need to know about + * them. The client may have access to framework abstractions, like template data sources, + * but these should work the same whether they are in a batch or not. + * * @author Dave Syer - * + * */ public interface RepeatOperations { /** - * Execute the callback repeatedly, until a decision can be made to - * complete. The decision about how many times to execute or when to - * complete, and what to do in the case of an error is delegated to a - * {@link CompletionPolicy}. - * + * Execute the callback repeatedly, until a decision can be made to complete. The + * decision about how many times to execute or when to complete, and what to do in the + * case of an error is delegated to a {@link CompletionPolicy}. * @param callback the batch callback. - * @return the aggregate of the result of all the callback operations. An - * indication of whether the {@link RepeatOperations} can continue - * processing if this method is called again. + * @return the aggregate of the result of all the callback operations. An indication + * of whether the {@link RepeatOperations} can continue processing if this method is + * called again. */ RepeatStatus iterate(RepeatCallback callback) throws RepeatException; diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/RepeatStatus.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/RepeatStatus.java index fe8ffd5bc..c94fa1d44 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/RepeatStatus.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/RepeatStatus.java @@ -21,7 +21,7 @@ public enum RepeatStatus { /** * Indicates that processing can continue. */ - CONTINUABLE(true), + CONTINUABLE(true), /** * Indicates that processing is finished (either successful or unsuccessful) */ diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/callback/NestedRepeatCallback.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/callback/NestedRepeatCallback.java index 773fb10a6..873a5acfe 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/callback/NestedRepeatCallback.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/callback/NestedRepeatCallback.java @@ -22,12 +22,12 @@ import org.springframework.batch.repeat.RepeatOperations; import org.springframework.batch.repeat.RepeatStatus; /** - * Callback that delegates to another callback, via a {@link RepeatOperations} - * instance. Useful when nesting or composing batches in one another, e.g. for - * breaking a batch down into chunks. - * + * Callback that delegates to another callback, via a {@link RepeatOperations} instance. + * Useful when nesting or composing batches in one another, e.g. for breaking a batch down + * into chunks. + * * @author Dave Syer - * + * */ public class NestedRepeatCallback implements RepeatCallback { @@ -37,9 +37,8 @@ public class NestedRepeatCallback implements RepeatCallback { /** * Constructor setting mandatory fields. - * - * @param template the {@link RepeatOperations} to use when calling the - * delegate callback + * @param template the {@link RepeatOperations} to use when calling the delegate + * callback * @param callback the {@link RepeatCallback} delegate */ public NestedRepeatCallback(RepeatOperations template, RepeatCallback callback) { @@ -49,14 +48,15 @@ public class NestedRepeatCallback implements RepeatCallback { } /** - * Simply calls template.execute(callback). Clients can use this to repeat a - * batch process, or to break a process up into smaller chunks (e.g. to - * change the transaction boundaries). - * + * Simply calls template.execute(callback). Clients can use this to repeat a batch + * process, or to break a process up into smaller chunks (e.g. to change the + * transaction boundaries). + * * @see org.springframework.batch.repeat.RepeatCallback#doInIteration(RepeatContext) */ - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { return template.iterate(callback); } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/context/RepeatContextCounter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/context/RepeatContextCounter.java index cc02a6453..f18c193e6 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/context/RepeatContextCounter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/context/RepeatContextCounter.java @@ -22,22 +22,21 @@ import org.springframework.batch.repeat.RepeatContext; import org.springframework.util.Assert; /** - * Helper class for policies that need to count the number of occurrences of - * some event (e.g. an exception type in the context) in the scope of a batch. - * The value of the counter can be stored between batches in a nested context, - * so that the termination decision is based on the aggregate of a number of - * sibling batches. - * + * Helper class for policies that need to count the number of occurrences of some event + * (e.g. an exception type in the context) in the scope of a batch. The value of the + * counter can be stored between batches in a nested context, so that the termination + * decision is based on the aggregate of a number of sibling batches. + * * @author Dave Syer - * + * */ public class RepeatContextCounter { final private String countKey; /** - * Flag to indicate whether the count is stored at the level of the parent - * context, or just local to the current context. Default value is false. + * Flag to indicate whether the count is stored at the level of the parent context, or + * just local to the current context. Default value is false. */ final private boolean useParent; @@ -45,14 +44,13 @@ public class RepeatContextCounter { /** * Increment the counter. - * * @param delta the amount by which to increment the counter. */ final public void increment(int delta) { AtomicInteger count = getCounter(); count.addAndGet(delta); } - + /** * Increment by 1. */ @@ -71,17 +69,16 @@ public class RepeatContextCounter { /** * Construct a new {@link RepeatContextCounter}. - * * @param context the current context. * @param countKey the key to use to store the counter in the context. - * @param useParent true if the counter is to be shared between siblings. - * The state will be stored in the parent of the context (if it exists) - * instead of the context itself. + * @param useParent true if the counter is to be shared between siblings. The state + * will be stored in the parent of the context (if it exists) instead of the context + * itself. */ public RepeatContextCounter(RepeatContext context, String countKey, boolean useParent) { super(); - + Assert.notNull(context, "The context must be provided to initialize a counter"); this.countKey = countKey; diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/context/RepeatContextSupport.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/context/RepeatContextSupport.java index 9f2fb5dcb..d8db03fbf 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/context/RepeatContextSupport.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/context/RepeatContextSupport.java @@ -38,9 +38,9 @@ public class RepeatContextSupport extends SynchronizedAttributeAccessor implemen private Map> callbacks = new HashMap<>(); /** - * Constructor for {@link RepeatContextSupport}. The parent can be null, but - * should be set to the enclosing repeat context if there is one, e.g. if - * this context is an inner loop. + * Constructor for {@link RepeatContextSupport}. The parent can be null, but should be + * set to the enclosing repeat context if there is one, e.g. if this context is an + * inner loop. * @param parent {@link RepeatContext} to be used as the parent context. */ public RepeatContextSupport(RepeatContext parent) { @@ -50,40 +50,40 @@ public class RepeatContextSupport extends SynchronizedAttributeAccessor implemen /* * (non-Javadoc) - * + * * @see org.springframework.batch.repeat.RepeatContext#isCompleteOnly() */ - @Override + @Override public boolean isCompleteOnly() { return completeOnly; } /* * (non-Javadoc) - * + * * @see org.springframework.batch.repeat.RepeatContext#setCompleteOnly() */ - @Override + @Override public void setCompleteOnly() { completeOnly = true; } /* * (non-Javadoc) - * + * * @see org.springframework.batch.repeat.RepeatContext#isTerminateOnly() */ - @Override + @Override public boolean isTerminateOnly() { return terminateOnly; } /* * (non-Javadoc) - * + * * @see org.springframework.batch.repeat.RepeatContext#setTerminateOnly() */ - @Override + @Override public void setTerminateOnly() { terminateOnly = true; setCompleteOnly(); @@ -91,10 +91,10 @@ public class RepeatContextSupport extends SynchronizedAttributeAccessor implemen /* * (non-Javadoc) - * + * * @see org.springframework.batch.repeat.RepeatContext#getParent() */ - @Override + @Override public RepeatContext getParent() { return parent; } @@ -108,22 +108,21 @@ public class RepeatContextSupport extends SynchronizedAttributeAccessor implemen /* * (non-Javadoc) - * + * * @see org.springframework.batch.repeat.RepeatContext#getStartedCount() */ - @Override + @Override public synchronized int getStartedCount() { return count; } /* * (non-Javadoc) - * - * @see - * org.springframework.batch.repeat.RepeatContext#registerDestructionCallback + * + * @see org.springframework.batch.repeat.RepeatContext#registerDestructionCallback * (java.lang.String, java.lang.Runnable) */ - @Override + @Override public void registerDestructionCallback(String name, Runnable callback) { synchronized (callbacks) { Set set = callbacks.get(name); @@ -137,10 +136,10 @@ public class RepeatContextSupport extends SynchronizedAttributeAccessor implemen /* * (non-Javadoc) - * + * * @see org.springframework.batch.repeat.RepeatContext#close() */ - @Override + @Override public void close() { List errors = new ArrayList<>(); @@ -155,16 +154,15 @@ public class RepeatContextSupport extends SynchronizedAttributeAccessor implemen for (Runnable callback : entry.getValue()) { /* - * Potentially we could check here if there is an attribute with - * the given name - if it has been removed, maybe the callback - * is invalid. On the other hand it is less surprising for the - * callback register if it is always executed. + * Potentially we could check here if there is an attribute with the given + * name - if it has been removed, maybe the callback is invalid. On the + * other hand it is less surprising for the callback register if it is + * always executed. */ if (callback != null) { /* - * The documentation of the interface says that these - * callbacks must not throw exceptions, but we don't trust - * them necessarily... + * The documentation of the interface says that these callbacks must + * not throw exceptions, but we don't trust them necessarily... */ try { callback.run(); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/context/SynchronizedAttributeAccessor.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/context/SynchronizedAttributeAccessor.java index a3444f8bd..bef84e66d 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/context/SynchronizedAttributeAccessor.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/context/SynchronizedAttributeAccessor.java @@ -20,11 +20,11 @@ import org.springframework.core.AttributeAccessor; import org.springframework.core.AttributeAccessorSupport; /** - * An {@link AttributeAccessor} that synchronizes on a mutex (not this) before - * modifying or accessing the underlying attributes. - * + * An {@link AttributeAccessor} that synchronizes on a mutex (not this) before modifying + * or accessing the underlying attributes. + * * @author Dave Syer - * + * */ public class SynchronizedAttributeAccessor implements AttributeAccessor { @@ -36,13 +36,15 @@ public class SynchronizedAttributeAccessor implements AttributeAccessor { * Generated serial UID. */ private static final long serialVersionUID = -7664290016506582290L; + }; /* * (non-Javadoc) + * * @see org.springframework.core.AttributeAccessor#attributeNames() */ - @Override + @Override public String[] attributeNames() { synchronized (support) { return support.attributeNames(); @@ -51,9 +53,10 @@ public class SynchronizedAttributeAccessor implements AttributeAccessor { /* * (non-Javadoc) + * * @see java.lang.Object#equals(java.lang.Object) */ - @Override + @Override public boolean equals(Object other) { if (this == other) { return true; @@ -75,9 +78,10 @@ public class SynchronizedAttributeAccessor implements AttributeAccessor { /* * (non-Javadoc) + * * @see org.springframework.core.AttributeAccessor#getAttribute(java.lang.String) */ - @Override + @Override public Object getAttribute(String name) { synchronized (support) { return support.getAttribute(name); @@ -86,9 +90,10 @@ public class SynchronizedAttributeAccessor implements AttributeAccessor { /* * (non-Javadoc) + * * @see org.springframework.core.AttributeAccessor#hasAttribute(java.lang.String) */ - @Override + @Override public boolean hasAttribute(String name) { synchronized (support) { return support.hasAttribute(name); @@ -97,18 +102,20 @@ public class SynchronizedAttributeAccessor implements AttributeAccessor { /* * (non-Javadoc) + * * @see java.lang.Object#hashCode() */ - @Override + @Override public int hashCode() { return support.hashCode(); } /* * (non-Javadoc) + * * @see org.springframework.core.AttributeAccessor#removeAttribute(java.lang.String) */ - @Override + @Override public Object removeAttribute(String name) { synchronized (support) { return support.removeAttribute(name); @@ -117,10 +124,11 @@ public class SynchronizedAttributeAccessor implements AttributeAccessor { /* * (non-Javadoc) + * * @see org.springframework.core.AttributeAccessor#setAttribute(java.lang.String, * java.lang.Object) */ - @Override + @Override public void setAttribute(String name, Object value) { synchronized (support) { support.setAttribute(name, value); @@ -131,8 +139,7 @@ public class SynchronizedAttributeAccessor implements AttributeAccessor { * Additional support for atomic put if absent. * @param name the key for the attribute name * @param value the value of the attribute - * @return null if the attribute was not already set, the existing value - * otherwise. + * @return null if the attribute was not already set, the existing value otherwise. */ public Object setAttributeIfAbsent(String name, Object value) { synchronized (support) { @@ -147,9 +154,10 @@ public class SynchronizedAttributeAccessor implements AttributeAccessor { /* * (non-Javadoc) + * * @see java.lang.Object#toString() */ - @Override + @Override public String toString() { StringBuilder buffer = new StringBuilder("SynchronizedAttributeAccessor: ["); synchronized (support) { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/exception/CompositeExceptionHandler.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/exception/CompositeExceptionHandler.java index 0b1e2b917..62185e713 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/exception/CompositeExceptionHandler.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/exception/CompositeExceptionHandler.java @@ -22,9 +22,9 @@ import org.springframework.batch.repeat.RepeatContext; /** * Composite {@link ExceptionHandler} that loops though a list of delegates. - * + * * @author Dave Syer - * + * */ public class CompositeExceptionHandler implements ExceptionHandler { @@ -35,16 +35,17 @@ public class CompositeExceptionHandler implements ExceptionHandler { } /** - * Iterate over the handlers delegating the call to each in turn. The chain - * ends if an exception is thrown. - * + * Iterate over the handlers delegating the call to each in turn. The chain ends if an + * exception is thrown. + * * @see ExceptionHandler#handleException(RepeatContext, Throwable) */ - @Override + @Override public void handleException(RepeatContext context, Throwable throwable) throws Throwable { for (int i = 0; i < handlers.length; i++) { ExceptionHandler handler = handlers[i]; handler.handleException(context, throwable); } } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/exception/DefaultExceptionHandler.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/exception/DefaultExceptionHandler.java index 57089aa39..8e3c10e5e 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/exception/DefaultExceptionHandler.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/exception/DefaultExceptionHandler.java @@ -19,20 +19,21 @@ package org.springframework.batch.repeat.exception; import org.springframework.batch.repeat.RepeatContext; /** - * Default implementation of {@link ExceptionHandler} - just re-throws the exception it encounters. - * + * Default implementation of {@link ExceptionHandler} - just re-throws the exception it + * encounters. + * * @author Dave Syer - * + * */ public class DefaultExceptionHandler implements ExceptionHandler { /** * Re-throw the throwable. - * + * * @see org.springframework.batch.repeat.exception.ExceptionHandler#handleException(RepeatContext, - * Throwable) + * Throwable) */ - @Override + @Override public void handleException(RepeatContext context, Throwable throwable) throws Throwable { throw throwable; } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/exception/ExceptionHandler.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/exception/ExceptionHandler.java index 814f38a81..789d957a3 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/exception/ExceptionHandler.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/exception/ExceptionHandler.java @@ -21,25 +21,23 @@ import org.springframework.batch.repeat.RepeatContext; /** * Handler to allow strategies for re-throwing exceptions. Normally a - * {@link CompletionPolicy} will be used to decide whether to end a batch when - * there is no exception, and the {@link ExceptionHandler} is used to signal an - * abnormal ending - an abnormal ending would result in an - * {@link ExceptionHandler} throwing an exception. The caller will catch and - * re-throw it if necessary. - * + * {@link CompletionPolicy} will be used to decide whether to end a batch when there is no + * exception, and the {@link ExceptionHandler} is used to signal an abnormal ending - an + * abnormal ending would result in an {@link ExceptionHandler} throwing an exception. The + * caller will catch and re-throw it if necessary. + * * @author Dave Syer * @author Robert Kasanicky - * + * */ public interface ExceptionHandler { /** - * Deal with a Throwable during a batch - decide whether it should be - * re-thrown in the first place. - * - * @param context the current {@link RepeatContext}. Can be used to store - * state (via attributes), for example to count the number of occurrences of - * a particular exception type and implement a threshold policy. + * Deal with a Throwable during a batch - decide whether it should be re-thrown in the + * first place. + * @param context the current {@link RepeatContext}. Can be used to store state (via + * attributes), for example to count the number of occurrences of a particular + * exception type and implement a threshold policy. * @param throwable an exception. * @throws Throwable implementations are free to re-throw the exception */ diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/exception/LogOrRethrowExceptionHandler.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/exception/LogOrRethrowExceptionHandler.java index 17af7bb68..01be9f802 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/exception/LogOrRethrowExceptionHandler.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/exception/LogOrRethrowExceptionHandler.java @@ -24,45 +24,45 @@ import org.springframework.batch.repeat.RepeatContext; import org.springframework.batch.repeat.RepeatException; /** - * Implementation of {@link ExceptionHandler} based on an {@link Classifier}. - * The classifier determines whether to log the exception or rethrow it. The - * keys in the classifier must be the same as the static enum in this class. - * + * Implementation of {@link ExceptionHandler} based on an {@link Classifier}. The + * classifier determines whether to log the exception or rethrow it. The keys in the + * classifier must be the same as the static enum in this class. + * * @author Dave Syer - * + * */ public class LogOrRethrowExceptionHandler implements ExceptionHandler { /** * Logging levels for the handler. - * + * * @author Dave Syer - * + * */ public static enum Level { /** - * Key for {@link Classifier} signalling that the throwable should be - * rethrown. If the throwable is not a RuntimeException it is wrapped in - * a {@link RepeatException}. + * Key for {@link Classifier} signalling that the throwable should be rethrown. If + * the throwable is not a RuntimeException it is wrapped in a + * {@link RepeatException}. */ RETHROW, /** - * Key for {@link Classifier} signalling that the throwable should be - * logged at debug level. + * Key for {@link Classifier} signalling that the throwable should be logged at + * debug level. */ DEBUG, /** - * Key for {@link Classifier} signalling that the throwable should be - * logged at warn level. + * Key for {@link Classifier} signalling that the throwable should be logged at + * warn level. */ WARN, /** - * Key for {@link Classifier} signalling that the throwable should be - * logged at error level. + * Key for {@link Classifier} signalling that the throwable should be logged at + * error level. */ ERROR @@ -73,9 +73,8 @@ public class LogOrRethrowExceptionHandler implements ExceptionHandler { private Classifier exceptionClassifier = new ClassifierSupport<>(Level.RETHROW); /** - * Setter for the {@link Classifier} used by this handler. The default is to - * map all throwable instances to {@link Level#RETHROW}. - * + * Setter for the {@link Classifier} used by this handler. The default is to map all + * throwable instances to {@link Level#RETHROW}. * @param exceptionClassifier the ExceptionClassifier to use */ public void setExceptionClassifier(Classifier exceptionClassifier) { @@ -83,15 +82,15 @@ public class LogOrRethrowExceptionHandler implements ExceptionHandler { } /** - * Classify the throwables and decide whether to rethrow based on the - * result. The context is not used. - * - * @throws Throwable thrown if {@link LogOrRethrowExceptionHandler#exceptionClassifier} - * is classified as {@link Level#RETHROW}. - * + * Classify the throwables and decide whether to rethrow based on the result. The + * context is not used. + * @throws Throwable thrown if + * {@link LogOrRethrowExceptionHandler#exceptionClassifier} is classified as + * {@link Level#RETHROW}. + * * @see ExceptionHandler#handleException(RepeatContext, Throwable) */ - @Override + @Override public void handleException(RepeatContext context, Throwable throwable) throws Throwable { Level key = exceptionClassifier.classify(throwable); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/exception/RethrowOnThresholdExceptionHandler.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/exception/RethrowOnThresholdExceptionHandler.java index 4394ed7a3..a97867adf 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/exception/RethrowOnThresholdExceptionHandler.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/exception/RethrowOnThresholdExceptionHandler.java @@ -29,13 +29,12 @@ import org.springframework.batch.repeat.context.RepeatContextCounter; import org.springframework.util.ObjectUtils; /** - * Implementation of {@link ExceptionHandler} that rethrows when exceptions of a - * given type reach a threshold. Requires an {@link Classifier} that maps - * exception types to unique keys, and also a map from those keys to threshold - * values (Integer type). - * + * Implementation of {@link ExceptionHandler} that rethrows when exceptions of a given + * type reach a threshold. Requires an {@link Classifier} that maps exception types to + * unique keys, and also a map from those keys to threshold values (Integer type). + * * @author Dave Syer - * + * */ public class RethrowOnThresholdExceptionHandler implements ExceptionHandler { @@ -48,20 +47,18 @@ public class RethrowOnThresholdExceptionHandler implements ExceptionHandler { private boolean useParent = false; /** - * Flag to indicate the exception counters should be shared between - * sibling contexts in a nested batch. Default is false. - * - * @param useParent true if the parent context should be used to store the - * counters. + * Flag to indicate the exception counters should be shared between sibling contexts + * in a nested batch. Default is false. + * @param useParent true if the parent context should be used to store the counters. */ public void setUseParent(boolean useParent) { this.useParent = useParent; } /** - * Set up the exception handler. Creates a default exception handler and - * threshold that maps all exceptions to a threshold of 0 - all exceptions - * are rethrown by default. + * Set up the exception handler. Creates a default exception handler and threshold + * that maps all exceptions to a threshold of 0 - all exceptions are rethrown by + * default. */ public RethrowOnThresholdExceptionHandler() { super(); @@ -69,7 +66,6 @@ public class RethrowOnThresholdExceptionHandler implements ExceptionHandler { /** * A map from exception classes to a threshold value of type Integer. - * * @param thresholds the threshold value map. */ public void setThresholds(Map, Integer> thresholds) { @@ -81,14 +77,13 @@ public class RethrowOnThresholdExceptionHandler implements ExceptionHandler { } /** - * Classify the throwables and decide whether to re-throw based on the - * result. The context is used to accumulate the number of exceptions of the - * same type according to the classifier. - * + * Classify the throwables and decide whether to re-throw based on the result. The + * context is used to accumulate the number of exceptions of the same type according + * to the classifier. * @throws Throwable is thrown if number of exceptions exceeds threshold. * @see ExceptionHandler#handleException(RepeatContext, Throwable) */ - @Override + @Override public void handleException(RepeatContext context, Throwable throwable) throws Throwable { IntegerHolder key = exceptionClassifier.classify(throwable); @@ -111,7 +106,7 @@ public class RethrowOnThresholdExceptionHandler implements ExceptionHandler { /** * @author Dave Syer - * + * */ private static class IntegerHolder { @@ -134,7 +129,7 @@ public class RethrowOnThresholdExceptionHandler implements ExceptionHandler { /* * (non-Javadoc) - * + * * @see java.lang.Object#toString() */ @Override diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/exception/SimpleLimitExceptionHandler.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/exception/SimpleLimitExceptionHandler.java index 784b199e4..5709eb34b 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/exception/SimpleLimitExceptionHandler.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/exception/SimpleLimitExceptionHandler.java @@ -25,13 +25,13 @@ import org.springframework.batch.repeat.RepeatContext; import org.springframework.beans.factory.InitializingBean; /** - * Simple implementation of exception handler which looks for given exception - * types. If one of the types is found then a counter is incremented and the - * limit is checked to determine if it has been exceeded and the Throwable - * should be re-thrown. Also allows to specify list of 'fatal' exceptions that - * are never subject to counting, but are immediately re-thrown. The fatal list - * has higher priority so the two lists needn't be exclusive. - * + * Simple implementation of exception handler which looks for given exception types. If + * one of the types is found then a counter is incremented and the limit is checked to + * determine if it has been exceeded and the Throwable should be re-thrown. Also allows to + * specify list of 'fatal' exceptions that are never subject to counting, but are + * immediately re-thrown. The fatal list has higher priority so the two lists needn't be + * exclusive. + * * @author Dave Syer * @author Robert Kasanicky */ @@ -40,19 +40,19 @@ public class SimpleLimitExceptionHandler implements ExceptionHandler, Initializi private RethrowOnThresholdExceptionHandler delegate = new RethrowOnThresholdExceptionHandler(); private Collection> exceptionClasses = Collections - .> singleton(Exception.class); + .>singleton(Exception.class); private Collection> fatalExceptionClasses = Collections - .> singleton(Error.class); + .>singleton(Error.class); private int limit = 0; /** * Apply the provided properties to create a delegate handler. - * + * * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() */ - @Override + @Override public void afterPropertiesSet() throws Exception { if (limit <= 0) { return; @@ -69,22 +69,18 @@ public class SimpleLimitExceptionHandler implements ExceptionHandler, Initializi } /** - * Flag to indicate the exception counters should be shared between - * sibling contexts in a nested batch (i.e. inner loop). Default is false. - * Set this flag to true if you want to count exceptions for the whole - * (outer) loop in a typical container. - * - * @param useParent true if the parent context should be used to store the - * counters. + * Flag to indicate the exception counters should be shared between sibling contexts + * in a nested batch (i.e. inner loop). Default is false. Set this flag to true if you + * want to count exceptions for the whole (outer) loop in a typical container. + * @param useParent true if the parent context should be used to store the counters. */ public void setUseParent(boolean useParent) { delegate.setUseParent(useParent); } /** - * Convenience constructor for the {@link SimpleLimitExceptionHandler} to - * set the limit. - * + * Convenience constructor for the {@link SimpleLimitExceptionHandler} to set the + * limit. * @param limit the limit */ public SimpleLimitExceptionHandler(int limit) { @@ -100,24 +96,23 @@ public class SimpleLimitExceptionHandler implements ExceptionHandler, Initializi } /** - * Rethrows only if the limit is breached for this context on the exception - * type specified. - * + * Rethrows only if the limit is breached for this context on the exception type + * specified. + * * @see #setExceptionClasses(Collection) * @see #setLimit(int) - * + * * @see org.springframework.batch.repeat.exception.ExceptionHandler#handleException(org.springframework.batch.repeat.RepeatContext, * Throwable) */ - @Override + @Override public void handleException(RepeatContext context, Throwable throwable) throws Throwable { delegate.handleException(context, throwable); } /** - * The limit on the given exception type within a single context before it - * is rethrown. - * + * The limit on the given exception type within a single context before it is + * rethrown. * @param limit the limit */ public void setLimit(final int limit) { @@ -126,9 +121,9 @@ public class SimpleLimitExceptionHandler implements ExceptionHandler, Initializi /** * Setter for the exception classes that this handler counts. Defaults to - * {@link Exception}. If more exceptionClasses are specified handler uses - * single counter that is incremented when one of the recognized exception - * exceptionClasses is handled. + * {@link Exception}. If more exceptionClasses are specified handler uses single + * counter that is incremented when one of the recognized exception exceptionClasses + * is handled. * @param classes exceptionClasses */ public void setExceptionClasses(Collection> classes) { @@ -139,7 +134,6 @@ public class SimpleLimitExceptionHandler implements ExceptionHandler, Initializi * Setter for the exception classes that shouldn't be counted, but rethrown * immediately. This list has higher priority than * {@link #setExceptionClasses(Collection)}. - * * @param fatalExceptionClasses defaults to {@link Error} */ public void setFatalExceptionClasses(Collection> fatalExceptionClasses) { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/interceptor/RepeatOperationsInterceptor.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/interceptor/RepeatOperationsInterceptor.java index 2b3ea8103..9dc93e4f7 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/interceptor/RepeatOperationsInterceptor.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/interceptor/RepeatOperationsInterceptor.java @@ -28,16 +28,15 @@ import org.springframework.batch.repeat.support.RepeatTemplate; import org.springframework.util.Assert; /** - * A {@link MethodInterceptor} that can be used to automatically repeat calls to - * a method on a service. The injected {@link RepeatOperations} is used to - * control the completion of the loop. Independent of the completion policy in - * the {@link RepeatOperations} the loop will repeat until the target method - * returns null or false. Be careful when injecting a bespoke - * {@link RepeatOperations} that the loop will actually terminate, because the - * default policy for a vanilla {@link RepeatTemplate} will never complete if - * the return type of the target method is void (the value returned is always - * not-null, representing the {@link Void#TYPE}). - * + * A {@link MethodInterceptor} that can be used to automatically repeat calls to a method + * on a service. The injected {@link RepeatOperations} is used to control the completion + * of the loop. Independent of the completion policy in the {@link RepeatOperations} the + * loop will repeat until the target method returns null or false. Be careful when + * injecting a bespoke {@link RepeatOperations} that the loop will actually terminate, + * because the default policy for a vanilla {@link RepeatTemplate} will never complete if + * the return type of the target method is void (the value returned is always not-null, + * representing the {@link Void#TYPE}). + * * @author Dave Syer */ public class RepeatOperationsInterceptor implements MethodInterceptor { @@ -46,7 +45,6 @@ public class RepeatOperationsInterceptor implements MethodInterceptor { /** * Setter for the {@link RepeatOperations}. - * * @param batchTemplate template to be used * @throws IllegalArgumentException if the argument is null. */ @@ -56,12 +54,12 @@ public class RepeatOperationsInterceptor implements MethodInterceptor { } /** - * Invoke the proceeding method call repeatedly, according to the properties - * of the injected {@link RepeatOperations}. - * + * Invoke the proceeding method call repeatedly, according to the properties of the + * injected {@link RepeatOperations}. + * * @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation) */ - @Override + @Override public Object invoke(final MethodInvocation invocation) throws Throwable { final ResultHolder result = new ResultHolder(); @@ -76,7 +74,7 @@ public class RepeatOperationsInterceptor implements MethodInterceptor { try { repeatOperations.iterate(new RepeatCallback() { - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { try { @@ -138,14 +136,15 @@ public class RepeatOperationsInterceptor implements MethodInterceptor { } /** - * Simple wrapper exception class to enable nasty errors to be passed out of - * the scope of the repeat operations and handled by the caller. - * + * Simple wrapper exception class to enable nasty errors to be passed out of the scope + * of the repeat operations and handled by the caller. + * * @author Dave Syer - * + * */ @SuppressWarnings("serial") private static class RepeatOperationsInterceptorException extends RepeatException { + /** * @param message * @param e @@ -153,15 +152,17 @@ public class RepeatOperationsInterceptor implements MethodInterceptor { public RepeatOperationsInterceptorException(String message, Throwable e) { super(message, e); } + } /** * Simple wrapper object for the result from a method invocation. - * + * * @author Dave Syer - * + * */ private static class ResultHolder { + private Object value = null; private boolean ready = false; @@ -201,6 +202,7 @@ public class RepeatOperationsInterceptor implements MethodInterceptor { public boolean isReady() { return ready; } + } } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/listener/CompositeRepeatListener.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/listener/CompositeRepeatListener.java index 68919c42c..42d4e74f7 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/listener/CompositeRepeatListener.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/listener/CompositeRepeatListener.java @@ -27,7 +27,7 @@ import org.springframework.batch.repeat.RepeatListener; * Allows a user to register one or more RepeatListeners to be notified on batch events. * * @author Dave Syer - * + * */ public class CompositeRepeatListener implements RepeatListener { @@ -42,8 +42,8 @@ public class CompositeRepeatListener implements RepeatListener { /** * Convenience constructor for setting the {@link RepeatListener}s. - * - * @param listeners {@link List} of RepeatListeners to be used by the CompositeRepeatListener. + * @param listeners {@link List} of RepeatListeners to be used by the + * CompositeRepeatListener. */ public CompositeRepeatListener(List listeners) { setListeners(listeners); @@ -51,8 +51,8 @@ public class CompositeRepeatListener implements RepeatListener { /** * Convenience constructor for setting the {@link RepeatListener}s. - * - * @param listeners array of RepeatListeners to be used by the CompositeRepeatListener. + * @param listeners array of RepeatListeners to be used by the + * CompositeRepeatListener. */ public CompositeRepeatListener(RepeatListener... listeners) { setListeners(listeners); @@ -60,8 +60,8 @@ public class CompositeRepeatListener implements RepeatListener { /** * Public setter for the listeners. - * - * @param listeners {@link List} of RepeatListeners to be used by the CompositeRepeatListener. + * @param listeners {@link List} of RepeatListeners to be used by the + * CompositeRepeatListener. */ public void setListeners(List listeners) { this.listeners = listeners; @@ -69,8 +69,8 @@ public class CompositeRepeatListener implements RepeatListener { /** * Public setter for the listeners. - * - * @param listeners array of RepeatListeners to be used by the CompositeRepeatListener. + * @param listeners array of RepeatListeners to be used by the + * CompositeRepeatListener. */ public void setListeners(RepeatListener[] listeners) { this.listeners = Arrays.asList(listeners); @@ -78,8 +78,8 @@ public class CompositeRepeatListener implements RepeatListener { /** * Register additional listener. - * - * @param listener the RepeatListener to be added to the list of listeners to be notified. + * @param listener the RepeatListener to be added to the list of listeners to be + * notified. */ public void register(RepeatListener listener) { if (!listeners.contains(listener)) { @@ -87,50 +87,70 @@ public class CompositeRepeatListener implements RepeatListener { } } - /* (non-Javadoc) - * @see org.springframework.batch.repeat.RepeatListener#after(org.springframework.batch.repeat.RepeatContext, org.springframework.batch.repeat.ExitStatus) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.repeat.RepeatListener#after(org.springframework.batch. + * repeat.RepeatContext, org.springframework.batch.repeat.ExitStatus) */ - @Override + @Override public void after(RepeatContext context, RepeatStatus result) { for (RepeatListener listener : listeners) { listener.after(context, result); } } - /* (non-Javadoc) - * @see org.springframework.batch.repeat.RepeatListener#before(org.springframework.batch.repeat.RepeatContext) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.repeat.RepeatListener#before(org.springframework.batch. + * repeat.RepeatContext) */ - @Override + @Override public void before(RepeatContext context) { for (RepeatListener listener : listeners) { listener.before(context); } } - /* (non-Javadoc) - * @see org.springframework.batch.repeat.RepeatListener#close(org.springframework.batch.repeat.RepeatContext) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.repeat.RepeatListener#close(org.springframework.batch. + * repeat.RepeatContext) */ - @Override + @Override public void close(RepeatContext context) { for (RepeatListener listener : listeners) { listener.close(context); } } - /* (non-Javadoc) - * @see org.springframework.batch.repeat.RepeatListener#onError(org.springframework.batch.repeat.RepeatContext, java.lang.Throwable) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.repeat.RepeatListener#onError(org.springframework.batch. + * repeat.RepeatContext, java.lang.Throwable) */ - @Override + @Override public void onError(RepeatContext context, Throwable e) { for (RepeatListener listener : listeners) { listener.onError(context, e); } } - /* (non-Javadoc) - * @see org.springframework.batch.repeat.RepeatListener#open(org.springframework.batch.repeat.RepeatContext) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.repeat.RepeatListener#open(org.springframework.batch. + * repeat.RepeatContext) */ - @Override + @Override public void open(RepeatContext context) { for (RepeatListener listener : listeners) { listener.open(context); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/listener/RepeatListenerSupport.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/listener/RepeatListenerSupport.java index d97e818c2..cea6e890d 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/listener/RepeatListenerSupport.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/listener/RepeatListenerSupport.java @@ -22,32 +22,31 @@ import org.springframework.batch.repeat.RepeatListener; /** * Empty method implementation of {@link RepeatListener}. - * + * * @author Dave Syer * @author Mahmoud Ben Hassine - * * @deprecated as of v5.0 in favor of the default methods in {@link RepeatListener}. */ @Deprecated public class RepeatListenerSupport implements RepeatListener { - @Override + @Override public void before(RepeatContext context) { } - @Override + @Override public void after(RepeatContext context, RepeatStatus result) { } - @Override + @Override public void close(RepeatContext context) { } - @Override + @Override public void onError(RepeatContext context, Throwable e) { } - @Override + @Override public void open(RepeatContext context) { } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/policy/CompletionPolicySupport.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/policy/CompletionPolicySupport.java index 52e5bc9de..a5acaf935 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/policy/CompletionPolicySupport.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/policy/CompletionPolicySupport.java @@ -23,20 +23,20 @@ import org.springframework.batch.repeat.context.RepeatContextSupport; /** * Very simple base class for {@link CompletionPolicy} implementations. - * + * * @author Dave Syer - * + * */ public class CompletionPolicySupport implements CompletionPolicy { /** - * If exit status is not continuable return true, otherwise - * delegate to {@link #isComplete(RepeatContext)}. - * + * If exit status is not continuable return true, otherwise delegate to + * {@link #isComplete(RepeatContext)}. + * * @see org.springframework.batch.repeat.CompletionPolicy#isComplete(org.springframework.batch.repeat.RepeatContext, * RepeatStatus) */ - @Override + @Override public boolean isComplete(RepeatContext context, RepeatStatus result) { if (result != null && !result.isContinuable()) { return true; @@ -48,30 +48,30 @@ public class CompletionPolicySupport implements CompletionPolicy { /** * Always true. - * + * * @see org.springframework.batch.repeat.CompletionPolicy#isComplete(org.springframework.batch.repeat.RepeatContext) */ - @Override + @Override public boolean isComplete(RepeatContext context) { return true; } /** * Build a new {@link RepeatContextSupport} and return it. - * + * * @see org.springframework.batch.repeat.CompletionPolicy#start(RepeatContext) */ - @Override + @Override public RepeatContext start(RepeatContext context) { return new RepeatContextSupport(context); } /** * Increment the context so the counter is up to date. Do nothing else. - * + * * @see org.springframework.batch.repeat.CompletionPolicy#update(org.springframework.batch.repeat.RepeatContext) */ - @Override + @Override public void update(RepeatContext context) { if (context instanceof RepeatContextSupport) { ((RepeatContextSupport) context).increment(); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/policy/CompositeCompletionPolicy.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/policy/CompositeCompletionPolicy.java index 1f27c6bd1..d5d32c79c 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/policy/CompositeCompletionPolicy.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/policy/CompositeCompletionPolicy.java @@ -26,11 +26,11 @@ import org.springframework.batch.repeat.RepeatStatus; import org.springframework.batch.repeat.context.RepeatContextSupport; /** - * Composite policy that loops through a list of delegate policies and answers - * calls by a consensus. - * + * Composite policy that loops through a list of delegate policies and answers calls by a + * consensus. + * * @author Dave Syer - * + * */ public class CompositeCompletionPolicy implements CompletionPolicy { @@ -38,9 +38,8 @@ public class CompositeCompletionPolicy implements CompletionPolicy { /** * Setter for the policies. - * * @param policies an array of completion policies to be used to determine - * {@link #isComplete(RepeatContext)} by consensus. + * {@link #isComplete(RepeatContext)} by consensus. */ public void setPolicies(CompletionPolicy[] policies) { this.policies = Arrays.asList(policies).toArray(new CompletionPolicy[policies.length]); @@ -48,11 +47,11 @@ public class CompositeCompletionPolicy implements CompletionPolicy { /** * This policy is complete if any of the composed policies is complete. - * + * * @see org.springframework.batch.repeat.CompletionPolicy#isComplete(org.springframework.batch.repeat.RepeatContext, * RepeatStatus) */ - @Override + @Override public boolean isComplete(RepeatContext context, RepeatStatus result) { RepeatContext[] contexts = ((CompositeBatchContext) context).contexts; CompletionPolicy[] policies = ((CompositeBatchContext) context).policies; @@ -66,10 +65,10 @@ public class CompositeCompletionPolicy implements CompletionPolicy { /** * This policy is complete if any of the composed policies is complete. - * + * * @see org.springframework.batch.repeat.CompletionPolicy#isComplete(org.springframework.batch.repeat.RepeatContext) */ - @Override + @Override public boolean isComplete(RepeatContext context) { RepeatContext[] contexts = ((CompositeBatchContext) context).contexts; CompletionPolicy[] policies = ((CompositeBatchContext) context).policies; @@ -83,10 +82,10 @@ public class CompositeCompletionPolicy implements CompletionPolicy { /** * Create a new composite context from all the available policies. - * + * * @see org.springframework.batch.repeat.CompletionPolicy#start(RepeatContext) */ - @Override + @Override public RepeatContext start(RepeatContext context) { List list = new ArrayList<>(); for (int i = 0; i < policies.length; i++) { @@ -98,10 +97,10 @@ public class CompositeCompletionPolicy implements CompletionPolicy { /** * Update all the composed contexts, and also increment the parent context. - * + * * @see org.springframework.batch.repeat.CompletionPolicy#update(org.springframework.batch.repeat.RepeatContext) */ - @Override + @Override public void update(RepeatContext context) { RepeatContext[] contexts = ((CompositeBatchContext) context).contexts; CompletionPolicy[] policies = ((CompositeBatchContext) context).policies; @@ -112,11 +111,10 @@ public class CompositeCompletionPolicy implements CompletionPolicy { } /** - * Composite context that knows about the policies and contexts is was - * created with. - * + * Composite context that knows about the policies and contexts is was created with. + * * @author Dave Syer - * + * */ protected class CompositeBatchContext extends RepeatContextSupport { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/policy/CountingCompletionPolicy.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/policy/CountingCompletionPolicy.java index 8b4ec15a3..17fd2f838 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/policy/CountingCompletionPolicy.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/policy/CountingCompletionPolicy.java @@ -21,14 +21,13 @@ import org.springframework.batch.repeat.context.RepeatContextCounter; import org.springframework.batch.repeat.context.RepeatContextSupport; /** - * Abstract base class for policies that need to count the number of occurrences - * of some event (e.g. an exception type in the context), and terminate based on - * a limit for the counter. The value of the counter can be stored between - * batches in a nested context, so that the termination decision is based on the - * aggregate of a number of sibling batches. - * + * Abstract base class for policies that need to count the number of occurrences of some + * event (e.g. an exception type in the context), and terminate based on a limit for the + * counter. The value of the counter can be stored between batches in a nested context, so + * that the termination decision is based on the aggregate of a number of sibling batches. + * * @author Dave Syer - * + * */ public abstract class CountingCompletionPolicy extends DefaultResultCompletionPolicy { @@ -42,12 +41,11 @@ public abstract class CountingCompletionPolicy extends DefaultResultCompletionPo private int maxCount = 0; /** - * Flag to indicate whether the count is at the level of the parent context, - * or just local to the context. If true then the count is aggregated among - * siblings in a nested batch. - * - * @param useParent whether to use the parent context to cache the total - * count. Default value is false. + * Flag to indicate whether the count is at the level of the parent context, or just + * local to the context. If true then the count is aggregated among siblings in a + * nested batch. + * @param useParent whether to use the parent context to cache the total count. + * Default value is false. */ public void setUseParent(boolean useParent) { this.useParent = useParent; @@ -55,33 +53,28 @@ public abstract class CountingCompletionPolicy extends DefaultResultCompletionPo /** * Setter for maximum value of count before termination. - * - * @param maxCount the maximum number of counts before termination. Default - * 0 so termination is immediate. + * @param maxCount the maximum number of counts before termination. Default 0 so + * termination is immediate. */ public void setMaxCount(int maxCount) { this.maxCount = maxCount; } /** - * Extension point for subclasses. Obtain the value of the count in the - * current context. Subclasses can count the number of attempts or - * violations and store the result in their context. This policy base class - * will take care of the termination contract and aggregating at the level - * of the session if required. - * + * Extension point for subclasses. Obtain the value of the count in the current + * context. Subclasses can count the number of attempts or violations and store the + * result in their context. This policy base class will take care of the termination + * contract and aggregating at the level of the session if required. * @param context the current context, specific to the subclass. * @return the value of the counter in the context. */ protected abstract int getCount(RepeatContext context); /** - * Extension point for subclasses. Inspect the context and update the state - * of a counter in whatever way is appropriate. This will be added to the - * session-level counter if {@link #setUseParent(boolean)} is true. - * + * Extension point for subclasses. Inspect the context and update the state of a + * counter in whatever way is appropriate. This will be added to the session-level + * counter if {@link #setUseParent(boolean)} is true. * @param context the current context. - * * @return the change in the value of the counter (default 0). */ protected int doUpdate(RepeatContext context) { @@ -90,9 +83,12 @@ public abstract class CountingCompletionPolicy extends DefaultResultCompletionPo /* * (non-Javadoc) - * @see org.springframework.batch.repeat.policy.CompletionPolicySupport#isComplete(org.springframework.batch.repeat.BatchContext) + * + * @see + * org.springframework.batch.repeat.policy.CompletionPolicySupport#isComplete(org. + * springframework.batch.repeat.BatchContext) */ - @Override + @Override final public boolean isComplete(RepeatContext context) { int count = ((CountingBatchContext) context).getCounter().getCount(); return count >= maxCount; @@ -100,18 +96,22 @@ public abstract class CountingCompletionPolicy extends DefaultResultCompletionPo /* * (non-Javadoc) - * @see org.springframework.batch.repeat.policy.CompletionPolicySupport#start(org.springframework.batch.repeat.BatchContext) + * + * @see org.springframework.batch.repeat.policy.CompletionPolicySupport#start(org. + * springframework.batch.repeat.BatchContext) */ - @Override + @Override public RepeatContext start(RepeatContext parent) { return new CountingBatchContext(parent); } /* * (non-Javadoc) - * @see org.springframework.batch.repeat.policy.CompletionPolicySupport#update(org.springframework.batch.repeat.BatchContext) + * + * @see org.springframework.batch.repeat.policy.CompletionPolicySupport#update(org. + * springframework.batch.repeat.BatchContext) */ - @Override + @Override final public void update(RepeatContext context) { super.update(context); int delta = doUpdate(context); @@ -132,4 +132,5 @@ public abstract class CountingCompletionPolicy extends DefaultResultCompletionPo } } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/policy/DefaultResultCompletionPolicy.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/policy/DefaultResultCompletionPolicy.java index 74d3c0626..75cb2266f 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/policy/DefaultResultCompletionPolicy.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/policy/DefaultResultCompletionPolicy.java @@ -21,33 +21,32 @@ import org.springframework.batch.repeat.RepeatStatus; import org.springframework.batch.repeat.RepeatContext; /** - * Very simple {@link CompletionPolicy} that bases its decision on the result of - * a batch operation. If the result is null or not continuable according to the + * Very simple {@link CompletionPolicy} that bases its decision on the result of a batch + * operation. If the result is null or not continuable according to the * {@link RepeatStatus} the batch is complete, otherwise not. - * + * * @author Dave Syer - * + * */ public class DefaultResultCompletionPolicy extends CompletionPolicySupport { /** - * True if the result is null, or a {@link RepeatStatus} indicating - * completion. - * + * True if the result is null, or a {@link RepeatStatus} indicating completion. + * * @see org.springframework.batch.repeat.CompletionPolicy#isComplete(org.springframework.batch.repeat.RepeatContext, - * RepeatStatus) + * RepeatStatus) */ - @Override + @Override public boolean isComplete(RepeatContext context, RepeatStatus result) { return (result == null || !result.isContinuable()); } /** * Always false. - * + * * @see org.springframework.batch.repeat.CompletionPolicy#isComplete(org.springframework.batch.repeat.RepeatContext) */ - @Override + @Override public boolean isComplete(RepeatContext context) { return false; } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/policy/SimpleCompletionPolicy.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/policy/SimpleCompletionPolicy.java index 8e30ccfb4..896173672 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/policy/SimpleCompletionPolicy.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/policy/SimpleCompletionPolicy.java @@ -23,14 +23,14 @@ import org.springframework.batch.repeat.support.RepeatTemplate; import org.springframework.util.ClassUtils; /** - * Policy for terminating a batch after a fixed number of operations. Internal - * state is maintained and a counter incremented, so successful use of this - * policy requires that isComplete() is only called once per batch item. Using - * the standard {@link RepeatTemplate} should ensure this contract is kept, but it needs - * to be carefully monitored. - * + * Policy for terminating a batch after a fixed number of operations. Internal state is + * maintained and a counter incremented, so successful use of this policy requires that + * isComplete() is only called once per batch item. Using the standard + * {@link RepeatTemplate} should ensure this contract is kept, but it needs to be + * carefully monitored. + * * @author Dave Syer - * + * */ public class SimpleCompletionPolicy extends DefaultResultCompletionPolicy { @@ -57,43 +57,43 @@ public class SimpleCompletionPolicy extends DefaultResultCompletionPolicy { /** * Reset the counter. - * + * * @see org.springframework.batch.repeat.CompletionPolicy#start(RepeatContext) */ - @Override + @Override public RepeatContext start(RepeatContext context) { return new SimpleTerminationContext(context); } /** * Terminate if the chunk size has been reached, or the result is null. - * + * * @see org.springframework.batch.repeat.CompletionPolicy#isComplete(RepeatContext, * RepeatStatus) - * @throws RuntimeException (normally terminating the batch) if the result is - * itself an exception. + * @throws RuntimeException (normally terminating the batch) if the result is itself + * an exception. */ - @Override + @Override public boolean isComplete(RepeatContext context, RepeatStatus result) { return super.isComplete(context, result) || ((SimpleTerminationContext) context).isComplete(); } /** * Terminate if the chunk size has been reached. - * + * * @see org.springframework.batch.repeat.CompletionPolicy#isComplete(RepeatContext) */ - @Override + @Override public boolean isComplete(RepeatContext context) { return ((SimpleTerminationContext) context).isComplete(); } /** * Increment the counter in the context. - * + * * @see org.springframework.batch.repeat.CompletionPolicy#update(RepeatContext) */ - @Override + @Override public void update(RepeatContext context) { ((SimpleTerminationContext) context).update(); } @@ -111,14 +111,17 @@ public class SimpleCompletionPolicy extends DefaultResultCompletionPolicy { public boolean isComplete() { return getStartedCount() >= chunkSize; } + } - - /* (non-Javadoc) + + /* + * (non-Javadoc) + * * @see java.lang.Object#toString() */ - @Override + @Override public String toString() { - return ClassUtils.getShortName(SimpleCompletionPolicy.class)+": chunkSize="+chunkSize; + return ClassUtils.getShortName(SimpleCompletionPolicy.class) + ": chunkSize=" + chunkSize; } } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/policy/TimeoutTerminationPolicy.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/policy/TimeoutTerminationPolicy.java index 1f7a47eb3..dae86e3aa 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/policy/TimeoutTerminationPolicy.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/policy/TimeoutTerminationPolicy.java @@ -20,17 +20,17 @@ import org.springframework.batch.repeat.RepeatContext; import org.springframework.batch.repeat.context.RepeatContextSupport; /** - * Termination policy that times out after a fixed period. Allows graceful exit - * from a batch if the latest result comes in after the timeout expires (i.e. - * does not throw a timeout exception).
      - * + * Termination policy that times out after a fixed period. Allows graceful exit from a + * batch if the latest result comes in after the timeout expires (i.e. does not throw a + * timeout exception).
      + * * N.B. It may often be the case that the batch governed by this policy will be - * transactional, and the transaction might have its own timeout. In this case - * the transaction might throw a timeout exception on commit if its timeout - * threshold is lower than the termination policy. - * + * transactional, and the transaction might have its own timeout. In this case the + * transaction might throw a timeout exception on commit if its timeout threshold is lower + * than the termination policy. + * * @author Dave Syer - * + * */ public class TimeoutTerminationPolicy extends CompletionPolicySupport { @@ -49,9 +49,8 @@ public class TimeoutTerminationPolicy extends CompletionPolicySupport { } /** - * Construct a {@link TimeoutTerminationPolicy} with the specified timeout - * value (in milliseconds). - * + * Construct a {@link TimeoutTerminationPolicy} with the specified timeout value (in + * milliseconds). * @param timeout duration of the timeout. */ public TimeoutTerminationPolicy(long timeout) { @@ -61,7 +60,7 @@ public class TimeoutTerminationPolicy extends CompletionPolicySupport { /** * Check the timeout and complete gracefully if it has expires. - * + * * @see org.springframework.batch.repeat.CompletionPolicy#isComplete(org.springframework.batch.repeat.RepeatContext) */ @Override @@ -71,7 +70,7 @@ public class TimeoutTerminationPolicy extends CompletionPolicySupport { /** * Start the clock on the timeout. - * + * * @see org.springframework.batch.repeat.CompletionPolicy#start(RepeatContext) */ @Override diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/RepeatInternalState.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/RepeatInternalState.java index 077d1999c..a3aae6db9 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/RepeatInternalState.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/RepeatInternalState.java @@ -20,16 +20,15 @@ import java.util.Collection; /** * Internal interface for extensions of {@link RepeatTemplate}. - * + * * @author Dave Syer - * + * */ public interface RepeatInternalState { /** - * Returns a mutable collection of exceptions that have occurred in the - * current repeat context. Clients are expected to mutate this collection. - * + * Returns a mutable collection of exceptions that have occurred in the current repeat + * context. Clients are expected to mutate this collection. * @return the collection of exceptions being accumulated */ Collection getThrowables(); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/RepeatInternalStateSupport.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/RepeatInternalStateSupport.java index c5fd6f3f9..162e1c87f 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/RepeatInternalStateSupport.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/RepeatInternalStateSupport.java @@ -21,14 +21,16 @@ import java.util.HashSet; import java.util.Set; public class RepeatInternalStateSupport implements RepeatInternalState { - - // Accumulation of failed results. + + // Accumulation of failed results. private final Set throwables = new HashSet<>(); - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.springframework.batch.repeat.support.BatchInternalState#getThrowables() */ - @Override + @Override public Collection getThrowables() { return throwables; } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/RepeatSynchronizationManager.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/RepeatSynchronizationManager.java index 7946d4a15..8a809cfca 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/RepeatSynchronizationManager.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/RepeatSynchronizationManager.java @@ -21,17 +21,16 @@ import org.springframework.batch.repeat.RepeatContext; import org.springframework.batch.repeat.RepeatOperations; /** - * Global variable support for repeat clients. Normally it is not necessary for - * clients to be aware of the surrounding environment because a - * {@link RepeatCallback} can always use the context it is passed by the - * enclosing {@link RepeatOperations}. But occasionally it might be helpful to - * have lower level access to the ongoing {@link RepeatContext} so we provide a - * global accessor here. The mutator methods ({@link #clear()} and + * Global variable support for repeat clients. Normally it is not necessary for clients to + * be aware of the surrounding environment because a {@link RepeatCallback} can always use + * the context it is passed by the enclosing {@link RepeatOperations}. But occasionally it + * might be helpful to have lower level access to the ongoing {@link RepeatContext} so we + * provide a global accessor here. The mutator methods ({@link #clear()} and * {@link #register(RepeatContext)} should not be used except internally by * {@link RepeatOperations} implementations. - * + * * @author Dave Syer - * + * */ public final class RepeatSynchronizationManager { @@ -41,21 +40,19 @@ public final class RepeatSynchronizationManager { } /** - * Getter for the current context. A context is shared by all items in the - * batch, so this method is intended to return the same context object - * independent of whether the callback is running synchronously or - * asynchronously with the surrounding {@link RepeatOperations}. - * - * @return the current {@link RepeatContext} or null if there is none (if we - * are not in a batch). + * Getter for the current context. A context is shared by all items in the batch, so + * this method is intended to return the same context object independent of whether + * the callback is running synchronously or asynchronously with the surrounding + * {@link RepeatOperations}. + * @return the current {@link RepeatContext} or null if there is none (if we are not + * in a batch). */ public static RepeatContext getContext() { return contextHolder.get(); } /** - * Convenience method to set the current repeat operation to complete if it - * exists. + * Convenience method to set the current repeat operation to complete if it exists. */ public static void setCompleteOnly() { RepeatContext context = getContext(); @@ -65,10 +62,9 @@ public final class RepeatSynchronizationManager { } /** - * Method for registering a context - should only be used by - * {@link RepeatOperations} implementations to ensure that - * {@link #getContext()} always returns the correct value. - * + * Method for registering a context - should only be used by {@link RepeatOperations} + * implementations to ensure that {@link #getContext()} always returns the correct + * value. * @param context a new context at the start of a batch. * @return the old value if there was one. */ @@ -81,7 +77,6 @@ public final class RepeatSynchronizationManager { /** * Clear the current context at the end of a batch - should only be used by * {@link RepeatOperations} implementations. - * * @return the old value if there was one. */ public static RepeatContext clear() { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/RepeatTemplate.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/RepeatTemplate.java index 1820f9e43..5690655c6 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/RepeatTemplate.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/RepeatTemplate.java @@ -38,30 +38,29 @@ import org.springframework.util.Assert; /** * Simple implementation and base class for batch templates implementing - * {@link RepeatOperations}. Provides a framework including interceptors and - * policies. Subclasses just need to provide a method that gets the next result - * and one that waits for all the results to be returned from concurrent - * processes or threads.
      - * - * N.B. the template accumulates thrown exceptions during the iteration, and - * they are all processed together when the main loop ends (i.e. finished - * processing the items). Clients that do not want to stop execution when an - * exception is thrown can use a specific {@link CompletionPolicy} that does not - * finish when exceptions are received. This is not the default behaviour.
      - * - * Clients that want to take some business action when an exception is thrown by - * the {@link RepeatCallback} can consider using a custom {@link RepeatListener} - * instead of trying to customise the {@link CompletionPolicy}. This is - * generally a friendlier interface to implement, and the - * {@link RepeatListener#after(RepeatContext, RepeatStatus)} method is passed in - * the result of the callback, which would be an instance of {@link Throwable} - * if the business processing had thrown an exception. If the exception is not - * to be propagated to the caller, then a non-default {@link CompletionPolicy} - * needs to be provided as well, but that could be off the shelf, with the - * business action implemented only in the interceptor. - * + * {@link RepeatOperations}. Provides a framework including interceptors and policies. + * Subclasses just need to provide a method that gets the next result and one that waits + * for all the results to be returned from concurrent processes or threads.
      + * + * N.B. the template accumulates thrown exceptions during the iteration, and they are all + * processed together when the main loop ends (i.e. finished processing the items). + * Clients that do not want to stop execution when an exception is thrown can use a + * specific {@link CompletionPolicy} that does not finish when exceptions are received. + * This is not the default behaviour.
      + * + * Clients that want to take some business action when an exception is thrown by the + * {@link RepeatCallback} can consider using a custom {@link RepeatListener} instead of + * trying to customise the {@link CompletionPolicy}. This is generally a friendlier + * interface to implement, and the + * {@link RepeatListener#after(RepeatContext, RepeatStatus)} method is passed in the + * result of the callback, which would be an instance of {@link Throwable} if the business + * processing had thrown an exception. If the exception is not to be propagated to the + * caller, then a non-default {@link CompletionPolicy} needs to be provided as well, but + * that could be off the shelf, with the business action implemented only in the + * interceptor. + * * @author Dave Syer - * + * */ public class RepeatTemplate implements RepeatOperations { @@ -74,9 +73,8 @@ public class RepeatTemplate implements RepeatOperations { private ExceptionHandler exceptionHandler = new DefaultExceptionHandler(); /** - * Set the listeners for this template, registering them for callbacks at - * appropriate times in the iteration. - * + * Set the listeners for this template, registering them for callbacks at appropriate + * times in the iteration. * @param listeners listeners to be used */ public void setListeners(RepeatListener[] listeners) { @@ -85,7 +83,6 @@ public class RepeatTemplate implements RepeatOperations { /** * Register an additional listener. - * * @param listener a single listener to be added to the list */ public void registerListener(RepeatListener listener) { @@ -95,14 +92,13 @@ public class RepeatTemplate implements RepeatOperations { } /** - * Setter for exception handler strategy. The exception handler is called at - * the end of a batch, after the {@link CompletionPolicy} has determined - * that the batch is complete. By default all exceptions are re-thrown. - * + * Setter for exception handler strategy. The exception handler is called at the end + * of a batch, after the {@link CompletionPolicy} has determined that the batch is + * complete. By default all exceptions are re-thrown. + * * @see ExceptionHandler * @see DefaultExceptionHandler * @see #setCompletionPolicy(CompletionPolicy) - * * @param exceptionHandler the {@link ExceptionHandler} to use. */ public void setExceptionHandler(ExceptionHandler exceptionHandler) { @@ -110,14 +106,12 @@ public class RepeatTemplate implements RepeatOperations { } /** - * Setter for policy to decide when the batch is complete. The default is to - * complete normally when the callback returns a {@link RepeatStatus} which - * is not marked as continuable, and abnormally when the callback throws an - * exception (but the decision to re-throw the exception is deferred to the - * {@link ExceptionHandler}). - * + * Setter for policy to decide when the batch is complete. The default is to complete + * normally when the callback returns a {@link RepeatStatus} which is not marked as + * continuable, and abnormally when the callback throws an exception (but the decision + * to re-throw the exception is deferred to the {@link ExceptionHandler}). + * * @see #setExceptionHandler(ExceptionHandler) - * * @param terminationPolicy a TerminationPolicy. * @throws IllegalArgumentException if the argument is null */ @@ -127,13 +121,13 @@ public class RepeatTemplate implements RepeatOperations { } /** - * Execute the batch callback until the completion policy decides that we - * are finished. Wait for the whole batch to finish before returning even if - * the task executor is asynchronous. - * + * Execute the batch callback until the completion policy decides that we are + * finished. Wait for the whole batch to finish before returning even if the task + * executor is asynchronous. + * * @see org.springframework.batch.repeat.RepeatOperations#iterate(org.springframework.batch.repeat.RepeatCallback) */ - @Override + @Override public RepeatStatus iterate(RepeatCallback callback) { RepeatContext outer = RepeatSynchronizationManager.getContext(); @@ -155,14 +149,11 @@ public class RepeatTemplate implements RepeatOperations { } /** - * Internal convenience method to loop over interceptors and batch - * callbacks. - * + * Internal convenience method to loop over interceptors and batch callbacks. * @param callback the callback to process each element of the loop. - * - * @return the aggregate of {@link RepeatTemplate#canContinue(RepeatStatus)} - * for all the results from the callback. - * + * @return the aggregate of {@link RepeatTemplate#canContinue(RepeatStatus)} for all + * the results from the callback. + * */ private RepeatStatus executeInternal(final RepeatCallback callback) { @@ -195,9 +186,9 @@ public class RepeatTemplate implements RepeatOperations { while (running) { /* - * Run the before interceptors here, not in the task executor so - * that they all happen in the same thread - it's easier for - * tracking batch status, amongst other things. + * Run the before interceptors here, not in the task executor so that they + * all happen in the same thread - it's easier for tracking batch status, + * amongst other things. */ for (int i = 0; i < listeners.length; i++) { RepeatListener interceptor = listeners[i]; @@ -239,9 +230,9 @@ public class RepeatTemplate implements RepeatOperations { } /* - * No need for explicit catch here - if the business processing threw an - * exception it was already handled by the helper methods. An exception - * here is necessarily fatal. + * No need for explicit catch here - if the business processing threw an exception + * it was already handled by the helper methods. An exception here is necessarily + * fatal. */ finally { @@ -250,8 +241,8 @@ public class RepeatTemplate implements RepeatOperations { if (!deferred.isEmpty()) { Throwable throwable = deferred.iterator().next(); if (logger.isDebugEnabled()) { - logger.debug("Handling fatal exception explicitly (rethrowing first of " + deferred.size() + "): " - + throwable.getClass().getName() + ": " + throwable.getMessage()); + logger.debug("Handling fatal exception explicitly (rethrowing first of " + deferred.size() + + "): " + throwable.getClass().getName() + ": " + throwable.getMessage()); } rethrow(throwable); } @@ -288,7 +279,8 @@ public class RepeatTemplate implements RepeatOperations { // This is not an error - only log at debug // level. if (logger.isDebugEnabled()) { - logger.debug("Exception intercepted (" + (i + 1) + " of " + listeners.length + ")", unwrappedThrowable); + logger.debug("Exception intercepted (" + (i + 1) + " of " + listeners.length + ")", + unwrappedThrowable); } interceptor.onError(context, unwrappedThrowable); } @@ -306,8 +298,8 @@ public class RepeatTemplate implements RepeatOperations { } /** - * Re-throws the original throwable if it is unchecked, wraps checked - * exceptions into {@link RepeatException}. + * Re-throws the original throwable if it is unchecked, wraps checked exceptions into + * {@link RepeatException}. */ private static void rethrow(Throwable throwable) throws RuntimeException { if (throwable instanceof Error) { @@ -322,8 +314,7 @@ public class RepeatTemplate implements RepeatOperations { } /** - * Unwraps the throwable if it has been wrapped by - * {@link #rethrow(Throwable)}. + * Unwraps the throwable if it has been wrapped by {@link #rethrow(Throwable)}. */ private static Throwable unwrapIfRethrown(Throwable throwable) { if (throwable instanceof RepeatException) { @@ -335,15 +326,13 @@ public class RepeatTemplate implements RepeatOperations { } /** - * Create an internal state object that is used to store data needed - * internally in the scope of an iteration. Used by subclasses to manage the - * queueing and retrieval of asynchronous results. The default just provides - * an accumulation of Throwable instances for processing at the end of the - * batch. - * + * Create an internal state object that is used to store data needed internally in the + * scope of an iteration. Used by subclasses to manage the queueing and retrieval of + * asynchronous results. The default just provides an accumulation of Throwable + * instances for processing at the end of the batch. * @param context the current {@link RepeatContext} * @return a {@link RepeatInternalState} instance. - * + * * @see RepeatTemplate#waitForResults(RepeatInternalState) */ protected RepeatInternalState createInternalState(RepeatContext context) { @@ -351,18 +340,16 @@ public class RepeatTemplate implements RepeatOperations { } /** - * Get the next completed result, possibly executing several callbacks until - * one finally finishes. Normally a subclass would have to override both - * this method and {@link #createInternalState(RepeatContext)} because the - * implementation of this method would rely on the details of the internal - * state. - * + * Get the next completed result, possibly executing several callbacks until one + * finally finishes. Normally a subclass would have to override both this method and + * {@link #createInternalState(RepeatContext)} because the implementation of this + * method would rely on the details of the internal state. * @param context current BatchContext. * @param callback the callback to execute. * @param state maintained by the implementation. * @return a finished result. * @throws Throwable any Throwable emitted during the iteration - * + * * @see #isComplete(RepeatContext) * @see #createInternalState(RepeatContext) */ @@ -377,12 +364,11 @@ public class RepeatTemplate implements RepeatOperations { } /** - * If necessary, wait for results to come back from remote or concurrent - * processes. By default does nothing and returns true. - * + * If necessary, wait for results to come back from remote or concurrent processes. By + * default does nothing and returns true. * @param state the internal state. - * @return true if {@link #canContinue(RepeatStatus)} is true for all - * results retrieved. + * @return true if {@link #canContinue(RepeatStatus)} is true for all results + * retrieved. */ protected boolean waitForResults(RepeatInternalState state) { // no-op by default @@ -391,7 +377,6 @@ public class RepeatTemplate implements RepeatOperations { /** * Check return value from batch operation. - * * @param value the last callback result. * @return true if the value is {@link RepeatStatus#CONTINUABLE}. */ @@ -413,7 +398,6 @@ public class RepeatTemplate implements RepeatOperations { /** * Convenience method to execute after interceptors on a callback result. - * * @param context the current batch context. * @param value the result of the callback to process. */ @@ -452,8 +436,9 @@ public class RepeatTemplate implements RepeatOperations { /** * Delegate to {@link CompletionPolicy}. * @param context the current batch context. - * @return true if complete according to policy alone not including result value, else false. - * + * @return true if complete according to policy alone not including result value, else + * false. + * * @see org.springframework.batch.repeat.CompletionPolicy#isComplete(RepeatContext) */ protected boolean isComplete(RepeatContext context) { @@ -466,10 +451,9 @@ public class RepeatTemplate implements RepeatOperations { /** * Delegate to the {@link CompletionPolicy}. + * @return a {@link RepeatContext} object that can be used by the implementation to + * store internal state for a batch step. * - * @return a {@link RepeatContext} object that can be used by the implementation to store - * internal state for a batch step. - * * @see org.springframework.batch.repeat.CompletionPolicy#start(RepeatContext) */ protected RepeatContext start() { @@ -483,7 +467,7 @@ public class RepeatTemplate implements RepeatOperations { /** * Delegate to the {@link CompletionPolicy}. * @param context the value returned by start. - * + * * @see org.springframework.batch.repeat.CompletionPolicy#update(RepeatContext) */ protected void update(RepeatContext context) { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/ResultHolder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/ResultHolder.java index 679a8799a..3abd45ef5 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/ResultHolder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/ResultHolder.java @@ -20,24 +20,23 @@ import org.springframework.batch.repeat.RepeatStatus; import org.springframework.batch.repeat.RepeatContext; /** - * Interface for result holder. - * + * Interface for result holder. + * * @author Dave Syer */ interface ResultHolder { + /** - * Get the result for client from this holder. Does not block if none is - * available yet. - * + * Get the result for client from this holder. Does not block if none is available + * yet. * @return the result, or null if there is none. * @throws IllegalStateException */ RepeatStatus getResult(); /** - * Get the error for client from this holder if any. Does not block if - * none is available yet. - * + * Get the error for client from this holder if any. Does not block if none is + * available yet. * @return the error, or null if there is none. * @throws IllegalStateException */ @@ -45,8 +44,8 @@ interface ResultHolder { /** * Get the context in which the result evaluation is executing. - * * @return the context of the result evaluation. */ RepeatContext getContext(); + } \ No newline at end of file diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/ResultHolderResultQueue.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/ResultHolderResultQueue.java index f8248475f..c2c3be7b1 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/ResultHolderResultQueue.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/ResultHolderResultQueue.java @@ -25,9 +25,9 @@ import java.util.concurrent.PriorityBlockingQueue; import java.util.concurrent.Semaphore; /** - * An implementation of the {@link ResultQueue} that throttles the number of - * expected results, limiting it to a maximum at any given time. - * + * An implementation of the {@link ResultQueue} that throttles the number of expected + * results, limiting it to a maximum at any given time. + * * @author Dave Syer */ public class ResultHolderResultQueue implements ResultQueue { @@ -43,25 +43,25 @@ public class ResultHolderResultQueue implements ResultQueue { private volatile int count = 0; /** - * @param throttleLimit the maximum number of results that can be expected - * at any given time. + * @param throttleLimit the maximum number of results that can be expected at any + * given time. */ public ResultHolderResultQueue(int throttleLimit) { results = new PriorityBlockingQueue<>(throttleLimit, new ResultHolderComparator()); waits = new Semaphore(throttleLimit); } - @Override + @Override public boolean isEmpty() { return results.isEmpty(); } /* * (non-Javadoc) - * + * * @see org.springframework.batch.repeat.support.ResultQueue#isExpecting() */ - @Override + @Override public boolean isExpecting() { // Base the decision about whether we expect more results on a // counter of the number of expected results actually collected. @@ -70,13 +70,12 @@ public class ResultHolderResultQueue implements ResultQueue { } /** - * Tell the queue to expect one more result. Blocks until a new result is - * available if already expecting too many (as determined by the throttle - * limit). - * + * Tell the queue to expect one more result. Blocks until a new result is available if + * already expecting too many (as determined by the throttle limit). + * * @see ResultQueue#expect() */ - @Override + @Override public void expect() throws InterruptedException { waits.acquire(); // Don't acquire the lock in a synchronized block - might deadlock @@ -85,7 +84,7 @@ public class ResultHolderResultQueue implements ResultQueue { } } - @Override + @Override public void put(ResultHolder holder) throws IllegalArgumentException { if (!isExpecting()) { throw new IllegalArgumentException("Not expecting a result. Call expect() before put()."); @@ -116,10 +115,10 @@ public class ResultHolderResultQueue implements ResultQueue { *
    • Not expecting.
    • *
    • Interrupted.
    • * - * + * * @see ResultQueue#take() */ - @Override + @Override public ResultHolder take() throws NoSuchElementException, InterruptedException { if (!isExpecting()) { throw new NoSuchElementException("Not expecting a result. Call expect() before take()."); @@ -150,12 +149,13 @@ public class ResultHolderResultQueue implements ResultQueue { /** * Compares ResultHolders so that one that is continuable ranks lowest. - * + * * @author Dave Syer - * + * */ private static class ResultHolderComparator implements Comparator { - @Override + + @Override public int compare(ResultHolder h1, ResultHolder h2) { RepeatStatus result1 = h1.getResult(); RepeatStatus result2 = h2.getResult(); @@ -177,6 +177,7 @@ public class ResultHolderResultQueue implements ResultQueue { } return 1; } + } } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/ResultQueue.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/ResultQueue.java index c89dfbdee..0a8e02c45 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/ResultQueue.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/ResultQueue.java @@ -23,12 +23,11 @@ import org.springframework.core.task.TaskExecutor; /** * Abstraction for queue of {@link ResultHolder} objects. Acts a bit likeT a - * {@link BlockingQueue} with the ability to count the number of items it - * expects to ever hold. When clients schedule an item to be added they call - * {@link #expect()}, and then collect the result later with {@link #take()}. - * Result providers in another thread call {@link #put(Object)} to notify the - * expecting client of a new result. - * + * {@link BlockingQueue} with the ability to count the number of items it expects to ever + * hold. When clients schedule an item to be added they call {@link #expect()}, and then + * collect the result later with {@link #take()}. Result providers in another thread call + * {@link #put(Object)} to notify the expecting client of a new result. + * * @author Dave Syer * @author Ben Hale */ @@ -36,55 +35,46 @@ interface ResultQueue { /** * In a manager-worker pattern, the manager calls this method paired with - * {@link #take()} to manage the flow of items. Normally a task is submitted - * for processing in another thread, at which point the manager uses this - * method to keep track of the number of expected results. It has the - * personality of an counter increment, rather than a work queue, which is - * usually managed elsewhere, e.g. by a {@link TaskExecutor}.

      - * Implementations may choose to block here, if they need to limit the - * number or rate of tasks being submitted. - * + * {@link #take()} to manage the flow of items. Normally a task is submitted for + * processing in another thread, at which point the manager uses this method to keep + * track of the number of expected results. It has the personality of an counter + * increment, rather than a work queue, which is usually managed elsewhere, e.g. by a + * {@link TaskExecutor}.
      + *
      + * Implementations may choose to block here, if they need to limit the number or rate + * of tasks being submitted. * @throws InterruptedException if the call blocks and is then interrupted. */ void expect() throws InterruptedException; /** - * Once it is expecting a result, clients call this method to satisfy the - * expectation. In a manager-worker pattern, the workers call this method to - * deposit the result of a finished task on the queue for collection. - * + * Once it is expecting a result, clients call this method to satisfy the expectation. + * In a manager-worker pattern, the workers call this method to deposit the result of + * a finished task on the queue for collection. * @param result the result for later collection. - * - * @throws IllegalArgumentException if the queue is not expecting a new - * result + * @throws IllegalArgumentException if the queue is not expecting a new result */ void put(T result) throws IllegalArgumentException; /** * Gets the next available result, blocking if there are none yet available. - * * @return a result previously deposited - * * @throws NoSuchElementException if there is no result expected - * @throws InterruptedException if the operation is interrupted while - * waiting + * @throws InterruptedException if the operation is interrupted while waiting */ T take() throws NoSuchElementException, InterruptedException; /** * Used by manager thread to verify that there are results available from * {@link #take()} without possibly having to block and wait. - * * @return true if there are no results available */ boolean isEmpty(); /** - * Check if any results are expected. Usually used by manager thread to drain - * queue when it is finished. - * - * @return true if more results are expected, but possibly not yet - * available. + * Check if any results are expected. Usually used by manager thread to drain queue + * when it is finished. + * @return true if more results are expected, but possibly not yet available. */ public boolean isExpecting(); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/TaskExecutorRepeatTemplate.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/TaskExecutorRepeatTemplate.java index 8737033d9..e80e3c75a 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/TaskExecutorRepeatTemplate.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/TaskExecutorRepeatTemplate.java @@ -26,33 +26,31 @@ import org.springframework.core.task.TaskExecutor; import org.springframework.util.Assert; /** - * Provides {@link RepeatOperations} support including interceptors that can be - * used to modify or monitor the behaviour at run time.
      - * - * This implementation is sufficient to be used to configure transactional - * behaviour for each item by making the {@link RepeatCallback} transactional, - * or for the whole batch by making the execute method transactional (but only - * then if the task executor is synchronous).
      - * + * Provides {@link RepeatOperations} support including interceptors that can be used to + * modify or monitor the behaviour at run time.
      + * + * This implementation is sufficient to be used to configure transactional behaviour for + * each item by making the {@link RepeatCallback} transactional, or for the whole batch by + * making the execute method transactional (but only then if the task executor is + * synchronous).
      + * * This class is thread-safe if its collaborators are thread-safe (interceptors, - * terminationPolicy, callback). Normally this will be the case, but clients - * need to be aware that if the task executor is asynchronous, then the other - * collaborators should be also. In particular the {@link RepeatCallback} that - * is wrapped in the execute method must be thread-safe - often it is based on - * some form of data source, which itself should be both thread-safe and - * transactional (multiple threads could be accessing it at any given time, and - * each thread would have its own transaction).
      - * + * terminationPolicy, callback). Normally this will be the case, but clients need to be + * aware that if the task executor is asynchronous, then the other collaborators should be + * also. In particular the {@link RepeatCallback} that is wrapped in the execute method + * must be thread-safe - often it is based on some form of data source, which itself + * should be both thread-safe and transactional (multiple threads could be accessing it at + * any given time, and each thread would have its own transaction).
      + * * @author Dave Syer - * + * */ public class TaskExecutorRepeatTemplate extends RepeatTemplate { /** - * Default limit for maximum number of concurrent unfinished results allowed - * by the template. - * {@link #getNextResult(RepeatContext, RepeatCallback, RepeatInternalState)} - * . + * Default limit for maximum number of concurrent unfinished results allowed by the + * template. + * {@link #getNextResult(RepeatContext, RepeatCallback, RepeatInternalState)} . */ public static final int DEFAULT_THROTTLE_LIMIT = 4; @@ -61,15 +59,14 @@ public class TaskExecutorRepeatTemplate extends RepeatTemplate { private TaskExecutor taskExecutor = new SyncTaskExecutor(); /** - * Public setter for the throttle limit. The throttle limit is the largest - * number of concurrent tasks that can be executing at one time - if a new - * task arrives and the throttle limit is breached we wait for one of the - * executing tasks to finish before submitting the new one to the - * {@link TaskExecutor}. Default value is {@link #DEFAULT_THROTTLE_LIMIT}. - * N.B. when used with a thread pooled {@link TaskExecutor} the thread pool - * might prevent the throttle limit actually being reached (so make the core - * pool size larger than the throttle limit if possible). - * + * Public setter for the throttle limit. The throttle limit is the largest number of + * concurrent tasks that can be executing at one time - if a new task arrives and the + * throttle limit is breached we wait for one of the executing tasks to finish before + * submitting the new one to the {@link TaskExecutor}. Default value is + * {@link #DEFAULT_THROTTLE_LIMIT}. N.B. when used with a thread pooled + * {@link TaskExecutor} the thread pool might prevent the throttle limit actually + * being reached (so make the core pool size larger than the throttle limit if + * possible). * @param throttleLimit the throttleLimit to set. */ public void setThrottleLimit(int throttleLimit) { @@ -78,7 +75,6 @@ public class TaskExecutorRepeatTemplate extends RepeatTemplate { /** * Setter for task executor to be used to run the individual item callbacks. - * * @param taskExecutor a TaskExecutor * @throws IllegalArgumentException if the argument is null */ @@ -88,14 +84,14 @@ public class TaskExecutorRepeatTemplate extends RepeatTemplate { } /** - * Use the {@link #setTaskExecutor(TaskExecutor)} to generate a result. The - * internal state in this case is a queue of unfinished result holders of - * type {@link ResultHolder}. The holder with the return value should not be - * on the queue when this method exits. The queue is scoped in the calling - * method so there is no need to synchronize access. - * + * Use the {@link #setTaskExecutor(TaskExecutor)} to generate a result. The internal + * state in this case is a queue of unfinished result holders of type + * {@link ResultHolder}. The holder with the return value should not be on the queue + * when this method exits. The queue is scoped in the calling method so there is no + * need to synchronize access. + * */ - @Override + @Override protected RepeatStatus getNextResult(RepeatContext context, RepeatCallback callback, RepeatInternalState state) throws Throwable { @@ -106,16 +102,15 @@ public class TaskExecutorRepeatTemplate extends RepeatTemplate { do { /* - * Wrap the callback in a runnable that will add its result to the - * queue when it is ready. + * Wrap the callback in a runnable that will add its result to the queue when + * it is ready. */ runnable = new ExecutingRunnable(callback, context, queue); /** - * Tell the runnable that it can expect a result. This could have - * been in-lined with the constructor, but it might block, so it's - * better to do it here, since we have the option (it's a private - * class). + * Tell the runnable that it can expect a result. This could have been + * in-lined with the constructor, but it might block, so it's better to do it + * here, since we have the option (it's a private class). */ runnable.expect(); @@ -125,21 +120,20 @@ public class TaskExecutorRepeatTemplate extends RepeatTemplate { taskExecutor.execute(runnable); /* - * Allow termination policy to update its state. This must happen - * immediately before or after the call to the task executor. + * Allow termination policy to update its state. This must happen immediately + * before or after the call to the task executor. */ update(context); /* - * Keep going until we get a result that is finished, or early - * termination... + * Keep going until we get a result that is finished, or early termination... */ - } while (queue.isEmpty() && !isComplete(context)); + } + while (queue.isEmpty() && !isComplete(context)); /* - * N.B. If the queue is empty then take() blocks until a result appears, - * and there must be at least one because we just submitted one to the - * task executor. + * N.B. If the queue is empty then take() blocks until a result appears, and there + * must be at least one because we just submitted one to the task executor. */ ResultHolder result = queue.take(); if (result.getError() != null) { @@ -149,12 +143,12 @@ public class TaskExecutorRepeatTemplate extends RepeatTemplate { } /** - * Wait for all the results to appear on the queue and execute the after - * interceptors for each one. - * + * Wait for all the results to appear on the queue and execute the after interceptors + * for each one. + * * @see org.springframework.batch.repeat.support.RepeatTemplate#waitForResults(org.springframework.batch.repeat.support.RepeatInternalState) */ - @Override + @Override protected boolean waitForResults(RepeatInternalState state) { ResultQueue queue = ((ResultQueueInternalState) state).getResultQueue(); @@ -164,8 +158,8 @@ public class TaskExecutorRepeatTemplate extends RepeatTemplate { while (queue.isExpecting()) { /* - * Careful that no runnables that are not going to finish ever get - * onto the queue, else this may block forever. + * Careful that no runnables that are not going to finish ever get onto the + * queue, else this may block forever. */ ResultHolder future; try { @@ -193,7 +187,7 @@ public class TaskExecutorRepeatTemplate extends RepeatTemplate { return result; } - @Override + @Override protected RepeatInternalState createInternalState(RepeatContext context) { // Queue of pending results: return new ResultQueueInternalState(throttleLimit); @@ -201,9 +195,9 @@ public class TaskExecutorRepeatTemplate extends RepeatTemplate { /** * A runnable that puts its result on a queue when it is done. - * + * * @author Dave Syer - * + * */ private class ExecutingRunnable implements Runnable, ResultHolder { @@ -241,12 +235,12 @@ public class TaskExecutorRepeatTemplate extends RepeatTemplate { } /** - * Execute the batch callback, and store the result, or any exception - * that is thrown for retrieval later by caller. - * + * Execute the batch callback, and store the result, or any exception that is + * thrown for retrieval later by caller. + * * @see java.lang.Runnable#run() */ - @Override + @Override public void run() { boolean clearContext = false; try { @@ -277,19 +271,19 @@ public class TaskExecutorRepeatTemplate extends RepeatTemplate { } /** - * Get the result - never blocks because the queue manages waiting for - * the task to finish. + * Get the result - never blocks because the queue manages waiting for the task to + * finish. */ - @Override + @Override public RepeatStatus getResult() { return result; } /** - * Get the error - never blocks because the queue manages waiting for - * the task to finish. + * Get the error - never blocks because the queue manages waiting for the task to + * finish. */ - @Override + @Override public Throwable getError() { return error; } @@ -297,7 +291,7 @@ public class TaskExecutorRepeatTemplate extends RepeatTemplate { /** * Getter for the context. */ - @Override + @Override public RepeatContext getContext() { return this.context; } @@ -306,7 +300,7 @@ public class TaskExecutorRepeatTemplate extends RepeatTemplate { /** * @author Dave Syer - * + * */ private static class ResultQueueInternalState extends RepeatInternalStateSupport { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/ThrottleLimitResultQueue.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/ThrottleLimitResultQueue.java index dd764c443..8b3f1069a 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/ThrottleLimitResultQueue.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/ThrottleLimitResultQueue.java @@ -22,9 +22,9 @@ import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.Semaphore; /** - * An implementation of the {@link ResultQueue} that throttles the number of - * expected results, limiting it to a maximum at any given time. - * + * An implementation of the {@link ResultQueue} that throttles the number of expected + * results, limiting it to a maximum at any given time. + * * @author Dave Syer */ public class ThrottleLimitResultQueue implements ResultQueue { @@ -40,40 +40,39 @@ public class ThrottleLimitResultQueue implements ResultQueue { private volatile int count = 0; /** - * @param throttleLimit the maximum number of results that can be expected - * at any given time. + * @param throttleLimit the maximum number of results that can be expected at any + * given time. */ public ThrottleLimitResultQueue(int throttleLimit) { results = new LinkedBlockingQueue<>(); waits = new Semaphore(throttleLimit); } - @Override + @Override public boolean isEmpty() { return results.isEmpty(); } /* * (non-Javadoc) - * + * * @see org.springframework.batch.repeat.support.ResultQueue#isExpecting() */ - @Override + @Override public boolean isExpecting() { // Base the decision about whether we expect more results on a // counter of the number of expected results actually collected. - // Do not synchronize! Otherwise put and expect can deadlock. + // Do not synchronize! Otherwise put and expect can deadlock. return count > 0; } /** - * Tell the queue to expect one more result. Blocks until a new result is - * available if already expecting too many (as determined by the throttle - * limit). - * + * Tell the queue to expect one more result. Blocks until a new result is available if + * already expecting too many (as determined by the throttle limit). + * * @see ResultQueue#expect() */ - @Override + @Override public void expect() throws InterruptedException { synchronized (lock) { waits.acquire(); @@ -81,7 +80,7 @@ public class ThrottleLimitResultQueue implements ResultQueue { } } - @Override + @Override public void put(T holder) throws IllegalArgumentException { if (!isExpecting()) { throw new IllegalArgumentException("Not expecting a result. Call expect() before put()."); @@ -93,7 +92,7 @@ public class ThrottleLimitResultQueue implements ResultQueue { waits.release(); } - @Override + @Override public T take() throws NoSuchElementException, InterruptedException { if (!isExpecting()) { throw new NoSuchElementException("Not expecting a result. Call expect() before take()."); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/AnnotationMethodResolver.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/AnnotationMethodResolver.java index 33f420114..819ca280e 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/AnnotationMethodResolver.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/AnnotationMethodResolver.java @@ -30,44 +30,37 @@ import org.springframework.util.ObjectUtils; import org.springframework.util.ReflectionUtils; /** - * {@link MethodResolver} implementation that finds a single Method on the - * given Class that contains the specified annotation type. - * + * {@link MethodResolver} implementation that finds a single Method on the given + * Class that contains the specified annotation type. + * * @author Mark Fisher */ public class AnnotationMethodResolver implements MethodResolver { private Class annotationType; - /** * Create a {@link MethodResolver} for the specified Method-level annotation type. - * * @param annotationType establish the annotation to be used. */ public AnnotationMethodResolver(Class annotationType) { Assert.notNull(annotationType, "annotationType must not be null"); - Assert.isTrue(ObjectUtils.containsElement( - annotationType.getAnnotation(Target.class).value(), ElementType.METHOD), + Assert.isTrue( + ObjectUtils.containsElement(annotationType.getAnnotation(Target.class).value(), ElementType.METHOD), "Annotation [" + annotationType + "] is not a Method-level annotation."); this.annotationType = annotationType; } - /** - * Find a single Method on the Class of the given candidate object - * that contains the annotation type for which this resolver is searching. - * - * @param candidate the instance whose Class will be checked for the + * Find a single Method on the Class of the given candidate object that + * contains the annotation type for which this resolver is searching. + * @param candidate the instance whose Class will be checked for the annotation + * @return a single matching Method instance or null if the candidate's + * Class contains no Methods with the specified annotation + * @throws IllegalArgumentException if more than one Method has the specified * annotation - * - * @return a single matching Method instance or null if the - * candidate's Class contains no Methods with the specified annotation - * - * @throws IllegalArgumentException if more than one Method has the - * specified annotation */ - @Nullable + @Nullable @Override public Method findMethod(Object candidate) { Assert.notNull(candidate, "candidate object must not be null"); @@ -79,29 +72,26 @@ public class AnnotationMethodResolver implements MethodResolver { } /** - * Find a single Method on the given Class that contains the - * annotation type for which this resolver is searching. - * + * Find a single Method on the given Class that contains the annotation type + * for which this resolver is searching. * @param clazz the Class instance to check for the annotation - * - * @return a single matching Method instance or null if the - * Class contains no Methods with the specified annotation - * - * @throws IllegalArgumentException if more than one Method has the - * specified annotation + * @return a single matching Method instance or null if the Class + * contains no Methods with the specified annotation + * @throws IllegalArgumentException if more than one Method has the specified + * annotation */ - @Nullable + @Nullable @Override public Method findMethod(final Class clazz) { Assert.notNull(clazz, "class must not be null"); final AtomicReference annotatedMethod = new AtomicReference<>(); ReflectionUtils.doWithMethods(clazz, new ReflectionUtils.MethodCallback() { - @Override + @Override public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException { Annotation annotation = AnnotationUtils.findAnnotation(method, annotationType); if (annotation != null) { - Assert.isNull(annotatedMethod.get(), "found more than one method on target class [" - + clazz + "] with the annotation type [" + annotationType + "]"); + Assert.isNull(annotatedMethod.get(), "found more than one method on target class [" + clazz + + "] with the annotation type [" + annotationType + "]"); annotatedMethod.set(method); } } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/DatabaseType.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/DatabaseType.java index 0033efd73..e57f2ada6 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/DatabaseType.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/DatabaseType.java @@ -25,42 +25,30 @@ import java.sql.DatabaseMetaData; import java.util.HashMap; import java.util.Map; - /** - * Enum representing a database type, such as DB2 or oracle. The type also - * contains a product name, which is expected to be the same as the product name - * provided by the database driver's metadata. + * Enum representing a database type, such as DB2 or oracle. The type also contains a + * product name, which is expected to be the same as the product name provided by the + * database driver's metadata. * * @author Lucas Ward * @since 2.0 */ public enum DatabaseType { - DERBY("Apache Derby"), - DB2("DB2"), - DB2VSE("DB2VSE"), - DB2ZOS("DB2ZOS"), - DB2AS400("DB2AS400"), - HSQL("HSQL Database Engine"), - SQLSERVER("Microsoft SQL Server"), - MYSQL("MySQL"), - ORACLE("Oracle"), - POSTGRES("PostgreSQL"), - SYBASE("Sybase"), - H2("H2"), - SQLITE("SQLite"), - HANA("HDB"); + DERBY("Apache Derby"), DB2("DB2"), DB2VSE("DB2VSE"), DB2ZOS("DB2ZOS"), DB2AS400("DB2AS400"), + HSQL("HSQL Database Engine"), SQLSERVER("Microsoft SQL Server"), MYSQL("MySQL"), ORACLE("Oracle"), + POSTGRES("PostgreSQL"), SYBASE("Sybase"), H2("H2"), SQLITE("SQLite"), HANA("HDB"); private static final Map nameMap; - static{ + static { nameMap = new HashMap<>(); - for(DatabaseType type: values()){ + for (DatabaseType type : values()) { nameMap.put(type.getProductName(), type); } } - //A description is necessary due to the nature of database descriptions - //in metadata. + // A description is necessary due to the nature of database descriptions + // in metadata. private final String productName; private DatabaseType(String productName) { @@ -73,46 +61,43 @@ public enum DatabaseType { /** * Static method to obtain a DatabaseType from the provided product name. - * * @param productName {@link String} containing the product name. * @return the {@link DatabaseType} for given product name. - * * @throws IllegalArgumentException if none is found. */ - public static DatabaseType fromProductName(String productName){ - if(productName.equals("MariaDB")) + public static DatabaseType fromProductName(String productName) { + if (productName.equals("MariaDB")) productName = "MySQL"; - if(!nameMap.containsKey(productName)){ - throw new IllegalArgumentException("DatabaseType not found for product name: [" + - productName + "]"); + if (!nameMap.containsKey(productName)) { + throw new IllegalArgumentException("DatabaseType not found for product name: [" + productName + "]"); } - else{ + else { return nameMap.get(productName); } } /** - * Convenience method that pulls a database product name from the DataSource's metadata. - * + * Convenience method that pulls a database product name from the DataSource's + * metadata. * @param dataSource {@link DataSource} to the database to be used. * @return {@link DatabaseType} for the {@link DataSource} specified. - * * @throws MetaDataAccessException thrown if error occured during Metadata lookup. */ public static DatabaseType fromMetaData(DataSource dataSource) throws MetaDataAccessException { - String databaseProductName = - JdbcUtils.extractDatabaseMetaData(dataSource, DatabaseMetaData::getDatabaseProductName); + String databaseProductName = JdbcUtils.extractDatabaseMetaData(dataSource, + DatabaseMetaData::getDatabaseProductName); if (StringUtils.hasText(databaseProductName) && databaseProductName.startsWith("DB2")) { - String databaseProductVersion = - JdbcUtils.extractDatabaseMetaData(dataSource, DatabaseMetaData::getDatabaseProductVersion); + String databaseProductVersion = JdbcUtils.extractDatabaseMetaData(dataSource, + DatabaseMetaData::getDatabaseProductVersion); if (databaseProductVersion.startsWith("ARI")) { databaseProductName = "DB2VSE"; } else if (databaseProductVersion.startsWith("DSN")) { databaseProductName = "DB2ZOS"; } - else if (databaseProductName.contains("AS") && (databaseProductVersion.startsWith("QSQ") || - databaseProductVersion.substring(databaseProductVersion.indexOf('V')).matches("V\\dR\\d[mM]\\d"))) { + else if (databaseProductName.contains("AS") + && (databaseProductVersion.startsWith("QSQ") || databaseProductVersion + .substring(databaseProductVersion.indexOf('V')).matches("V\\dR\\d[mM]\\d"))) { databaseProductName = "DB2AS400"; } else { @@ -124,4 +109,5 @@ public enum DatabaseType { } return fromProductName(databaseProductName); } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/DefaultPropertyEditorRegistrar.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/DefaultPropertyEditorRegistrar.java index 42389382d..0b9a0f645 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/DefaultPropertyEditorRegistrar.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/DefaultPropertyEditorRegistrar.java @@ -26,15 +26,14 @@ import org.springframework.beans.factory.config.CustomEditorConfigurer; import org.springframework.util.ClassUtils; /** - * A re-usable {@link PropertyEditorRegistrar} that can be used wherever one - * needs to register custom {@link PropertyEditor} instances with a - * {@link PropertyEditorRegistry} (like a bean wrapper, or a type converter). It - * is not thread safe, but useful where one is confident that binding or - * initialisation can only be single threaded (e.g in a standalone application - * with no threads). - * + * A re-usable {@link PropertyEditorRegistrar} that can be used wherever one needs to + * register custom {@link PropertyEditor} instances with a {@link PropertyEditorRegistry} + * (like a bean wrapper, or a type converter). It is not thread safe, but useful + * where one is confident that binding or initialisation can only be single threaded (e.g + * in a standalone application with no threads). + * * @author Dave Syer - * + * */ public class DefaultPropertyEditorRegistrar implements PropertyEditorRegistrar { @@ -42,10 +41,10 @@ public class DefaultPropertyEditorRegistrar implements PropertyEditorRegistrar { /** * Register the custom editors with the given registry. - * + * * @see org.springframework.beans.PropertyEditorRegistrar#registerCustomEditors(org.springframework.beans.PropertyEditorRegistry) */ - @Override + @Override public void registerCustomEditors(PropertyEditorRegistry registry) { if (this.customEditors != null) { for (Entry, PropertyEditor> entry : customEditors.entrySet()) { @@ -56,8 +55,6 @@ public class DefaultPropertyEditorRegistrar implements PropertyEditorRegistrar { /** * Specify the {@link PropertyEditor custom editors} to register. - * - * * @param customEditors a map of Class to PropertyEditor (or class name to * PropertyEditor). * @see CustomEditorConfigurer#setCustomEditors(Map) @@ -75,8 +72,8 @@ public class DefaultPropertyEditorRegistrar implements PropertyEditorRegistrar { requiredType = ClassUtils.resolveClassName(className, getClass().getClassLoader()); } else { - throw new IllegalArgumentException("Invalid key [" + key - + "] for custom editor: needs to be Class or String."); + throw new IllegalArgumentException( + "Invalid key [" + key + "] for custom editor: needs to be Class or String."); } PropertyEditor value = entry.getValue(); this.customEditors.put(requiredType, value); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/IntArrayPropertyEditor.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/IntArrayPropertyEditor.java index 140b75b7b..5325de05d 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/IntArrayPropertyEditor.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/IntArrayPropertyEditor.java @@ -22,7 +22,7 @@ import org.springframework.util.StringUtils; public class IntArrayPropertyEditor extends PropertyEditorSupport { - @Override + @Override public void setAsText(String text) throws IllegalArgumentException { String[] strs = StringUtils.commaDelimitedListToStringArray(text); int[] value = new int[strs.length]; @@ -31,5 +31,5 @@ public class IntArrayPropertyEditor extends PropertyEditorSupport { } setValue(value); } - + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/LastModifiedResourceComparator.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/LastModifiedResourceComparator.java index 658e5432e..162a9c294 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/LastModifiedResourceComparator.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/LastModifiedResourceComparator.java @@ -1,54 +1,53 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.support; - -import java.io.IOException; -import java.util.Comparator; - -import org.springframework.core.io.Resource; -import org.springframework.util.Assert; - -/** - * Comparator to sort resources by the file last modified time. - * - * @author Dave Syer - * - */ -public class LastModifiedResourceComparator implements Comparator { - - /** - * Compare the two resources by last modified time, so that a sorted list of - * resources will have oldest first. - * - * @throws IllegalArgumentException if one of the resources doesn't exist or - * its last modified date cannot be determined - * - * @see Comparator#compare(Object, Object) - */ - @Override - public int compare(Resource r1, Resource r2) { - Assert.isTrue(r1.exists(), "Resource does not exist: " + r1); - Assert.isTrue(r2.exists(), "Resource does not exist: " + r2); - try { - long diff = r1.getFile().lastModified() - r2.getFile().lastModified(); - return diff > 0 ? 1 : diff < 0 ? -1 : 0; - } - catch (IOException e) { - throw new IllegalArgumentException("Resource modification times cannot be determined (unexpected).", e); - } - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.support; + +import java.io.IOException; +import java.util.Comparator; + +import org.springframework.core.io.Resource; +import org.springframework.util.Assert; + +/** + * Comparator to sort resources by the file last modified time. + * + * @author Dave Syer + * + */ +public class LastModifiedResourceComparator implements Comparator { + + /** + * Compare the two resources by last modified time, so that a sorted list of resources + * will have oldest first. + * @throws IllegalArgumentException if one of the resources doesn't exist or its last + * modified date cannot be determined + * + * @see Comparator#compare(Object, Object) + */ + @Override + public int compare(Resource r1, Resource r2) { + Assert.isTrue(r1.exists(), "Resource does not exist: " + r1); + Assert.isTrue(r2.exists(), "Resource does not exist: " + r2); + try { + long diff = r1.getFile().lastModified() - r2.getFile().lastModified(); + return diff > 0 ? 1 : diff < 0 ? -1 : 0; + } + catch (IOException e) { + throw new IllegalArgumentException("Resource modification times cannot be determined (unexpected).", e); + } + } + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/MethodInvoker.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/MethodInvoker.java index fb14ec07d..16d95c709 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/MethodInvoker.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/MethodInvoker.java @@ -19,15 +19,14 @@ package org.springframework.batch.support; import org.springframework.lang.Nullable; /** - * A strategy interface for invoking a method. - * Typically used by adapters. - * + * A strategy interface for invoking a method. Typically used by adapters. + * * @author Mark Fisher * @author Mahmoud Ben Hassine */ public interface MethodInvoker { @Nullable - Object invokeMethod(Object ... args); + Object invokeMethod(Object... args); } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/MethodInvokerUtils.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/MethodInvokerUtils.java index 9a5001801..febfe44e2 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/MethodInvokerUtils.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/MethodInvokerUtils.java @@ -30,7 +30,7 @@ import org.springframework.util.ReflectionUtils; /** * Utility methods for create MethodInvoker instances. - * + * * @author Lucas Ward * @since 2.0 */ @@ -38,11 +38,10 @@ public class MethodInvokerUtils { /** * Create a {@link MethodInvoker} using the provided method name to search. - * * @param object to be invoked * @param methodName of the method to be invoked - * @param paramsRequired boolean indicating whether the parameters are - * required, if false, a no args version of the method will be searched for. + * @param paramsRequired boolean indicating whether the parameters are required, if + * false, a no args version of the method will be searched for. * @param paramTypes - parameter types of the method to search for. * @return MethodInvoker if the method is found, null if it is not. */ @@ -65,7 +64,6 @@ public class MethodInvokerUtils { /** * Create a String representation of the array of parameter types. - * * @param paramTypes types of the parameters to be used * @return String a String representation of those types */ @@ -81,9 +79,8 @@ public class MethodInvokerUtils { } /** - * Create a {@link MethodInvoker} using the provided interface, and method - * name from that interface. - * + * Create a {@link MethodInvoker} using the provided interface, and method name from + * that interface. * @param cls the interface to search for the method named * @param methodName of the method to be invoked * @param object to be invoked @@ -102,9 +99,8 @@ public class MethodInvokerUtils { } /** - * Create a MethodInvoker from the delegate based on the annotationType. - * Ensure that the annotated method has a valid set of parameters. - * + * Create a MethodInvoker from the delegate based on the annotationType. Ensure that + * the annotated method has a valid set of parameters. * @param annotationType the annotation to scan for * @param target the target object * @param expectedParamTypes the expected parameter types for the method @@ -113,8 +109,8 @@ public class MethodInvokerUtils { public static MethodInvoker getMethodInvokerByAnnotation(final Class annotationType, final Object target, final Class... expectedParamTypes) { MethodInvoker mi = MethodInvokerUtils.getMethodInvokerByAnnotation(annotationType, target); - final Class targetClass = (target instanceof Advised) ? ((Advised) target).getTargetSource() - .getTargetClass() : target.getClass(); + final Class targetClass = (target instanceof Advised) ? ((Advised) target).getTargetSource().getTargetClass() + : target.getClass(); if (mi != null) { ReflectionUtils.doWithMethods(targetClass, method -> { Annotation annotation = AnnotationUtils.findAnnotation(method, annotationType); @@ -138,11 +134,9 @@ public class MethodInvokerUtils { } /** - * Create {@link MethodInvoker} for the method with the provided annotation - * on the provided object. Annotations that cannot be applied to methods - * (i.e. that aren't annotated with an element type of METHOD) will cause an - * exception to be thrown. - * + * Create {@link MethodInvoker} for the method with the provided annotation on the + * provided object. Annotations that cannot be applied to methods (i.e. that aren't + * annotated with an element type of METHOD) will cause an exception to be thrown. * @param annotationType to be searched for * @param target to be invoked * @return MethodInvoker for the provided annotation, null if none is found. @@ -151,10 +145,11 @@ public class MethodInvokerUtils { final Object target) { Assert.notNull(target, "Target must not be null"); Assert.notNull(annotationType, "AnnotationType must not be null"); - Assert.isTrue(ObjectUtils.containsElement(annotationType.getAnnotation(Target.class).value(), - ElementType.METHOD), "Annotation [" + annotationType + "] is not a Method-level annotation."); - final Class targetClass = (target instanceof Advised) ? ((Advised) target).getTargetSource() - .getTargetClass() : target.getClass(); + Assert.isTrue( + ObjectUtils.containsElement(annotationType.getAnnotation(Target.class).value(), ElementType.METHOD), + "Annotation [" + annotationType + "] is not a Method-level annotation."); + final Class targetClass = (target instanceof Advised) ? ((Advised) target).getTargetSource().getTargetClass() + : target.getClass(); if (targetClass == null) { // Proxy with no target cannot have annotations return null; @@ -163,9 +158,9 @@ public class MethodInvokerUtils { ReflectionUtils.doWithMethods(targetClass, method -> { Annotation annotation = AnnotationUtils.findAnnotation(method, annotationType); if (annotation != null) { - Assert.isNull(annotatedMethod.get(), "found more than one method on target class [" - + targetClass.getSimpleName() + "] with the annotation type [" - + annotationType.getSimpleName() + "]."); + Assert.isNull(annotatedMethod.get(), + "found more than one method on target class [" + targetClass.getSimpleName() + + "] with the annotation type [" + annotationType.getSimpleName() + "]."); annotatedMethod.set(method); } }); @@ -179,9 +174,7 @@ public class MethodInvokerUtils { } /** - * Create a {@link MethodInvoker} for the delegate from a single public - * method. - * + * Create a {@link MethodInvoker} for the delegate from a single public method. * @param target an object to search for an appropriate method. * @param the class. * @param the type. @@ -203,4 +196,5 @@ public class MethodInvokerUtils { Method method = methodHolder.get(); return new SimpleMethodInvoker(target, method); } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/MethodResolver.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/MethodResolver.java index b8b970697..d06ca4980 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/MethodResolver.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/MethodResolver.java @@ -22,39 +22,31 @@ import org.springframework.lang.Nullable; /** * Strategy interface for detecting a single Method on a Class. - * + * * @author Mark Fisher * @author Mahmoud Ben Hassine */ public interface MethodResolver { /** - * Find a single Method on the provided Object that matches this resolver's - * criteria. - * - * @param candidate the candidate Object whose Class should be searched for - * a Method - * - * @return a single Method or null if no Method matching this - * resolver's criteria can be found. - * - * @throws IllegalArgumentException if more than one Method defined on the - * given candidate's Class matches this resolver's criteria + * Find a single Method on the provided Object that matches this resolver's criteria. + * @param candidate the candidate Object whose Class should be searched for a Method + * @return a single Method or null if no Method matching this resolver's + * criteria can be found. + * @throws IllegalArgumentException if more than one Method defined on the given + * candidate's Class matches this resolver's criteria */ @Nullable Method findMethod(Object candidate) throws IllegalArgumentException; /** - * Find a single Method on the given Class that matches this - * resolver's criteria. - * + * Find a single Method on the given Class that matches this resolver's + * criteria. * @param clazz the Class instance on which to search for a Method - * - * @return a single Method or null if no Method matching this - * resolver's criteria can be found. - * - * @throws IllegalArgumentException if more than one Method defined on the - * given Class matches this resolver's criteria + * @return a single Method or null if no Method matching this resolver's + * criteria can be found. + * @throws IllegalArgumentException if more than one Method defined on the given Class + * matches this resolver's criteria */ @Nullable Method findMethod(Class clazz); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/PatternMatcher.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/PatternMatcher.java index f692a2550..f5f543440 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/PatternMatcher.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/PatternMatcher.java @@ -30,6 +30,7 @@ import org.springframework.util.Assert; public class PatternMatcher { private final Map map; + private final List sorted; /** @@ -45,12 +46,10 @@ public class PatternMatcher { } /** - * Lifted from AntPathMatcher in Spring Core. Tests whether or not a string - * matches against a pattern. The pattern may contain two special - * characters:
      + * Lifted from AntPathMatcher in Spring Core. Tests whether or not a string matches + * against a pattern. The pattern may contain two special characters:
      * '*' means zero or more characters
      * '?' means one and only one character - * * @param pattern pattern to match against. Must not be null. * @param str string which must be matched against the pattern. Must not be * null. @@ -183,20 +182,17 @@ public class PatternMatcher { /** *

      - * This method takes a String key and a map from Strings to values of any - * type. During processing, the method will identify the most specific key - * in the map that matches the line. Once the correct is identified, its - * value is returned. Note that if the map contains the wildcard string "*" - * as a key, then it will serve as the "default" case, matching every line - * that does not match anything else. - * + * This method takes a String key and a map from Strings to values of any type. During + * processing, the method will identify the most specific key in the map that matches + * the line. Once the correct is identified, its value is returned. Note that if the + * map contains the wildcard string "*" as a key, then it will serve as the "default" + * case, matching every line that does not match anything else. + * *

      - * If no matching prefix is found, a {@link IllegalStateException} will be - * thrown. - * + * If no matching prefix is found, a {@link IllegalStateException} will be thrown. + * *

      * Null keys are not allowed in the map. - * * @param line An input string * @return the value whose prefix matches the given line */ diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/PropertiesConverter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/PropertiesConverter.java index e7c1028b8..926b8ec4c 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/PropertiesConverter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/PropertiesConverter.java @@ -28,17 +28,16 @@ import org.springframework.util.PropertiesPersister; import org.springframework.util.StringUtils; /** - * Utility to convert a Properties object to a String and back. Ideally this - * utility should have been used to convert to string in order to convert that - * string back to a Properties Object. Attempting to convert a string obtained - * by calling Properties.toString() will return an invalid Properties object. - * The format of Properties is that used by {@link PropertiesPersister} from the - * Spring Core, so a String in the correct format for a Spring property editor - * is fine (key=value pairs separated by new lines). - * + * Utility to convert a Properties object to a String and back. Ideally this utility + * should have been used to convert to string in order to convert that string back to a + * Properties Object. Attempting to convert a string obtained by calling + * Properties.toString() will return an invalid Properties object. The format of + * Properties is that used by {@link PropertiesPersister} from the Spring Core, so a + * String in the correct format for a Spring property editor is fine (key=value pairs + * separated by new lines). + * * @author Lucas Ward * @author Dave Syer - * * @see PropertiesPersister */ public final class PropertiesConverter { @@ -52,12 +51,10 @@ public final class PropertiesConverter { } /** - * Parse a String to a Properties object. If string is null, an empty - * Properties object will be returned. The input String is a set of - * name=value pairs, delimited by either newline or comma (for brevity). If - * the input String contains a newline it is assumed that the separator is - * newline, otherwise comma. - * + * Parse a String to a Properties object. If string is null, an empty Properties + * object will be returned. The input String is a set of name=value pairs, delimited + * by either newline or comma (for brevity). If the input String contains a newline it + * is assumed that the separator is newline, otherwise comma. * @param stringToParse String to parse. * @return Properties parsed from each string. * @see PropertiesPersister @@ -69,8 +66,8 @@ public final class PropertiesConverter { } if (!contains(stringToParse, "\n")) { - stringToParse = StringUtils.arrayToDelimitedString( - StringUtils.commaDelimitedListToStringArray(stringToParse), "\n"); + stringToParse = StringUtils + .arrayToDelimitedString(StringUtils.commaDelimitedListToStringArray(stringToParse), "\n"); } StringReader stringReader = new StringReader(stringToParse); @@ -83,19 +80,18 @@ public final class PropertiesConverter { // so never in this case. } catch (IOException ex) { - throw new IllegalStateException("Error while trying to parse String to java.util.Properties," - + " given String: " + properties); + throw new IllegalStateException( + "Error while trying to parse String to java.util.Properties," + " given String: " + properties); } return properties; } /** - * Convert Properties object to String. This is only necessary for - * compatibility with converting the String back to a properties object. If - * an empty properties object is passed in, a blank string is returned, - * otherwise it's string representation is returned. - * + * Convert Properties object to String. This is only necessary for compatibility with + * converting the String back to a properties object. If an empty properties object is + * passed in, a blank string is returned, otherwise it's string representation is + * returned. * @param propertiesToParse contains the properties be converted. * @return String representation of properties object */ @@ -120,8 +116,8 @@ public final class PropertiesConverter { // comma-separated... String value = stringWriter.toString(); if (value.length() < 160) { - List list = Arrays.asList(StringUtils.delimitedListToStringArray(value, LINE_SEPARATOR, - LINE_SEPARATOR)); + List list = Arrays + .asList(StringUtils.delimitedListToStringArray(value, LINE_SEPARATOR, LINE_SEPARATOR)); String shortValue = StringUtils.collectionToCommaDelimitedString(list.subList(1, list.size())); int count = StringUtils.countOccurrencesOf(shortValue, ","); if (count == list.size() - 2) { @@ -137,4 +133,5 @@ public final class PropertiesConverter { private static boolean contains(String str, String searchStr) { return str.indexOf(searchStr) != -1; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/ReflectionUtils.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/ReflectionUtils.java index 4b0c64f14..849982522 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/ReflectionUtils.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/ReflectionUtils.java @@ -23,38 +23,40 @@ import java.util.Set; import org.springframework.core.annotation.AnnotationUtils; /** - * Provides reflection based utilities for Spring Batch that are not available - * via Spring Core + * Provides reflection based utilities for Spring Batch that are not available via Spring + * Core * * @author Michael Minella * @since 2.2.6 */ public class ReflectionUtils { - private ReflectionUtils() {} + private ReflectionUtils() { + } /** * Returns a {@link java.util.Set} of {@link java.lang.reflect.Method} instances that * are annotated with the annotation provided. - * * @param clazz The class to search for a method with the given annotation type * @param annotationType The type of annotation to look for - * @return a set of {@link java.lang.reflect.Method} instances if any are found, an empty set if not. + * @return a set of {@link java.lang.reflect.Method} instances if any are found, an + * empty set if not. */ @SuppressWarnings("rawtypes") public static final Set findMethod(Class clazz, Class annotationType) { - Method [] declaredMethods = org.springframework.util.ReflectionUtils.getAllDeclaredMethods(clazz); + Method[] declaredMethods = org.springframework.util.ReflectionUtils.getAllDeclaredMethods(clazz); Set results = new HashSet<>(); for (Method curMethod : declaredMethods) { Annotation annotation = AnnotationUtils.findAnnotation(curMethod, annotationType); - if(annotation != null) { + if (annotation != null) { results.add(curMethod); } } return results; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/SimpleMethodInvoker.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/SimpleMethodInvoker.java index fe16883a8..1903174e6 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/SimpleMethodInvoker.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/SimpleMethodInvoker.java @@ -40,11 +40,11 @@ import org.springframework.util.Assert; import org.springframework.util.ClassUtils; /** - * Simple implementation of the {@link MethodInvoker} interface that invokes a - * method on an object. If the method has no arguments, but arguments are - * provided, they are ignored and the method is invoked anyway. If there are - * more arguments than there are provided, then an exception is thrown. - * + * Simple implementation of the {@link MethodInvoker} interface that invokes a method on + * an object. If the method has no arguments, but arguments are provided, they are ignored + * and the method is invoked anyway. If there are more arguments than there are provided, + * then an exception is thrown. + * * @author Lucas Ward * @since 2.0 */ @@ -77,12 +77,11 @@ public class SimpleMethodInvoker implements MethodInvoker { /* * (non-Javadoc) - * - * @see - * org.springframework.batch.core.configuration.util.MethodInvoker#invokeMethod + * + * @see org.springframework.batch.core.configuration.util.MethodInvoker#invokeMethod * (java.lang.Object[]) */ - @Nullable + @Nullable @Override public Object invokeMethod(Object... args) { @@ -92,8 +91,8 @@ public class SimpleMethodInvoker implements MethodInvoker { invokeArgs = new Object[] {}; } else if (parameterTypes.length != args.length) { - throw new IllegalArgumentException("Wrong number of arguments, expected no more than: [" - + parameterTypes.length + "]"); + throw new IllegalArgumentException( + "Wrong number of arguments, expected no more than: [" + parameterTypes.length + "]"); } else { invokeArgs = args; @@ -152,4 +151,5 @@ public class SimpleMethodInvoker implements MethodInvoker { result = 31 * result + method.hashCode(); return result; } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/SystemPropertyInitializer.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/SystemPropertyInitializer.java index 8e0ea2e42..08e96b2eb 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/SystemPropertyInitializer.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/SystemPropertyInitializer.java @@ -1,72 +1,70 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.support; - -import org.springframework.beans.factory.InitializingBean; -import org.springframework.util.Assert; - -/** - * Helper class that sets up a System property with a default value. A System - * property is created with the specified key name, and default value (i.e. if - * the property already exists it is not changed). - * - * @author Dave Syer - * - */ -public class SystemPropertyInitializer implements InitializingBean { - - /** - * Name of system property used by default. - */ - public static final String ENVIRONMENT = "org.springframework.batch.support.SystemPropertyInitializer.ENVIRONMENT"; - - private String keyName = ENVIRONMENT; - - private String defaultValue; - - /** - * Set the key name for the System property that is created. Defaults to - * {@link #ENVIRONMENT}. - * - * @param keyName the key name to set - */ - public void setKeyName(String keyName) { - this.keyName = keyName; - } - - /** - * Mandatory property specifying the default value of the System property. - * - * @param defaultValue the default value to set - */ - public void setDefaultValue(String defaultValue) { - this.defaultValue = defaultValue; - } - - /** - * Sets the System property with the provided name and default value. - * - * @see InitializingBean#afterPropertiesSet() - */ - @Override - public void afterPropertiesSet() throws Exception { - Assert.state(defaultValue != null || System.getProperty(keyName) != null, - "Either a default value must be specified or the value should already be set for System property: " - + keyName); - System.setProperty(keyName, System.getProperty(keyName, defaultValue)); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.support; + +import org.springframework.beans.factory.InitializingBean; +import org.springframework.util.Assert; + +/** + * Helper class that sets up a System property with a default value. A System property is + * created with the specified key name, and default value (i.e. if the property already + * exists it is not changed). + * + * @author Dave Syer + * + */ +public class SystemPropertyInitializer implements InitializingBean { + + /** + * Name of system property used by default. + */ + public static final String ENVIRONMENT = "org.springframework.batch.support.SystemPropertyInitializer.ENVIRONMENT"; + + private String keyName = ENVIRONMENT; + + private String defaultValue; + + /** + * Set the key name for the System property that is created. Defaults to + * {@link #ENVIRONMENT}. + * @param keyName the key name to set + */ + public void setKeyName(String keyName) { + this.keyName = keyName; + } + + /** + * Mandatory property specifying the default value of the System property. + * @param defaultValue the default value to set + */ + public void setDefaultValue(String defaultValue) { + this.defaultValue = defaultValue; + } + + /** + * Sets the System property with the provided name and default value. + * + * @see InitializingBean#afterPropertiesSet() + */ + @Override + public void afterPropertiesSet() throws Exception { + Assert.state(defaultValue != null || System.getProperty(keyName) != null, + "Either a default value must be specified or the value should already be set for System property: " + + keyName); + System.setProperty(keyName, System.getProperty(keyName, defaultValue)); + } + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/annotation/Classifier.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/annotation/Classifier.java index 6e7aa6c14..efda2b849 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/annotation/Classifier.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/annotation/Classifier.java @@ -1,38 +1,38 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.support.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Mark a method as capable of classifying its input to an instance of its - * output. Should only be used on non-void methods with one parameter. - * - * @author Dave Syer - * - */ -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.RUNTIME) -@Inherited -@Documented -public @interface Classifier { - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.support.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Mark a method as capable of classifying its input to an instance of its output. Should + * only be used on non-void methods with one parameter. + * + * @author Dave Syer + * + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Inherited +@Documented +public @interface Classifier { + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/transaction/FlushFailedException.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/transaction/FlushFailedException.java index 4dcac0986..6ad68df1e 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/transaction/FlushFailedException.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/transaction/FlushFailedException.java @@ -15,10 +15,10 @@ */ package org.springframework.batch.support.transaction; - /** - * Unchecked exception indicating that an error has occurred while trying to flush a buffer. - * + * Unchecked exception indicating that an error has occurred while trying to flush a + * buffer. + * * @author Lucas Ward * @author Ben Hale */ @@ -27,7 +27,6 @@ public class FlushFailedException extends RuntimeException { /** * Create a new {@link FlushFailedException} based on a message and another exception. - * * @param message the message for this exception * @param cause the other exception */ @@ -37,7 +36,6 @@ public class FlushFailedException extends RuntimeException { /** * Create a new {@link FlushFailedException} based on a message. - * * @param message the message for this exception */ public FlushFailedException(String message) { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/transaction/ResourcelessTransactionManager.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/transaction/ResourcelessTransactionManager.java index 66d10d2b9..d3516eb94 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/transaction/ResourcelessTransactionManager.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/transaction/ResourcelessTransactionManager.java @@ -28,19 +28,19 @@ import org.springframework.transaction.support.TransactionSynchronizationManager @SuppressWarnings("serial") public class ResourcelessTransactionManager extends AbstractPlatformTransactionManager { - @Override + @Override protected void doBegin(Object transaction, TransactionDefinition definition) throws TransactionException { ((ResourcelessTransaction) transaction).begin(); } - @Override + @Override protected void doCommit(DefaultTransactionStatus status) throws TransactionException { if (logger.isDebugEnabled()) { logger.debug("Committing resourceless transaction on [" + status.getTransaction() + "]"); } } - @Override + @Override protected Object doGetTransaction() throws TransactionException { Object transaction = new ResourcelessTransaction(); List resources; @@ -57,14 +57,14 @@ public class ResourcelessTransactionManager extends AbstractPlatformTransactionM return transaction; } - @Override + @Override protected void doRollback(DefaultTransactionStatus status) throws TransactionException { if (logger.isDebugEnabled()) { logger.debug("Rolling back resourceless transaction on [" + status.getTransaction() + "]"); } } - @Override + @Override protected boolean isExistingTransaction(Object transaction) throws TransactionException { if (TransactionSynchronizationManager.hasResource(this)) { List stack = (List) TransactionSynchronizationManager.getResource(this); @@ -73,11 +73,11 @@ public class ResourcelessTransactionManager extends AbstractPlatformTransactionM return ((ResourcelessTransaction) transaction).isActive(); } - @Override + @Override protected void doSetRollbackOnly(DefaultTransactionStatus status) throws TransactionException { } - @Override + @Override protected void doCleanupAfterCompletion(Object transaction) { List resources = (List) TransactionSynchronizationManager.getResource(this); resources.clear(); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/transaction/TransactionAwareBufferedWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/transaction/TransactionAwareBufferedWriter.java index 1875c6aa9..c839a3c75 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/transaction/TransactionAwareBufferedWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/transaction/TransactionAwareBufferedWriter.java @@ -26,10 +26,10 @@ import org.springframework.transaction.support.TransactionSynchronization; import org.springframework.transaction.support.TransactionSynchronizationManager; /** - * Wrapper for a {@link FileChannel} that delays actually writing to or closing the - * buffer if a transaction is active. If a transaction is detected on the call - * to {@link #write(String)} the parameter is buffered and passed on to the - * underlying writer only when the transaction is committed. + * Wrapper for a {@link FileChannel} that delays actually writing to or closing the buffer + * if a transaction is active. If a transaction is detected on the call to + * {@link #write(String)} the parameter is buffered and passed on to the underlying writer + * only when the transaction is committed. * * @author Dave Syer * @author Michael Minella @@ -54,10 +54,9 @@ public class TransactionAwareBufferedWriter extends Writer { private boolean forceSync = false; /** - * Create a new instance with the underlying file channel provided, and a callback - * to execute on close. The callback should clean up related resources like - * output streams or channels. - * + * Create a new instance with the underlying file channel provided, and a callback to + * execute on close. The callback should clean up related resources like output + * streams or channels. * @param channel channel used to do the actual file IO * @param closeCallback callback to execute on close */ @@ -74,12 +73,10 @@ public class TransactionAwareBufferedWriter extends Writer { } /** - * Flag to indicate that changes should be force-synced to disk on flush. - * Defaults to false, which means that even with a local disk changes could - * be lost if the OS crashes in between a write and a cache flush. Setting - * to true may result in slower performance for usage patterns involving - * many frequent writes. - * + * Flag to indicate that changes should be force-synced to disk on flush. Defaults to + * false, which means that even with a local disk changes could be lost if the OS + * crashes in between a write and a cache flush. Setting to true may result in slower + * performance for usage patterns involving many frequent writes. * @param forceSync the flag value to set */ public void setForceSync(boolean forceSync) { @@ -104,7 +101,7 @@ public class TransactionAwareBufferedWriter extends Writer { @Override public void beforeCommit(boolean readOnly) { try { - if(!readOnly) { + if (!readOnly) { complete(); } } @@ -121,7 +118,7 @@ public class TransactionAwareBufferedWriter extends Writer { int bufferLength = bytes.length; ByteBuffer bb = ByteBuffer.wrap(bytes); int bytesWritten = channel.write(bb); - if(bytesWritten != bufferLength) { + if (bytesWritten != bufferLength) { throw new IOException("All bytes to be written were not successfully written"); } if (forceSync) { @@ -151,9 +148,7 @@ public class TransactionAwareBufferedWriter extends Writer { } /** - * Convenience method for clients to determine if there is any unflushed - * data. - * + * Convenience method for clients to determine if there is any unflushed data. * @return the current size (in bytes) of unflushed buffered data */ public long getBufferSize() { @@ -162,8 +157,10 @@ public class TransactionAwareBufferedWriter extends Writer { } try { return getCurrentBuffer().toString().getBytes(encoding).length; - } catch (UnsupportedEncodingException e) { - throw new WriteFailedException("Could not determine buffer size because of unsupported encoding: " + encoding, e); + } + catch (UnsupportedEncodingException e) { + throw new WriteFailedException( + "Could not determine buffer size because of unsupported encoding: " + encoding, e); } } @@ -215,8 +212,9 @@ public class TransactionAwareBufferedWriter extends Writer { int length = bytes.length; ByteBuffer bb = ByteBuffer.wrap(bytes); int bytesWritten = channel.write(bb); - if(bytesWritten != length) { - throw new IOException("Unable to write all data. Bytes to write: " + len + ". Bytes written: " + bytesWritten); + if (bytesWritten != length) { + throw new IOException( + "Unable to write all data. Bytes to write: " + len + ". Bytes written: " + bytesWritten); } return; } @@ -238,8 +236,9 @@ public class TransactionAwareBufferedWriter extends Writer { int length = bytes.length; ByteBuffer bb = ByteBuffer.wrap(bytes); int bytesWritten = channel.write(bb); - if(bytesWritten != length) { - throw new IOException("Unable to write all data. Bytes to write: " + len + ". Bytes written: " + bytesWritten); + if (bytesWritten != length) { + throw new IOException( + "Unable to write all data. Bytes to write: " + len + ". Bytes written: " + bytesWritten); } return; } @@ -247,4 +246,5 @@ public class TransactionAwareBufferedWriter extends Writer { StringBuilder buffer = getCurrentBuffer(); buffer.append(str, off, off + len); } + } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/transaction/TransactionAwareProxyFactory.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/transaction/TransactionAwareProxyFactory.java index 4bca834cc..c7ffbc5e3 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/transaction/TransactionAwareProxyFactory.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/transaction/TransactionAwareProxyFactory.java @@ -36,30 +36,29 @@ import org.springframework.transaction.support.TransactionSynchronizationManager /** *

      - * Factory for transaction aware objects (like lists, sets, maps). If a - * transaction is active when a method is called on an instance created by the - * factory, it makes a copy of the target object and carries out all operations - * on the copy. Only when the transaction commits is the target re-initialised - * with the copy. + * Factory for transaction aware objects (like lists, sets, maps). If a transaction is + * active when a method is called on an instance created by the factory, it makes a copy + * of the target object and carries out all operations on the copy. Only when the + * transaction commits is the target re-initialised with the copy. *

      - * + * *

      - * Works well with collections and maps for testing transactional behaviour - * without needing a database. The base implementation handles lists, sets and - * maps. Subclasses can implement {@link #begin(Object)} and - * {@link #commit(Object, Object)} to provide support for other resources. + * Works well with collections and maps for testing transactional behaviour without + * needing a database. The base implementation handles lists, sets and maps. Subclasses + * can implement {@link #begin(Object)} and {@link #commit(Object, Object)} to provide + * support for other resources. *

      - * + * *

      * Generally not intended for multi-threaded use, but the - * {@link #createAppendOnlyTransactionalMap() append only version} of - * collections gives isolation between threads operating on different keys in a - * map, provided they only append to the map. (Threads are limited to removing - * entries that were created in the same transaction.) + * {@link #createAppendOnlyTransactionalMap() append only version} of collections gives + * isolation between threads operating on different keys in a map, provided they only + * append to the map. (Threads are limited to removing entries that were created in the + * same transaction.) *

      - * + * * @author Dave Syer - * + * */ public class TransactionAwareProxyFactory { @@ -79,10 +78,9 @@ public class TransactionAwareProxyFactory { } /** - * Make a copy of the target that can be used inside a transaction to - * isolate changes from the original. Also called from the factory - * constructor to isolate the target from the original value passed in. - * + * Make a copy of the target that can be used inside a transaction to isolate changes + * from the original. Also called from the factory constructor to isolate the target + * from the original value passed in. * @param target the target object (List, Set or Map) * @return an independent copy */ @@ -116,10 +114,8 @@ public class TransactionAwareProxyFactory { } /** - * Take the working copy state and commit it back to the original target. - * The target then reflects all the changes applied to the copy during a - * transaction. - * + * Take the working copy state and commit it back to the original target. The target + * then reflects all the changes applied to the copy during a transaction. * @param copy the working copy. * @param target the original target of the factory. */ @@ -205,7 +201,7 @@ public class TransactionAwareProxyFactory { this.key = key; } - @Override + @Override public void afterCompletion(int status) { if (status == TransactionSynchronization.STATUS_COMMITTED) { synchronized (target) { @@ -214,11 +210,12 @@ public class TransactionAwareProxyFactory { } TransactionSynchronizationManager.unbindResource(key); } + } private class TransactionAwareInterceptor implements MethodInterceptor { - @Override + @Override public Object invoke(MethodInvocation invocation) throws Throwable { if (!TransactionSynchronizationManager.isActualTransactionActive()) { @@ -243,8 +240,8 @@ public class TransactionAwareProxyFactory { if (appendOnly) { String methodName = invocation.getMethod().getName(); if ((result == null && methodName.equals("get")) - || (Boolean.FALSE.equals(result) && (methodName.startsWith("contains")) || (Boolean.TRUE - .equals(result) && methodName.startsWith("isEmpty")))) { + || (Boolean.FALSE.equals(result) && (methodName.startsWith("contains")) + || (Boolean.TRUE.equals(result) && methodName.startsWith("isEmpty")))) { // In appendOnly mode the result of a get might not be // in the cache... return invocation.proceed(); @@ -259,6 +256,7 @@ public class TransactionAwareProxyFactory { return result; } + } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/config/DatasourceTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/config/DatasourceTests.java index 8bc20bf20..121fb0c84 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/config/DatasourceTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/config/DatasourceTests.java @@ -34,7 +34,8 @@ public class DatasourceTests { @Autowired private JdbcTemplate jdbcTemplate; - @Transactional @Test + @Transactional + @Test public void testTemplate() throws Exception { System.err.println(System.getProperty("java.class.path")); JdbcTestUtils.deleteFromTables(jdbcTemplate, "T_BARS"); @@ -43,4 +44,5 @@ public class DatasourceTests { jdbcTemplate.update("INSERT into T_BARS (id,name,foo_date) values (?,?,null)", 0, "foo"); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/config/MessagingTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/config/MessagingTests.java index c41f6d65f..b56a8f7c4 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/config/MessagingTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/config/MessagingTests.java @@ -63,4 +63,5 @@ public class MessagingTests { } return msgs; } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/container/jms/BatchMessageListenerContainer.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/container/jms/BatchMessageListenerContainer.java index fd34db125..6c9967fd3 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/container/jms/BatchMessageListenerContainer.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/container/jms/BatchMessageListenerContainer.java @@ -31,42 +31,44 @@ import jakarta.jms.MessageConsumer; import jakarta.jms.Session; /** - * Message listener container adapted for intercepting the message reception - * with advice provided through configuration.
      - * + * Message listener container adapted for intercepting the message reception with advice + * provided through configuration.
      + * * To enable batching of messages in a single transaction, use the - * {@link TransactionInterceptor} and the {@link RepeatOperationsInterceptor} in - * the advice chain (with or without a transaction manager set in the base - * class). Instead of receiving a single message and processing it, the - * container will then use a {@link RepeatOperations} to receive multiple - * messages in the same thread. Use with a {@link RepeatOperations} and a - * transaction interceptor. If the transaction interceptor uses XA then use an - * XA connection factory, or else the - * {@link TransactionAwareConnectionFactoryProxy} to synchronize the JMS session - * with the ongoing transaction (opening up the possibility of duplicate - * messages after a failure). In the latter case you will not need to provide a - * transaction manager in the base class - it only gets on the way and prevents - * the JMS session from synchronizing with the database transaction. - * + * {@link TransactionInterceptor} and the {@link RepeatOperationsInterceptor} in the + * advice chain (with or without a transaction manager set in the base class). Instead of + * receiving a single message and processing it, the container will then use a + * {@link RepeatOperations} to receive multiple messages in the same thread. Use with a + * {@link RepeatOperations} and a transaction interceptor. If the transaction interceptor + * uses XA then use an XA connection factory, or else the + * {@link TransactionAwareConnectionFactoryProxy} to synchronize the JMS session with the + * ongoing transaction (opening up the possibility of duplicate messages after a failure). + * In the latter case you will not need to provide a transaction manager in the base class + * - it only gets on the way and prevents the JMS session from synchronizing with the + * database transaction. + * * @author Dave Syer * @author Mahmoud Ben Hassine - * + * */ public class BatchMessageListenerContainer extends DefaultMessageListenerContainer { /** * @author Dave Syer - * + * */ public static interface ContainerDelegate { + boolean receiveAndExecute(Object invoker, Session session, MessageConsumer consumer) throws JMSException; + } private Advice[] advices = new Advice[0]; private ContainerDelegate delegate = new ContainerDelegate() { @Override - public boolean receiveAndExecute(Object invoker, Session session, MessageConsumer consumer) throws JMSException { + public boolean receiveAndExecute(Object invoker, Session session, MessageConsumer consumer) + throws JMSException { return BatchMessageListenerContainer.super.receiveAndExecute(invoker, session, consumer); } }; @@ -84,7 +86,7 @@ public class BatchMessageListenerContainer extends DefaultMessageListenerContain /** * Set up interceptor with provided advice on the * {@link #receiveAndExecute(Object, Session, MessageConsumer)} method. - * + * * @see org.springframework.jms.listener.AbstractJmsListeningContainer#afterPropertiesSet() */ @Override @@ -94,9 +96,9 @@ public class BatchMessageListenerContainer extends DefaultMessageListenerContain } /** - * Override base class to prevent exceptions from being swallowed. Should be - * an injectable strategy (see SPR-4733). - * + * Override base class to prevent exceptions from being swallowed. Should be an + * injectable strategy (see SPR-4733). + * * @see org.springframework.jms.listener.AbstractMessageListenerContainer#handleListenerException(java.lang.Throwable) */ @Override @@ -131,7 +133,7 @@ public class BatchMessageListenerContainer extends DefaultMessageListenerContain } /** - * + * */ public void initializeProxy() { ProxyFactory factory = new ProxyFactory(); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/container/jms/BatchMessageListenerContainerTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/container/jms/BatchMessageListenerContainerTests.java index 4be1b2504..207485f64 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/container/jms/BatchMessageListenerContainerTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/container/jms/BatchMessageListenerContainerTests.java @@ -100,7 +100,8 @@ public class BatchMessageListenerContainerTests { boolean received = doTestWithException(new IllegalStateException("No way!"), true, 2); assertFalse("Message received", received); fail("Expected IllegalStateException"); - } catch (IllegalStateException e) { + } + catch (IllegalStateException e) { assertEquals("No way!", e.getMessage()); } } @@ -133,19 +134,21 @@ public class BatchMessageListenerContainerTests { private BatchMessageListenerContainer getContainer(RepeatTemplate template) { ConnectionFactory connectionFactory = mock(ConnectionFactory.class); - // Yuck: we need to turn these method in base class to no-ops because the invoker is a private class + // Yuck: we need to turn these method in base class to no-ops because the invoker + // is a private class // we can't create for test purposes... BatchMessageListenerContainer container = new BatchMessageListenerContainer() { @Override protected void messageReceived(Object invoker, Session session) { } + @Override protected void noMessageReceived(Object invoker, Session session) { } }; RepeatOperationsInterceptor interceptor = new RepeatOperationsInterceptor(); interceptor.setRepeatOperations(template); - container.setAdviceChain(new Advice[] {interceptor}); + container.setAdviceChain(new Advice[] { interceptor }); container.setConnectionFactory(connectionFactory); container.setDestinationName("queue"); container.afterPropertiesSet(); @@ -169,7 +172,7 @@ public class BatchMessageListenerContainerTests { MessageConsumer consumer = mock(MessageConsumer.class); Message message = mock(Message.class); - if (expectGetTransactionCount>0) { + if (expectGetTransactionCount > 0) { when(session.getTransacted()).thenReturn(true); } @@ -186,17 +189,20 @@ public class BatchMessageListenerContainerTests { } private boolean doExecute(Session session, MessageConsumer consumer) throws IllegalAccessException { - Method method = ReflectionUtils.findMethod(container.getClass(), "receiveAndExecute", Object.class, Session.class, MessageConsumer.class); + Method method = ReflectionUtils.findMethod(container.getClass(), "receiveAndExecute", Object.class, + Session.class, MessageConsumer.class); method.setAccessible(true); boolean received; try { - // A null invoker is not normal, but we don't care about the invoker for a unit test + // A null invoker is not normal, but we don't care about the invoker for a + // unit test received = (Boolean) method.invoke(container, null, session, consumer); } catch (InvocationTargetException e) { if (e.getCause() instanceof RuntimeException) { throw (RuntimeException) e.getCause(); - } else { + } + else { throw (Error) e.getCause(); } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/AbstractItemReaderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/AbstractItemReaderTests.java index 42ab5322f..541f2295d 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/AbstractItemReaderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/AbstractItemReaderTests.java @@ -1,88 +1,84 @@ -/* - * Copyright 2009-2010 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - -import org.junit.Before; -import org.junit.Test; -import org.springframework.batch.item.sample.Foo; - -/** - * Common tests for {@link ItemReader} implementations. Expected input is five - * {@link Foo} objects with values 1 to 5. - */ -public abstract class AbstractItemReaderTests { - - protected ItemReader tested; - - /** - * @return configured ItemReader ready for use. - */ - protected abstract ItemReader getItemReader() throws Exception; - - @Before - public void setUp() throws Exception { - tested = getItemReader(); - } - - /** - * Regular scenario - read the input and eventually return null. - */ - @Test - public void testRead() throws Exception { - - Foo foo1 = tested.read(); - assertEquals(1, foo1.getValue()); - - Foo foo2 = tested.read(); - assertEquals(2, foo2.getValue()); - - Foo foo3 = tested.read(); - assertEquals(3, foo3.getValue()); - - Foo foo4 = tested.read(); - assertEquals(4, foo4.getValue()); - - Foo foo5 = tested.read(); - assertEquals(5, foo5.getValue()); - - assertNull(tested.read()); - } - - /** - * Empty input should be handled gracefully - null is returned on first - * read. - */ - @Test - public void testEmptyInput() throws Exception { - pointToEmptyInput(tested); - tested.read(); - assertNull(tested.read()); - } - - /** - * Point the reader to empty input (close and open if necessary for the new - * settings to apply). - * - * @param tested - * the reader - */ - protected abstract void pointToEmptyInput(ItemReader tested) - throws Exception; - -} +/* + * Copyright 2009-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.batch.item.sample.Foo; + +/** + * Common tests for {@link ItemReader} implementations. Expected input is five {@link Foo} + * objects with values 1 to 5. + */ +public abstract class AbstractItemReaderTests { + + protected ItemReader tested; + + /** + * @return configured ItemReader ready for use. + */ + protected abstract ItemReader getItemReader() throws Exception; + + @Before + public void setUp() throws Exception { + tested = getItemReader(); + } + + /** + * Regular scenario - read the input and eventually return null. + */ + @Test + public void testRead() throws Exception { + + Foo foo1 = tested.read(); + assertEquals(1, foo1.getValue()); + + Foo foo2 = tested.read(); + assertEquals(2, foo2.getValue()); + + Foo foo3 = tested.read(); + assertEquals(3, foo3.getValue()); + + Foo foo4 = tested.read(); + assertEquals(4, foo4.getValue()); + + Foo foo5 = tested.read(); + assertEquals(5, foo5.getValue()); + + assertNull(tested.read()); + } + + /** + * Empty input should be handled gracefully - null is returned on first read. + */ + @Test + public void testEmptyInput() throws Exception { + pointToEmptyInput(tested); + tested.read(); + assertNull(tested.read()); + } + + /** + * Point the reader to empty input (close and open if necessary for the new settings + * to apply). + * @param tested the reader + */ + protected abstract void pointToEmptyInput(ItemReader tested) throws Exception; + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/AbstractItemStreamItemReaderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/AbstractItemStreamItemReaderTests.java index 8a4b5d7d2..4d8510e8e 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/AbstractItemStreamItemReaderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/AbstractItemStreamItemReaderTests.java @@ -23,9 +23,8 @@ import org.junit.After; import org.junit.Test; /** - * Common tests for readers implementing both {@link ItemReader} and - * {@link ItemStream}. Expected input is five {@link Foo} objects with values 1 - * to 5. + * Common tests for readers implementing both {@link ItemReader} and {@link ItemStream}. + * Expected input is five {@link Foo} objects with values 1 to 5. */ public abstract class AbstractItemStreamItemReaderTests extends AbstractItemReaderTests { @@ -38,7 +37,7 @@ public abstract class AbstractItemStreamItemReaderTests extends AbstractItemRead return (ItemStream) tested; } - @Override + @Override @Before public void setUp() throws Exception { super.setUp(); @@ -51,9 +50,9 @@ public abstract class AbstractItemStreamItemReaderTests extends AbstractItemRead } /** - * Restart scenario - read items, update execution context, create new - * reader and restore from restart data - the new input source should - * continue where the old one finished. + * Restart scenario - read items, update execution context, create new reader and + * restore from restart data - the new input source should continue where the old one + * finished. */ @Test public void testRestart() throws Exception { @@ -80,9 +79,9 @@ public abstract class AbstractItemStreamItemReaderTests extends AbstractItemRead } /** - * Restart scenario - read items, rollback to last marked position, update - * execution context, create new reader and restore from restart data - the - * new input source should continue where the old one finished. + * Restart scenario - read items, rollback to last marked position, update execution + * context, create new reader and restore from restart data - the new input source + * should continue where the old one finished. */ @Test public void testResetAndRestart() throws Exception { @@ -94,9 +93,9 @@ public abstract class AbstractItemStreamItemReaderTests extends AbstractItemRead Foo foo2 = tested.read(); assertEquals(2, foo2.getValue()); - + testedAsStream().update(executionContext); - + Foo foo3 = tested.read(); assertEquals(3, foo3.getValue()); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/ItemRecoveryHandlerTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/ItemRecoveryHandlerTests.java index 8e1f0f2cb..df0230836 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/ItemRecoveryHandlerTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/ItemRecoveryHandlerTests.java @@ -23,7 +23,7 @@ import junit.framework.TestCase; public class ItemRecoveryHandlerTests extends TestCase { MethodInvocationRecoverer recoverer = new MethodInvocationRecoverer() { - @Override + @Override public String recover(Object[] data, Throwable cause) { return null; } @@ -31,9 +31,11 @@ public class ItemRecoveryHandlerTests extends TestCase { public void testRecover() throws Exception { try { - recoverer.recover(new Object[]{"foo"}, null); - } catch (Exception e) { + recoverer.recover(new Object[] { "foo" }, null); + } + catch (Exception e) { fail("Unexpected Exception"); } } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/ItemStreamExceptionTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/ItemStreamExceptionTests.java index 92220cf0f..2da58e0a0 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/ItemStreamExceptionTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/ItemStreamExceptionTests.java @@ -20,7 +20,7 @@ import org.springframework.batch.support.AbstractExceptionTests; public class ItemStreamExceptionTests extends AbstractExceptionTests { - @Override + @Override public Exception getException(String msg) throws Exception { return new ItemStreamException(msg); } @@ -29,7 +29,7 @@ public class ItemStreamExceptionTests extends AbstractExceptionTests { return new ItemStreamException(t); } - @Override + @Override public Exception getException(String msg, Throwable t) throws Exception { return new ItemStreamException(msg, t); } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/UnexpectedInputExceptionTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/UnexpectedInputExceptionTests.java index 75c32f676..9c190419f 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/UnexpectedInputExceptionTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/UnexpectedInputExceptionTests.java @@ -20,12 +20,12 @@ import org.springframework.batch.repeat.AbstractExceptionTests; public class UnexpectedInputExceptionTests extends AbstractExceptionTests { - @Override + @Override public Exception getException(String msg) throws Exception { return new UnexpectedInputException(msg, null); } - @Override + @Override public Exception getException(String msg, Throwable t) throws Exception { return new UnexpectedInputException(msg, t); } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/adapter/AbstractDelegatorTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/adapter/AbstractDelegatorTests.java index 4c3a926c5..525351e31 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/adapter/AbstractDelegatorTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/adapter/AbstractDelegatorTests.java @@ -37,6 +37,7 @@ import static org.junit.Assert.fail; public class AbstractDelegatorTests { private static class ConcreteDelegator extends AbstractMethodInvokingDelegator { + } private AbstractMethodInvokingDelegator delegator = new ConcreteDelegator(); @@ -50,8 +51,7 @@ public class AbstractDelegatorTests { } /** - * Regular use - calling methods directly and via delegator leads to same - * results + * Regular use - calling methods directly and via delegator leads to same results */ @Test public void testDelegation() throws Exception { @@ -62,8 +62,7 @@ public class AbstractDelegatorTests { } /** - * Regular use - calling methods directly and via delegator leads to same - * results + * Regular use - calling methods directly and via delegator leads to same results */ @Test public void testDelegationWithArgument() throws Exception { @@ -84,8 +83,7 @@ public class AbstractDelegatorTests { } /** - * Null argument value doesn't cause trouble when validating method - * signature. + * Null argument value doesn't cause trouble when validating method signature. */ @Test public void testDelegationWithCheckedNullArgument() throws Exception { @@ -97,11 +95,10 @@ public class AbstractDelegatorTests { } /** - * Regular use - calling methods directly and via delegator leads to same - * results + * Regular use - calling methods directly and via delegator leads to same results */ @Test - @Ignore //FIXME + @Ignore // FIXME public void testDelegationWithMultipleArguments() throws Exception { FooService fooService = new FooService(); delegator.setTargetObject(fooService); @@ -158,8 +155,7 @@ public class AbstractDelegatorTests { } /** - * Exception scenario - target method is called with incorrect number of - * arguments. + * Exception scenario - target method is called with incorrect number of arguments. */ @Test public void testTooFewArguments() throws Exception { @@ -212,9 +208,8 @@ public class AbstractDelegatorTests { } /** - * Exception scenario - target method is successfully invoked but throws - * exception. Such 'business' exception should be re-thrown as is (without - * wrapping). + * Exception scenario - target method is successfully invoked but throws exception. + * Such 'business' exception should be re-thrown as is (without wrapping). */ @Test public void testDelegateException() throws Exception { diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/adapter/HippyMethodInvokerTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/adapter/HippyMethodInvokerTests.java index f675bfb62..cbe13b7bb 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/adapter/HippyMethodInvokerTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/adapter/HippyMethodInvokerTests.java @@ -82,12 +82,15 @@ public class HippyMethodInvokerTests { invoker.setTargetMethod("foo"); @SuppressWarnings("unused") class OverloadingPojo { + public Class foo(List arg) { return List.class; } + public Class foo(Set arg) { return Set.class; } + } TreeSet arg = new TreeSet<>(); @@ -108,12 +111,15 @@ public class HippyMethodInvokerTests { invoker.setTargetMethod("foo"); @SuppressWarnings("unused") class OverloadingPojo { + public Class foo(String arg1, Number arg2) { return Number.class; } + public Class foo(String arg1, List arg2) { return List.class; } + } String exactArg = "string"; @@ -129,6 +135,7 @@ public class HippyMethodInvokerTests { } public static class PlainPojo { + public String handle(double value, String input) { return value + "." + input; } @@ -148,15 +155,18 @@ public class HippyMethodInvokerTests { public String empty() { return "."; } + } public static interface Service { + String getMessage(double value, String input); + } public static class TestMethodAdapter extends AbstractMethodInvokingDelegator implements Service { - @Override + @Override public String getMessage(double value, String input) { try { return invokeDelegateMethodWithArguments(new Object[] { value, input }); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/adapter/ItemProcessorAdapterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/adapter/ItemProcessorAdapterTests.java index dfa1d4090..aa79a63c2 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/adapter/ItemProcessorAdapterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/adapter/ItemProcessorAdapterTests.java @@ -26,7 +26,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * Tests for {@link ItemProcessorAdapter}. - * + * * @author Dave Syer */ @RunWith(SpringJUnit4ClassRunner.class) @@ -34,11 +34,11 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; public class ItemProcessorAdapterTests { @Autowired - private ItemProcessorAdapter processor; + private ItemProcessorAdapter processor; @Test public void testProcess() throws Exception { - Foo item = new Foo(0,"foo",1); + Foo item = new Foo(0, "foo", 1); assertEquals("foo", processor.process(item)); } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/adapter/ItemReaderAdapterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/adapter/ItemReaderAdapterTests.java index 983277ff2..2d51e8c56 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/adapter/ItemReaderAdapterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/adapter/ItemReaderAdapterTests.java @@ -30,7 +30,7 @@ import org.junit.runner.RunWith; /** * Tests for {@link ItemReaderAdapter}. - * + * * @author Robert Kasanicky */ @RunWith(SpringJUnit4ClassRunner.class) @@ -44,7 +44,8 @@ public class ItemReaderAdapterTests { private FooService fooService; /* - * Regular usage scenario - items are retrieved from the service injected invoker points to. + * Regular usage scenario - items are retrieved from the service injected invoker + * points to. */ @Test public void testNext() throws Exception { diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/adapter/ItemWriterAdapterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/adapter/ItemWriterAdapterTests.java index 107d52b0d..375990cff 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/adapter/ItemWriterAdapterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/adapter/ItemWriterAdapterTests.java @@ -33,7 +33,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * Tests for {@link ItemWriterAdapter}. - * + * * @author Robert Kasanicky */ @RunWith(SpringJUnit4ClassRunner.class) @@ -47,7 +47,8 @@ public class ItemWriterAdapterTests { private FooService fooService; /* - * Regular usage scenario - input object should be passed to the service the injected invoker points to. + * Regular usage scenario - input object should be passed to the service the injected + * invoker points to. */ @Test public void testProcess() throws Exception { diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/adapter/PropertyExtractingDelegatingItemProcessorIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/adapter/PropertyExtractingDelegatingItemProcessorIntegrationTests.java index 10f60daf4..398a80358 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/adapter/PropertyExtractingDelegatingItemProcessorIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/adapter/PropertyExtractingDelegatingItemProcessorIntegrationTests.java @@ -30,7 +30,7 @@ import org.springframework.beans.factory.annotation.Autowired; /** * Tests for {@link PropertyExtractingDelegatingItemWriter} - * + * * @author Robert Kasanicky * @author Mahmoud Ben Hassine */ @@ -45,7 +45,8 @@ public class PropertyExtractingDelegatingItemProcessorIntegrationTests { private FooService fooService; /* - * Regular usage scenario - input object should be passed to the service the injected invoker points to. + * Regular usage scenario - input object should be passed to the service the injected + * invoker points to. */ @Test public void testProcess() throws Exception { diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/amqp/AmqpItemReaderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/amqp/AmqpItemReaderTests.java index 819ee2682..83f49f02c 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/amqp/AmqpItemReaderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/amqp/AmqpItemReaderTests.java @@ -36,69 +36,72 @@ import static org.junit.Assert.fail; * @author Will Schipp */ public class AmqpItemReaderTests { - @Test(expected = IllegalArgumentException.class) - public void testNullAmqpTemplate() { - new AmqpItemReader(null); - } - @Test - public void testNoItemType() { - final AmqpTemplate amqpTemplate = mock(AmqpTemplate.class); - when(amqpTemplate.receiveAndConvert()).thenReturn("foo"); + @Test(expected = IllegalArgumentException.class) + public void testNullAmqpTemplate() { + new AmqpItemReader(null); + } - final AmqpItemReader amqpItemReader = new AmqpItemReader<>(amqpTemplate); - assertEquals("foo", amqpItemReader.read()); - } + @Test + public void testNoItemType() { + final AmqpTemplate amqpTemplate = mock(AmqpTemplate.class); + when(amqpTemplate.receiveAndConvert()).thenReturn("foo"); - @Test - public void testNonMessageItemType() { - final AmqpTemplate amqpTemplate = mock(AmqpTemplate.class); - when(amqpTemplate.receiveAndConvert()).thenReturn("foo"); + final AmqpItemReader amqpItemReader = new AmqpItemReader<>(amqpTemplate); + assertEquals("foo", amqpItemReader.read()); + } - final AmqpItemReader amqpItemReader = new AmqpItemReader<>(amqpTemplate); - amqpItemReader.setItemType(String.class); + @Test + public void testNonMessageItemType() { + final AmqpTemplate amqpTemplate = mock(AmqpTemplate.class); + when(amqpTemplate.receiveAndConvert()).thenReturn("foo"); - assertEquals("foo", amqpItemReader.read()); + final AmqpItemReader amqpItemReader = new AmqpItemReader<>(amqpTemplate); + amqpItemReader.setItemType(String.class); - } + assertEquals("foo", amqpItemReader.read()); - @Test - public void testMessageItemType() { - final AmqpTemplate amqpTemplate = mock(AmqpTemplate.class); - final Message message = mock(Message.class); + } - when(amqpTemplate.receive()).thenReturn(message); + @Test + public void testMessageItemType() { + final AmqpTemplate amqpTemplate = mock(AmqpTemplate.class); + final Message message = mock(Message.class); - final AmqpItemReader amqpItemReader = new AmqpItemReader<>(amqpTemplate); - amqpItemReader.setItemType(Message.class); + when(amqpTemplate.receive()).thenReturn(message); - assertEquals(message, amqpItemReader.read()); + final AmqpItemReader amqpItemReader = new AmqpItemReader<>(amqpTemplate); + amqpItemReader.setItemType(Message.class); - } + assertEquals(message, amqpItemReader.read()); - @Test - public void testTypeMismatch() { - final AmqpTemplate amqpTemplate = mock(AmqpTemplate.class); + } - when(amqpTemplate.receiveAndConvert()).thenReturn("foo"); + @Test + public void testTypeMismatch() { + final AmqpTemplate amqpTemplate = mock(AmqpTemplate.class); - final AmqpItemReader amqpItemReader = new AmqpItemReader<>(amqpTemplate); - amqpItemReader.setItemType(Integer.class); + when(amqpTemplate.receiveAndConvert()).thenReturn("foo"); - try { - amqpItemReader.read(); - fail("Expected IllegalStateException"); - } catch (IllegalStateException e) { - assertTrue(e.getMessage().contains("wrong type")); - } + final AmqpItemReader amqpItemReader = new AmqpItemReader<>(amqpTemplate); + amqpItemReader.setItemType(Integer.class); - } + try { + amqpItemReader.read(); + fail("Expected IllegalStateException"); + } + catch (IllegalStateException e) { + assertTrue(e.getMessage().contains("wrong type")); + } - @Test(expected = IllegalArgumentException.class) - public void testNullItemType() { - final AmqpTemplate amqpTemplate = mock(AmqpTemplate.class); + } + + @Test(expected = IllegalArgumentException.class) + public void testNullItemType() { + final AmqpTemplate amqpTemplate = mock(AmqpTemplate.class); + + final AmqpItemReader amqpItemReader = new AmqpItemReader<>(amqpTemplate); + amqpItemReader.setItemType(null); + } - final AmqpItemReader amqpItemReader = new AmqpItemReader<>(amqpTemplate); - amqpItemReader.setItemType(null); - } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/amqp/AmqpItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/amqp/AmqpItemWriterTests.java index d5cd61078..980148064 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/amqp/AmqpItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/amqp/AmqpItemWriterTests.java @@ -32,21 +32,23 @@ import java.util.Arrays; * @author Will Schipp */ public class AmqpItemWriterTests { - @Test(expected = IllegalArgumentException.class) - public void testNullAmqpTemplate() { - new AmqpItemWriter(null); - } - @Test - public void voidTestWrite() throws Exception { - AmqpTemplate amqpTemplate = mock(AmqpTemplate.class); + @Test(expected = IllegalArgumentException.class) + public void testNullAmqpTemplate() { + new AmqpItemWriter(null); + } - amqpTemplate.convertAndSend("foo"); + @Test + public void voidTestWrite() throws Exception { + AmqpTemplate amqpTemplate = mock(AmqpTemplate.class); - amqpTemplate.convertAndSend("bar"); + amqpTemplate.convertAndSend("foo"); - AmqpItemWriter amqpItemWriter = new AmqpItemWriter<>(amqpTemplate); - amqpItemWriter.write(Arrays.asList("foo", "bar")); + amqpTemplate.convertAndSend("bar"); + + AmqpItemWriter amqpItemWriter = new AmqpItemWriter<>(amqpTemplate); + amqpItemWriter.write(Arrays.asList("foo", "bar")); + + } - } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/amqp/builder/AmqpItemReaderBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/amqp/builder/AmqpItemReaderBuilderTests.java index 12f6943c2..8acb1b1c4 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/amqp/builder/AmqpItemReaderBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/amqp/builder/AmqpItemReaderBuilderTests.java @@ -83,4 +83,5 @@ public class AmqpItemReaderBuilderTests { "amqpTemplate is required.", iae.getMessage()); } } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/amqp/builder/AmqpItemWriterBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/amqp/builder/AmqpItemWriterBuilderTests.java index 050b51f36..5f4007dce 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/amqp/builder/AmqpItemWriterBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/amqp/builder/AmqpItemWriterBuilderTests.java @@ -50,10 +50,10 @@ public class AmqpItemWriterBuilderTests { public void voidTestWrite() throws Exception { AmqpTemplate amqpTemplate = mock(AmqpTemplate.class); - AmqpItemWriter amqpItemWriter = - new AmqpItemWriterBuilder().amqpTemplate(amqpTemplate).build(); + AmqpItemWriter amqpItemWriter = new AmqpItemWriterBuilder().amqpTemplate(amqpTemplate).build(); amqpItemWriter.write(Arrays.asList("foo", "bar")); verify(amqpTemplate).convertAndSend("foo"); verify(amqpTemplate).convertAndSend("bar"); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/avro/AvroItemReaderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/avro/AvroItemReaderTests.java index 2166b3d74..c8c24676e 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/avro/AvroItemReaderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/avro/AvroItemReaderTests.java @@ -38,7 +38,6 @@ public class AvroItemReaderTests extends AvroItemReaderTestSupport { verify(itemReader, genericAvroGeneratedUsers()); } - @Test public void readSpecificUsers() throws Exception { @@ -78,4 +77,5 @@ public class AvroItemReaderTests extends AvroItemReaderTestSupport { public void schemaResourceDoesNotExist() { new AvroItemReader(dataResource, new ClassPathResource("doesnotexist")); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/avro/AvroItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/avro/AvroItemWriterTests.java index d1f672f15..7c2cce235 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/avro/AvroItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/avro/AvroItemWriterTests.java @@ -50,21 +50,23 @@ public class AvroItemWriterTests extends AvroItemWriterTestSupport { @Test public void itemWriterForGenericRecords() throws Exception { - AvroItemWriter avroItemWriter = - new AvroItemWriter<>(this.output, this.plainOldUserSchemaResource, GenericRecord.class); + AvroItemWriter avroItemWriter = new AvroItemWriter<>(this.output, + this.plainOldUserSchemaResource, GenericRecord.class); avroItemWriter.open(new ExecutionContext()); avroItemWriter.write(this.genericPlainOldUsers()); avroItemWriter.close(); - verifyRecordsWithEmbeddedHeader(this.outputStream.toByteArray(), this.genericPlainOldUsers(), GenericRecord.class); + verifyRecordsWithEmbeddedHeader(this.outputStream.toByteArray(), this.genericPlainOldUsers(), + GenericRecord.class); } @Test public void itemWriterForPojos() throws Exception { - AvroItemWriter avroItemWriter = new AvroItemWriter<>(this.output, this.plainOldUserSchemaResource, PlainOldUser.class); + AvroItemWriter avroItemWriter = new AvroItemWriter<>(this.output, this.plainOldUserSchemaResource, + PlainOldUser.class); avroItemWriter.open(new ExecutionContext()); avroItemWriter.write(this.plainOldUsers()); avroItemWriter.close(); @@ -95,4 +97,5 @@ public class AvroItemWriterTests extends AvroItemWriterTestSupport { public void shouldFailWitNoType() { new AvroItemWriter<>(this.output, this.schemaResource, null).open(new ExecutionContext()); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/avro/builder/AvroItemWriterBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/avro/builder/AvroItemWriterBuilderTests.java index bd30682fc..9c7425b12 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/avro/builder/AvroItemWriterBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/avro/builder/AvroItemWriterBuilderTests.java @@ -33,50 +33,41 @@ import org.springframework.core.io.WritableResource; public class AvroItemWriterBuilderTests extends AvroItemWriterTestSupport { private ByteArrayOutputStream outputStream = new ByteArrayOutputStream(2048); + private WritableResource output = new OutputStreamResource(outputStream); - @Test - public void itemWriterForAvroGeneratedClass() throws Exception { + @Test + public void itemWriterForAvroGeneratedClass() throws Exception { - AvroItemWriter avroItemWriter = new AvroItemWriterBuilder() - .resource(output) - .schema(schemaResource) - .type(User.class) - .build(); + AvroItemWriter avroItemWriter = new AvroItemWriterBuilder().resource(output).schema(schemaResource) + .type(User.class).build(); - avroItemWriter.open(new ExecutionContext()); - avroItemWriter.write(this.avroGeneratedUsers()); - avroItemWriter.close(); - - verifyRecordsWithEmbeddedHeader(outputStream.toByteArray(), this.avroGeneratedUsers(), User.class); - } + avroItemWriter.open(new ExecutionContext()); + avroItemWriter.write(this.avroGeneratedUsers()); + avroItemWriter.close(); + verifyRecordsWithEmbeddedHeader(outputStream.toByteArray(), this.avroGeneratedUsers(), User.class); + } @Test public void itemWriterForGenericRecords() throws Exception { AvroItemWriter avroItemWriter = new AvroItemWriterBuilder() - .type(GenericRecord.class) - .schema(plainOldUserSchemaResource) - .resource(output) - .build(); + .type(GenericRecord.class).schema(plainOldUserSchemaResource).resource(output).build(); avroItemWriter.open(new ExecutionContext()); avroItemWriter.write(this.genericPlainOldUsers()); avroItemWriter.close(); - verifyRecordsWithEmbeddedHeader(outputStream.toByteArray(), this.genericPlainOldUsers(), GenericRecord.class); + verifyRecordsWithEmbeddedHeader(outputStream.toByteArray(), this.genericPlainOldUsers(), GenericRecord.class); } @Test public void itemWriterForPojos() throws Exception { - AvroItemWriter avroItemWriter = new AvroItemWriterBuilder() - .resource(output) - .schema(plainOldUserSchemaResource) - .type(PlainOldUser.class) - .build(); + AvroItemWriter avroItemWriter = new AvroItemWriterBuilder().resource(output) + .schema(plainOldUserSchemaResource).type(PlainOldUser.class).build(); avroItemWriter.open(new ExecutionContext()); avroItemWriter.write(this.plainOldUsers()); @@ -89,10 +80,8 @@ public class AvroItemWriterBuilderTests extends AvroItemWriterTestSupport { @Test public void itemWriterWithNoEmbeddedSchema() throws Exception { - AvroItemWriter avroItemWriter = new AvroItemWriterBuilder() - .resource(output) - .type(PlainOldUser.class) - .build(); + AvroItemWriter avroItemWriter = new AvroItemWriterBuilder().resource(output) + .type(PlainOldUser.class).build(); avroItemWriter.open(new ExecutionContext()); avroItemWriter.write(this.plainOldUsers()); avroItemWriter.close(); @@ -101,23 +90,17 @@ public class AvroItemWriterBuilderTests extends AvroItemWriterTestSupport { } - @Test(expected = IllegalArgumentException.class) public void shouldFailWitNoOutput() { - new AvroItemWriterBuilder() - .type(GenericRecord.class) - .build(); + new AvroItemWriterBuilder().type(GenericRecord.class).build(); } @Test(expected = IllegalArgumentException.class) public void shouldFailWitNoType() { - new AvroItemWriterBuilder<>() - .resource(output) - .schema(schemaResource) - .build(); + new AvroItemWriterBuilder<>().resource(output).schema(schemaResource).build(); } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/avro/example/AvroTestUtils.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/avro/example/AvroTestUtils.java index be78295e8..8b1bd307b 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/avro/example/AvroTestUtils.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/avro/example/AvroTestUtils.java @@ -35,46 +35,45 @@ import org.springframework.core.io.Resource; */ class AvroTestUtils { - public static void main(String... args) { - try { - createTestDataWithNoEmbeddedSchema(); - createTestData(); - } catch (Exception e) { - e.printStackTrace(); - } - } + public static void main(String... args) { + try { + createTestDataWithNoEmbeddedSchema(); + createTestData(); + } + catch (Exception e) { + e.printStackTrace(); + } + } - static void createTestDataWithNoEmbeddedSchema() throws Exception { + static void createTestDataWithNoEmbeddedSchema() throws Exception { - DatumWriter userDatumWriter = new SpecificDatumWriter<>(User.class); + DatumWriter userDatumWriter = new SpecificDatumWriter<>(User.class); - FileOutputStream fileOutputStream = new FileOutputStream("user-data-no-schema.avro"); + FileOutputStream fileOutputStream = new FileOutputStream("user-data-no-schema.avro"); - Encoder encoder = EncoderFactory.get().binaryEncoder(fileOutputStream,null); - userDatumWriter.write(new User("David", 20, "blue"), encoder); - userDatumWriter.write(new User("Sue", 4, "red"), encoder); - userDatumWriter.write(new User("Alana", 13, "yellow"), encoder); - userDatumWriter.write(new User("Joe", 1, "pink"), encoder); + Encoder encoder = EncoderFactory.get().binaryEncoder(fileOutputStream, null); + userDatumWriter.write(new User("David", 20, "blue"), encoder); + userDatumWriter.write(new User("Sue", 4, "red"), encoder); + userDatumWriter.write(new User("Alana", 13, "yellow"), encoder); + userDatumWriter.write(new User("Joe", 1, "pink"), encoder); - encoder.flush(); - fileOutputStream.flush(); - fileOutputStream.close(); - } + encoder.flush(); + fileOutputStream.flush(); + fileOutputStream.close(); + } + static void createTestData() throws Exception { - static void createTestData() throws Exception { - - Resource schemaResource = new ClassPathResource("org/springframework/batch/item/avro/user-schema.json"); - - DatumWriter userDatumWriter = new SpecificDatumWriter<>(User.class); - DataFileWriter dataFileWriter = new DataFileWriter<>(userDatumWriter); - dataFileWriter.create(new Schema.Parser().parse(schemaResource.getInputStream()), new File("users.avro")); - dataFileWriter.append(new User("David", 20, "blue")); - dataFileWriter.append(new User("Sue", 4, "red")); - dataFileWriter.append(new User("Alana", 13, "yellow")); - dataFileWriter.append(new User("Joe", 1, "pink")); - dataFileWriter.close(); - } + Resource schemaResource = new ClassPathResource("org/springframework/batch/item/avro/user-schema.json"); + DatumWriter userDatumWriter = new SpecificDatumWriter<>(User.class); + DataFileWriter dataFileWriter = new DataFileWriter<>(userDatumWriter); + dataFileWriter.create(new Schema.Parser().parse(schemaResource.getInputStream()), new File("users.avro")); + dataFileWriter.append(new User("David", 20, "blue")); + dataFileWriter.append(new User("Sue", 4, "red")); + dataFileWriter.append(new User("Alana", 13, "yellow")); + dataFileWriter.append(new User("Joe", 1, "pink")); + dataFileWriter.close(); + } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/avro/example/User.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/avro/example/User.java index e755852ec..7efeb9109 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/avro/example/User.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/avro/example/User.java @@ -28,490 +28,518 @@ import org.apache.avro.message.BinaryMessageDecoder; import org.apache.avro.message.SchemaStore; @org.apache.avro.specific.AvroGenerated -public class User extends org.apache.avro.specific.SpecificRecordBase implements org.apache.avro.specific.SpecificRecord { - private static final long serialVersionUID = 1293362237195430714L; - public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"org.springframework.batch.item.avro.example\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"int\",\"null\"]},{\"name\":\"favorite_color\",\"type\":[\"string\",\"null\"]}]}"); - public static org.apache.avro.Schema getClassSchema() { return SCHEMA$; } - - private static SpecificData MODEL$ = new SpecificData(); - - private static final BinaryMessageEncoder ENCODER = - new BinaryMessageEncoder(MODEL$, SCHEMA$); - - private static final BinaryMessageDecoder DECODER = - new BinaryMessageDecoder(MODEL$, SCHEMA$); - - /** - * Return the BinaryMessageEncoder instance used by this class. - * @return the message encoder used by this class - */ - public static BinaryMessageEncoder getEncoder() { - return ENCODER; - } - - /** - * Return the BinaryMessageDecoder instance used by this class. - * @return the message decoder used by this class - */ - public static BinaryMessageDecoder getDecoder() { - return DECODER; - } - - /** - * Create a new BinaryMessageDecoder instance for this class that uses the specified {@link SchemaStore}. - * @param resolver a {@link SchemaStore} used to find schemas by fingerprint - * @return a BinaryMessageDecoder instance for this class backed by the given SchemaStore - */ - public static BinaryMessageDecoder createDecoder(SchemaStore resolver) { - return new BinaryMessageDecoder(MODEL$, SCHEMA$, resolver); - } - - /** - * Serializes this User to a ByteBuffer. - * @return a buffer holding the serialized data for this instance - * @throws java.io.IOException if this instance could not be serialized - */ - public java.nio.ByteBuffer toByteBuffer() throws java.io.IOException { - return ENCODER.encode(this); - } - - /** - * Deserializes a User from a ByteBuffer. - * @param b a byte buffer holding serialized data for an instance of this class - * @return a User instance decoded from the given buffer - * @throws java.io.IOException if the given bytes could not be deserialized into an instance of this class - */ - public static User fromByteBuffer( - java.nio.ByteBuffer b) throws java.io.IOException { - return DECODER.decode(b); - } - - private CharSequence name; - private Integer favorite_number; - private CharSequence favorite_color; - - /** - * Default constructor. Note that this does not initialize fields - * to their default values from the SCHEMA. If that is desired then - * one should use newBuilder(). - */ - public User() {} - - /** - * All-args constructor. - * @param name The new value for name - * @param favorite_number The new value for favorite_number - * @param favorite_color The new value for favorite_color - */ - public User(CharSequence name, Integer favorite_number, CharSequence favorite_color) { - this.name = name; - this.favorite_number = favorite_number; - this.favorite_color = favorite_color; - } - - public SpecificData getSpecificData() { return MODEL$; } - public org.apache.avro.Schema getSchema() { return SCHEMA$; } - // Used by DatumWriter. Applications should not call. - public Object get(int field$) { - switch (field$) { - case 0: return name; - case 1: return favorite_number; - case 2: return favorite_color; - default: throw new org.apache.avro.AvroRuntimeException("Bad index"); - } - } - - // Used by DatumReader. Applications should not call. - @SuppressWarnings(value="unchecked") - public void put(int field$, Object value$) { - switch (field$) { - case 0: name = (CharSequence)value$; break; - case 1: favorite_number = (Integer)value$; break; - case 2: favorite_color = (CharSequence)value$; break; - default: throw new org.apache.avro.AvroRuntimeException("Bad index"); - } - } - - /** - * Gets the value of the 'name' field. - * @return The value of the 'name' field. - */ - public CharSequence getName() { - return name; - } - - - /** - * Sets the value of the 'name' field. - * @param value the value to set. - */ - public void setName(CharSequence value) { - this.name = value; - } - - /** - * Gets the value of the 'favorite_number' field. - * @return The value of the 'favorite_number' field. - */ - public Integer getFavoriteNumber() { - return favorite_number; - } - - - /** - * Sets the value of the 'favorite_number' field. - * @param value the value to set. - */ - public void setFavoriteNumber(Integer value) { - this.favorite_number = value; - } - - /** - * Gets the value of the 'favorite_color' field. - * @return The value of the 'favorite_color' field. - */ - public CharSequence getFavoriteColor() { - return favorite_color; - } - - - /** - * Sets the value of the 'favorite_color' field. - * @param value the value to set. - */ - public void setFavoriteColor(CharSequence value) { - this.favorite_color = value; - } - - /** - * Creates a new User RecordBuilder. - * @return A new User RecordBuilder - */ - public static Builder newBuilder() { - return new Builder(); - } - - /** - * Creates a new User RecordBuilder by copying an existing Builder. - * @param other The existing builder to copy. - * @return A new User RecordBuilder - */ - public static Builder newBuilder(Builder other) { - if (other == null) { - return new Builder(); - } else { - return new Builder(other); - } - } - - /** - * Creates a new User RecordBuilder by copying an existing User instance. - * @param other The existing instance to copy. - * @return A new User RecordBuilder - */ - public static Builder newBuilder(User other) { - if (other == null) { - return new Builder(); - } else { - return new Builder(other); - } - } - - /** - * RecordBuilder for User instances. - */ - public static class Builder extends org.apache.avro.specific.SpecificRecordBuilderBase - implements org.apache.avro.data.RecordBuilder { - - private CharSequence name; - private Integer favorite_number; - private CharSequence favorite_color; - - /** Creates a new Builder */ - private Builder() { - super(SCHEMA$); - } - - /** - * Creates a Builder by copying an existing Builder. - * @param other The existing Builder to copy. - */ - private Builder(Builder other) { - super(other); - if (isValidValue(fields()[0], other.name)) { - this.name = data().deepCopy(fields()[0].schema(), other.name); - fieldSetFlags()[0] = other.fieldSetFlags()[0]; - } - if (isValidValue(fields()[1], other.favorite_number)) { - this.favorite_number = data().deepCopy(fields()[1].schema(), other.favorite_number); - fieldSetFlags()[1] = other.fieldSetFlags()[1]; - } - if (isValidValue(fields()[2], other.favorite_color)) { - this.favorite_color = data().deepCopy(fields()[2].schema(), other.favorite_color); - fieldSetFlags()[2] = other.fieldSetFlags()[2]; - } - } - - /** - * Creates a Builder by copying an existing User instance - * @param other The existing instance to copy. - */ - private Builder(User other) { - super(SCHEMA$); - if (isValidValue(fields()[0], other.name)) { - this.name = data().deepCopy(fields()[0].schema(), other.name); - fieldSetFlags()[0] = true; - } - if (isValidValue(fields()[1], other.favorite_number)) { - this.favorite_number = data().deepCopy(fields()[1].schema(), other.favorite_number); - fieldSetFlags()[1] = true; - } - if (isValidValue(fields()[2], other.favorite_color)) { - this.favorite_color = data().deepCopy(fields()[2].schema(), other.favorite_color); - fieldSetFlags()[2] = true; - } - } - - /** - * Gets the value of the 'name' field. - * @return The value. - */ - public CharSequence getName() { - return name; - } - - - /** - * Sets the value of the 'name' field. - * @param value The value of 'name'. - * @return This builder. - */ - public Builder setName(CharSequence value) { - validate(fields()[0], value); - this.name = value; - fieldSetFlags()[0] = true; - return this; - } - - /** - * Checks whether the 'name' field has been set. - * @return True if the 'name' field has been set, false otherwise. - */ - public boolean hasName() { - return fieldSetFlags()[0]; - } - - - /** - * Clears the value of the 'name' field. - * @return This builder. - */ - public Builder clearName() { - name = null; - fieldSetFlags()[0] = false; - return this; - } - - /** - * Gets the value of the 'favorite_number' field. - * @return The value. - */ - public Integer getFavoriteNumber() { - return favorite_number; - } - - - /** - * Sets the value of the 'favorite_number' field. - * @param value The value of 'favorite_number'. - * @return This builder. - */ - public Builder setFavoriteNumber(Integer value) { - validate(fields()[1], value); - this.favorite_number = value; - fieldSetFlags()[1] = true; - return this; - } - - /** - * Checks whether the 'favorite_number' field has been set. - * @return True if the 'favorite_number' field has been set, false otherwise. - */ - public boolean hasFavoriteNumber() { - return fieldSetFlags()[1]; - } - - - /** - * Clears the value of the 'favorite_number' field. - * @return This builder. - */ - public Builder clearFavoriteNumber() { - favorite_number = null; - fieldSetFlags()[1] = false; - return this; - } - - /** - * Gets the value of the 'favorite_color' field. - * @return The value. - */ - public CharSequence getFavoriteColor() { - return favorite_color; - } - - - /** - * Sets the value of the 'favorite_color' field. - * @param value The value of 'favorite_color'. - * @return This builder. - */ - public Builder setFavoriteColor(CharSequence value) { - validate(fields()[2], value); - this.favorite_color = value; - fieldSetFlags()[2] = true; - return this; - } - - /** - * Checks whether the 'favorite_color' field has been set. - * @return True if the 'favorite_color' field has been set, false otherwise. - */ - public boolean hasFavoriteColor() { - return fieldSetFlags()[2]; - } - - - /** - * Clears the value of the 'favorite_color' field. - * @return This builder. - */ - public Builder clearFavoriteColor() { - favorite_color = null; - fieldSetFlags()[2] = false; - return this; - } - - @Override - @SuppressWarnings("unchecked") - public User build() { - try { - User record = new User(); - record.name = fieldSetFlags()[0] ? this.name : (CharSequence) defaultValue(fields()[0]); - record.favorite_number = fieldSetFlags()[1] ? this.favorite_number : (Integer) defaultValue(fields()[1]); - record.favorite_color = fieldSetFlags()[2] ? this.favorite_color : (CharSequence) defaultValue(fields()[2]); - return record; - } catch (org.apache.avro.AvroMissingFieldException e) { - throw e; - } catch (Exception e) { - throw new org.apache.avro.AvroRuntimeException(e); - } - } - } - - @SuppressWarnings("unchecked") - private static final org.apache.avro.io.DatumWriter - WRITER$ = (org.apache.avro.io.DatumWriter)MODEL$.createDatumWriter(SCHEMA$); - - @Override public void writeExternal(java.io.ObjectOutput out) - throws java.io.IOException { - WRITER$.write(this, SpecificData.getEncoder(out)); - } - - @SuppressWarnings("unchecked") - private static final org.apache.avro.io.DatumReader - READER$ = (org.apache.avro.io.DatumReader)MODEL$.createDatumReader(SCHEMA$); - - @Override public void readExternal(java.io.ObjectInput in) - throws java.io.IOException { - READER$.read(this, SpecificData.getDecoder(in)); - } - - @Override protected boolean hasCustomCoders() { return true; } - - @Override public void customEncode(org.apache.avro.io.Encoder out) - throws java.io.IOException - { - out.writeString(this.name); - - if (this.favorite_number == null) { - out.writeIndex(1); - out.writeNull(); - } else { - out.writeIndex(0); - out.writeInt(this.favorite_number); - } - - if (this.favorite_color == null) { - out.writeIndex(1); - out.writeNull(); - } else { - out.writeIndex(0); - out.writeString(this.favorite_color); - } - - } - - @Override public void customDecode(org.apache.avro.io.ResolvingDecoder in) - throws java.io.IOException - { - org.apache.avro.Schema.Field[] fieldOrder = in.readFieldOrderIfDiff(); - if (fieldOrder == null) { - this.name = in.readString(this.name instanceof Utf8 ? (Utf8)this.name : null); - - if (in.readIndex() != 0) { - in.readNull(); - this.favorite_number = null; - } else { - this.favorite_number = in.readInt(); - } - - if (in.readIndex() != 0) { - in.readNull(); - this.favorite_color = null; - } else { - this.favorite_color = in.readString(this.favorite_color instanceof Utf8 ? (Utf8)this.favorite_color : null); - } - - } else { - for (int i = 0; i < 3; i++) { - switch (fieldOrder[i].pos()) { - case 0: - this.name = in.readString(this.name instanceof Utf8 ? (Utf8)this.name : null); - break; - - case 1: - if (in.readIndex() != 0) { - in.readNull(); - this.favorite_number = null; - } else { - this.favorite_number = in.readInt(); - } - break; - - case 2: - if (in.readIndex() != 0) { - in.readNull(); - this.favorite_color = null; - } else { - this.favorite_color = in.readString(this.favorite_color instanceof Utf8 ? (Utf8)this.favorite_color : null); - } - break; - - default: - throw new java.io.IOException("Corrupt ResolvingDecoder."); - } - } - } - } +public class User extends org.apache.avro.specific.SpecificRecordBase + implements org.apache.avro.specific.SpecificRecord { + + private static final long serialVersionUID = 1293362237195430714L; + + public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse( + "{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"org.springframework.batch.item.avro.example\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"int\",\"null\"]},{\"name\":\"favorite_color\",\"type\":[\"string\",\"null\"]}]}"); + + public static org.apache.avro.Schema getClassSchema() { + return SCHEMA$; + } + + private static SpecificData MODEL$ = new SpecificData(); + + private static final BinaryMessageEncoder ENCODER = new BinaryMessageEncoder(MODEL$, SCHEMA$); + + private static final BinaryMessageDecoder DECODER = new BinaryMessageDecoder(MODEL$, SCHEMA$); + + /** + * Return the BinaryMessageEncoder instance used by this class. + * @return the message encoder used by this class + */ + public static BinaryMessageEncoder getEncoder() { + return ENCODER; + } + + /** + * Return the BinaryMessageDecoder instance used by this class. + * @return the message decoder used by this class + */ + public static BinaryMessageDecoder getDecoder() { + return DECODER; + } + + /** + * Create a new BinaryMessageDecoder instance for this class that uses the specified + * {@link SchemaStore}. + * @param resolver a {@link SchemaStore} used to find schemas by fingerprint + * @return a BinaryMessageDecoder instance for this class backed by the given + * SchemaStore + */ + public static BinaryMessageDecoder createDecoder(SchemaStore resolver) { + return new BinaryMessageDecoder(MODEL$, SCHEMA$, resolver); + } + + /** + * Serializes this User to a ByteBuffer. + * @return a buffer holding the serialized data for this instance + * @throws java.io.IOException if this instance could not be serialized + */ + public java.nio.ByteBuffer toByteBuffer() throws java.io.IOException { + return ENCODER.encode(this); + } + + /** + * Deserializes a User from a ByteBuffer. + * @param b a byte buffer holding serialized data for an instance of this class + * @return a User instance decoded from the given buffer + * @throws java.io.IOException if the given bytes could not be deserialized into an + * instance of this class + */ + public static User fromByteBuffer(java.nio.ByteBuffer b) throws java.io.IOException { + return DECODER.decode(b); + } + + private CharSequence name; + + private Integer favorite_number; + + private CharSequence favorite_color; + + /** + * Default constructor. Note that this does not initialize fields to their default + * values from the SCHEMA. If that is desired then one should use + * newBuilder(). + */ + public User() { + } + + /** + * All-args constructor. + * @param name The new value for name + * @param favorite_number The new value for favorite_number + * @param favorite_color The new value for favorite_color + */ + public User(CharSequence name, Integer favorite_number, CharSequence favorite_color) { + this.name = name; + this.favorite_number = favorite_number; + this.favorite_color = favorite_color; + } + + public SpecificData getSpecificData() { + return MODEL$; + } + + public org.apache.avro.Schema getSchema() { + return SCHEMA$; + } + + // Used by DatumWriter. Applications should not call. + public Object get(int field$) { + switch (field$) { + case 0: + return name; + case 1: + return favorite_number; + case 2: + return favorite_color; + default: + throw new org.apache.avro.AvroRuntimeException("Bad index"); + } + } + + // Used by DatumReader. Applications should not call. + @SuppressWarnings(value = "unchecked") + public void put(int field$, Object value$) { + switch (field$) { + case 0: + name = (CharSequence) value$; + break; + case 1: + favorite_number = (Integer) value$; + break; + case 2: + favorite_color = (CharSequence) value$; + break; + default: + throw new org.apache.avro.AvroRuntimeException("Bad index"); + } + } + + /** + * Gets the value of the 'name' field. + * @return The value of the 'name' field. + */ + public CharSequence getName() { + return name; + } + + /** + * Sets the value of the 'name' field. + * @param value the value to set. + */ + public void setName(CharSequence value) { + this.name = value; + } + + /** + * Gets the value of the 'favorite_number' field. + * @return The value of the 'favorite_number' field. + */ + public Integer getFavoriteNumber() { + return favorite_number; + } + + /** + * Sets the value of the 'favorite_number' field. + * @param value the value to set. + */ + public void setFavoriteNumber(Integer value) { + this.favorite_number = value; + } + + /** + * Gets the value of the 'favorite_color' field. + * @return The value of the 'favorite_color' field. + */ + public CharSequence getFavoriteColor() { + return favorite_color; + } + + /** + * Sets the value of the 'favorite_color' field. + * @param value the value to set. + */ + public void setFavoriteColor(CharSequence value) { + this.favorite_color = value; + } + + /** + * Creates a new User RecordBuilder. + * @return A new User RecordBuilder + */ + public static Builder newBuilder() { + return new Builder(); + } + + /** + * Creates a new User RecordBuilder by copying an existing Builder. + * @param other The existing builder to copy. + * @return A new User RecordBuilder + */ + public static Builder newBuilder(Builder other) { + if (other == null) { + return new Builder(); + } + else { + return new Builder(other); + } + } + + /** + * Creates a new User RecordBuilder by copying an existing User instance. + * @param other The existing instance to copy. + * @return A new User RecordBuilder + */ + public static Builder newBuilder(User other) { + if (other == null) { + return new Builder(); + } + else { + return new Builder(other); + } + } + + /** + * RecordBuilder for User instances. + */ + public static class Builder extends org.apache.avro.specific.SpecificRecordBuilderBase + implements org.apache.avro.data.RecordBuilder { + + private CharSequence name; + + private Integer favorite_number; + + private CharSequence favorite_color; + + /** Creates a new Builder */ + private Builder() { + super(SCHEMA$); + } + + /** + * Creates a Builder by copying an existing Builder. + * @param other The existing Builder to copy. + */ + private Builder(Builder other) { + super(other); + if (isValidValue(fields()[0], other.name)) { + this.name = data().deepCopy(fields()[0].schema(), other.name); + fieldSetFlags()[0] = other.fieldSetFlags()[0]; + } + if (isValidValue(fields()[1], other.favorite_number)) { + this.favorite_number = data().deepCopy(fields()[1].schema(), other.favorite_number); + fieldSetFlags()[1] = other.fieldSetFlags()[1]; + } + if (isValidValue(fields()[2], other.favorite_color)) { + this.favorite_color = data().deepCopy(fields()[2].schema(), other.favorite_color); + fieldSetFlags()[2] = other.fieldSetFlags()[2]; + } + } + + /** + * Creates a Builder by copying an existing User instance + * @param other The existing instance to copy. + */ + private Builder(User other) { + super(SCHEMA$); + if (isValidValue(fields()[0], other.name)) { + this.name = data().deepCopy(fields()[0].schema(), other.name); + fieldSetFlags()[0] = true; + } + if (isValidValue(fields()[1], other.favorite_number)) { + this.favorite_number = data().deepCopy(fields()[1].schema(), other.favorite_number); + fieldSetFlags()[1] = true; + } + if (isValidValue(fields()[2], other.favorite_color)) { + this.favorite_color = data().deepCopy(fields()[2].schema(), other.favorite_color); + fieldSetFlags()[2] = true; + } + } + + /** + * Gets the value of the 'name' field. + * @return The value. + */ + public CharSequence getName() { + return name; + } + + /** + * Sets the value of the 'name' field. + * @param value The value of 'name'. + * @return This builder. + */ + public Builder setName(CharSequence value) { + validate(fields()[0], value); + this.name = value; + fieldSetFlags()[0] = true; + return this; + } + + /** + * Checks whether the 'name' field has been set. + * @return True if the 'name' field has been set, false otherwise. + */ + public boolean hasName() { + return fieldSetFlags()[0]; + } + + /** + * Clears the value of the 'name' field. + * @return This builder. + */ + public Builder clearName() { + name = null; + fieldSetFlags()[0] = false; + return this; + } + + /** + * Gets the value of the 'favorite_number' field. + * @return The value. + */ + public Integer getFavoriteNumber() { + return favorite_number; + } + + /** + * Sets the value of the 'favorite_number' field. + * @param value The value of 'favorite_number'. + * @return This builder. + */ + public Builder setFavoriteNumber(Integer value) { + validate(fields()[1], value); + this.favorite_number = value; + fieldSetFlags()[1] = true; + return this; + } + + /** + * Checks whether the 'favorite_number' field has been set. + * @return True if the 'favorite_number' field has been set, false otherwise. + */ + public boolean hasFavoriteNumber() { + return fieldSetFlags()[1]; + } + + /** + * Clears the value of the 'favorite_number' field. + * @return This builder. + */ + public Builder clearFavoriteNumber() { + favorite_number = null; + fieldSetFlags()[1] = false; + return this; + } + + /** + * Gets the value of the 'favorite_color' field. + * @return The value. + */ + public CharSequence getFavoriteColor() { + return favorite_color; + } + + /** + * Sets the value of the 'favorite_color' field. + * @param value The value of 'favorite_color'. + * @return This builder. + */ + public Builder setFavoriteColor(CharSequence value) { + validate(fields()[2], value); + this.favorite_color = value; + fieldSetFlags()[2] = true; + return this; + } + + /** + * Checks whether the 'favorite_color' field has been set. + * @return True if the 'favorite_color' field has been set, false otherwise. + */ + public boolean hasFavoriteColor() { + return fieldSetFlags()[2]; + } + + /** + * Clears the value of the 'favorite_color' field. + * @return This builder. + */ + public Builder clearFavoriteColor() { + favorite_color = null; + fieldSetFlags()[2] = false; + return this; + } + + @Override + @SuppressWarnings("unchecked") + public User build() { + try { + User record = new User(); + record.name = fieldSetFlags()[0] ? this.name : (CharSequence) defaultValue(fields()[0]); + record.favorite_number = fieldSetFlags()[1] ? this.favorite_number + : (Integer) defaultValue(fields()[1]); + record.favorite_color = fieldSetFlags()[2] ? this.favorite_color + : (CharSequence) defaultValue(fields()[2]); + return record; + } + catch (org.apache.avro.AvroMissingFieldException e) { + throw e; + } + catch (Exception e) { + throw new org.apache.avro.AvroRuntimeException(e); + } + } + + } + + @SuppressWarnings("unchecked") + private static final org.apache.avro.io.DatumWriter WRITER$ = (org.apache.avro.io.DatumWriter) MODEL$ + .createDatumWriter(SCHEMA$); + + @Override + public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException { + WRITER$.write(this, SpecificData.getEncoder(out)); + } + + @SuppressWarnings("unchecked") + private static final org.apache.avro.io.DatumReader READER$ = (org.apache.avro.io.DatumReader) MODEL$ + .createDatumReader(SCHEMA$); + + @Override + public void readExternal(java.io.ObjectInput in) throws java.io.IOException { + READER$.read(this, SpecificData.getDecoder(in)); + } + + @Override + protected boolean hasCustomCoders() { + return true; + } + + @Override + public void customEncode(org.apache.avro.io.Encoder out) throws java.io.IOException { + out.writeString(this.name); + + if (this.favorite_number == null) { + out.writeIndex(1); + out.writeNull(); + } + else { + out.writeIndex(0); + out.writeInt(this.favorite_number); + } + + if (this.favorite_color == null) { + out.writeIndex(1); + out.writeNull(); + } + else { + out.writeIndex(0); + out.writeString(this.favorite_color); + } + + } + + @Override + public void customDecode(org.apache.avro.io.ResolvingDecoder in) throws java.io.IOException { + org.apache.avro.Schema.Field[] fieldOrder = in.readFieldOrderIfDiff(); + if (fieldOrder == null) { + this.name = in.readString(this.name instanceof Utf8 ? (Utf8) this.name : null); + + if (in.readIndex() != 0) { + in.readNull(); + this.favorite_number = null; + } + else { + this.favorite_number = in.readInt(); + } + + if (in.readIndex() != 0) { + in.readNull(); + this.favorite_color = null; + } + else { + this.favorite_color = in + .readString(this.favorite_color instanceof Utf8 ? (Utf8) this.favorite_color : null); + } + + } + else { + for (int i = 0; i < 3; i++) { + switch (fieldOrder[i].pos()) { + case 0: + this.name = in.readString(this.name instanceof Utf8 ? (Utf8) this.name : null); + break; + + case 1: + if (in.readIndex() != 0) { + in.readNull(); + this.favorite_number = null; + } + else { + this.favorite_number = in.readInt(); + } + break; + + case 2: + if (in.readIndex() != 0) { + in.readNull(); + this.favorite_color = null; + } + else { + this.favorite_color = in + .readString(this.favorite_color instanceof Utf8 ? (Utf8) this.favorite_color : null); + } + break; + + default: + throw new java.io.IOException("Corrupt ResolvingDecoder."); + } + } + } + } + } - - - - - - - - - - diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/avro/support/AvroItemReaderTestSupport.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/avro/support/AvroItemReaderTestSupport.java index 62bb321ad..76dc7e4b3 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/avro/support/AvroItemReaderTestSupport.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/avro/support/AvroItemReaderTestSupport.java @@ -44,4 +44,5 @@ public abstract class AvroItemReaderTestSupport extends AvroTestFixtures { avroItemReader.close(); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/avro/support/AvroItemWriterTestSupport.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/avro/support/AvroItemWriterTestSupport.java index fb9cf2ffc..4586b0f87 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/avro/support/AvroItemWriterTestSupport.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/avro/support/AvroItemWriterTestSupport.java @@ -39,99 +39,96 @@ import static org.assertj.core.api.Assertions.assertThat; */ public abstract class AvroItemWriterTestSupport extends AvroTestFixtures { - /* - * This item reader configured for Specific Avro types. - */ - protected void verifyRecords(byte[] bytes, List actual, Class clazz, boolean embeddedSchema) throws Exception { - doVerify(bytes, clazz, actual, embeddedSchema); - } + /* + * This item reader configured for Specific Avro types. + */ + protected void verifyRecords(byte[] bytes, List actual, Class clazz, boolean embeddedSchema) + throws Exception { + doVerify(bytes, clazz, actual, embeddedSchema); + } - protected void verifyRecordsWithEmbeddedHeader(byte[] bytes, List actual, Class clazz) throws Exception { - doVerify(bytes, clazz, actual, true); - } + protected void verifyRecordsWithEmbeddedHeader(byte[] bytes, List actual, Class clazz) throws Exception { + doVerify(bytes, clazz, actual, true); + } + private void doVerify(byte[] bytes, Class clazz, List actual, boolean embeddedSchema) throws Exception { + AvroItemReader avroItemReader = new AvroItemReaderBuilder().type(clazz) + .resource(new ByteArrayResource(bytes)).embeddedSchema(embeddedSchema).build(); - private void doVerify(byte[] bytes, Class clazz, List actual, boolean embeddedSchema) throws Exception { - AvroItemReader avroItemReader = new AvroItemReaderBuilder() - .type(clazz) - .resource(new ByteArrayResource(bytes)) - .embeddedSchema(embeddedSchema) - .build(); + avroItemReader.open(new ExecutionContext()); - avroItemReader.open(new ExecutionContext()); + List records = new ArrayList<>(); + T record; + while ((record = avroItemReader.read()) != null) { + records.add(record); + } + assertThat(records).hasSize(4); + assertThat(records).containsExactlyInAnyOrder(actual.get(0), actual.get(1), actual.get(2), actual.get(3)); + } - List records = new ArrayList<>(); - T record; - while ((record = avroItemReader.read()) != null) { - records.add(record); - } - assertThat(records).hasSize(4); - assertThat(records).containsExactlyInAnyOrder(actual.get(0), actual.get(1), actual.get(2), actual.get(3)); - } + protected static class OutputStreamResource implements WritableResource { + final private OutputStream outputStream; - protected static class OutputStreamResource implements WritableResource { + public OutputStreamResource(OutputStream outputStream) { + this.outputStream = outputStream; + } - final private OutputStream outputStream; + @Override + public OutputStream getOutputStream() throws IOException { + return this.outputStream; + } - public OutputStreamResource(OutputStream outputStream) { - this.outputStream = outputStream; - } + @Override + public boolean exists() { + return true; + } - @Override - public OutputStream getOutputStream() throws IOException { - return this.outputStream; - } + @Override + public URL getURL() throws IOException { + return null; + } - @Override - public boolean exists() { - return true; - } + @Override + public URI getURI() throws IOException { + return null; + } - @Override - public URL getURL() throws IOException { - return null; - } + @Override + public File getFile() throws IOException { + return null; + } - @Override - public URI getURI() throws IOException { - return null; - } + @Override + public long contentLength() throws IOException { + return 0; + } - @Override - public File getFile() throws IOException { - return null; - } + @Override + public long lastModified() throws IOException { + return 0; + } - @Override - public long contentLength() throws IOException { - return 0; - } + @Override + public Resource createRelative(String relativePath) throws IOException { + return null; + } - @Override - public long lastModified() throws IOException { - return 0; - } + @Override + public String getFilename() { + return null; + } - @Override - public Resource createRelative(String relativePath) throws IOException { - return null; - } + @Override + public String getDescription() { + return "Output stream resource"; + } - @Override - public String getFilename() { - return null; - } + @Override + public InputStream getInputStream() throws IOException { + return null; + } - @Override - public String getDescription() { - return "Output stream resource"; - } - - @Override - public InputStream getInputStream() throws IOException { - return null; - } - } + } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/avro/support/AvroTestFixtures.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/avro/support/AvroTestFixtures.java index 2d1a6a7f0..968cd84f6 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/avro/support/AvroTestFixtures.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/avro/support/AvroTestFixtures.java @@ -58,10 +58,8 @@ public abstract class AvroTestFixtures { new PlainOldUser("Joe", 1, "pink")); //@formatter:on - protected Resource schemaResource = new ClassPathResource("org/springframework/batch/item/avro/user-schema.json"); - protected Resource plainOldUserSchemaResource = new ByteArrayResource(PlainOldUser.SCHEMA.toString().getBytes()); // Serialized data only @@ -72,8 +70,8 @@ public abstract class AvroTestFixtures { protected Resource dataResourceWithSchema = new ClassPathResource( "org/springframework/batch/item/avro/user-data.avro"); - protected Resource plainOldUserDataResource - = new ClassPathResource("org/springframework/batch/item/avro/plain-old-user-data-no-schema.avro"); + protected Resource plainOldUserDataResource = new ClassPathResource( + "org/springframework/batch/item/avro/plain-old-user-data-no-schema.avro"); protected String schemaString(Resource resource) { { @@ -93,15 +91,14 @@ public abstract class AvroTestFixtures { } protected List genericAvroGeneratedUsers() { - return this.avroGeneratedUsers.stream().map(u-> { - GenericData.Record avroRecord; - avroRecord = new GenericData.Record(u.getSchema()); - avroRecord.put("name", u.getName()); - avroRecord.put("favorite_number", u.getFavoriteNumber()); - avroRecord.put("favorite_color",u.getFavoriteColor()); - return avroRecord; - } - ).collect(Collectors.toList()); + return this.avroGeneratedUsers.stream().map(u -> { + GenericData.Record avroRecord; + avroRecord = new GenericData.Record(u.getSchema()); + avroRecord.put("name", u.getName()); + avroRecord.put("favorite_number", u.getFavoriteNumber()); + avroRecord.put("favorite_color", u.getFavoriteColor()); + return avroRecord; + }).collect(Collectors.toList()); } protected List plainOldUsers() { @@ -113,14 +110,16 @@ public abstract class AvroTestFixtures { } protected static class PlainOldUser { + public static final Schema SCHEMA = ReflectData.get().getSchema(PlainOldUser.class); + private CharSequence name; private int favoriteNumber; private CharSequence favoriteColor; - public PlainOldUser(){ + public PlainOldUser() { } @@ -146,33 +145,35 @@ public abstract class AvroTestFixtures { GenericData.Record avroRecord = new GenericData.Record(SCHEMA); avroRecord.put("name", this.name); avroRecord.put("favoriteNumber", this.favoriteNumber); - avroRecord.put("favoriteColor",this.favoriteColor); + avroRecord.put("favoriteColor", this.favoriteColor); return avroRecord; } @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; PlainOldUser that = (PlainOldUser) o; - return favoriteNumber == that.favoriteNumber && - Objects.equals(name, that.name) && - Objects.equals(favoriteColor, that.favoriteColor); + return favoriteNumber == that.favoriteNumber && Objects.equals(name, that.name) + && Objects.equals(favoriteColor, that.favoriteColor); } @Override public int hashCode() { return Objects.hash(name, favoriteNumber, favoriteColor); } + } public static void createPlainOldUsersWithNoEmbeddedSchema() throws Exception { DatumWriter userDatumWriter = new ReflectDatumWriter<>(AvroTestFixtures.PlainOldUser.class); - FileOutputStream fileOutputStream = new FileOutputStream("plain-old-user-data-no-schema.avro"); + FileOutputStream fileOutputStream = new FileOutputStream("plain-old-user-data-no-schema.avro"); - Encoder encoder = EncoderFactory.get().binaryEncoder(fileOutputStream,null); + Encoder encoder = EncoderFactory.get().binaryEncoder(fileOutputStream, null); userDatumWriter.write(new PlainOldUser("David", 20, "blue"), encoder); userDatumWriter.write(new PlainOldUser("Sue", 4, "red"), encoder); userDatumWriter.write(new PlainOldUser("Alana", 13, "yellow"), encoder); @@ -182,4 +183,5 @@ public abstract class AvroTestFixtures { fileOutputStream.flush(); fileOutputStream.close(); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/GemfireItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/GemfireItemWriterTests.java index 80e13d51b..fad7cb850 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/GemfireItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/GemfireItemWriterTests.java @@ -39,6 +39,7 @@ public class GemfireItemWriterTests { public MockitoRule rule = MockitoJUnit.rule().silent(); private GemfireItemWriter writer; + @Mock private GemfireTemplate template; @@ -57,14 +58,16 @@ public class GemfireItemWriterTests { try { writer.afterPropertiesSet(); fail("Expected exception was not thrown"); - } catch (IllegalArgumentException iae) { + } + catch (IllegalArgumentException iae) { } writer.setTemplate(template); try { writer.afterPropertiesSet(); fail("Expected exception was not thrown"); - } catch (IllegalArgumentException iae) { + } + catch (IllegalArgumentException iae) { } writer.setItemKeyMapper(new SpELItemKeyMapper<>("foo")); @@ -133,18 +136,23 @@ public class GemfireItemWriterTests { } static class Foo { + public Bar bar; public Foo(Bar bar) { this.bar = bar; } + } static class Bar { + public String val; public Bar(String b1) { this.val = b1; } + } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/MongoItemReaderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/MongoItemReaderTests.java index 35471b0a6..936150ca8 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/MongoItemReaderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/MongoItemReaderTests.java @@ -51,8 +51,10 @@ public class MongoItemReaderTests { public MockitoRule rule = MockitoJUnit.rule().silent(); private MongoItemReader reader; + @Mock private MongoOperations template; + private Map sortOptions; @Before @@ -71,15 +73,17 @@ public class MongoItemReaderTests { } @Test - public void testAfterPropertiesSetForQueryString() throws Exception{ + public void testAfterPropertiesSetForQueryString() throws Exception { reader = new MongoItemReader<>(); try { reader.afterPropertiesSet(); fail("Template was not set but exception was not thrown."); - } catch (IllegalStateException iae) { + } + catch (IllegalStateException iae) { assertEquals("An implementation of MongoOperations is required.", iae.getMessage()); - } catch (Throwable t) { + } + catch (Throwable t) { fail("Wrong exception was thrown."); } @@ -88,9 +92,11 @@ public class MongoItemReaderTests { try { reader.afterPropertiesSet(); fail("type was not set but exception was not thrown."); - } catch (IllegalStateException iae) { + } + catch (IllegalStateException iae) { assertEquals("A type to convert the input into is required.", iae.getMessage()); - } catch (Throwable t) { + } + catch (Throwable t) { fail("Wrong exception was thrown."); } @@ -99,9 +105,11 @@ public class MongoItemReaderTests { try { reader.afterPropertiesSet(); fail("Query was not set but exception was not thrown."); - } catch (IllegalStateException iae) { + } + catch (IllegalStateException iae) { assertEquals("A query is required.", iae.getMessage()); - } catch (Throwable t) { + } + catch (Throwable t) { fail("Wrong exception was thrown."); } @@ -110,9 +118,11 @@ public class MongoItemReaderTests { try { reader.afterPropertiesSet(); fail("Sort was not set but exception was not thrown."); - } catch (IllegalStateException iae) { + } + catch (IllegalStateException iae) { assertEquals("A sort is required.", iae.getMessage()); - } catch (Throwable t) { + } + catch (Throwable t) { fail("Wrong exception was thrown."); } @@ -120,14 +130,14 @@ public class MongoItemReaderTests { reader.afterPropertiesSet(); } - + @Test - public void testAfterPropertiesSetForQueryObject() throws Exception{ + public void testAfterPropertiesSetForQueryObject() throws Exception { reader = new MongoItemReader<>(); - + reader.setTemplate(template); reader.setTargetType(String.class); - + Query query1 = new Query().with(Sort.by(new Order(Sort.Direction.ASC, "_id"))); reader.setQuery(query1); @@ -230,7 +240,8 @@ public class MongoItemReaderTests { ArgumentCaptor queryContainer = ArgumentCaptor.forClass(Query.class); ArgumentCaptor collectionContainer = ArgumentCaptor.forClass(String.class); - when(template.find(queryContainer.capture(), eq(String.class), collectionContainer.capture())).thenReturn(new ArrayList<>()); + when(template.find(queryContainer.capture(), eq(String.class), collectionContainer.capture())) + .thenReturn(new ArrayList<>()); assertFalse(reader.doPageRead().hasNext()); @@ -241,73 +252,68 @@ public class MongoItemReaderTests { assertEquals("{\"name\": -1}", query.getSortObject().toJson()); assertEquals("collection", collectionContainer.getValue()); } - + @Test public void testQueryObject() throws Exception { reader = new MongoItemReader<>(); reader.setTemplate(template); - - Query query = new Query() - .with(Sort.by(new Order(Sort.Direction.ASC, "_id"))); + + Query query = new Query().with(Sort.by(new Order(Sort.Direction.ASC, "_id"))); reader.setQuery(query); reader.setTargetType(String.class); - + reader.afterPropertiesSet(); - + ArgumentCaptor queryContainer = ArgumentCaptor.forClass(Query.class); when(template.find(queryContainer.capture(), eq(String.class))).thenReturn(new ArrayList<>()); - + assertFalse(reader.doPageRead().hasNext()); - + Query actualQuery = queryContainer.getValue(); assertFalse(reader.doPageRead().hasNext()); assertEquals(10, actualQuery.getLimit()); assertEquals(0, actualQuery.getSkip()); } - + @Test public void testQueryObjectWithIgnoredPageSize() throws Exception { reader = new MongoItemReader<>(); reader.setTemplate(template); - - Query query = new Query() - .with(Sort.by(new Order(Sort.Direction.ASC, "_id"))) - .with(PageRequest.of(0, 50)); + + Query query = new Query().with(Sort.by(new Order(Sort.Direction.ASC, "_id"))).with(PageRequest.of(0, 50)); reader.setQuery(query); reader.setTargetType(String.class); - + reader.afterPropertiesSet(); - + ArgumentCaptor queryContainer = ArgumentCaptor.forClass(Query.class); when(template.find(queryContainer.capture(), eq(String.class))).thenReturn(new ArrayList<>()); - + assertFalse(reader.doPageRead().hasNext()); - + Query actualQuery = queryContainer.getValue(); assertFalse(reader.doPageRead().hasNext()); assertEquals(10, actualQuery.getLimit()); assertEquals(0, actualQuery.getSkip()); } - + @Test public void testQueryObjectWithPageSize() throws Exception { reader = new MongoItemReader<>(); reader.setTemplate(template); - - Query query = new Query() - .with(Sort.by(new Order(Sort.Direction.ASC, "_id"))) - .with(PageRequest.of(30, 50)); + + Query query = new Query().with(Sort.by(new Order(Sort.Direction.ASC, "_id"))).with(PageRequest.of(30, 50)); reader.setQuery(query); reader.setTargetType(String.class); reader.setPageSize(100); - + reader.afterPropertiesSet(); - + ArgumentCaptor queryContainer = ArgumentCaptor.forClass(Query.class); when(template.find(queryContainer.capture(), eq(String.class))).thenReturn(new ArrayList<>()); - + assertFalse(reader.doPageRead().hasNext()); - + Query actualQuery = queryContainer.getValue(); assertFalse(reader.doPageRead().hasNext()); assertEquals(100, actualQuery.getLimit()); @@ -357,21 +363,21 @@ public class MongoItemReaderTests { public void testQueryObjectWithCollection() throws Exception { reader = new MongoItemReader<>(); reader.setTemplate(template); - - Query query = new Query() - .with(Sort.by(new Order(Sort.Direction.ASC, "_id"))); + + Query query = new Query().with(Sort.by(new Order(Sort.Direction.ASC, "_id"))); reader.setQuery(query); reader.setTargetType(String.class); reader.setCollection("collection"); - + reader.afterPropertiesSet(); - + ArgumentCaptor queryContainer = ArgumentCaptor.forClass(Query.class); ArgumentCaptor stringContainer = ArgumentCaptor.forClass(String.class); - when(template.find(queryContainer.capture(), eq(String.class), stringContainer.capture())).thenReturn(new ArrayList<>()); - + when(template.find(queryContainer.capture(), eq(String.class), stringContainer.capture())) + .thenReturn(new ArrayList<>()); + assertFalse(reader.doPageRead().hasNext()); - + Query actualQuery = queryContainer.getValue(); assertFalse(reader.doPageRead().hasNext()); assertEquals(10, actualQuery.getLimit()); @@ -385,8 +391,8 @@ public class MongoItemReaderTests { reader = new MongoItemReader<>(); // when + then - assertThatIllegalArgumentException() - .isThrownBy(() -> reader.setSort(null)) - .withMessage("Sorts must not be null"); + assertThatIllegalArgumentException().isThrownBy(() -> reader.setSort(null)) + .withMessage("Sorts must not be null"); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/MongoItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/MongoItemWriterTests.java index 47711d43f..0fe701ab6 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/MongoItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/MongoItemWriterTests.java @@ -67,10 +67,13 @@ public class MongoItemWriterTests { public MockitoRule rule = MockitoJUnit.rule().silent(); private MongoItemWriter writer; + @Mock private MongoOperations template; + @Mock private BulkOperations bulkOperations; + @Mock DbRefResolver dbRefResolver; @@ -97,7 +100,8 @@ public class MongoItemWriterTests { try { writer.afterPropertiesSet(); fail("Expected exception was not thrown"); - } catch (IllegalStateException ignore) { + } + catch (IllegalStateException ignore) { } writer.setTemplate(template); @@ -141,7 +145,8 @@ public class MongoItemWriterTests { new TransactionTemplate(transactionManager).execute((TransactionCallback) status -> { try { writer.write(items); - } catch (Exception e) { + } + catch (Exception e) { fail("An exception was thrown while writing: " + e.getMessage()); } @@ -161,7 +166,8 @@ public class MongoItemWriterTests { new TransactionTemplate(transactionManager).execute((TransactionCallback) status -> { try { writer.write(items); - } catch (Exception e) { + } + catch (Exception e) { fail("An exception was thrown while writing: " + e.getMessage()); } @@ -182,14 +188,17 @@ public class MongoItemWriterTests { new TransactionTemplate(transactionManager).execute((TransactionCallback) status -> { try { writer.write(items); - } catch (Exception ignore) { + } + catch (Exception ignore) { fail("unexpected exception thrown"); } throw new RuntimeException("force rollback"); }); - } catch (RuntimeException re) { + } + catch (RuntimeException re) { assertEquals(re.getMessage(), "force rollback"); - } catch (Throwable t) { + } + catch (Throwable t) { fail("Unexpected exception was thrown"); } @@ -213,12 +222,14 @@ public class MongoItemWriterTests { transactionTemplate.execute((TransactionCallback) status -> { try { writer.write(items); - } catch (Exception ignore) { + } + catch (Exception ignore) { fail("unexpected exception thrown"); } return null; }); - } catch (Throwable t) { + } + catch (Throwable t) { fail("Unexpected exception was thrown"); } @@ -269,7 +280,7 @@ public class MongoItemWriterTests { writer.write(items); - verify(template).bulkOps(any(), eq("collection")); + verify(template).bulkOps(any(), eq("collection")); verify(bulkOperations, times(2)).remove(any(Query.class)); } @@ -280,7 +291,7 @@ public class MongoItemWriterTests { List> writers = new ArrayList<>(limit); final String[] documents = new String[limit]; final String[] results = new String[limit]; - for(int i = 0; i< limit; i++) { + for (int i = 0; i < limit; i++) { final int index = i; MongoOperations mongoOperations = mock(MongoOperations.class); BulkOperations bulkOperations = mock(BulkOperations.class); @@ -289,16 +300,18 @@ public class MongoItemWriterTests { when(mongoOperations.bulkOps(any(), any(Class.class))).thenReturn(bulkOperations); when(mongoOperations.getConverter()).thenReturn(mongoConverter); - // mocking the object to document conversion which is used in forming bulk operation + // mocking the object to document conversion which is used in forming bulk + // operation doAnswer(invocation -> { documents[index] = (String) invocation.getArguments()[0]; return null; }).when(mongoConverter).write(any(String.class), any(Document.class)); doAnswer(invocation -> { - if(results[index] == null) { + if (results[index] == null) { results[index] = documents[index]; - } else { + } + else { results[index] += documents[index]; } return null; @@ -310,7 +323,7 @@ public class MongoItemWriterTests { new TransactionTemplate(transactionManager).execute((TransactionCallback) status -> { try { - for(int i=0; i< limit; i++) { + for (int i = 0; i < limit; i++) { writers.get(i).write(Collections.singletonList(String.valueOf(i))); } } @@ -320,19 +333,25 @@ public class MongoItemWriterTests { return null; }); - for(int i=0; i< limit; i++) { + for (int i = 0; i < limit; i++) { assertEquals(String.valueOf(i), results[i]); } } static class Item { + Integer id; + String name; + public Item(Integer id) { this.id = id; } + public Item(String name) { this.name = name; } + } + } \ No newline at end of file diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/Neo4jItemReaderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/Neo4jItemReaderTests.java index f8b1eb276..50bbdf58b 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/Neo4jItemReaderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/Neo4jItemReaderTests.java @@ -44,8 +44,10 @@ public class Neo4jItemReaderTests { @Mock private Iterable result; + @Mock private SessionFactory sessionFactory; + @Mock private Session session; @@ -71,9 +73,11 @@ public class Neo4jItemReaderTests { try { reader.afterPropertiesSet(); fail("SessionFactory was not set but exception was not thrown."); - } catch (IllegalStateException iae) { + } + catch (IllegalStateException iae) { assertEquals("A SessionFactory is required", iae.getMessage()); - } catch (Throwable t) { + } + catch (Throwable t) { fail("Wrong exception was thrown:" + t); } @@ -82,9 +86,11 @@ public class Neo4jItemReaderTests { try { reader.afterPropertiesSet(); fail("Target Type was not set but exception was not thrown."); - } catch (IllegalStateException iae) { + } + catch (IllegalStateException iae) { assertEquals("The type to be returned is required", iae.getMessage()); - } catch (Throwable t) { + } + catch (Throwable t) { fail("Wrong exception was thrown:" + t); } @@ -93,9 +99,11 @@ public class Neo4jItemReaderTests { try { reader.afterPropertiesSet(); fail("START was not set but exception was not thrown."); - } catch (IllegalStateException iae) { + } + catch (IllegalStateException iae) { assertEquals("A START statement is required", iae.getMessage()); - } catch (Throwable t) { + } + catch (Throwable t) { fail("Wrong exception was thrown:" + t); } @@ -104,9 +112,11 @@ public class Neo4jItemReaderTests { try { reader.afterPropertiesSet(); fail("RETURN was not set but exception was not thrown."); - } catch (IllegalStateException iae) { + } + catch (IllegalStateException iae) { assertEquals("A RETURN statement is required", iae.getMessage()); - } catch (Throwable t) { + } + catch (Throwable t) { fail("Wrong exception was thrown:" + t); } @@ -115,9 +125,11 @@ public class Neo4jItemReaderTests { try { reader.afterPropertiesSet(); fail("ORDER BY was not set but exception was not thrown."); - } catch (IllegalStateException iae) { + } + catch (IllegalStateException iae) { assertEquals("A ORDER BY statement is required", iae.getMessage()); - } catch (Throwable t) { + } + catch (Throwable t) { fail("Wrong exception was thrown:" + t); } @@ -174,7 +186,9 @@ public class Neo4jItemReaderTests { itemReader.afterPropertiesSet(); when(this.sessionFactory.openSession()).thenReturn(this.session); - when(this.session.query(String.class, "START n=node(*) MATCH n -- m WHERE has(n.name) RETURN m ORDER BY n.age SKIP 0 LIMIT 50", null)).thenReturn(result); + when(this.session.query(String.class, + "START n=node(*) MATCH n -- m WHERE has(n.name) RETURN m ORDER BY n.age SKIP 0 LIMIT 50", null)) + .thenReturn(result); when(result.iterator()).thenReturn(Arrays.asList("foo", "bar", "baz").iterator()); assertTrue(itemReader.doPageRead().hasNext()); @@ -193,9 +207,12 @@ public class Neo4jItemReaderTests { itemReader.afterPropertiesSet(); when(this.sessionFactory.openSession()).thenReturn(this.session); - when(this.session.query(String.class, "START n=node(*) MATCH n -- m WHERE has(n.name) RETURN m ORDER BY n.age SKIP 0 LIMIT 50", params)).thenReturn(result); + when(this.session.query(String.class, + "START n=node(*) MATCH n -- m WHERE has(n.name) RETURN m ORDER BY n.age SKIP 0 LIMIT 50", params)) + .thenReturn(result); when(result.iterator()).thenReturn(Arrays.asList("foo", "bar", "baz").iterator()); assertTrue(itemReader.doPageRead().hasNext()); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/Neo4jItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/Neo4jItemWriterTests.java index 142e52e3b..a4759bf85 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/Neo4jItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/Neo4jItemWriterTests.java @@ -41,20 +41,23 @@ public class Neo4jItemWriterTests { @Mock private SessionFactory sessionFactory; + @Mock private Session session; @Test - public void testAfterPropertiesSet() throws Exception{ + public void testAfterPropertiesSet() throws Exception { writer = new Neo4jItemWriter<>(); try { writer.afterPropertiesSet(); fail("SessionFactory was not set but exception was not thrown."); - } catch (IllegalStateException iae) { + } + catch (IllegalStateException iae) { assertEquals("A SessionFactory is required", iae.getMessage()); - } catch (Throwable t) { + } + catch (Throwable t) { fail("Wrong exception was thrown."); } @@ -145,4 +148,5 @@ public class Neo4jItemWriterTests { verify(this.session).delete("foo"); verify(this.session).delete("bar"); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/RepositoryItemReaderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/RepositoryItemReaderTests.java index b35698a50..459c4e334 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/RepositoryItemReaderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/RepositoryItemReaderTests.java @@ -58,8 +58,10 @@ public class RepositoryItemReaderTests { public MockitoRule rule = MockitoJUnit.rule().silent(); private RepositoryItemReader reader; + @Mock private PagingAndSortingRepository repository; + private Map sorts; @Before @@ -77,7 +79,8 @@ public class RepositoryItemReaderTests { try { new RepositoryItemReader<>().afterPropertiesSet(); fail(); - } catch (IllegalStateException e) { + } + catch (IllegalStateException e) { // expected } @@ -86,7 +89,8 @@ public class RepositoryItemReaderTests { reader.setRepository(repository); reader.afterPropertiesSet(); fail(); - } catch (IllegalStateException iae) { + } + catch (IllegalStateException iae) { // expected } @@ -96,7 +100,8 @@ public class RepositoryItemReaderTests { reader.setPageSize(-1); reader.afterPropertiesSet(); fail(); - } catch (IllegalStateException iae) { + } + catch (IllegalStateException iae) { // expected } @@ -106,7 +111,8 @@ public class RepositoryItemReaderTests { reader.setPageSize(1); reader.afterPropertiesSet(); fail(); - } catch (IllegalStateException iae) { + } + catch (IllegalStateException iae) { // expected } @@ -137,9 +143,7 @@ public class RepositoryItemReaderTests { ArgumentCaptor pageRequestContainer = ArgumentCaptor.forClass(PageRequest.class); final Object result = new Object(); - when(repository.findAll(pageRequestContainer.capture())).thenReturn(new PageImpl<>(singletonList( - result - ))); + when(repository.findAll(pageRequestContainer.capture())).thenReturn(new PageImpl<>(singletonList(result))); assertEquals(result, reader.doRead()); @@ -154,11 +158,8 @@ public class RepositoryItemReaderTests { public void testDoReadFirstReadSecondPage() throws Exception { ArgumentCaptor pageRequestContainer = ArgumentCaptor.forClass(PageRequest.class); final Object result = new Object(); - when(repository.findAll(pageRequestContainer.capture())).thenReturn(new PageImpl<>(singletonList( - new Object() - ))).thenReturn(new PageImpl<>(singletonList( - result - ))); + when(repository.findAll(pageRequestContainer.capture())).thenReturn(new PageImpl<>(singletonList(new Object()))) + .thenReturn(new PageImpl<>(singletonList(result))); assertFalse(reader.doRead() == result); assertEquals(result, reader.doRead()); @@ -174,11 +175,8 @@ public class RepositoryItemReaderTests { public void testDoReadFirstReadExhausted() throws Exception { ArgumentCaptor pageRequestContainer = ArgumentCaptor.forClass(PageRequest.class); final Object result = new Object(); - when(repository.findAll(pageRequestContainer.capture())).thenReturn(new PageImpl<>(singletonList( - new Object() - ))).thenReturn(new PageImpl<>(singletonList( - result - ))).thenReturn(new PageImpl<>(new ArrayList<>())); + when(repository.findAll(pageRequestContainer.capture())).thenReturn(new PageImpl<>(singletonList(new Object()))) + .thenReturn(new PageImpl<>(singletonList(result))).thenReturn(new PageImpl<>(new ArrayList<>())); assertFalse(reader.doRead() == result); assertEquals(result, reader.doRead()); @@ -196,9 +194,7 @@ public class RepositoryItemReaderTests { reader.setPageSize(100); final List objectList = fillWithNewObjects(100); ArgumentCaptor pageRequestContainer = ArgumentCaptor.forClass(PageRequest.class); - when(repository.findAll(pageRequestContainer.capture())).thenReturn(new PageImpl<>( - objectList - )); + when(repository.findAll(pageRequestContainer.capture())).thenReturn(new PageImpl<>(objectList)); reader.jumpToItem(485); // no page requested at this stage @@ -220,9 +216,7 @@ public class RepositoryItemReaderTests { reader.setPageSize(50); final List objectList = fillWithNewObjects(50); ArgumentCaptor pageRequestContainer = ArgumentCaptor.forClass(PageRequest.class); - when(repository.findAll(pageRequestContainer.capture())).thenReturn(new PageImpl<>( - objectList - )); + when(repository.findAll(pageRequestContainer.capture())).thenReturn(new PageImpl<>(objectList)); reader.jumpToItem(150); verify(repository, never()).findAll(any(Pageable.class)); @@ -250,7 +244,8 @@ public class RepositoryItemReaderTests { try { reader.doPageRead(); fail(); - } catch (DynamicMethodInvocationException dmie) { + } + catch (DynamicMethodInvocationException dmie) { assertTrue(dmie.getCause() instanceof NoSuchMethodException); } } @@ -266,9 +261,8 @@ public class RepositoryItemReaderTests { reader.setMethodName("findFirstNames"); ArgumentCaptor pageRequestContainer = ArgumentCaptor.forClass(PageRequest.class); - when(differentRepository.findFirstNames(pageRequestContainer.capture())).thenReturn(new PageImpl<>(singletonList( - "result" - ))); + when(differentRepository.findFirstNames(pageRequestContainer.capture())) + .thenReturn(new PageImpl<>(singletonList("result"))); assertEquals("result", reader.doRead()); @@ -282,20 +276,14 @@ public class RepositoryItemReaderTests { @Test public void testSettingCurrentItemCountExplicitly() throws Exception { // Dataset : ("1" "2") | "3" "4" | "5" "6" - reader.setCurrentItemCount(3); // item as index 3 is : "4" + reader.setCurrentItemCount(3); // item as index 3 is : "4" reader.setPageSize(2); PageRequest request = PageRequest.of(1, 2, Sort.by(Direction.ASC, "id")); - when(repository.findAll(request)).thenReturn(new PageImpl<>(Arrays. asList( - "3", - "4" - ))); + when(repository.findAll(request)).thenReturn(new PageImpl<>(Arrays.asList("3", "4"))); request = PageRequest.of(2, 2, Sort.by(Direction.ASC, "id")); - when(repository.findAll(request)).thenReturn(new PageImpl<>(Arrays. asList( - "5", - "6" - ))); + when(repository.findAll(request)).thenReturn(new PageImpl<>(Arrays.asList("5", "6"))); reader.open(new ExecutionContext()); @@ -308,20 +296,14 @@ public class RepositoryItemReaderTests { @Test public void testSettingCurrentItemCountRestart() throws Exception { - reader.setCurrentItemCount(3); // item as index 3 is : "4" + reader.setCurrentItemCount(3); // item as index 3 is : "4" reader.setPageSize(2); PageRequest request = PageRequest.of(1, 2, Sort.by(Direction.ASC, "id")); - when(repository.findAll(request)).thenReturn(new PageImpl<>(Arrays. asList( - "3", - "4" - ))); + when(repository.findAll(request)).thenReturn(new PageImpl<>(Arrays.asList("3", "4"))); request = PageRequest.of(2, 2, Sort.by(Direction.ASC, "id")); - when(repository.findAll(request)).thenReturn(new PageImpl<>(Arrays. asList( - "5", - "6" - ))); + when(repository.findAll(request)).thenReturn(new PageImpl<>(Arrays.asList("5", "6"))); ExecutionContext executionContext = new ExecutionContext(); reader.open(executionContext); @@ -342,16 +324,10 @@ public class RepositoryItemReaderTests { reader.setPageSize(2); PageRequest request = PageRequest.of(0, 2, Sort.by(Direction.ASC, "id")); - when(repository.findAll(request)).thenReturn(new PageImpl<>(Arrays. asList( - "1", - "2" - ))); + when(repository.findAll(request)).thenReturn(new PageImpl<>(Arrays.asList("1", "2"))); request = PageRequest.of(1, 2, Sort.by(Direction.ASC, "id")); - when(repository.findAll(request)).thenReturn(new PageImpl<>(Arrays. asList( - "3", - "4" - ))); + when(repository.findAll(request)).thenReturn(new PageImpl<>(Arrays.asList("3", "4"))); ExecutionContext executionContext = new ExecutionContext(); reader.open(executionContext); @@ -368,11 +344,14 @@ public class RepositoryItemReaderTests { } public interface TestRepository extends PagingAndSortingRepository { + Page findFirstNames(Pageable pageable); + } // Simple object for readability private static class TestItem { + private final int myIndex; TestItem(int myIndex) { @@ -383,5 +362,7 @@ public class RepositoryItemReaderTests { public String toString() { return "TestItem at index " + myIndex; } + } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/RepositoryItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/RepositoryItemWriterTests.java index 09d925dc0..9a48768d9 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/RepositoryItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/RepositoryItemWriterTests.java @@ -38,6 +38,7 @@ public class RepositoryItemWriterTests { @Rule public MockitoRule rule = MockitoJUnit.rule().silent(); + @Mock private CrudRepository repository; @@ -59,7 +60,8 @@ public class RepositoryItemWriterTests { try { writer.afterPropertiesSet(); fail(); - } catch (IllegalStateException e) { + } + catch (IllegalStateException e) { } writer.setRepository(repository); @@ -68,9 +70,11 @@ public class RepositoryItemWriterTests { try { writer.afterPropertiesSet(); fail("Expected IllegalArgumentException"); - } catch (IllegalArgumentException e) { + } + catch (IllegalArgumentException e) { // expected - assertEquals("Wrong message for exception: " + e.getMessage(), "methodName must not be empty.", e.getMessage()); + assertEquals("Wrong message for exception: " + e.getMessage(), "methodName must not be empty.", + e.getMessage()); } } @@ -102,4 +106,5 @@ public class RepositoryItemWriterTests { verify(repository).saveAll(items); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/GemfireItemWriterBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/GemfireItemWriterBuilderTests.java index 08fb765e7..7ed9f2e54 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/GemfireItemWriterBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/GemfireItemWriterBuilderTests.java @@ -41,6 +41,7 @@ public class GemfireItemWriterBuilderTests { @Rule public MockitoRule rule = MockitoJUnit.rule().silent(); + @Mock private GemfireTemplate template; @@ -107,18 +108,23 @@ public class GemfireItemWriterBuilderTests { } static class Foo { + public GemfireItemWriterBuilderTests.Bar bar; public Foo(GemfireItemWriterBuilderTests.Bar bar) { this.bar = bar; } + } static class Bar { + public String val; public Bar(String b1) { this.val = b1; } + } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/MongoItemReaderBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/MongoItemReaderBuilderTests.java index 4531aab2c..d32e6b957 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/MongoItemReaderBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/MongoItemReaderBuilderTests.java @@ -51,6 +51,7 @@ public class MongoItemReaderBuilderTests { @Rule public MockitoRule rule = MockitoJUnit.rule().silent(); + @Mock private MongoOperations template; @@ -82,9 +83,7 @@ public class MongoItemReaderBuilderTests { @Test public void testFields() throws Exception { - MongoItemReader reader = getBasicBuilder() - .fields("{name : 1, age : 1, _id: 0}") - .build(); + MongoItemReader reader = getBasicBuilder().fields("{name : 1, age : 1, _id: 0}").build(); when(this.template.find(this.queryContainer.capture(), eq(String.class))).thenReturn(new ArrayList<>()); @@ -98,9 +97,7 @@ public class MongoItemReaderBuilderTests { @Test public void testHint() throws Exception { - MongoItemReader reader = getBasicBuilder() - .hint("{ $natural : 1}") - .build(); + MongoItemReader reader = getBasicBuilder().hint("{ $natural : 1}").build(); when(this.template.find(this.queryContainer.capture(), eq(String.class))).thenReturn(new ArrayList<>()); @@ -112,11 +109,8 @@ public class MongoItemReaderBuilderTests { @Test public void testCollection() throws Exception { - MongoItemReader reader = getBasicBuilder() - .parameterValues(Collections.singletonList("foo")) - .jsonQuery("{ name : ?0 }") - .collection("collection") - .build(); + MongoItemReader reader = getBasicBuilder().parameterValues(Collections.singletonList("foo")) + .jsonQuery("{ name : ?0 }").collection("collection").build(); ArgumentCaptor collectionContainer = ArgumentCaptor.forClass(String.class); @@ -133,11 +127,8 @@ public class MongoItemReaderBuilderTests { @Test public void testVarargs() throws Exception { - MongoItemReader reader = getBasicBuilder() - .parameterValues("foo") - .jsonQuery("{ name : ?0 }") - .collection("collection") - .build(); + MongoItemReader reader = getBasicBuilder().parameterValues("foo").jsonQuery("{ name : ?0 }") + .collection("collection").build(); ArgumentCaptor collectionContainer = ArgumentCaptor.forClass(String.class); @@ -155,12 +146,8 @@ public class MongoItemReaderBuilderTests { @Test public void testWithoutQueryLimit() throws Exception { MongoItemReader reader = new MongoItemReaderBuilder().template(this.template) - .targetType(String.class) - .query(new Query()) - .sorts(this.sortOptions) - .name("mongoReaderTest") - .pageSize(50) - .build(); + .targetType(String.class).query(new Query()).sorts(this.sortOptions).name("mongoReaderTest") + .pageSize(50).build(); when(template.find(this.queryContainer.capture(), eq(String.class))).thenReturn(new ArrayList<>()); @@ -173,11 +160,7 @@ public class MongoItemReaderBuilderTests { @Test public void testWithoutQueryLimitAndPageSize() throws Exception { MongoItemReader reader = new MongoItemReaderBuilder().template(this.template) - .targetType(String.class) - .query(new Query()) - .sorts(this.sortOptions) - .name("mongoReaderTest") - .build(); + .targetType(String.class).query(new Query()).sorts(this.sortOptions).name("mongoReaderTest").build(); when(template.find(this.queryContainer.capture(), eq(String.class))).thenReturn(new ArrayList<>()); @@ -189,56 +172,41 @@ public class MongoItemReaderBuilderTests { @Test public void testNullTemplate() { - validateExceptionMessage(new MongoItemReaderBuilder().targetType(String.class) - .jsonQuery("{ }") - .sorts(this.sortOptions) - .name("mongoReaderTest") - .pageSize(50), "template is required."); + validateExceptionMessage(new MongoItemReaderBuilder().targetType(String.class).jsonQuery("{ }") + .sorts(this.sortOptions).name("mongoReaderTest").pageSize(50), "template is required."); } @Test public void testNullTargetType() { - validateExceptionMessage(new MongoItemReaderBuilder().template(this.template) - .jsonQuery("{ }") - .sorts(this.sortOptions) - .name("mongoReaderTest") - .pageSize(50), "targetType is required."); + validateExceptionMessage(new MongoItemReaderBuilder().template(this.template).jsonQuery("{ }") + .sorts(this.sortOptions).name("mongoReaderTest").pageSize(50), "targetType is required."); } @Test public void testNullQuery() { - validateExceptionMessage(new MongoItemReaderBuilder().template(this.template) - .targetType(String.class) - .sorts(this.sortOptions) - .name("mongoReaderTest") - .pageSize(50), "A query is required"); + validateExceptionMessage(new MongoItemReaderBuilder().template(this.template).targetType(String.class) + .sorts(this.sortOptions).name("mongoReaderTest").pageSize(50), "A query is required"); } @Test public void testNullSortsWithQueryString() { - validateExceptionMessage(new MongoItemReaderBuilder().template(this.template) - .targetType(String.class) - .jsonQuery("{ }") - .name("mongoReaderTest") - .pageSize(50), "sorts map is required."); + validateExceptionMessage(new MongoItemReaderBuilder().template(this.template).targetType(String.class) + .jsonQuery("{ }").name("mongoReaderTest").pageSize(50), "sorts map is required."); } @Test public void testNullSortsWithQuery() { - validateExceptionMessage(new MongoItemReaderBuilder().template(this.template) - .targetType(String.class) - .query(query(where("_id").is("10"))) - .name("mongoReaderTest") - .pageSize(50), "sorts map is required."); + validateExceptionMessage( + new MongoItemReaderBuilder().template(this.template).targetType(String.class) + .query(query(where("_id").is("10"))).name("mongoReaderTest").pageSize(50), + "sorts map is required."); } @Test public void testNullName() { - validateExceptionMessage(new MongoItemReaderBuilder().template(this.template) - .targetType(String.class) - .jsonQuery("{ }") - .sorts(this.sortOptions) - .pageSize(50), "A name is required when saveState is set to true"); + validateExceptionMessage(new MongoItemReaderBuilder().template(this.template).targetType(String.class) + .jsonQuery("{ }").sorts(this.sortOptions).pageSize(50), + "A name is required when saveState is set to true"); } private void validateExceptionMessage(MongoItemReaderBuilder builder, String message) { @@ -251,17 +219,13 @@ public class MongoItemReaderBuilderTests { iae.getMessage()); } catch (IllegalStateException ise) { - assertEquals("IllegalStateException message did not match the expected result.", message, - ise.getMessage()); + assertEquals("IllegalStateException message did not match the expected result.", message, ise.getMessage()); } } private MongoItemReaderBuilder getBasicBuilder() { - return new MongoItemReaderBuilder().template(this.template) - .targetType(String.class) - .jsonQuery("{ }") - .sorts(this.sortOptions) - .name("mongoReaderTest") - .pageSize(50); + return new MongoItemReaderBuilder().template(this.template).targetType(String.class).jsonQuery("{ }") + .sorts(this.sortOptions).name("mongoReaderTest").pageSize(50); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/MongoItemWriterBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/MongoItemWriterBuilderTests.java index 46c867ae5..9248deb0d 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/MongoItemWriterBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/MongoItemWriterBuilderTests.java @@ -58,15 +58,20 @@ public class MongoItemWriterBuilderTests { @Rule public MockitoRule rule = MockitoJUnit.rule().silent(); + @Mock private MongoOperations template; + @Mock private BulkOperations bulkOperations; + @Mock DbRefResolver dbRefResolver; + private MongoConverter mongoConverter; private List saveItems; + private List removeItems; @Before @@ -97,8 +102,7 @@ public class MongoItemWriterBuilderTests { @Test public void testWriteToCollection() throws Exception { MongoItemWriter writer = new MongoItemWriterBuilder().collection("collection") - .template(this.template) - .build(); + .template(this.template).build(); writer.write(this.saveItems); @@ -111,9 +115,7 @@ public class MongoItemWriterBuilderTests { @Test public void testDelete() throws Exception { - MongoItemWriter writer = new MongoItemWriterBuilder().template(this.template) - .delete(true) - .build(); + MongoItemWriter writer = new MongoItemWriterBuilder().template(this.template).delete(true).build(); writer.write(this.removeItems); @@ -134,13 +136,19 @@ public class MongoItemWriterBuilderTests { } static class Item { + Integer id; + String name; + public Item(Integer id) { this.id = id; } + public Item(String name) { this.name = name; } + } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/Neo4jItemReaderBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/Neo4jItemReaderBuilderTests.java index a1cae5434..b180c58e8 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/Neo4jItemReaderBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/Neo4jItemReaderBuilderTests.java @@ -54,20 +54,14 @@ public class Neo4jItemReaderBuilderTests { @Test public void testFullyQualifiedItemReader() throws Exception { - Neo4jItemReader itemReader = new Neo4jItemReaderBuilder() - .sessionFactory(this.sessionFactory) - .targetType(String.class) - .startStatement("n=node(*)") - .orderByStatement("n.age") - .pageSize(50).name("bar") - .matchStatement("n -- m") - .whereStatement("has(n.name)") - .returnStatement("m").build(); + Neo4jItemReader itemReader = new Neo4jItemReaderBuilder().sessionFactory(this.sessionFactory) + .targetType(String.class).startStatement("n=node(*)").orderByStatement("n.age").pageSize(50).name("bar") + .matchStatement("n -- m").whereStatement("has(n.name)").returnStatement("m").build(); when(this.sessionFactory.openSession()).thenReturn(this.session); when(this.session.query(String.class, "START n=node(*) MATCH n -- m WHERE has(n.name) RETURN m ORDER BY n.age SKIP 0 LIMIT 50", null)) - .thenReturn(result); + .thenReturn(result); when(result.iterator()).thenReturn(Arrays.asList("foo", "bar", "baz").iterator()); assertEquals("The expected value was not returned by reader.", "foo", itemReader.read()); @@ -77,16 +71,9 @@ public class Neo4jItemReaderBuilderTests { @Test public void testCurrentSize() throws Exception { - Neo4jItemReader itemReader = new Neo4jItemReaderBuilder() - .sessionFactory(this.sessionFactory) - .targetType(String.class) - .startStatement("n=node(*)") - .orderByStatement("n.age") - .pageSize(50).name("bar") - .returnStatement("m") - .currentItemCount(0) - .maxItemCount(1) - .build(); + Neo4jItemReader itemReader = new Neo4jItemReaderBuilder().sessionFactory(this.sessionFactory) + .targetType(String.class).startStatement("n=node(*)").orderByStatement("n.age").pageSize(50).name("bar") + .returnStatement("m").currentItemCount(0).maxItemCount(1).build(); when(this.sessionFactory.openSession()).thenReturn(this.session); when(this.session.query(String.class, "START n=node(*) RETURN m ORDER BY n.age SKIP 0 LIMIT 50", null)) @@ -101,24 +88,15 @@ public class Neo4jItemReaderBuilderTests { public void testResultsWithMatchAndWhereWithParametersWithSession() throws Exception { Map params = new HashMap<>(); params.put("foo", "bar"); - Neo4jItemReader itemReader = new Neo4jItemReaderBuilder() - .sessionFactory(this.sessionFactory) - .targetType(String.class) - .startStatement("n=node(*)") - .returnStatement("*") - .orderByStatement("n.age") - .pageSize(50) - .name("foo") - .parameterValues(params) - .matchStatement("n -- m") - .whereStatement("has(n.name)") - .returnStatement("m") - .build(); + Neo4jItemReader itemReader = new Neo4jItemReaderBuilder().sessionFactory(this.sessionFactory) + .targetType(String.class).startStatement("n=node(*)").returnStatement("*").orderByStatement("n.age") + .pageSize(50).name("foo").parameterValues(params).matchStatement("n -- m").whereStatement("has(n.name)") + .returnStatement("m").build(); when(this.sessionFactory.openSession()).thenReturn(this.session); when(this.session.query(String.class, "START n=node(*) MATCH n -- m WHERE has(n.name) RETURN m ORDER BY n.age SKIP 0 LIMIT 50", params)) - .thenReturn(result); + .thenReturn(result); when(result.iterator()).thenReturn(Arrays.asList("foo", "bar", "baz").iterator()); assertEquals("The expected value was not returned by reader.", "foo", itemReader.read()); @@ -127,13 +105,8 @@ public class Neo4jItemReaderBuilderTests { @Test public void testNoSessionFactory() { try { - new Neo4jItemReaderBuilder() - .targetType(String.class) - .startStatement("n=node(*)") - .returnStatement("*") - .orderByStatement("n.age") - .pageSize(50) - .name("bar").build(); + new Neo4jItemReaderBuilder().targetType(String.class).startStatement("n=node(*)") + .returnStatement("*").orderByStatement("n.age").pageSize(50).name("bar").build(); fail("IllegalArgumentException should have been thrown"); } @@ -145,135 +118,75 @@ public class Neo4jItemReaderBuilderTests { @Test public void testZeroPageSize() { - validateExceptionMessage(new Neo4jItemReaderBuilder() - .sessionFactory(this.sessionFactory) - .targetType(String.class) - .startStatement("n=node(*)") - .returnStatement("*") - .orderByStatement("n.age") - .pageSize(0) - .name("foo") - .matchStatement("n -- m") - .whereStatement("has(n.name)") - .returnStatement("m"), + validateExceptionMessage( + new Neo4jItemReaderBuilder().sessionFactory(this.sessionFactory).targetType(String.class) + .startStatement("n=node(*)").returnStatement("*").orderByStatement("n.age").pageSize(0) + .name("foo").matchStatement("n -- m").whereStatement("has(n.name)").returnStatement("m"), "pageSize must be greater than zero"); } @Test public void testZeroMaxItemCount() { - validateExceptionMessage(new Neo4jItemReaderBuilder() - .sessionFactory(this.sessionFactory) - .targetType(String.class) - .startStatement("n=node(*)") - .returnStatement("*") - .orderByStatement("n.age") - .pageSize(5) - .maxItemCount(0) - .name("foo") - .matchStatement("n -- m") - .whereStatement("has(n.name)") - .returnStatement("m"), - "maxItemCount must be greater than zero"); + validateExceptionMessage(new Neo4jItemReaderBuilder().sessionFactory(this.sessionFactory) + .targetType(String.class).startStatement("n=node(*)").returnStatement("*").orderByStatement("n.age") + .pageSize(5).maxItemCount(0).name("foo").matchStatement("n -- m").whereStatement("has(n.name)") + .returnStatement("m"), "maxItemCount must be greater than zero"); } @Test public void testCurrentItemCountGreaterThanMaxItemCount() { - validateExceptionMessage(new Neo4jItemReaderBuilder() - .sessionFactory(this.sessionFactory) - .targetType(String.class) - .startStatement("n=node(*)") - .returnStatement("*") - .orderByStatement("n.age") - .pageSize(5) - .maxItemCount(5) - .currentItemCount(6) - .name("foo") - .matchStatement("n -- m") - .whereStatement("has(n.name)") - .returnStatement("m"), + validateExceptionMessage( + new Neo4jItemReaderBuilder().sessionFactory(this.sessionFactory).targetType(String.class) + .startStatement("n=node(*)").returnStatement("*").orderByStatement("n.age").pageSize(5) + .maxItemCount(5).currentItemCount(6).name("foo").matchStatement("n -- m") + .whereStatement("has(n.name)").returnStatement("m"), "maxItemCount must be greater than currentItemCount"); } @Test public void testNullName() { validateExceptionMessage( - new Neo4jItemReaderBuilder() - .sessionFactory(this.sessionFactory) - .targetType(String.class) - .startStatement("n=node(*)") - .returnStatement("*") - .orderByStatement("n.age") - .pageSize(50), + new Neo4jItemReaderBuilder().sessionFactory(this.sessionFactory).targetType(String.class) + .startStatement("n=node(*)").returnStatement("*").orderByStatement("n.age").pageSize(50), "A name is required when saveState is set to true"); // tests that name is not required if saveState is set to false. - new Neo4jItemReaderBuilder() - .sessionFactory(this.sessionFactory) - .targetType(String.class) - .startStatement("n=node(*)") - .returnStatement("*") - .orderByStatement("n.age") - .saveState(false) - .pageSize(50) - .build(); + new Neo4jItemReaderBuilder().sessionFactory(this.sessionFactory).targetType(String.class) + .startStatement("n=node(*)").returnStatement("*").orderByStatement("n.age").saveState(false) + .pageSize(50).build(); } @Test public void testNullTargetType() { validateExceptionMessage( - new Neo4jItemReaderBuilder() - .sessionFactory(this.sessionFactory) - .startStatement("n=node(*)") - .returnStatement("*") - .orderByStatement("n.age") - .pageSize(50) - .name("bar") - .matchStatement("n -- m") - .whereStatement("has(n.name)") - .returnStatement("m"), + new Neo4jItemReaderBuilder().sessionFactory(this.sessionFactory).startStatement("n=node(*)") + .returnStatement("*").orderByStatement("n.age").pageSize(50).name("bar") + .matchStatement("n -- m").whereStatement("has(n.name)").returnStatement("m"), "targetType is required."); } @Test public void testNullStartStatement() { validateExceptionMessage( - new Neo4jItemReaderBuilder() - .sessionFactory(this.sessionFactory) - .targetType(String.class) - .returnStatement("*") - .orderByStatement("n.age") - .pageSize(50).name("bar") - .matchStatement("n -- m") - .whereStatement("has(n.name)") - .returnStatement("m"), + new Neo4jItemReaderBuilder().sessionFactory(this.sessionFactory).targetType(String.class) + .returnStatement("*").orderByStatement("n.age").pageSize(50).name("bar") + .matchStatement("n -- m").whereStatement("has(n.name)").returnStatement("m"), "startStatement is required."); } @Test public void testNullReturnStatement() { - validateExceptionMessage(new Neo4jItemReaderBuilder() - .sessionFactory(this.sessionFactory) - .targetType(String.class) - .startStatement("n=node(*)") - .orderByStatement("n.age") - .pageSize(50).name("bar") - .matchStatement("n -- m") - .whereStatement("has(n.name)"), "returnStatement is required."); + validateExceptionMessage(new Neo4jItemReaderBuilder().sessionFactory(this.sessionFactory) + .targetType(String.class).startStatement("n=node(*)").orderByStatement("n.age").pageSize(50).name("bar") + .matchStatement("n -- m").whereStatement("has(n.name)"), "returnStatement is required."); } @Test public void testNullOrderByStatement() { validateExceptionMessage( - new Neo4jItemReaderBuilder() - .sessionFactory(this.sessionFactory) - .targetType(String.class) - .startStatement("n=node(*)") - .returnStatement("*") - .pageSize(50) - .name("bar") - .matchStatement("n -- m") - .whereStatement("has(n.name)") - .returnStatement("m"), + new Neo4jItemReaderBuilder().sessionFactory(this.sessionFactory).targetType(String.class) + .startStatement("n=node(*)").returnStatement("*").pageSize(50).name("bar") + .matchStatement("n -- m").whereStatement("has(n.name)").returnStatement("m"), "orderByStatement is required."); } @@ -287,4 +200,5 @@ public class Neo4jItemReaderBuilderTests { iae.getMessage()); } } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/Neo4jItemWriterBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/Neo4jItemWriterBuilderTests.java index f64c0b53c..38f143c93 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/Neo4jItemWriterBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/Neo4jItemWriterBuilderTests.java @@ -45,12 +45,14 @@ public class Neo4jItemWriterBuilderTests { @Mock private SessionFactory sessionFactory; + @Mock private Session session; @Test - public void testBasicWriter() throws Exception{ - Neo4jItemWriter writer = new Neo4jItemWriterBuilder().sessionFactory(this.sessionFactory).build(); + public void testBasicWriter() throws Exception { + Neo4jItemWriter writer = new Neo4jItemWriterBuilder().sessionFactory(this.sessionFactory) + .build(); List items = new ArrayList<>(); items.add("foo"); items.add("bar"); @@ -65,8 +67,9 @@ public class Neo4jItemWriterBuilderTests { } @Test - public void testBasicDelete() throws Exception{ - Neo4jItemWriter writer = new Neo4jItemWriterBuilder().delete(true).sessionFactory(this.sessionFactory).build(); + public void testBasicDelete() throws Exception { + Neo4jItemWriter writer = new Neo4jItemWriterBuilder().delete(true) + .sessionFactory(this.sessionFactory).build(); List items = new ArrayList<>(); items.add("foo"); items.add("bar"); @@ -85,7 +88,8 @@ public class Neo4jItemWriterBuilderTests { try { new Neo4jItemWriterBuilder().build(); fail("SessionFactory was not set but exception was not thrown."); - } catch (IllegalArgumentException iae) { + } + catch (IllegalArgumentException iae) { assertEquals("sessionFactory is required.", iae.getMessage()); } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/RepositoryItemReaderBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/RepositoryItemReaderBuilderTests.java index fc825a523..91ffec3cc 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/RepositoryItemReaderBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/RepositoryItemReaderBuilderTests.java @@ -46,8 +46,10 @@ import static org.mockito.Mockito.when; public class RepositoryItemReaderBuilderTests { private static final String ARG1 = "foo"; - private static final String ARG2 = "bar"; - private static final String ARG3 = "baz"; + + private static final String ARG2 = "bar"; + + private static final String ARG3 = "baz"; private static final String TEST_CONTENT = "FOOBAR"; @@ -80,11 +82,7 @@ public class RepositoryItemReaderBuilderTests { @Test public void testBasicRead() throws Exception { RepositoryItemReader reader = new RepositoryItemReaderBuilder<>().repository(this.repository) - .sorts(this.sorts) - .maxItemCount(5) - .methodName("foo") - .name("bar") - .build(); + .sorts(this.sorts).maxItemCount(5).methodName("foo").name("bar").build(); String result = (String) reader.read(); assertEquals("Result returned from reader was not expected value.", TEST_CONTENT, result); assertEquals("page size was not expected value.", 10, this.pageRequestContainer.getValue().getPageSize()); @@ -92,14 +90,11 @@ public class RepositoryItemReaderBuilderTests { @Test public void testRepositoryMethodReference() throws Exception { - RepositoryItemReaderBuilder.RepositoryMethodReference repositoryMethodReference = - new RepositoryItemReaderBuilder.RepositoryMethodReference<>(this.repository); + RepositoryItemReaderBuilder.RepositoryMethodReference repositoryMethodReference = new RepositoryItemReaderBuilder.RepositoryMethodReference<>( + this.repository); repositoryMethodReference.methodIs().foo(null); - RepositoryItemReader reader = new RepositoryItemReaderBuilder<>() - .repository(repositoryMethodReference) - .sorts(this.sorts) - .maxItemCount(5) - .name("bar").build(); + RepositoryItemReader reader = new RepositoryItemReaderBuilder<>().repository(repositoryMethodReference) + .sorts(this.sorts).maxItemCount(5).name("bar").build(); String result = (String) reader.read(); assertEquals("Result returned from reader was not expected value.", TEST_CONTENT, result); assertEquals("page size was not expected value.", 10, this.pageRequestContainer.getValue().getPageSize()); @@ -107,14 +102,11 @@ public class RepositoryItemReaderBuilderTests { @Test public void testRepositoryMethodReferenceWithArgs() throws Exception { - RepositoryItemReaderBuilder.RepositoryMethodReference repositoryMethodReference = - new RepositoryItemReaderBuilder.RepositoryMethodReference<>(this.repository); + RepositoryItemReaderBuilder.RepositoryMethodReference repositoryMethodReference = new RepositoryItemReaderBuilder.RepositoryMethodReference<>( + this.repository); repositoryMethodReference.methodIs().foo(ARG1, ARG2, ARG3, null); - RepositoryItemReader reader = new RepositoryItemReaderBuilder<>() - .repository(repositoryMethodReference) - .sorts(this.sorts) - .maxItemCount(5) - .name("bar").build(); + RepositoryItemReader reader = new RepositoryItemReaderBuilder<>().repository(repositoryMethodReference) + .sorts(this.sorts).maxItemCount(5).name("bar").build(); ArgumentCaptor arg1Captor = ArgumentCaptor.forClass(String.class); ArgumentCaptor arg2Captor = ArgumentCaptor.forClass(String.class); ArgumentCaptor arg3Captor = ArgumentCaptor.forClass(String.class); @@ -129,24 +121,14 @@ public class RepositoryItemReaderBuilderTests { @Test public void testCurrentItemCount() throws Exception { RepositoryItemReader reader = new RepositoryItemReaderBuilder<>().repository(this.repository) - .sorts(this.sorts) - .currentItemCount(6) - .maxItemCount(5) - .methodName("foo") - .name("bar") - .build(); + .sorts(this.sorts).currentItemCount(6).maxItemCount(5).methodName("foo").name("bar").build(); assertNull("Result returned from reader was not null.", reader.read()); } @Test public void testPageSize() throws Exception { RepositoryItemReader reader = new RepositoryItemReaderBuilder<>().repository(this.repository) - .sorts(this.sorts) - .maxItemCount(5) - .methodName("foo") - .name("bar") - .pageSize(2) - .build(); + .sorts(this.sorts).maxItemCount(5).methodName("foo").name("bar").pageSize(2).build(); reader.read(); assertEquals("page size was not expected value.", 2, this.pageRequestContainer.getValue().getPageSize()); } @@ -154,10 +136,7 @@ public class RepositoryItemReaderBuilderTests { @Test public void testNoMethodName() throws Exception { try { - new RepositoryItemReaderBuilder<>().repository(this.repository) - .sorts(this.sorts) - .maxItemCount(10) - .build(); + new RepositoryItemReaderBuilder<>().repository(this.repository).sorts(this.sorts).maxItemCount(10).build(); fail("IllegalArgumentException should have been thrown"); } @@ -166,11 +145,8 @@ public class RepositoryItemReaderBuilderTests { "methodName is required.", iae.getMessage()); } try { - new RepositoryItemReaderBuilder<>().repository(this.repository) - .sorts(this.sorts) - .methodName("") - .maxItemCount(5) - .build(); + new RepositoryItemReaderBuilder<>().repository(this.repository).sorts(this.sorts).methodName("") + .maxItemCount(5).build(); fail("IllegalArgumentException should have been thrown"); } @@ -183,10 +159,7 @@ public class RepositoryItemReaderBuilderTests { @Test public void testSaveState() throws Exception { try { - new RepositoryItemReaderBuilder<>().repository(repository) - .methodName("foo") - .sorts(sorts) - .maxItemCount(5) + new RepositoryItemReaderBuilder<>().repository(repository).methodName("foo").sorts(sorts).maxItemCount(5) .build(); fail("IllegalArgumentException should have been thrown"); @@ -197,21 +170,14 @@ public class RepositoryItemReaderBuilderTests { } // No IllegalStateException for a name that is not set, should not be thrown since // saveState was false. - new RepositoryItemReaderBuilder<>().repository(repository) - .saveState(false) - .methodName("foo") - .sorts(sorts) - .maxItemCount(5) - .build(); + new RepositoryItemReaderBuilder<>().repository(repository).saveState(false).methodName("foo").sorts(sorts) + .maxItemCount(5).build(); } @Test public void testNullSort() throws Exception { try { - new RepositoryItemReaderBuilder<>().repository(repository) - .methodName("foo") - .maxItemCount(5) - .build(); + new RepositoryItemReaderBuilder<>().repository(repository).methodName("foo").maxItemCount(5).build(); fail("IllegalArgumentException should have been thrown"); } @@ -224,10 +190,7 @@ public class RepositoryItemReaderBuilderTests { @Test public void testNoRepository() throws Exception { try { - new RepositoryItemReaderBuilder<>().sorts(this.sorts) - .maxItemCount(10) - .methodName("foo") - .build(); + new RepositoryItemReaderBuilder<>().sorts(this.sorts).maxItemCount(10).methodName("foo").build(); fail("IllegalArgumentException should have been thrown"); } @@ -250,12 +213,7 @@ public class RepositoryItemReaderBuilderTests { this.pageRequestContainer.capture())).thenReturn(this.page); RepositoryItemReader reader = new RepositoryItemReaderBuilder<>().repository(this.repository) - .sorts(this.sorts) - .maxItemCount(5) - .methodName("foo") - .name("bar") - .arguments(args) - .build(); + .sorts(this.sorts).maxItemCount(5).methodName("foo").name("bar").arguments(args).build(); String result = (String) reader.read(); verifyMultiArgRead(arg1Captor, arg2Captor, arg3Captor, result); @@ -270,12 +228,7 @@ public class RepositoryItemReaderBuilderTests { this.pageRequestContainer.capture())).thenReturn(this.page); RepositoryItemReader reader = new RepositoryItemReaderBuilder<>().repository(this.repository) - .sorts(this.sorts) - .maxItemCount(5) - .methodName("foo") - .name("bar") - .arguments(ARG1, ARG2, ARG3) - .build(); + .sorts(this.sorts).maxItemCount(5).methodName("foo").name("bar").arguments(ARG1, ARG2, ARG3).build(); String result = (String) reader.read(); verifyMultiArgRead(arg1Captor, arg2Captor, arg3Captor, result); @@ -286,9 +239,11 @@ public class RepositoryItemReaderBuilderTests { Object foo(PageRequest request); Object foo(String arg1, String arg2, String arg3, PageRequest request); + } - private void verifyMultiArgRead(ArgumentCaptor arg1Captor, ArgumentCaptor arg2Captor, ArgumentCaptor arg3Captor, String result) { + private void verifyMultiArgRead(ArgumentCaptor arg1Captor, ArgumentCaptor arg2Captor, + ArgumentCaptor arg3Captor, String result) { assertEquals("Result returned from reader was not expected value.", TEST_CONTENT, result); assertEquals("ARG1 for calling method did not match expected result", ARG1, arg1Captor.getValue()); assertEquals("ARG2 for calling method did not match expected result", ARG2, arg2Captor.getValue()); @@ -296,4 +251,5 @@ public class RepositoryItemReaderBuilderTests { assertEquals("Result Total Pages did not match expected result", 10, this.pageRequestContainer.getValue().getPageSize()); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/RepositoryItemWriterBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/RepositoryItemWriterBuilderTests.java index c13db860c..99a1db72c 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/RepositoryItemWriterBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/builder/RepositoryItemWriterBuilderTests.java @@ -40,6 +40,7 @@ public class RepositoryItemWriterBuilderTests { @Rule public MockitoRule rule = MockitoJUnit.rule().silent(); + @Mock private TestRepository repository; @@ -59,10 +60,7 @@ public class RepositoryItemWriterBuilderTests { @Test public void testEmptyMethodName() { try { - new RepositoryItemWriterBuilder() - .repository(this.repository) - .methodName("") - .build(); + new RepositoryItemWriterBuilder().repository(this.repository).methodName("").build(); fail("IllegalArgumentException should have been thrown"); } @@ -74,10 +72,8 @@ public class RepositoryItemWriterBuilderTests { @Test public void testWriteItems() throws Exception { - RepositoryItemWriter writer = new RepositoryItemWriterBuilder() - .methodName("save") - .repository(this.repository) - .build(); + RepositoryItemWriter writer = new RepositoryItemWriterBuilder().methodName("save") + .repository(this.repository).build(); List items = Collections.singletonList("foo"); @@ -88,10 +84,8 @@ public class RepositoryItemWriterBuilderTests { @Test public void testWriteItemsTestRepository() throws Exception { - RepositoryItemWriter writer = new RepositoryItemWriterBuilder() - .methodName("foo") - .repository(this.repository) - .build(); + RepositoryItemWriter writer = new RepositoryItemWriterBuilder().methodName("foo") + .repository(this.repository).build(); List items = Collections.singletonList("foo"); @@ -102,15 +96,12 @@ public class RepositoryItemWriterBuilderTests { @Test public void testWriteItemsTestRepositoryMethodIs() throws Exception { - RepositoryItemWriterBuilder.RepositoryMethodReference - repositoryMethodReference = new RepositoryItemWriterBuilder.RepositoryMethodReference<>( + RepositoryItemWriterBuilder.RepositoryMethodReference repositoryMethodReference = new RepositoryItemWriterBuilder.RepositoryMethodReference<>( this.repository); repositoryMethodReference.methodIs().foo(null); - RepositoryItemWriter writer = new RepositoryItemWriterBuilder() - .methodName("foo") - .repository(repositoryMethodReference) - .build(); + RepositoryItemWriter writer = new RepositoryItemWriterBuilder().methodName("foo") + .repository(repositoryMethodReference).build(); List items = Collections.singletonList("foo"); @@ -124,4 +115,5 @@ public class RepositoryItemWriterBuilderTests { Object foo(String arg1); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/AbstractDataSourceItemReaderIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/AbstractDataSourceItemReaderIntegrationTests.java index a0da99754..c80327f56 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/AbstractDataSourceItemReaderIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/AbstractDataSourceItemReaderIntegrationTests.java @@ -36,9 +36,9 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; /** - * Common scenarios for testing {@link ItemReader} implementations which read - * data from database. - * + * Common scenarios for testing {@link ItemReader} implementations which read data from + * database. + * * @author Lucas Ward * @author Robert Kasanicky * @author Thomas Risberg @@ -82,7 +82,7 @@ public abstract class AbstractDataSourceItemReaderIntegrationTests { public void testNormalProcessing() throws Exception { getAsInitializingBean(reader).afterPropertiesSet(); getAsItemStream(reader).open(executionContext); - + Foo foo1 = reader.read(); assertEquals(1, foo1.getValue()); @@ -102,9 +102,9 @@ public abstract class AbstractDataSourceItemReaderIntegrationTests { } /* - * Restart scenario - read records, save restart data, create new input - * source and restore from restart data - the new input source should - * continue where the old one finished. + * Restart scenario - read records, save restart data, create new input source and + * restore from restart data - the new input source should continue where the old one + * finished. */ @Test @Transactional @@ -112,7 +112,7 @@ public abstract class AbstractDataSourceItemReaderIntegrationTests { public void testRestart() throws Exception { getAsItemStream(reader).open(executionContext); - + Foo foo1 = reader.read(); assertEquals(1, foo1.getValue()); @@ -120,7 +120,7 @@ public abstract class AbstractDataSourceItemReaderIntegrationTests { assertEquals(2, foo2.getValue()); getAsItemStream(reader).update(executionContext); - + getAsItemStream(reader).close(); // create new input source @@ -133,9 +133,9 @@ public abstract class AbstractDataSourceItemReaderIntegrationTests { } /* - * Restart scenario - read records, save restart data, create new input - * source and restore from restart data - the new input source should - * continue where the old one finished. + * Restart scenario - read records, save restart data, create new input source and + * restore from restart data - the new input source should continue where the old one + * finished. */ @Test @Transactional @@ -143,7 +143,7 @@ public abstract class AbstractDataSourceItemReaderIntegrationTests { public void testRestartOnSecondPage() throws Exception { getAsItemStream(reader).open(executionContext); - + Foo foo1 = reader.read(); assertEquals(1, foo1.getValue()); Foo foo2 = reader.read(); @@ -154,7 +154,7 @@ public abstract class AbstractDataSourceItemReaderIntegrationTests { assertEquals(4, foo4.getValue()); getAsItemStream(reader).update(executionContext); - + getAsItemStream(reader).close(); // create new input source @@ -177,7 +177,7 @@ public abstract class AbstractDataSourceItemReaderIntegrationTests { public void testInvalidRestore() throws Exception { getAsItemStream(reader).open(executionContext); - + Foo foo1 = reader.read(); assertEquals(1, foo1.getValue()); @@ -185,7 +185,7 @@ public abstract class AbstractDataSourceItemReaderIntegrationTests { assertEquals(2, foo2.getValue()); getAsItemStream(reader).update(executionContext); - + getAsItemStream(reader).close(); // create new input source @@ -218,8 +218,7 @@ public abstract class AbstractDataSourceItemReaderIntegrationTests { } /* - * Rollback scenario with restart - input source rollbacks to last - * commit point. + * Rollback scenario with restart - input source rollbacks to last commit point. */ @Test @Transactional @@ -227,7 +226,7 @@ public abstract class AbstractDataSourceItemReaderIntegrationTests { public void testRollbackAndRestart() throws Exception { getAsItemStream(reader).open(executionContext); - + Foo foo1 = reader.read(); getAsItemStream(reader).update(executionContext); @@ -237,7 +236,7 @@ public abstract class AbstractDataSourceItemReaderIntegrationTests { Foo foo3 = reader.read(); assertTrue(!foo2.equals(foo3)); - + getAsItemStream(reader).close(); // create new input source @@ -248,10 +247,9 @@ public abstract class AbstractDataSourceItemReaderIntegrationTests { assertEquals(foo2, reader.read()); assertEquals(foo3, reader.read()); } - + /* - * Rollback scenario with restart - input source rollbacks to last - * commit point. + * Rollback scenario with restart - input source rollbacks to last commit point. */ @Test @Transactional @@ -259,7 +257,7 @@ public abstract class AbstractDataSourceItemReaderIntegrationTests { public void testRollbackOnFirstChunkAndRestart() throws Exception { getAsItemStream(reader).open(executionContext); - + Foo foo1 = reader.read(); Foo foo2 = reader.read(); @@ -267,7 +265,7 @@ public abstract class AbstractDataSourceItemReaderIntegrationTests { Foo foo3 = reader.read(); assertTrue(!foo2.equals(foo3)); - + getAsItemStream(reader).close(); // create new input source @@ -283,9 +281,8 @@ public abstract class AbstractDataSourceItemReaderIntegrationTests { @Transactional @DirtiesContext public void testMultipleRestarts() throws Exception { - + getAsItemStream(reader).open(executionContext); - Foo foo1 = reader.read(); @@ -296,7 +293,7 @@ public abstract class AbstractDataSourceItemReaderIntegrationTests { Foo foo3 = reader.read(); assertTrue(!foo2.equals(foo3)); - + getAsItemStream(reader).close(); // create new input source @@ -306,30 +303,30 @@ public abstract class AbstractDataSourceItemReaderIntegrationTests { assertEquals(foo2, reader.read()); assertEquals(foo3, reader.read()); - + getAsItemStream(reader).update(executionContext); - + getAsItemStream(reader).close(); // create new input source reader = createItemReader(); getAsItemStream(reader).open(executionContext); - + Foo foo4 = reader.read(); Foo foo5 = reader.read(); assertEquals(4, foo4.getValue()); assertEquals(5, foo5.getValue()); } - - //set transaction to false and make sure the tests work + + // set transaction to false and make sure the tests work @Test @DirtiesContext public void testTransacted() throws Exception { if (reader instanceof JpaPagingItemReader) { - ((JpaPagingItemReader)reader).setTransacted(false); + ((JpaPagingItemReader) reader).setTransacted(false); this.testNormalProcessing(); - }//end if + } // end if } protected ItemStream getAsItemStream(ItemReader source) { diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/AbstractDatabaseItemStreamItemReaderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/AbstractDatabaseItemStreamItemReaderTests.java index 74d6b3bad..0b61ca2b3 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/AbstractDatabaseItemStreamItemReaderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/AbstractDatabaseItemStreamItemReaderTests.java @@ -1,76 +1,76 @@ -/* - * Copyright 2009-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.database; - -import javax.sql.DataSource; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import org.springframework.batch.item.AbstractItemStreamItemReaderTests; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.ItemStream; -import org.springframework.batch.item.sample.Foo; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -import static org.junit.Assert.assertEquals; - -public abstract class AbstractDatabaseItemStreamItemReaderTests extends AbstractItemStreamItemReaderTests { - - protected ClassPathXmlApplicationContext ctx; - - @Override - @Before - public void setUp() throws Exception { - initializeContext(); - super.setUp(); - } - - @Override - @After - public void tearDown() throws Exception { - super.tearDown(); - ctx.close(); - } - - /** - * Sub-classes can override this and create their own context. - */ - protected void initializeContext() throws Exception { - ctx = new ClassPathXmlApplicationContext("org/springframework/batch/item/database/data-source-context.xml"); - } - - @Test - public void testReadToExhaustion() throws Exception { - ItemReader reader = getItemReader(); - ((ItemStream) reader).open(new ExecutionContext()); - // pointToEmptyInput(reader); - int count = 0; - Foo item = new Foo(); - while (count++<100 && item!=null) { - item = reader.read(); - } - ((ItemStream) reader).close(); - assertEquals(7, count); - } - - protected DataSource getDataSource() { - return (DataSource) ctx.getBean("dataSource"); - } - -} +/* + * Copyright 2009-2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item.database; + +import javax.sql.DataSource; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import org.springframework.batch.item.AbstractItemStreamItemReaderTests; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemStream; +import org.springframework.batch.item.sample.Foo; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +import static org.junit.Assert.assertEquals; + +public abstract class AbstractDatabaseItemStreamItemReaderTests extends AbstractItemStreamItemReaderTests { + + protected ClassPathXmlApplicationContext ctx; + + @Override + @Before + public void setUp() throws Exception { + initializeContext(); + super.setUp(); + } + + @Override + @After + public void tearDown() throws Exception { + super.tearDown(); + ctx.close(); + } + + /** + * Sub-classes can override this and create their own context. + */ + protected void initializeContext() throws Exception { + ctx = new ClassPathXmlApplicationContext("org/springframework/batch/item/database/data-source-context.xml"); + } + + @Test + public void testReadToExhaustion() throws Exception { + ItemReader reader = getItemReader(); + ((ItemStream) reader).open(new ExecutionContext()); + // pointToEmptyInput(reader); + int count = 0; + Foo item = new Foo(); + while (count++ < 100 && item != null) { + item = reader.read(); + } + ((ItemStream) reader).close(); + assertEquals(7, count); + } + + protected DataSource getDataSource() { + return (DataSource) ctx.getBean("dataSource"); + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/AbstractGenericDataSourceItemReaderIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/AbstractGenericDataSourceItemReaderIntegrationTests.java index cd3303778..b7d91e51f 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/AbstractGenericDataSourceItemReaderIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/AbstractGenericDataSourceItemReaderIntegrationTests.java @@ -15,22 +15,20 @@ */ package org.springframework.batch.item.database; - - import org.junit.runner.RunWith; import org.springframework.batch.item.ItemReader; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** - * Generic configuration for testing {@link ItemReader} implementations which read - * data from database. Uses a common test context and HSQLDB database. - * + * Generic configuration for testing {@link ItemReader} implementations which read data + * from database. Uses a common test context and HSQLDB database. + * * @author Thomas Risberg */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "data-source-context.xml") -public abstract class AbstractGenericDataSourceItemReaderIntegrationTests +public abstract class AbstractGenericDataSourceItemReaderIntegrationTests extends AbstractDataSourceItemReaderIntegrationTests { } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/AbstractHibernateCursorItemReaderIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/AbstractHibernateCursorItemReaderIntegrationTests.java index ee9d44439..cecc0262c 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/AbstractHibernateCursorItemReaderIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/AbstractHibernateCursorItemReaderIntegrationTests.java @@ -29,8 +29,8 @@ import org.springframework.orm.hibernate5.LocalSessionFactoryBean; * @author Robert Kasanicky * @author Dave Syer */ -public abstract class AbstractHibernateCursorItemReaderIntegrationTests extends -AbstractGenericDataSourceItemReaderIntegrationTests { +public abstract class AbstractHibernateCursorItemReaderIntegrationTests + extends AbstractGenericDataSourceItemReaderIntegrationTests { @Override protected ItemReader createItemReader() throws Exception { diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/AbstractJdbcItemReaderIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/AbstractJdbcItemReaderIntegrationTests.java index 6244e6d43..4d2b7cfed 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/AbstractJdbcItemReaderIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/AbstractJdbcItemReaderIntegrationTests.java @@ -35,7 +35,8 @@ import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.transaction.annotation.Transactional; /** - * Common scenarios for testing {@link ItemReader} implementations which read data from database. + * Common scenarios for testing {@link ItemReader} implementations which read data from + * database. * * @author Lucas Ward * @author Robert Kasanicky @@ -45,7 +46,7 @@ public abstract class AbstractJdbcItemReaderIntegrationTests { protected ItemReader itemReader; protected ExecutionContext executionContext; - + protected abstract ItemReader createItemReader() throws Exception; protected DataSource dataSource; @@ -59,21 +60,22 @@ public abstract class AbstractJdbcItemReaderIntegrationTests { } @Before - public void onSetUp()throws Exception{ + public void onSetUp() throws Exception { itemReader = createItemReader(); getAsInitializingBean(itemReader).afterPropertiesSet(); executionContext = new ExecutionContext(); } @After - public void onTearDown()throws Exception { + public void onTearDown() throws Exception { getAsDisposableBean(itemReader).destroy(); } /* * Regular scenario - read all rows and eventually return null. */ - @Transactional @Test + @Transactional + @Test public void testNormalProcessing() throws Exception { getAsInitializingBean(itemReader).afterPropertiesSet(); getAsItemStream(itemReader).open(executionContext); @@ -99,7 +101,8 @@ public abstract class AbstractJdbcItemReaderIntegrationTests { /* * Restart scenario. */ - @Transactional @Test + @Transactional + @Test public void testRestart() throws Exception { getAsItemStream(itemReader).open(executionContext); Foo foo1 = itemReader.read(); @@ -121,7 +124,8 @@ public abstract class AbstractJdbcItemReaderIntegrationTests { /* * Reading from an input source and then trying to restore causes an error. */ - @Transactional @Test + @Transactional + @Test public void testInvalidRestore() throws Exception { getAsItemStream(itemReader).open(executionContext); @@ -152,7 +156,8 @@ public abstract class AbstractJdbcItemReaderIntegrationTests { /* * Empty restart data should be handled gracefully. */ - @Transactional @Test + @Transactional + @Test public void testRestoreFromEmptyData() throws Exception { ExecutionContext streamContext = new ExecutionContext(); getAsItemStream(itemReader).open(streamContext); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/AbstractPagingItemReaderParameterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/AbstractPagingItemReaderParameterTests.java index 62b1f80aa..70c0b5031 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/AbstractPagingItemReaderParameterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/AbstractPagingItemReaderParameterTests.java @@ -33,6 +33,7 @@ import org.springframework.beans.factory.annotation.Autowired; public abstract class AbstractPagingItemReaderParameterTests { protected AbstractPagingItemReader tested; + protected ExecutionContext executionContext = new ExecutionContext(); @Autowired @@ -45,13 +46,13 @@ public abstract class AbstractPagingItemReaderParameterTests { @After public void tearDown() { - ((ItemStream)tested).close(); + ((ItemStream) tested).close(); } @Test public void testRead() throws Exception { - ((ItemStream)tested).open(executionContext); + ((ItemStream) tested).open(executionContext); Foo foo2 = tested.read(); Assert.assertEquals(2, foo2.getValue()); @@ -72,8 +73,8 @@ public abstract class AbstractPagingItemReaderParameterTests { @Test public void testReadAfterJumpFirstPage() throws Exception { - executionContext.putInt(getName()+".read.count", 2); - ((ItemStream)tested).open(executionContext); + executionContext.putInt(getName() + ".read.count", 2); + ((ItemStream) tested).open(executionContext); Foo foo4 = tested.read(); Assert.assertEquals(4, foo4.getValue()); @@ -88,8 +89,8 @@ public abstract class AbstractPagingItemReaderParameterTests { @Test public void testReadAfterJumpSecondPage() throws Exception { - executionContext.putInt(getName()+".read.count", 3); - ((ItemStream)tested).open(executionContext); + executionContext.putInt(getName() + ".read.count", 3); + ((ItemStream) tested).open(executionContext); Foo foo5 = tested.read(); Assert.assertEquals(5, foo5.getValue()); @@ -97,10 +98,11 @@ public abstract class AbstractPagingItemReaderParameterTests { Object o = tested.read(); Assert.assertNull(o); } - + protected String getName() { return tested.getClass().getSimpleName(); } - + protected abstract AbstractPagingItemReader getItemReader() throws Exception; + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/CompositeKeyFooDao.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/CompositeKeyFooDao.java index 43b4adb48..135e3ba78 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/CompositeKeyFooDao.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/CompositeKeyFooDao.java @@ -35,18 +35,20 @@ public class CompositeKeyFooDao extends JdbcDaoSupport implements FooDao { public CompositeKeyFooDao(DataSource dataSource) { this.setDataSource(dataSource); } - - /* (non-Javadoc) + + /* + * (non-Javadoc) + * * @see org.springframework.batch.io.sql.scratch.FooDao#getFoo(java.lang.Object) */ - @Override + @Override public Foo getFoo(Object key) { - Map keys = (Map)key; + Map keys = (Map) key; Object[] args = keys.values().toArray(); - RowMapper fooMapper = new RowMapper(){ - @Override + RowMapper fooMapper = new RowMapper() { + @Override public Foo mapRow(ResultSet rs, int rowNum) throws SQLException { Foo foo = new Foo(); foo.setId(rs.getInt(1)); @@ -56,8 +58,8 @@ public class CompositeKeyFooDao extends JdbcDaoSupport implements FooDao { } }; - return getJdbcTemplate().query("SELECT ID, NAME, VALUE from T_FOOS where ID = ? and VALUE = ?", - fooMapper, args).get(0); + return getJdbcTemplate().query("SELECT ID, NAME, VALUE from T_FOOS where ID = ? and VALUE = ?", fooMapper, args) + .get(0); } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/ExtendedConnectionDataSourceProxyTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/ExtendedConnectionDataSourceProxyTests.java index 164697d16..06d2d74f5 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/ExtendedConnectionDataSourceProxyTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/ExtendedConnectionDataSourceProxyTests.java @@ -91,7 +91,6 @@ public class ExtendedConnectionDataSourceProxyTests { assertTrue("should be able to close connection", csds.shouldClose(con4)); con4.close(); - } @Test @@ -104,7 +103,6 @@ public class ExtendedConnectionDataSourceProxyTests { when(ds.getConnection()).thenReturn(con); // con2 con.close(); - final ExtendedConnectionDataSourceProxy csds = new ExtendedConnectionDataSourceProxy(ds); Connection con1 = csds.getConnection(); @@ -124,7 +122,6 @@ public class ExtendedConnectionDataSourceProxyTests { assertTrue("should be able to close connection", csds.shouldClose(con2)); con2.close(); - } @Test @@ -184,7 +181,6 @@ public class ExtendedConnectionDataSourceProxyTests { when(rs.next()).thenReturn(false); con.close(); - final ExtendedConnectionDataSourceProxy csds = new ExtendedConnectionDataSourceProxy(); csds.setDataSource(ds); PlatformTransactionManager tm = new DataSourceTransactionManager(csds); @@ -250,8 +246,8 @@ public class ExtendedConnectionDataSourceProxyTests { fail(); } catch (SQLException expected) { - // this would be the correct behavior in a Java6-only recursive implementation - // assertEquals(DataSourceStub.UNWRAP_ERROR_MESSAGE, expected.getMessage()); + // this would be the correct behavior in a Java6-only recursive implementation + // assertEquals(DataSourceStub.UNWRAP_ERROR_MESSAGE, expected.getMessage()); assertEquals("Unsupported class " + Unsupported.class.getSimpleName(), expected.getMessage()); } } @@ -282,17 +278,19 @@ public class ExtendedConnectionDataSourceProxyTests { * Interface implemented by the wrapped DataSource */ private static interface Supported { + } /** * Interface *not* implemented by the wrapped DataSource */ private static interface Unsupported { + } /** - * Stub for a wrapped DataSource that implements additional interface. Its - * purpose is testing of {@link DataSource#isWrapperFor(Class)} and + * Stub for a wrapped DataSource that implements additional interface. Its purpose is + * testing of {@link DataSource#isWrapperFor(Class)} and * {@link DataSource#unwrap(Class)} methods. */ private static class DataSourceStub implements DataSource, Supported { @@ -353,5 +351,7 @@ public class ExtendedConnectionDataSourceProxyTests { public Logger getParentLogger() throws SQLFeatureNotSupportedException { throw new SQLFeatureNotSupportedException(); } + } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/FooDao.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/FooDao.java index c6d8d890d..0d984c44c 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/FooDao.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/FooDao.java @@ -28,4 +28,5 @@ public interface FooDao { Foo getFoo(Object key); void setDataSource(DataSource dataSource); + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/FooRowMapper.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/FooRowMapper.java index bcb64f6a8..cdf7e6a5e 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/FooRowMapper.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/FooRowMapper.java @@ -21,17 +21,17 @@ import java.sql.SQLException; import org.springframework.batch.item.sample.Foo; import org.springframework.jdbc.core.RowMapper; - public class FooRowMapper implements RowMapper { - @Override - public Foo mapRow(ResultSet rs, int rowNum) throws SQLException { + @Override + public Foo mapRow(ResultSet rs, int rowNum) throws SQLException { + + Foo foo = new Foo(); + foo.setId(rs.getInt(1)); + foo.setName(rs.getString(2)); + foo.setValue(rs.getInt(3)); + + return foo; + } - Foo foo = new Foo(); - foo.setId(rs.getInt(1)); - foo.setName(rs.getString(2)); - foo.setValue(rs.getInt(3)); - - return foo; - } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorItemReaderCommonTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorItemReaderCommonTests.java index 11c39c462..d99adf816 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorItemReaderCommonTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorItemReaderCommonTests.java @@ -1,65 +1,65 @@ -/* - * Copyright 2008-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.database; - -import org.hibernate.SessionFactory; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.sample.Foo; -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.Resource; -import org.springframework.orm.hibernate5.LocalSessionFactoryBean; - -public class HibernateCursorItemReaderCommonTests extends AbstractDatabaseItemStreamItemReaderTests { - - @Override - protected ItemReader getItemReader() throws Exception { - - SessionFactory sessionFactory = createSessionFactory(); - - String hsqlQuery = "from Foo"; - - HibernateCursorItemReader reader = new HibernateCursorItemReader<>(); - reader.setQueryString(hsqlQuery); - reader.setSessionFactory(sessionFactory); - reader.setUseStatelessSession(true); - reader.setFetchSize(10); - reader.afterPropertiesSet(); - reader.setSaveState(true); - - return reader; - } - - private SessionFactory createSessionFactory() throws Exception { - LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean(); - factoryBean.setDataSource(getDataSource()); - factoryBean.setMappingLocations(new Resource[] { new ClassPathResource("Foo.hbm.xml", getClass()) }); - factoryBean.afterPropertiesSet(); - - return factoryBean.getObject(); - - } - - @Override - protected void pointToEmptyInput(ItemReader tested) throws Exception { - HibernateCursorItemReader reader = (HibernateCursorItemReader) tested; - reader.close(); - reader.setQueryString("from Foo foo where foo.id = -1"); - reader.afterPropertiesSet(); - reader.open(new ExecutionContext()); - } - -} +/* + * Copyright 2008-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item.database; + +import org.hibernate.SessionFactory; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.sample.Foo; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.springframework.orm.hibernate5.LocalSessionFactoryBean; + +public class HibernateCursorItemReaderCommonTests extends AbstractDatabaseItemStreamItemReaderTests { + + @Override + protected ItemReader getItemReader() throws Exception { + + SessionFactory sessionFactory = createSessionFactory(); + + String hsqlQuery = "from Foo"; + + HibernateCursorItemReader reader = new HibernateCursorItemReader<>(); + reader.setQueryString(hsqlQuery); + reader.setSessionFactory(sessionFactory); + reader.setUseStatelessSession(true); + reader.setFetchSize(10); + reader.afterPropertiesSet(); + reader.setSaveState(true); + + return reader; + } + + private SessionFactory createSessionFactory() throws Exception { + LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean(); + factoryBean.setDataSource(getDataSource()); + factoryBean.setMappingLocations(new Resource[] { new ClassPathResource("Foo.hbm.xml", getClass()) }); + factoryBean.afterPropertiesSet(); + + return factoryBean.getObject(); + + } + + @Override + protected void pointToEmptyInput(ItemReader tested) throws Exception { + HibernateCursorItemReader reader = (HibernateCursorItemReader) tested; + reader.close(); + reader.setQueryString("from Foo foo where foo.id = -1"); + reader.afterPropertiesSet(); + reader.open(new ExecutionContext()); + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorItemReaderIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorItemReaderIntegrationTests.java index 6ad8078a2..421fafa5b 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorItemReaderIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorItemReaderIntegrationTests.java @@ -24,20 +24,20 @@ import org.springframework.batch.item.sample.Foo; /** * Tests for {@link HibernateCursorItemReader} using {@link StatelessSession}. - * + * * @author Robert Kasanicky */ public class HibernateCursorItemReaderIntegrationTests extends AbstractHibernateCursorItemReaderIntegrationTests { /** * Exception scenario. - * - * {@link HibernateCursorItemReader#setUseStatelessSession(boolean)} can be - * called only in uninitialized state. + * + * {@link HibernateCursorItemReader#setUseStatelessSession(boolean)} can be called + * only in uninitialized state. */ @Test public void testSetUseStatelessSession() { - HibernateCursorItemReader inputSource = (HibernateCursorItemReader)reader; + HibernateCursorItemReader inputSource = (HibernateCursorItemReader) reader; // initialize and call setter => error inputSource.open(new ExecutionContext()); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorItemReaderNamedQueryIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorItemReaderNamedQueryIntegrationTests.java index 84b4048e8..37ecb8690 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorItemReaderNamedQueryIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorItemReaderNamedQueryIntegrationTests.java @@ -1,30 +1,31 @@ -/* - * Copyright 2009-2010 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.database; - -import org.springframework.batch.item.sample.Foo; - -/** - * Tests {@link HibernateCursorItemReader} configured with named query. - */ -public class HibernateCursorItemReaderNamedQueryIntegrationTests extends AbstractHibernateCursorItemReaderIntegrationTests { - - @Override - protected void setQuery(HibernateCursorItemReader reader) { - reader.setQueryName("allFoos"); - } - -} +/* + * Copyright 2009-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item.database; + +import org.springframework.batch.item.sample.Foo; + +/** + * Tests {@link HibernateCursorItemReader} configured with named query. + */ +public class HibernateCursorItemReaderNamedQueryIntegrationTests + extends AbstractHibernateCursorItemReaderIntegrationTests { + + @Override + protected void setQuery(HibernateCursorItemReader reader) { + reader.setQueryName("allFoos"); + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorItemReaderNativeQueryIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorItemReaderNativeQueryIntegrationTests.java index 3b06ea471..d46b9f8b4 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorItemReaderNativeQueryIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorItemReaderNativeQueryIntegrationTests.java @@ -22,22 +22,23 @@ import org.springframework.batch.item.sample.Foo; * @author Anatoly Polinsky * @author Dave Syer */ -public class HibernateCursorItemReaderNativeQueryIntegrationTests extends AbstractHibernateCursorItemReaderIntegrationTests { - - @Override - protected void setQuery(HibernateCursorItemReader hibernateReader) throws Exception { +public class HibernateCursorItemReaderNativeQueryIntegrationTests + extends AbstractHibernateCursorItemReaderIntegrationTests { - String nativeQuery = "select * from T_FOOS"; - - //creating a native query provider as it would be created in configuration - HibernateNativeQueryProvider queryProvider = - new HibernateNativeQueryProvider<>(); + @Override + protected void setQuery(HibernateCursorItemReader hibernateReader) throws Exception { + + String nativeQuery = "select * from T_FOOS"; + + // creating a native query provider as it would be created in configuration + HibernateNativeQueryProvider queryProvider = new HibernateNativeQueryProvider<>(); + + queryProvider.setSqlQuery(nativeQuery); + queryProvider.setEntityClass(Foo.class); + queryProvider.afterPropertiesSet(); + + hibernateReader.setQueryProvider(queryProvider); + + } - queryProvider.setSqlQuery(nativeQuery); - queryProvider.setEntityClass(Foo.class); - queryProvider.afterPropertiesSet(); - - hibernateReader.setQueryProvider(queryProvider); - - } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorItemReaderParametersIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorItemReaderParametersIntegrationTests.java index 2fb46bec1..90772286c 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorItemReaderParametersIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorItemReaderParametersIntegrationTests.java @@ -23,14 +23,14 @@ import org.springframework.batch.item.sample.Foo; /** * Tests for {@link HibernateCursorItemReader} using {@link StatelessSession}. - * + * * @author Robert Kasanicky * @author Dave Syer */ -public class HibernateCursorItemReaderParametersIntegrationTests extends - AbstractHibernateCursorItemReaderIntegrationTests { +public class HibernateCursorItemReaderParametersIntegrationTests + extends AbstractHibernateCursorItemReaderIntegrationTests { - @Override + @Override protected void setQuery(HibernateCursorItemReader reader) { reader.setQueryString("from Foo where name like :name"); reader.setParameterValues(Collections.singletonMap("name", "bar%")); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorItemReaderStatefulIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorItemReaderStatefulIntegrationTests.java index 5eb08e6f0..331de3f56 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorItemReaderStatefulIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorItemReaderStatefulIntegrationTests.java @@ -32,17 +32,18 @@ import static org.mockito.Mockito.when; * @author Robert Kasanicky * @author Will Schipp */ -public class HibernateCursorItemReaderStatefulIntegrationTests extends AbstractHibernateCursorItemReaderIntegrationTests { +public class HibernateCursorItemReaderStatefulIntegrationTests + extends AbstractHibernateCursorItemReaderIntegrationTests { @Override protected boolean isUseStatelessSession() { return false; } - //Ensure close is called on the stateful session correctly. + // Ensure close is called on the stateful session correctly. @Test @SuppressWarnings("unchecked") - public void testStatefulClose(){ + public void testStatefulClose() { SessionFactory sessionFactory = mock(SessionFactory.class); Session session = mock(Session.class); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorItemReaderStatefulNamedQueryIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorItemReaderStatefulNamedQueryIntegrationTests.java index b15ec16d8..a0b046c07 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorItemReaderStatefulNamedQueryIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorItemReaderStatefulNamedQueryIntegrationTests.java @@ -1,29 +1,30 @@ -/* - * Copyright 2009 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.database; - -/** - * Tests {@link HibernateCursorItemReader} configured with stateful session and - * named query. - */ -public class HibernateCursorItemReaderStatefulNamedQueryIntegrationTests extends - HibernateCursorItemReaderNamedQueryIntegrationTests { - - @Override - protected boolean isUseStatelessSession() { - return false; - } -} +/* + * Copyright 2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item.database; + +/** + * Tests {@link HibernateCursorItemReader} configured with stateful session and named + * query. + */ +public class HibernateCursorItemReaderStatefulNamedQueryIntegrationTests + extends HibernateCursorItemReaderNamedQueryIntegrationTests { + + @Override + protected boolean isUseStatelessSession() { + return false; + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorProjectionItemReaderIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorProjectionItemReaderIntegrationTests.java index 5975b4a57..4404c87a5 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorProjectionItemReaderIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorProjectionItemReaderIntegrationTests.java @@ -46,17 +46,14 @@ public class HibernateCursorProjectionItemReaderIntegrationTests { @Autowired private DataSource dataSource; - private void initializeItemReader(HibernateCursorItemReader reader, - String hsqlQuery) throws Exception { + private void initializeItemReader(HibernateCursorItemReader reader, String hsqlQuery) throws Exception { LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean(); factoryBean.setDataSource(dataSource); - factoryBean.setMappingLocations(new Resource[] { new ClassPathResource( - "Foo.hbm.xml", getClass()) }); + factoryBean.setMappingLocations(new Resource[] { new ClassPathResource("Foo.hbm.xml", getClass()) }); factoryBean.afterPropertiesSet(); - SessionFactory sessionFactory = factoryBean - .getObject(); + SessionFactory sessionFactory = factoryBean.getObject(); reader.setQueryString(hsqlQuery); reader.setSessionFactory(sessionFactory); @@ -90,7 +87,8 @@ public class HibernateCursorProjectionItemReaderIntegrationTests { Object[] foo1 = reader.read(); assertNotNull(foo1); fail("Expected ClassCastException"); - } catch(ClassCastException e) { + } + catch (ClassCastException e) { // expected } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateItemReaderHelperTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateItemReaderHelperTests.java index 6c73f1cee..33d202848 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateItemReaderHelperTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateItemReaderHelperTests.java @@ -1,73 +1,71 @@ -/* - * Copyright 2006-2009 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.item.database; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - - -import org.hibernate.SessionFactory; -import org.hibernate.StatelessSession; -import org.junit.Test; -import org.springframework.test.util.ReflectionTestUtils; - - -/** - * @author Dave Syer - * @author Will Schipp - * - */ -public class HibernateItemReaderHelperTests { - - private HibernateItemReaderHelper helper = new HibernateItemReaderHelper<>(); - - private SessionFactory sessionFactory = mock(SessionFactory.class); - - @Test - public void testOneSessionForAllPages() throws Exception { - - StatelessSession session = mock(StatelessSession.class); - when(sessionFactory.openStatelessSession()).thenReturn(session); - - helper.setSessionFactory(sessionFactory); - - helper.createQuery(); - // Multiple calls to createQuery only creates one session - helper.createQuery(); - - } - - @Test - public void testSessionReset() throws Exception { - - StatelessSession session = mock(StatelessSession.class); - when(sessionFactory.openStatelessSession()).thenReturn(session); - - helper.setSessionFactory(sessionFactory); - - helper.createQuery(); - assertNotNull(ReflectionTestUtils.getField(helper, "statelessSession")); - - helper.close(); - assertNull(ReflectionTestUtils.getField(helper, "statelessSession")); - - } - -} +/* + * Copyright 2006-2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.item.database; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import org.hibernate.SessionFactory; +import org.hibernate.StatelessSession; +import org.junit.Test; +import org.springframework.test.util.ReflectionTestUtils; + +/** + * @author Dave Syer + * @author Will Schipp + * + */ +public class HibernateItemReaderHelperTests { + + private HibernateItemReaderHelper helper = new HibernateItemReaderHelper<>(); + + private SessionFactory sessionFactory = mock(SessionFactory.class); + + @Test + public void testOneSessionForAllPages() throws Exception { + + StatelessSession session = mock(StatelessSession.class); + when(sessionFactory.openStatelessSession()).thenReturn(session); + + helper.setSessionFactory(sessionFactory); + + helper.createQuery(); + // Multiple calls to createQuery only creates one session + helper.createQuery(); + + } + + @Test + public void testSessionReset() throws Exception { + + StatelessSession session = mock(StatelessSession.class); + when(sessionFactory.openStatelessSession()).thenReturn(session); + + helper.setSessionFactory(sessionFactory); + + helper.createQuery(); + assertNotNull(ReflectionTestUtils.getField(helper, "statelessSession")); + + helper.close(); + assertNull(ReflectionTestUtils.getField(helper, "statelessSession")); + + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateItemWriterTests.java index 17d3be676..106e5e156 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateItemWriterTests.java @@ -42,6 +42,7 @@ public class HibernateItemWriterTests { HibernateItemWriter writer; SessionFactory factory; + Session currentSession; @Before @@ -56,7 +57,6 @@ public class HibernateItemWriterTests { /** * Test method for * {@link org.springframework.batch.item.database.HibernateItemWriter#afterPropertiesSet()} - * * @throws Exception */ @Test @@ -75,7 +75,6 @@ public class HibernateItemWriterTests { /** * Test method for * {@link org.springframework.batch.item.database.HibernateItemWriter#afterPropertiesSet()} - * * @throws Exception */ @Test @@ -144,4 +143,5 @@ public class HibernateItemWriterTests { assertEquals("ERROR", e.getMessage()); } } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernatePagingItemReaderIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernatePagingItemReaderIntegrationTests.java index 5d4f627ce..b2bf1fcd7 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernatePagingItemReaderIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernatePagingItemReaderIntegrationTests.java @@ -29,8 +29,7 @@ import org.springframework.orm.hibernate5.LocalSessionFactoryBean; * @author Robert Kasanicky * @author Dave Syer */ -public class HibernatePagingItemReaderIntegrationTests extends -AbstractGenericDataSourceItemReaderIntegrationTests { +public class HibernatePagingItemReaderIntegrationTests extends AbstractGenericDataSourceItemReaderIntegrationTests { @Override protected ItemReader createItemReader() throws Exception { diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcBatchItemWriterClassicTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcBatchItemWriterClassicTests.java index e4a58ab58..a88b699ae 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcBatchItemWriterClassicTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcBatchItemWriterClassicTests.java @@ -53,8 +53,8 @@ public class JdbcBatchItemWriterClassicTests { public void setUp() throws Exception { ps = mock(PreparedStatement.class); jdbcTemplate = new JdbcTemplate() { - @Override - public T execute(String sql, PreparedStatementCallback action) throws DataAccessException { + @Override + public T execute(String sql, PreparedStatementCallback action) throws DataAccessException { list.add(sql); try { return action.doInPreparedStatement(ps); @@ -67,7 +67,7 @@ public class JdbcBatchItemWriterClassicTests { writer.setSql("SQL"); writer.setJdbcTemplate(new NamedParameterJdbcTemplate(jdbcTemplate)); writer.setItemPreparedStatementSetter(new ItemPreparedStatementSetter() { - @Override + @Override public void setValues(String item, PreparedStatement ps) throws SQLException { list.add(item); } @@ -91,7 +91,8 @@ public class JdbcBatchItemWriterClassicTests { catch (IllegalArgumentException e) { // expected String message = e.getMessage(); - assertTrue("Message does not contain ' NamedParameterJdbcTemplate'.", message.indexOf("NamedParameterJdbcTemplate") >= 0); + assertTrue("Message does not contain ' NamedParameterJdbcTemplate'.", + message.indexOf("NamedParameterJdbcTemplate") >= 0); } writer.setJdbcTemplate(new NamedParameterJdbcTemplate(jdbcTemplate)); try { @@ -111,16 +112,15 @@ public class JdbcBatchItemWriterClassicTests { catch (IllegalArgumentException e) { // expected String message = e.getMessage(); - assertTrue("Message does not contain 'ItemPreparedStatementSetter'.", message.indexOf("ItemPreparedStatementSetter") >= 0); + assertTrue("Message does not contain 'ItemPreparedStatementSetter'.", + message.indexOf("ItemPreparedStatementSetter") >= 0); } - writer.setItemPreparedStatementSetter( - new ItemPreparedStatementSetter() { - @Override - public void setValues(String item, PreparedStatement ps) - throws SQLException { - } - - }); + writer.setItemPreparedStatementSetter(new ItemPreparedStatementSetter() { + @Override + public void setValues(String item, PreparedStatement ps) throws SQLException { + } + + }); writer.afterPropertiesSet(); } @@ -154,7 +154,7 @@ public class JdbcBatchItemWriterClassicTests { public void testWriteAndFlushWithFailure() throws Exception { final RuntimeException ex = new RuntimeException("bar"); writer.setItemPreparedStatementSetter(new ItemPreparedStatementSetter() { - @Override + @Override public void setValues(String item, PreparedStatement ps) throws SQLException { list.add(item); throw ex; @@ -171,7 +171,7 @@ public class JdbcBatchItemWriterClassicTests { } assertEquals(2, list.size()); writer.setItemPreparedStatementSetter(new ItemPreparedStatementSetter() { - @Override + @Override public void setValues(String item, PreparedStatement ps) throws SQLException { list.add(item); } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcBatchItemWriterNamedParameterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcBatchItemWriterNamedParameterTests.java index af1cff623..008a7cdae 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcBatchItemWriterNamedParameterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcBatchItemWriterNamedParameterTests.java @@ -54,7 +54,9 @@ public class JdbcBatchItemWriterNamedParameterTests { @SuppressWarnings("unused") private class Foo { + private Long id; + private String bar; public Foo(String bar) { @@ -85,8 +87,7 @@ public class JdbcBatchItemWriterNamedParameterTests { namedParameterJdbcOperations = mock(NamedParameterJdbcOperations.class); writer.setSql(sql); writer.setJdbcTemplate(namedParameterJdbcOperations); - writer.setItemSqlParameterSourceProvider( - new BeanPropertyItemSqlParameterSourceProvider<>()); + writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>()); writer.afterPropertiesSet(); } @@ -105,7 +106,8 @@ public class JdbcBatchItemWriterNamedParameterTests { catch (IllegalArgumentException e) { // expected String message = e.getMessage(); - assertTrue("Message does not contain 'NamedParameterJdbcTemplate'.", message.contains("NamedParameterJdbcTemplate")); + assertTrue("Message does not contain 'NamedParameterJdbcTemplate'.", + message.contains("NamedParameterJdbcTemplate")); } writer.setJdbcTemplate(namedParameterJdbcOperations); try { @@ -125,8 +127,9 @@ public class JdbcBatchItemWriterNamedParameterTests { @Test public void testWriteAndFlush() throws Exception { when(namedParameterJdbcOperations.batchUpdate(eq(sql), - eqSqlParameterSourceArray(new SqlParameterSource[] {new BeanPropertySqlParameterSource(new Foo("bar"))}))) - .thenReturn(new int[] {1}); + eqSqlParameterSourceArray( + new SqlParameterSource[] { new BeanPropertySqlParameterSource(new Foo("bar")) }))) + .thenReturn(new int[] { 1 }); writer.write(Collections.singletonList(new Foo("bar"))); } @@ -134,16 +137,14 @@ public class JdbcBatchItemWriterNamedParameterTests { @Test public void testWriteAndFlushMap() throws Exception { JdbcBatchItemWriter> mapWriter = new JdbcBatchItemWriter<>(); - + mapWriter.setSql(sql); mapWriter.setJdbcTemplate(namedParameterJdbcOperations); mapWriter.afterPropertiesSet(); - - ArgumentCaptor captor = ArgumentCaptor.forClass(Map[].class); - when(namedParameterJdbcOperations.batchUpdate(eq(sql), - captor.capture())) - .thenReturn(new int[] {1}); + ArgumentCaptor captor = ArgumentCaptor.forClass(Map[].class); + + when(namedParameterJdbcOperations.batchUpdate(eq(sql), captor.capture())).thenReturn(new int[] { 1 }); mapWriter.write(Collections.singletonList(Collections.singletonMap("foo", "bar"))); assertEquals(1, captor.getValue().length); @@ -165,11 +166,9 @@ public class JdbcBatchItemWriterNamedParameterTests { }); mapWriter.afterPropertiesSet(); - ArgumentCaptor captor = ArgumentCaptor.forClass(SqlParameterSource[].class); + ArgumentCaptor captor = ArgumentCaptor.forClass(SqlParameterSource[].class); - when(namedParameterJdbcOperations.batchUpdate(any(String.class), - captor.capture())) - .thenReturn(new int[] {1}); + when(namedParameterJdbcOperations.batchUpdate(any(String.class), captor.capture())).thenReturn(new int[] { 1 }); mapWriter.write(Collections.singletonList(Collections.singletonMap("foo", "bar"))); assertEquals(1, captor.getValue().length); @@ -180,8 +179,9 @@ public class JdbcBatchItemWriterNamedParameterTests { @Test public void testWriteAndFlushWithEmptyUpdate() throws Exception { when(namedParameterJdbcOperations.batchUpdate(eq(sql), - eqSqlParameterSourceArray(new SqlParameterSource[] {new BeanPropertySqlParameterSource(new Foo("bar"))}))) - .thenReturn(new int[] {0}); + eqSqlParameterSourceArray( + new SqlParameterSource[] { new BeanPropertySqlParameterSource(new Foo("bar")) }))) + .thenReturn(new int[] { 0 }); try { writer.write(Collections.singletonList(new Foo("bar"))); fail("Expected EmptyResultDataAccessException"); @@ -197,7 +197,8 @@ public class JdbcBatchItemWriterNamedParameterTests { public void testWriteAndFlushWithFailure() throws Exception { final RuntimeException ex = new RuntimeException("ERROR"); when(namedParameterJdbcOperations.batchUpdate(eq(sql), - eqSqlParameterSourceArray(new SqlParameterSource[] {new BeanPropertySqlParameterSource(new Foo("bar"))}))) + eqSqlParameterSourceArray( + new SqlParameterSource[] { new BeanPropertySqlParameterSource(new Foo("bar")) }))) .thenThrow(ex); try { writer.write(Collections.singletonList(new Foo("bar"))); @@ -214,6 +215,7 @@ public class JdbcBatchItemWriterNamedParameterTests { } public static class SqlParameterSourceArrayEquals extends BaseMatcher { + private SqlParameterSource[] expected; public SqlParameterSourceArrayEquals(SqlParameterSource[] expected) { @@ -225,7 +227,7 @@ public class JdbcBatchItemWriterNamedParameterTests { if (!(actual instanceof SqlParameterSource[])) { return false; } - SqlParameterSource[] actualArray = (SqlParameterSource[])actual; + SqlParameterSource[] actualArray = (SqlParameterSource[]) actual; if (expected.length != actualArray.length) { return false; } @@ -237,7 +239,6 @@ public class JdbcBatchItemWriterNamedParameterTests { return true; } - @Override public void describeTo(Description description) { description.appendText("eqSqlParameterSourceArray("); @@ -246,6 +247,7 @@ public class JdbcBatchItemWriterNamedParameterTests { description.appendValue(expected.length); description.appendText("\")"); } + } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcCursorItemReaderCommonTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcCursorItemReaderCommonTests.java index beef9ab70..804566cdb 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcCursorItemReaderCommonTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcCursorItemReaderCommonTests.java @@ -1,72 +1,72 @@ -/* - * Copyright 2008-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.database; - -import org.junit.Test; -import org.junit.runners.JUnit4; -import org.junit.runner.RunWith; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.ReaderNotOpenException; -import org.springframework.batch.item.sample.Foo; - -@RunWith(JUnit4.class) -public class JdbcCursorItemReaderCommonTests extends AbstractDatabaseItemStreamItemReaderTests { - - @Override - protected ItemReader getItemReader() throws Exception { - - JdbcCursorItemReader result = new JdbcCursorItemReader<>(); - result.setDataSource(getDataSource()); - result.setSql("select ID, NAME, VALUE from T_FOOS"); - result.setIgnoreWarnings(true); - result.setVerifyCursorPosition(true); - - result.setRowMapper(new FooRowMapper()); - result.setFetchSize(10); - result.setMaxRows(100); - result.setQueryTimeout(1000); - result.setSaveState(true); - result.setDriverSupportsAbsolute(false); - - return result; - } - - @Test - public void testRestartWithDriverSupportsAbsolute() throws Exception { - tested = getItemReader(); - ((JdbcCursorItemReader) tested).setDriverSupportsAbsolute(true); - testedAsStream().open(executionContext); - - testRestart(); - } - - @Override - protected void pointToEmptyInput(ItemReader tested) throws Exception { - JdbcCursorItemReader reader = (JdbcCursorItemReader) tested; - reader.close(); - reader.setSql("select ID from T_FOOS where ID < 0"); - reader.afterPropertiesSet(); - reader.open(new ExecutionContext()); - } - - @Test(expected=ReaderNotOpenException.class) - public void testReadBeforeOpen() throws Exception { - tested = getItemReader(); - tested.read(); - } - -} +/* + * Copyright 2008-2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item.database; + +import org.junit.Test; +import org.junit.runners.JUnit4; +import org.junit.runner.RunWith; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ReaderNotOpenException; +import org.springframework.batch.item.sample.Foo; + +@RunWith(JUnit4.class) +public class JdbcCursorItemReaderCommonTests extends AbstractDatabaseItemStreamItemReaderTests { + + @Override + protected ItemReader getItemReader() throws Exception { + + JdbcCursorItemReader result = new JdbcCursorItemReader<>(); + result.setDataSource(getDataSource()); + result.setSql("select ID, NAME, VALUE from T_FOOS"); + result.setIgnoreWarnings(true); + result.setVerifyCursorPosition(true); + + result.setRowMapper(new FooRowMapper()); + result.setFetchSize(10); + result.setMaxRows(100); + result.setQueryTimeout(1000); + result.setSaveState(true); + result.setDriverSupportsAbsolute(false); + + return result; + } + + @Test + public void testRestartWithDriverSupportsAbsolute() throws Exception { + tested = getItemReader(); + ((JdbcCursorItemReader) tested).setDriverSupportsAbsolute(true); + testedAsStream().open(executionContext); + + testRestart(); + } + + @Override + protected void pointToEmptyInput(ItemReader tested) throws Exception { + JdbcCursorItemReader reader = (JdbcCursorItemReader) tested; + reader.close(); + reader.setSql("select ID from T_FOOS where ID < 0"); + reader.afterPropertiesSet(); + reader.open(new ExecutionContext()); + } + + @Test(expected = ReaderNotOpenException.class) + public void testReadBeforeOpen() throws Exception { + tested = getItemReader(); + tested.read(); + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcCursorItemReaderConfigTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcCursorItemReaderConfigTests.java index b20e82351..ff963ec2e 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcCursorItemReaderConfigTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcCursorItemReaderConfigTests.java @@ -63,28 +63,28 @@ public class JdbcCursorItemReaderConfigTests { reader.setUseSharedExtendedConnection(true); reader.setSql("select foo from bar"); final ExecutionContext ec = new ExecutionContext(); - tt.execute( - new TransactionCallback() { - @Override - public Void doInTransaction(TransactionStatus status) { - reader.open(ec); - reader.close(); - return null; - } - }); + tt.execute(new TransactionCallback() { + @Override + public Void doInTransaction(TransactionStatus status) { + reader.open(ec); + reader.close(); + return null; + } + }); } - + /* * Should fail if trying to call getConnection() twice */ @Test public void testUsesItsOwnTransaction() throws Exception { - + DataSource ds = mock(DataSource.class); Connection con = mock(Connection.class); when(con.getAutoCommit()).thenReturn(false); PreparedStatement ps = mock(PreparedStatement.class); - when(con.prepareStatement("select foo from bar", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)).thenReturn(ps); + when(con.prepareStatement("select foo from bar", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)) + .thenReturn(ps); when(ds.getConnection()).thenReturn(con); when(ds.getConnection()).thenReturn(con); con.commit(); @@ -94,28 +94,27 @@ public class JdbcCursorItemReaderConfigTests { reader.setDataSource(ds); reader.setSql("select foo from bar"); final ExecutionContext ec = new ExecutionContext(); - tt.execute( - new TransactionCallback() { - @Override - public Void doInTransaction(TransactionStatus status) { - reader.open(ec); - reader.close(); - return null; - } - }); + tt.execute(new TransactionCallback() { + @Override + public Void doInTransaction(TransactionStatus status) { + reader.open(ec); + reader.close(); + return null; + } + }); } @Test public void testOverrideConnectionAutoCommit() throws Exception { - boolean initialAutoCommit= false; + boolean initialAutoCommit = false; boolean neededAutoCommit = true; DataSource ds = mock(DataSource.class); Connection con = mock(Connection.class); when(con.getAutoCommit()).thenReturn(initialAutoCommit); PreparedStatement ps = mock(PreparedStatement.class); - when(con.prepareStatement("select foo from bar", ResultSet.TYPE_FORWARD_ONLY, - ResultSet.CONCUR_READ_ONLY)).thenReturn(ps); + when(con.prepareStatement("select foo from bar", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)) + .thenReturn(ps); when(ds.getConnection()).thenReturn(con); final JdbcCursorItemReader reader = new JdbcCursorItemReader<>(); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcCursorItemReaderIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcCursorItemReaderIntegrationTests.java index 15dba3a62..f94f336a8 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcCursorItemReaderIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcCursorItemReaderIntegrationTests.java @@ -22,20 +22,20 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * Tests for {@link JdbcCursorItemReader} - * + * * @author Robert Kasanicky */ @RunWith(SpringJUnit4ClassRunner.class) public class JdbcCursorItemReaderIntegrationTests extends AbstractGenericDataSourceItemReaderIntegrationTests { - @Override + @Override protected ItemReader createItemReader() throws Exception { JdbcCursorItemReader result = new JdbcCursorItemReader<>(); result.setDataSource(dataSource); result.setSql("select ID, NAME, VALUE from T_FOOS"); result.setIgnoreWarnings(true); result.setVerifyCursorPosition(true); - + result.setRowMapper(new FooRowMapper()); result.setFetchSize(10); result.setMaxRows(100); @@ -45,6 +45,4 @@ public class JdbcCursorItemReaderIntegrationTests extends AbstractGenericDataSou return result; } - - } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderAsyncTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderAsyncTests.java index 607178a79..1b340574f 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderAsyncTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderAsyncTests.java @@ -107,8 +107,8 @@ public class JdbcPagingItemReaderAsyncTests { } } if (!throwables.isEmpty()) { - throw new IllegalStateException(String.format("Failed %d out of %d", throwables.size(), max), throwables - .get(0)); + throw new IllegalStateException(String.format("Failed %d out of %d", throwables.size(), max), + throwables.get(0)); } } @@ -119,11 +119,11 @@ public class JdbcPagingItemReaderAsyncTests { */ private void doTest() throws Exception, InterruptedException, ExecutionException { final ItemReader reader = getItemReader(); - CompletionService> completionService = new ExecutorCompletionService<>(Executors - .newFixedThreadPool(THREAD_COUNT)); + CompletionService> completionService = new ExecutorCompletionService<>( + Executors.newFixedThreadPool(THREAD_COUNT)); for (int i = 0; i < THREAD_COUNT; i++) { completionService.submit(new Callable>() { - @Override + @Override public List call() throws Exception { List list = new ArrayList<>(); Foo next = null; @@ -134,7 +134,8 @@ public class JdbcPagingItemReaderAsyncTests { if (next != null) { list.add(next); } - } while (next != null); + } + while (next != null); return list; } }); @@ -165,7 +166,7 @@ public class JdbcPagingItemReaderAsyncTests { queryProvider.setSortKeys(sortKeys); reader.setQueryProvider(queryProvider); reader.setRowMapper(new RowMapper() { - @Override + @Override public Foo mapRow(ResultSet rs, int i) throws SQLException { Foo foo = new Foo(); foo.setId(rs.getInt(1)); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderClassicParameterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderClassicParameterTests.java index ab88f6415..ec28c97fe 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderClassicParameterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderClassicParameterTests.java @@ -38,13 +38,14 @@ import org.springframework.test.util.ReflectionTestUtils; * */ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = "/org/springframework/batch/item/database/JdbcPagingItemReaderParameterTests-context.xml") +@ContextConfiguration( + locations = "/org/springframework/batch/item/database/JdbcPagingItemReaderParameterTests-context.xml") public class JdbcPagingItemReaderClassicParameterTests extends AbstractJdbcPagingItemReaderParameterTests { // force jumpToItemQuery in JdbcPagingItemReader.doJumpToPage(int) private static boolean forceJumpToItemQuery = false; - - @Override + + @Override protected AbstractPagingItemReader getItemReader() throws Exception { JdbcPagingItemReader reader = new JdbcPagingItemReader() { @Override @@ -65,18 +66,16 @@ public class JdbcPagingItemReaderClassicParameterTests extends AbstractJdbcPagin queryProvider.setSortKeys(sortKeys); reader.setParameterValues(Collections.singletonMap("limit", 2)); reader.setQueryProvider(queryProvider); - reader.setRowMapper( - new RowMapper() { - @Override - public Foo mapRow(ResultSet rs, int i) throws SQLException { - Foo foo = new Foo(); - foo.setId(rs.getInt(1)); - foo.setName(rs.getString(2)); - foo.setValue(rs.getInt(3)); - return foo; - } - } - ); + reader.setRowMapper(new RowMapper() { + @Override + public Foo mapRow(ResultSet rs, int i) throws SQLException { + Foo foo = new Foo(); + foo.setId(rs.getInt(1)); + foo.setName(rs.getString(2)); + foo.setValue(rs.getInt(3)); + return foo; + } + }); reader.setPageSize(3); reader.afterPropertiesSet(); reader.setSaveState(true); @@ -84,20 +83,21 @@ public class JdbcPagingItemReaderClassicParameterTests extends AbstractJdbcPagin return reader; } - + @Test - public void testReadAfterJumpSecondPageWithJumpToItemQuery() throws Exception { + public void testReadAfterJumpSecondPageWithJumpToItemQuery() throws Exception { try { forceJumpToItemQuery = true; super.testReadAfterJumpSecondPage(); - } finally { - forceJumpToItemQuery = false; + } + finally { + forceJumpToItemQuery = false; } } - - @Override - protected String getName() { - return "JdbcPagingItemReader"; - } + + @Override + protected String getName() { + return "JdbcPagingItemReader"; + } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderCommonTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderCommonTests.java index 90d12caca..d863d05b0 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderCommonTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderCommonTests.java @@ -46,7 +46,7 @@ public class JdbcPagingItemReaderCommonTests extends AbstractItemStreamItemReade @Autowired private DataSource dataSource; - @Override + @Override protected ItemReader getItemReader() throws Exception { JdbcPagingItemReader reader = new JdbcPagingItemReader<>(); @@ -58,18 +58,16 @@ public class JdbcPagingItemReaderCommonTests extends AbstractItemStreamItemReade sortKeys.put("ID", Order.ASCENDING); queryProvider.setSortKeys(sortKeys); reader.setQueryProvider(queryProvider); - reader.setRowMapper( - new RowMapper() { - @Override - public Foo mapRow(ResultSet rs, int i) throws SQLException { - Foo foo = new Foo(); - foo.setId(rs.getInt(1)); - foo.setName(rs.getString(2)); - foo.setValue(rs.getInt(3)); - return foo; - } - } - ); + reader.setRowMapper(new RowMapper() { + @Override + public Foo mapRow(ResultSet rs, int i) throws SQLException { + Foo foo = new Foo(); + foo.setId(rs.getInt(1)); + foo.setName(rs.getString(2)); + foo.setValue(rs.getInt(3)); + return foo; + } + }); reader.setPageSize(3); reader.afterPropertiesSet(); reader.setSaveState(true); @@ -77,7 +75,7 @@ public class JdbcPagingItemReaderCommonTests extends AbstractItemStreamItemReade return reader; } - @Override + @Override protected void pointToEmptyInput(ItemReader tested) throws Exception { JdbcPagingItemReader reader = (JdbcPagingItemReader) tested; reader.close(); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderConfigTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderConfigTests.java index 2caf2b7c9..460cbb6f2 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderConfigTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderConfigTests.java @@ -38,9 +38,9 @@ public class JdbcPagingItemReaderConfigTests { @Test public void testConfig() { assertNotNull(jdbcPagingItemReader); - NamedParameterJdbcTemplate namedParameterJdbcTemplate = (NamedParameterJdbcTemplate) - ReflectionTestUtils.getField(jdbcPagingItemReader, "namedParameterJdbcTemplate"); - JdbcTemplate jdbcTemplate = (JdbcTemplate) namedParameterJdbcTemplate.getJdbcOperations(); + NamedParameterJdbcTemplate namedParameterJdbcTemplate = (NamedParameterJdbcTemplate) ReflectionTestUtils + .getField(jdbcPagingItemReader, "namedParameterJdbcTemplate"); + JdbcTemplate jdbcTemplate = (JdbcTemplate) namedParameterJdbcTemplate.getJdbcOperations(); assertEquals(1000, jdbcTemplate.getMaxRows()); assertEquals(100, jdbcTemplate.getFetchSize()); } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderEmptyResultSetTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderEmptyResultSetTests.java index ee821ad3f..7582730d3 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderEmptyResultSetTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderEmptyResultSetTests.java @@ -36,6 +36,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; public class JdbcPagingItemReaderEmptyResultSetTests { private static final int PAGE_SIZE = 2; + private static final int EMPTY_READS = PAGE_SIZE + 1; @Autowired @@ -65,4 +66,5 @@ public class JdbcPagingItemReaderEmptyResultSetTests { return reader; } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderIntegrationTests.java index 9d375a151..1e5c6ef5e 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderIntegrationTests.java @@ -33,7 +33,7 @@ import org.springframework.jdbc.core.RowMapper; */ public class JdbcPagingItemReaderIntegrationTests extends AbstractGenericDataSourceItemReaderIntegrationTests { - @Override + @Override protected ItemReader createItemReader() throws Exception { JdbcPagingItemReader inputSource = new JdbcPagingItemReader<>(); @@ -45,18 +45,16 @@ public class JdbcPagingItemReaderIntegrationTests extends AbstractGenericDataSou sortKeys.put("ID", Order.ASCENDING); queryProvider.setSortKeys(sortKeys); inputSource.setQueryProvider(queryProvider); - inputSource.setRowMapper( - new RowMapper() { - @Override - public Foo mapRow(ResultSet rs, int i) throws SQLException { - Foo foo = new Foo(); - foo.setId(rs.getInt(1)); - foo.setName(rs.getString(2)); - foo.setValue(rs.getInt(3)); - return foo; - } - } - ); + inputSource.setRowMapper(new RowMapper() { + @Override + public Foo mapRow(ResultSet rs, int i) throws SQLException { + Foo foo = new Foo(); + foo.setId(rs.getInt(1)); + foo.setName(rs.getString(2)); + foo.setValue(rs.getInt(3)); + return foo; + } + }); inputSource.setPageSize(3); inputSource.afterPropertiesSet(); inputSource.setSaveState(true); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderNamedParameterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderNamedParameterTests.java index a3b7e9c0a..f7ddbe706 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderNamedParameterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderNamedParameterTests.java @@ -38,14 +38,17 @@ import org.springframework.test.util.ReflectionTestUtils; * @author Michael Minella */ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = "/org/springframework/batch/item/database/JdbcPagingItemReaderParameterTests-context.xml") -@Ignore("This test fails when integration tests are skipped..") // FIXME make this test independent of other tests +@ContextConfiguration( + locations = "/org/springframework/batch/item/database/JdbcPagingItemReaderParameterTests-context.xml") +@Ignore("This test fails when integration tests are skipped..") // FIXME make this test + // independent of other + // tests public class JdbcPagingItemReaderNamedParameterTests extends AbstractJdbcPagingItemReaderParameterTests { // force jumpToItemQuery in JdbcPagingItemReader.doJumpToPage(int) private static boolean forceJumpToItemQuery = false; - @Override + @Override protected AbstractPagingItemReader getItemReader() throws Exception { JdbcPagingItemReader reader = new JdbcPagingItemReader() { @Override @@ -66,39 +69,38 @@ public class JdbcPagingItemReaderNamedParameterTests extends AbstractJdbcPagingI queryProvider.setSortKeys(sortKeys); reader.setParameterValues(Collections.singletonMap("limit", 2)); reader.setQueryProvider(queryProvider); - reader.setRowMapper( - new RowMapper() { - @Override - public Foo mapRow(ResultSet rs, int i) throws SQLException { - Foo foo = new Foo(); - foo.setId(rs.getInt(1)); - foo.setName(rs.getString(2)); - foo.setValue(rs.getInt(3)); - return foo; - } - } - ); + reader.setRowMapper(new RowMapper() { + @Override + public Foo mapRow(ResultSet rs, int i) throws SQLException { + Foo foo = new Foo(); + foo.setId(rs.getInt(1)); + foo.setName(rs.getString(2)); + foo.setValue(rs.getInt(3)); + return foo; + } + }); reader.setPageSize(3); reader.afterPropertiesSet(); reader.setSaveState(true); return reader; - + } - + @Test - public void testReadAfterJumpSecondPageWithJumpToItemQuery() throws Exception { + public void testReadAfterJumpSecondPageWithJumpToItemQuery() throws Exception { try { forceJumpToItemQuery = true; super.testReadAfterJumpSecondPage(); - } finally { - forceJumpToItemQuery = false; + } + finally { + forceJumpToItemQuery = false; } } - - @Override - protected String getName() { - return "JdbcPagingItemReader"; - } + + @Override + protected String getName() { + return "JdbcPagingItemReader"; + } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderOrderIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderOrderIntegrationTests.java index c770817c1..a27fc81b7 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderOrderIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingItemReaderOrderIntegrationTests.java @@ -33,7 +33,7 @@ import org.springframework.jdbc.core.RowMapper; */ public class JdbcPagingItemReaderOrderIntegrationTests extends AbstractGenericDataSourceItemReaderIntegrationTests { - @Override + @Override protected ItemReader createItemReader() throws Exception { JdbcPagingItemReader inputSource = new JdbcPagingItemReader<>(); @@ -46,18 +46,16 @@ public class JdbcPagingItemReaderOrderIntegrationTests extends AbstractGenericDa sortKeys.put("NAME", Order.DESCENDING); queryProvider.setSortKeys(sortKeys); inputSource.setQueryProvider(queryProvider); - inputSource.setRowMapper( - new RowMapper() { - @Override - public Foo mapRow(ResultSet rs, int i) throws SQLException { - Foo foo = new Foo(); - foo.setId(rs.getInt(1)); - foo.setName(rs.getString(2)); - foo.setValue(rs.getInt(3)); - return foo; - } - } - ); + inputSource.setRowMapper(new RowMapper() { + @Override + public Foo mapRow(ResultSet rs, int i) throws SQLException { + Foo foo = new Foo(); + foo.setId(rs.getInt(1)); + foo.setName(rs.getString(2)); + foo.setValue(rs.getInt(3)); + return foo; + } + }); inputSource.setPageSize(3); inputSource.afterPropertiesSet(); inputSource.setSaveState(true); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingQueryIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingQueryIntegrationTests.java index 8c6e92cf4..b24504b6a 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingQueryIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingQueryIntegrationTests.java @@ -67,15 +67,16 @@ public class JdbcPagingQueryIntegrationTests { private int itemCount = 9; private int pageSize = 2; - + @Before public void testInit() { jdbcTemplate = new JdbcTemplate(dataSource); - String[] names = {"Foo", "Bar", "Baz", "Foo", "Bar", "Baz", "Foo", "Bar", "Baz"}; - String[] codes = {"A", "B", "A", "B", "B", "B", "A", "B", "A"}; + String[] names = { "Foo", "Bar", "Baz", "Foo", "Bar", "Baz", "Foo", "Bar", "Baz" }; + String[] codes = { "A", "B", "A", "B", "B", "B", "A", "B", "A" }; JdbcTestUtils.deleteFromTables(jdbcTemplate, "T_FOOS"); - for(int i = 0; i < names.length; i++) { - jdbcTemplate.update("INSERT into T_FOOS (ID,NAME, CODE, VALUE) values (?, ?, ?, ?)", maxId, names[i], codes[i], i); + for (int i = 0; i < names.length; i++) { + jdbcTemplate.update("INSERT into T_FOOS (ID,NAME, CODE, VALUE) values (?, ?, ?, ?)", maxId, names[i], + codes[i], i); maxId++; } assertEquals(itemCount, JdbcTestUtils.countRowsInTable(jdbcTemplate, "T_FOOS")); @@ -104,26 +105,26 @@ public class JdbcPagingQueryIntegrationTests { Map oldValues = null; while (count < pages * pageSize) { - Map startAfterValues = getStartAfterValues( - queryProvider, list); + Map startAfterValues = getStartAfterValues(queryProvider, list); assertNotSame(oldValues, startAfterValues); - list = jdbcTemplate.queryForList(queryProvider.generateRemainingPagesQuery(pageSize), getParameterList(null, startAfterValues).toArray()); + list = jdbcTemplate.queryForList(queryProvider.generateRemainingPagesQuery(pageSize), + getParameterList(null, startAfterValues).toArray()); assertEquals(pageSize, list.size()); count += pageSize; oldValues = startAfterValues; } if (count < total) { - Map startAfterValues = getStartAfterValues( - queryProvider, list); - list = jdbcTemplate.queryForList(queryProvider.generateRemainingPagesQuery(pageSize), getParameterList(null, startAfterValues).toArray()); + Map startAfterValues = getStartAfterValues(queryProvider, list); + list = jdbcTemplate.queryForList(queryProvider.generateRemainingPagesQuery(pageSize), + getParameterList(null, startAfterValues).toArray()); assertEquals(total - pages * pageSize, list.size()); count += list.size(); } assertEquals(total, count); } - + @Test public void testQueryFromStartWithGroupBy() throws Exception { AbstractSqlPagingQueryProvider queryProvider = (AbstractSqlPagingQueryProvider) getPagingQueryProvider(); @@ -144,13 +145,13 @@ public class JdbcPagingQueryIntegrationTests { Map oldValues = null; while (count < total) { - Map startAfterValues = getStartAfterValues( - queryProvider, list); + Map startAfterValues = getStartAfterValues(queryProvider, list); assertNotSame(oldValues, startAfterValues); - list = jdbcTemplate.queryForList(queryProvider.generateRemainingPagesQuery(pageSize), getParameterList(null, startAfterValues).toArray()); + list = jdbcTemplate.queryForList(queryProvider.generateRemainingPagesQuery(pageSize), + getParameterList(null, startAfterValues).toArray()); count += list.size(); - - if(list.size() < pageSize) { + + if (list.size() < pageSize) { assertEquals(1, list.size()); } else { @@ -162,8 +163,7 @@ public class JdbcPagingQueryIntegrationTests { assertEquals(total, count); } - private Map getStartAfterValues( - PagingQueryProvider queryProvider, List> list) { + private Map getStartAfterValues(PagingQueryProvider queryProvider, List> list) { Map startAfterValues = new LinkedHashMap<>(); for (Map.Entry sortKey : queryProvider.getSortKeys().entrySet()) { startAfterValues.put(sortKey.getKey(), list.get(list.size() - 1).get(sortKey.getKey())); @@ -202,7 +202,7 @@ public class JdbcPagingQueryIntegrationTests { return factory.getObject(); } - + private List getParameterList(Map values, Map sortKeyValue) { SortedMap sm = new TreeMap<>(); if (values != null) { @@ -213,18 +213,19 @@ public class JdbcPagingQueryIntegrationTests { if (sortKeyValue != null && sortKeyValue.size() > 0) { List> keys = new ArrayList<>(sortKeyValue.entrySet()); - for(int i = 0; i < keys.size(); i++) { - for(int j = 0; j < i; j++) { + for (int i = 0; i < keys.size(); i++) { + for (int j = 0; j < i; j++) { parameterList.add(keys.get(j).getValue()); } parameterList.add(keys.get(i).getValue()); } } - + if (logger.isDebugEnabled()) { logger.debug("Using parameterList:" + parameterList); } return parameterList; } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingRestartIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingRestartIntegrationTests.java index 73902e324..7c931090b 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingRestartIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcPagingRestartIntegrationTests.java @@ -87,7 +87,7 @@ public class JdbcPagingRestartIntegrationTests { } @Test - @Ignore //FIXME + @Ignore // FIXME public void testReaderFromStart() throws Exception { ItemReader reader = getItemReader(); @@ -110,25 +110,24 @@ public class JdbcPagingRestartIntegrationTests { } @Test - @Ignore //FIXME + @Ignore // FIXME public void testReaderOnRestart() throws Exception { ItemReader reader = getItemReader(); int total = JdbcTestUtils.countRowsInTable(jdbcTemplate, "T_FOOS"); int count = (total / pageSize) * pageSize; - int pagesToRead = Math.min(3, total/pageSize); - if (count >= pagesToRead*pageSize) { - count -= pagesToRead*pageSize; + int pagesToRead = Math.min(3, total / pageSize); + if (count >= pagesToRead * pageSize) { + count -= pagesToRead * pageSize; } ExecutionContext executionContext = new ExecutionContext(); executionContext.putInt("JdbcPagingItemReader.read.count", count); // Assume the primary keys are in order - List> ids = jdbcTemplate - .queryForList("SELECT ID,NAME FROM T_FOOS ORDER BY ID ASC"); - logger.debug("Ids: "+ids); + List> ids = jdbcTemplate.queryForList("SELECT ID,NAME FROM T_FOOS ORDER BY ID ASC"); + logger.debug("Ids: " + ids); int startAfterValue = Integer.parseInt(ids.get(count - 1).get("ID").toString()); logger.debug("Start after: " + startAfterValue); Map startAfterValues = new LinkedHashMap<>(); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcParameterUtilsTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcParameterUtilsTests.java index 33a318380..d6cf6dc5f 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcParameterUtilsTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcParameterUtilsTests.java @@ -40,18 +40,26 @@ public class JdbcParameterUtilsTests { assertEquals(1, JdbcParameterUtils.countParameterPlaceholders(":parameter", null)); assertEquals(1, JdbcParameterUtils.countParameterPlaceholders("The \"big\" :parameter 'bad wolf'", null)); assertEquals(1, JdbcParameterUtils.countParameterPlaceholders("The big :parameter :parameter bad wolf", null)); - assertEquals(2, JdbcParameterUtils.countParameterPlaceholders("The big :parameter :newpar :parameter bad wolf", null)); - assertEquals(2, JdbcParameterUtils.countParameterPlaceholders("The big :parameter, :newpar, :parameter bad wolf", null)); + assertEquals(2, + JdbcParameterUtils.countParameterPlaceholders("The big :parameter :newpar :parameter bad wolf", null)); + assertEquals(2, JdbcParameterUtils + .countParameterPlaceholders("The big :parameter, :newpar, :parameter bad wolf", null)); assertEquals(1, JdbcParameterUtils.countParameterPlaceholders("The \"big:\" 'ba''ad:p' :parameter wolf", null)); assertEquals(1, JdbcParameterUtils.countParameterPlaceholders("¶meter", null)); assertEquals(1, JdbcParameterUtils.countParameterPlaceholders("The \"big\" ¶meter 'bad wolf'", null)); assertEquals(1, JdbcParameterUtils.countParameterPlaceholders("The big ¶meter ¶meter bad wolf", null)); - assertEquals(2, JdbcParameterUtils.countParameterPlaceholders("The big ¶meter &newparameter ¶meter bad wolf", null)); - assertEquals(2, JdbcParameterUtils.countParameterPlaceholders("The big ¶meter, &newparameter, ¶meter bad wolf", null)); - assertEquals(1, JdbcParameterUtils.countParameterPlaceholders("The \"big &x \" 'ba''ad&p' ¶meter wolf", null)); - assertEquals(2, JdbcParameterUtils.countParameterPlaceholders("The big :parameter, &newparameter, ¶meter bad wolf", null)); - assertEquals(2, JdbcParameterUtils.countParameterPlaceholders("The big :parameter, &sameparameter, &sameparameter bad wolf", null)); - assertEquals(2, JdbcParameterUtils.countParameterPlaceholders("The big :parameter, :sameparameter, :sameparameter bad wolf", null)); + assertEquals(2, JdbcParameterUtils + .countParameterPlaceholders("The big ¶meter &newparameter ¶meter bad wolf", null)); + assertEquals(2, JdbcParameterUtils + .countParameterPlaceholders("The big ¶meter, &newparameter, ¶meter bad wolf", null)); + assertEquals(1, + JdbcParameterUtils.countParameterPlaceholders("The \"big &x \" 'ba''ad&p' ¶meter wolf", null)); + assertEquals(2, JdbcParameterUtils + .countParameterPlaceholders("The big :parameter, &newparameter, ¶meter bad wolf", null)); + assertEquals(2, JdbcParameterUtils + .countParameterPlaceholders("The big :parameter, &sameparameter, &sameparameter bad wolf", null)); + assertEquals(2, JdbcParameterUtils + .countParameterPlaceholders("The big :parameter, :sameparameter, :sameparameter bad wolf", null)); assertEquals(0, JdbcParameterUtils.countParameterPlaceholders("xxx & yyy", null)); List l = new ArrayList<>(); assertEquals(3, JdbcParameterUtils.countParameterPlaceholders("select :par1, :par2 :par3", l)); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaCursorItemReaderCommonTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaCursorItemReaderCommonTests.java index 8eca55293..8fe20bfdc 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaCursorItemReaderCommonTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaCursorItemReaderCommonTests.java @@ -24,13 +24,11 @@ import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; /** * @author Mahmoud Ben Hassine */ -public class JpaCursorItemReaderCommonTests extends - AbstractDatabaseItemStreamItemReaderTests { +public class JpaCursorItemReaderCommonTests extends AbstractDatabaseItemStreamItemReaderTests { @Override protected ItemReader getItemReader() throws Exception { - LocalContainerEntityManagerFactoryBean factoryBean = - new LocalContainerEntityManagerFactoryBean(); + LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean(); factoryBean.setDataSource(getDataSource()); factoryBean.setPersistenceUnitName("bar"); factoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); @@ -53,4 +51,5 @@ public class JpaCursorItemReaderCommonTests extends reader.afterPropertiesSet(); reader.open(new ExecutionContext()); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaItemWriterIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaItemWriterIntegrationTests.java index 44f39f79a..ca38e7b0f 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaItemWriterIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaItemWriterIntegrationTests.java @@ -74,9 +74,7 @@ public class JpaItemWriterIntegrationTests { JpaItemWriter writer = new JpaItemWriter<>(); writer.setEntityManagerFactory(this.entityManagerFactory); writer.afterPropertiesSet(); - List items = Arrays.asList( - new Person(1, "foo"), - new Person(2, "bar")); + List items = Arrays.asList(new Person(1, "foo"), new Person(2, "bar")); // when writer.write(items); @@ -92,9 +90,7 @@ public class JpaItemWriterIntegrationTests { writer.setEntityManagerFactory(this.entityManagerFactory); writer.setUsePersist(true); writer.afterPropertiesSet(); - List items = Arrays.asList( - new Person(1, "foo"), - new Person(2, "bar")); + List items = Arrays.asList(new Person(1, "foo"), new Person(2, "bar")); // when writer.write(items); @@ -108,10 +104,7 @@ public class JpaItemWriterIntegrationTests { @Bean public DataSource dataSource() { - return new EmbeddedDatabaseBuilder() - .setType(EmbeddedDatabaseType.HSQL) - .generateUniqueName(true) - .build(); + return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL).generateUniqueName(true).build(); } @Bean @@ -142,6 +135,7 @@ public class JpaItemWriterIntegrationTests { public PlatformTransactionManager transactionManager() { return new JpaTransactionManager(entityManagerFactory()); } + } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaItemWriterTests.java index b0f5ce3a7..ed592d13b 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaItemWriterTests.java @@ -52,7 +52,7 @@ public class JpaItemWriterTests { TransactionSynchronizationManager.clearSynchronization(); } writer = new JpaItemWriter<>(); - emf = mock(EntityManagerFactory.class,"emf"); + emf = mock(EntityManagerFactory.class, "emf"); writer.setEntityManagerFactory(emf); } @@ -72,7 +72,7 @@ public class JpaItemWriterTests { @Test public void testWriteAndFlushSunnyDay() throws Exception { - EntityManager em = mock(EntityManager.class,"em"); + EntityManager em = mock(EntityManager.class, "em"); em.contains("foo"); em.contains("bar"); em.merge("bar"); @@ -101,7 +101,7 @@ public class JpaItemWriterTests { @Test public void testWriteAndFlushWithFailure() throws Exception { final RuntimeException ex = new RuntimeException("ERROR"); - EntityManager em = mock(EntityManager.class,"em"); + EntityManager em = mock(EntityManager.class, "em"); em.contains("foo"); em.contains("bar"); em.merge("bar"); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaNativeQueryProviderIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaNativeQueryProviderIntegrationTests.java index 74a482409..cc27124da 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaNativeQueryProviderIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaNativeQueryProviderIntegrationTests.java @@ -39,7 +39,7 @@ import org.springframework.transaction.annotation.Transactional; * @author Mahmoud Ben Hassine */ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations={"JpaPagingItemReaderCommonTests-context.xml"}) +@ContextConfiguration(locations = { "JpaPagingItemReaderCommonTests-context.xml" }) public class JpaNativeQueryProviderIntegrationTests { @Autowired @@ -101,4 +101,5 @@ public class JpaNativeQueryProviderIntegrationTests { assertEquals(actualFoos, expectedFoos); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaPagingItemReaderAsyncTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaPagingItemReaderAsyncTests.java index 601d4040d..53ceca576 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaPagingItemReaderAsyncTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaPagingItemReaderAsyncTests.java @@ -98,8 +98,8 @@ public class JpaPagingItemReaderAsyncTests { } } if (!throwables.isEmpty()) { - throw new IllegalStateException(String.format("Failed %d out of %d", throwables.size(), max), throwables - .get(0)); + throw new IllegalStateException(String.format("Failed %d out of %d", throwables.size(), max), + throwables.get(0)); } } @@ -110,11 +110,11 @@ public class JpaPagingItemReaderAsyncTests { */ private void doTest() throws Exception, InterruptedException, ExecutionException { final JpaPagingItemReader reader = getItemReader(); - CompletionService> completionService = new ExecutorCompletionService<>(Executors - .newFixedThreadPool(THREAD_COUNT)); + CompletionService> completionService = new ExecutorCompletionService<>( + Executors.newFixedThreadPool(THREAD_COUNT)); for (int i = 0; i < THREAD_COUNT; i++) { completionService.submit(new Callable>() { - @Override + @Override public List call() throws Exception { List list = new ArrayList<>(); Foo next = null; @@ -125,7 +125,8 @@ public class JpaPagingItemReaderAsyncTests { if (next != null) { list.add(next); } - } while (next != null); + } + while (next != null); return list; } }); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaPagingItemReaderCommonTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaPagingItemReaderCommonTests.java index adbd9f9c0..e8d262ca1 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaPagingItemReaderCommonTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaPagingItemReaderCommonTests.java @@ -33,7 +33,7 @@ public class JpaPagingItemReaderCommonTests extends AbstractItemStreamItemReader @Autowired private EntityManagerFactory entityManagerFactory; - @Override + @Override protected ItemReader getItemReader() throws Exception { String jpqlQuery = "select f from Foo f"; @@ -48,7 +48,7 @@ public class JpaPagingItemReaderCommonTests extends AbstractItemStreamItemReader return reader; } - @Override + @Override protected void pointToEmptyInput(ItemReader tested) throws Exception { JpaPagingItemReader reader = (JpaPagingItemReader) tested; reader.close(); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaPagingItemReaderIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaPagingItemReaderIntegrationTests.java index b2c64492f..d6e14ebad 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaPagingItemReaderIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaPagingItemReaderIntegrationTests.java @@ -32,7 +32,7 @@ import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; */ public class JpaPagingItemReaderIntegrationTests extends AbstractGenericDataSourceItemReaderIntegrationTests { - @Override + @Override protected ItemReader createItemReader() throws Exception { LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean(); factoryBean.setDataSource(dataSource); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaPagingItemReaderNamedQueryIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaPagingItemReaderNamedQueryIntegrationTests.java index 62b613860..58f5487e2 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaPagingItemReaderNamedQueryIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaPagingItemReaderNamedQueryIntegrationTests.java @@ -32,12 +32,12 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; * @author Mahmoud Ben Hassine */ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations={"JpaPagingItemReaderCommonTests-context.xml"}) +@ContextConfiguration(locations = { "JpaPagingItemReaderCommonTests-context.xml" }) public class JpaPagingItemReaderNamedQueryIntegrationTests extends AbstractPagingItemReaderParameterTests { @Autowired private EntityManagerFactory entityManagerFactory; - + @Override protected AbstractPagingItemReader getItemReader() throws Exception { @@ -45,7 +45,7 @@ public class JpaPagingItemReaderNamedQueryIntegrationTests extends AbstractPagin JpaPagingItemReader reader = new JpaPagingItemReader<>(); - //creating a named query provider as it would be created in configuration + // creating a named query provider as it would be created in configuration JpaNamedQueryProvider jpaNamedQueryProvider = new JpaNamedQueryProvider<>(); jpaNamedQueryProvider.setNamedQuery(namedQuery); jpaNamedQueryProvider.setEntityClass(Foo.class); @@ -58,4 +58,5 @@ public class JpaPagingItemReaderNamedQueryIntegrationTests extends AbstractPagin return reader; } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaPagingItemReaderNativeQueryIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaPagingItemReaderNativeQueryIntegrationTests.java index 997ae8daa..d6e6d1035 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaPagingItemReaderNativeQueryIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaPagingItemReaderNativeQueryIntegrationTests.java @@ -45,66 +45,66 @@ import org.springframework.transaction.PlatformTransactionManager; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = JpaPagingItemReaderNativeQueryIntegrationTests.JpaConfiguration.class) public class JpaPagingItemReaderNativeQueryIntegrationTests extends AbstractPagingItemReaderParameterTests { - - @Autowired - private EntityManagerFactory entityManagerFactory; - @Override - protected AbstractPagingItemReader getItemReader() throws Exception { + @Autowired + private EntityManagerFactory entityManagerFactory; - String sqlQuery = "select * from T_FOOS where value >= :limit"; + @Override + protected AbstractPagingItemReader getItemReader() throws Exception { - JpaPagingItemReader reader = new JpaPagingItemReader<>(); - - //creating a native query provider as it would be created in configuration - JpaNativeQueryProvider queryProvider= new JpaNativeQueryProvider<>(); - queryProvider.setSqlQuery(sqlQuery); - queryProvider.setEntityClass(Foo.class); - queryProvider.afterPropertiesSet(); - - reader.setParameterValues(Collections.singletonMap("limit", 2)); - reader.setEntityManagerFactory(entityManagerFactory); - reader.setPageSize(3); - reader.setQueryProvider(queryProvider); - reader.afterPropertiesSet(); - reader.setSaveState(true); + String sqlQuery = "select * from T_FOOS where value >= :limit"; - return reader; - } + JpaPagingItemReader reader = new JpaPagingItemReader<>(); - @Configuration - public static class JpaConfiguration { + // creating a native query provider as it would be created in configuration + JpaNativeQueryProvider queryProvider = new JpaNativeQueryProvider<>(); + queryProvider.setSqlQuery(sqlQuery); + queryProvider.setEntityClass(Foo.class); + queryProvider.afterPropertiesSet(); - @Bean - public DataSource dataSource() { - return new EmbeddedDatabaseBuilder() - .setType(EmbeddedDatabaseType.HSQL) - .addScript("org/springframework/batch/item/database/init-foo-schema-hsqldb.sql") - .generateUniqueName(true) - .build(); - } + reader.setParameterValues(Collections.singletonMap("limit", 2)); + reader.setEntityManagerFactory(entityManagerFactory); + reader.setPageSize(3); + reader.setQueryProvider(queryProvider); + reader.afterPropertiesSet(); + reader.setSaveState(true); - @Bean - public PersistenceUnitManager persistenceUnitManager() { - DefaultPersistenceUnitManager persistenceUnitManager = new DefaultPersistenceUnitManager(); - persistenceUnitManager.setDefaultDataSource(dataSource()); - persistenceUnitManager.afterPropertiesSet(); - return persistenceUnitManager; - } + return reader; + } - @Bean - public EntityManagerFactory entityManagerFactory() { - LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean(); - factoryBean.setDataSource(dataSource()); - factoryBean.setPersistenceUnitManager(persistenceUnitManager()); - factoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); - factoryBean.afterPropertiesSet(); - return factoryBean.getObject(); - } + @Configuration + public static class JpaConfiguration { + + @Bean + public DataSource dataSource() { + return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL) + .addScript("org/springframework/batch/item/database/init-foo-schema-hsqldb.sql") + .generateUniqueName(true).build(); + } + + @Bean + public PersistenceUnitManager persistenceUnitManager() { + DefaultPersistenceUnitManager persistenceUnitManager = new DefaultPersistenceUnitManager(); + persistenceUnitManager.setDefaultDataSource(dataSource()); + persistenceUnitManager.afterPropertiesSet(); + return persistenceUnitManager; + } + + @Bean + public EntityManagerFactory entityManagerFactory() { + LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean(); + factoryBean.setDataSource(dataSource()); + factoryBean.setPersistenceUnitManager(persistenceUnitManager()); + factoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); + factoryBean.afterPropertiesSet(); + return factoryBean.getObject(); + } + + @Bean + public PlatformTransactionManager transactionManager() { + return new JpaTransactionManager(entityManagerFactory()); + } + + } - @Bean - public PlatformTransactionManager transactionManager() { - return new JpaTransactionManager(entityManagerFactory()); - } - } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaPagingItemReaderParameterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaPagingItemReaderParameterTests.java index d0b7532ed..b98b96671 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaPagingItemReaderParameterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaPagingItemReaderParameterTests.java @@ -32,7 +32,7 @@ public class JpaPagingItemReaderParameterTests extends AbstractPagingItemReaderP @Autowired private EntityManagerFactory entityManagerFactory; - @Override + @Override protected AbstractPagingItemReader getItemReader() throws Exception { String jpqlQuery = "select f from Foo f where f.value >= :limit"; diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/RepositoryItemReaderIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/RepositoryItemReaderIntegrationTests.java index e1dcfe12b..f7c397b57 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/RepositoryItemReaderIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/RepositoryItemReaderIntegrationTests.java @@ -33,93 +33,92 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.transaction.annotation.Transactional; - @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "RepositoryItemReaderCommonTests-context.xml") @Transactional public class RepositoryItemReaderIntegrationTests { - private static final String CONTEXT_KEY = "RepositoryItemReader.read.count"; + private static final String CONTEXT_KEY = "RepositoryItemReader.read.count"; - @Autowired - private RepositoryItemReader reader; + @Autowired + private RepositoryItemReader reader; - @After - public void reinitializeReader() { - reader.close(); - } + @After + public void reinitializeReader() { + reader.close(); + } - @Test - public void testReadFromFirstPos() throws Exception { - reader.open(new ExecutionContext()); + @Test + public void testReadFromFirstPos() throws Exception { + reader.open(new ExecutionContext()); - Author author = reader.read(); + Author author = reader.read(); - assertNotNull(author); - final List books = author.getBooks(); - assertEquals("Books list size must be = 2", 2, books.size()); - assertEquals("First book must be author 1 - book 1", "author 1 - book 1", books.get(0).getName()); - assertEquals("Second book must be author 1 - book 2", "author 1 - book 2", books.get(1).getName()); - } + assertNotNull(author); + final List books = author.getBooks(); + assertEquals("Books list size must be = 2", 2, books.size()); + assertEquals("First book must be author 1 - book 1", "author 1 - book 1", books.get(0).getName()); + assertEquals("Second book must be author 1 - book 2", "author 1 - book 2", books.get(1).getName()); + } - @Test - public void testReadFromWithinPage() throws Exception { - reader.setCurrentItemCount(1); - reader.open(new ExecutionContext()); + @Test + public void testReadFromWithinPage() throws Exception { + reader.setCurrentItemCount(1); + reader.open(new ExecutionContext()); - Author author = reader.read(); + Author author = reader.read(); - assertNotNull(author); - final List books = author.getBooks(); - assertEquals("Books list size must be = 2", 2, books.size()); - assertEquals("First book must be author 2 - book 1", "author 2 - book 1", books.get(0).getName()); - assertEquals("Second book must be author 2 - book 2", "author 2 - book 2", books.get(1).getName()); - } + assertNotNull(author); + final List books = author.getBooks(); + assertEquals("Books list size must be = 2", 2, books.size()); + assertEquals("First book must be author 2 - book 1", "author 2 - book 1", books.get(0).getName()); + assertEquals("Second book must be author 2 - book 2", "author 2 - book 2", books.get(1).getName()); + } - @Test - public void testReadFromNewPage() throws Exception { - reader.setPageSize(2); - reader.setCurrentItemCount(2); // 3rd item = 1rst of page 2 - reader.open(new ExecutionContext()); + @Test + public void testReadFromNewPage() throws Exception { + reader.setPageSize(2); + reader.setCurrentItemCount(2); // 3rd item = 1rst of page 2 + reader.open(new ExecutionContext()); - Author author = reader.read(); + Author author = reader.read(); - assertNotNull(author); - final List books = author.getBooks(); - assertEquals("Books list size must be = 2", 2, books.size()); - assertEquals("First book must be author 3 - book 1", "author 3 - book 1", books.get(0).getName()); - assertEquals("Second book must be author 3 - book 2", "author 3 - book 2", books.get(1).getName()); - } + assertNotNull(author); + final List books = author.getBooks(); + assertEquals("Books list size must be = 2", 2, books.size()); + assertEquals("First book must be author 3 - book 1", "author 3 - book 1", books.get(0).getName()); + assertEquals("Second book must be author 3 - book 2", "author 3 - book 2", books.get(1).getName()); + } - @Test - public void testReadFromWithinPage_Restart() throws Exception { - final ExecutionContext executionContext = new ExecutionContext(); - executionContext.putInt(CONTEXT_KEY, 1); - reader.open(executionContext); + @Test + public void testReadFromWithinPage_Restart() throws Exception { + final ExecutionContext executionContext = new ExecutionContext(); + executionContext.putInt(CONTEXT_KEY, 1); + reader.open(executionContext); - Author author = reader.read(); + Author author = reader.read(); - assertNotNull(author); - final List books = author.getBooks(); - assertEquals("Books list size must be = 2", 2, books.size()); - assertEquals("First book must be author 2 - book 1", "author 2 - book 1", books.get(0).getName()); - assertEquals("Second book must be author 2 - book 2", "author 2 - book 2", books.get(1).getName()); - } + assertNotNull(author); + final List books = author.getBooks(); + assertEquals("Books list size must be = 2", 2, books.size()); + assertEquals("First book must be author 2 - book 1", "author 2 - book 1", books.get(0).getName()); + assertEquals("Second book must be author 2 - book 2", "author 2 - book 2", books.get(1).getName()); + } - @Test - public void testReadFromNewPage_Restart() throws Exception { - reader.setPageSize(2); - final ExecutionContext executionContext = new ExecutionContext(); - executionContext.putInt(CONTEXT_KEY, 2); - reader.open(executionContext); + @Test + public void testReadFromNewPage_Restart() throws Exception { + reader.setPageSize(2); + final ExecutionContext executionContext = new ExecutionContext(); + executionContext.putInt(CONTEXT_KEY, 2); + reader.open(executionContext); - Author author = reader.read(); + Author author = reader.read(); + + assertNotNull(author); + final List books = author.getBooks(); + assertEquals("Books list size must be = 2", 2, books.size()); + assertEquals("First book must be author 3 - book 1", "author 3 - book 1", books.get(0).getName()); + assertEquals("Second book must be author 3 - book 2", "author 3 - book 2", books.get(1).getName()); + } - assertNotNull(author); - final List books = author.getBooks(); - assertEquals("Books list size must be = 2", 2, books.size()); - assertEquals("First book must be author 3 - book 1", "author 3 - book 1", books.get(0).getName()); - assertEquals("Second book must be author 3 - book 2", "author 3 - book 2", books.get(1).getName()); - } - } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/SingleKeyFooDao.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/SingleKeyFooDao.java index 62f2e0864..b31603bf4 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/SingleKeyFooDao.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/SingleKeyFooDao.java @@ -24,11 +24,11 @@ import org.springframework.jdbc.core.support.JdbcDaoSupport; public class SingleKeyFooDao extends JdbcDaoSupport implements FooDao { - @Override - public Foo getFoo(Object key){ + @Override + public Foo getFoo(Object key) { - RowMapper fooMapper = new RowMapper(){ - @Override + RowMapper fooMapper = new RowMapper() { + @Override public Foo mapRow(ResultSet rs, int rowNum) throws SQLException { Foo foo = new Foo(); foo.setId(rs.getInt(1)); @@ -38,8 +38,8 @@ public class SingleKeyFooDao extends JdbcDaoSupport implements FooDao { } }; - return getJdbcTemplate().query("SELECT ID, NAME, VALUE from T_FOOS where ID = ?", - fooMapper, key).get(0); + return getJdbcTemplate().query("SELECT ID, NAME, VALUE from T_FOOS where ID = ?", fooMapper, key).get(0); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/StoredProcedureItemReaderCommonTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/StoredProcedureItemReaderCommonTests.java index fe1fa7ba4..06b463770 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/StoredProcedureItemReaderCommonTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/StoredProcedureItemReaderCommonTests.java @@ -33,7 +33,7 @@ import org.springframework.jdbc.core.SqlParameter; @RunWith(JUnit4.class) public class StoredProcedureItemReaderCommonTests extends AbstractDatabaseItemStreamItemReaderTests { - @Override + @Override protected ItemReader getItemReader() throws Exception { StoredProcedureItemReader result = new StoredProcedureItemReader<>(); result.setDataSource(getDataSource()); @@ -44,9 +44,10 @@ public class StoredProcedureItemReaderCommonTests extends AbstractDatabaseItemSt return result; } - @Override + @Override protected void initializeContext() throws Exception { - ctx = new ClassPathXmlApplicationContext("org/springframework/batch/item/database/stored-procedure-context.xml"); + ctx = new ClassPathXmlApplicationContext( + "org/springframework/batch/item/database/stored-procedure-context.xml"); } @Test @@ -60,37 +61,32 @@ public class StoredProcedureItemReaderCommonTests extends AbstractDatabaseItemSt testRestart(); } - @Override + @Override protected void pointToEmptyInput(ItemReader tested) throws Exception { StoredProcedureItemReader reader = (StoredProcedureItemReader) tested; reader.close(); reader.setDataSource(getDataSource()); reader.setProcedureName("read_some_foos"); - reader.setParameters( - new SqlParameter[] { - new SqlParameter("from_id", Types.NUMERIC), - new SqlParameter("to_id", Types.NUMERIC) - }); - reader.setPreparedStatementSetter( - new PreparedStatementSetter() { - @Override - public void setValues(PreparedStatement ps) - throws SQLException { - ps.setInt(1, 1000); - ps.setInt(2, 1001); - } - }); + reader.setParameters(new SqlParameter[] { new SqlParameter("from_id", Types.NUMERIC), + new SqlParameter("to_id", Types.NUMERIC) }); + reader.setPreparedStatementSetter(new PreparedStatementSetter() { + @Override + public void setValues(PreparedStatement ps) throws SQLException { + ps.setInt(1, 1000); + ps.setInt(2, 1001); + } + }); reader.setRowMapper(new FooRowMapper()); reader.setVerifyCursorPosition(false); reader.afterPropertiesSet(); - reader.open(new ExecutionContext()); + reader.open(new ExecutionContext()); } - @Test(expected=ReaderNotOpenException.class) + @Test(expected = ReaderNotOpenException.class) public void testReadBeforeOpen() throws Exception { testedAsStream().close(); tested = getItemReader(); tested.read(); } - + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/StoredProcedureItemReaderIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/StoredProcedureItemReaderIntegrationTests.java index 939740c80..f8ef4478f 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/StoredProcedureItemReaderIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/StoredProcedureItemReaderIntegrationTests.java @@ -23,8 +23,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "stored-procedure-context.xml") -public class StoredProcedureItemReaderIntegrationTests - extends AbstractDataSourceItemReaderIntegrationTests { +public class StoredProcedureItemReaderIntegrationTests extends AbstractDataSourceItemReaderIntegrationTests { @Override protected ItemReader createItemReader() throws Exception { diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/StoredprocedureItemReaderConfigTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/StoredprocedureItemReaderConfigTests.java index 69af1ceb3..7228d11bb 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/StoredprocedureItemReaderConfigTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/StoredprocedureItemReaderConfigTests.java @@ -68,23 +68,22 @@ public class StoredprocedureItemReaderConfigTests { reader.setUseSharedExtendedConnection(true); reader.setProcedureName("foo_bar"); final ExecutionContext ec = new ExecutionContext(); - tt.execute( - new TransactionCallback() { - @Override - public Void doInTransaction(TransactionStatus status) { - reader.open(ec); - reader.close(); - return null; - } - }); + tt.execute(new TransactionCallback() { + @Override + public Void doInTransaction(TransactionStatus status) { + reader.open(ec); + reader.close(); + return null; + } + }); } - + /* * Should fail if trying to call getConnection() twice */ @Test public void testUsesItsOwnTransaction() throws Exception { - + DataSource ds = mock(DataSource.class); DatabaseMetaData dmd = mock(DatabaseMetaData.class); when(dmd.getDatabaseProductName()).thenReturn("Oracle"); @@ -93,7 +92,8 @@ public class StoredprocedureItemReaderConfigTests { when(con.getMetaData()).thenReturn(dmd); when(con.getAutoCommit()).thenReturn(false); CallableStatement cs = mock(CallableStatement.class); - when(con.prepareCall("{call foo_bar()}", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)).thenReturn(cs); + when(con.prepareCall("{call foo_bar()}", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)) + .thenReturn(cs); when(ds.getConnection()).thenReturn(con); when(ds.getConnection()).thenReturn(con); con.commit(); @@ -103,15 +103,14 @@ public class StoredprocedureItemReaderConfigTests { reader.setDataSource(ds); reader.setProcedureName("foo_bar"); final ExecutionContext ec = new ExecutionContext(); - tt.execute( - new TransactionCallback() { - @Override - public Void doInTransaction(TransactionStatus status) { - reader.open(ec); - reader.close(); - return null; - } - }); + tt.execute(new TransactionCallback() { + @Override + public Void doInTransaction(TransactionStatus status) { + reader.open(ec); + reader.close(); + return null; + } + }); } /* @@ -119,7 +118,7 @@ public class StoredprocedureItemReaderConfigTests { */ @Test public void testHandlesRefCursorPosition() throws Exception { - + DataSource ds = mock(DataSource.class); DatabaseMetaData dmd = mock(DatabaseMetaData.class); when(dmd.getDatabaseProductName()).thenReturn("Oracle"); @@ -128,7 +127,8 @@ public class StoredprocedureItemReaderConfigTests { when(con.getMetaData()).thenReturn(dmd); when(con.getAutoCommit()).thenReturn(false); CallableStatement cs = mock(CallableStatement.class); - when(con.prepareCall("{call foo_bar(?, ?)}", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)).thenReturn(cs); + when(con.prepareCall("{call foo_bar(?, ?)}", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)) + .thenReturn(cs); when(ds.getConnection()).thenReturn(con); when(ds.getConnection()).thenReturn(con); con.commit(); @@ -137,26 +137,23 @@ public class StoredprocedureItemReaderConfigTests { final StoredProcedureItemReader reader = new StoredProcedureItemReader<>(); reader.setDataSource(ds); reader.setProcedureName("foo_bar"); - reader.setParameters(new SqlParameter[] { - new SqlParameter("foo", Types.VARCHAR), - new SqlParameter("bar", Types.OTHER)}); - reader.setPreparedStatementSetter( - new PreparedStatementSetter() { - @Override - public void setValues(PreparedStatement ps) - throws SQLException { - } - }); + reader.setParameters( + new SqlParameter[] { new SqlParameter("foo", Types.VARCHAR), new SqlParameter("bar", Types.OTHER) }); + reader.setPreparedStatementSetter(new PreparedStatementSetter() { + @Override + public void setValues(PreparedStatement ps) throws SQLException { + } + }); reader.setRefCursorPosition(3); final ExecutionContext ec = new ExecutionContext(); - tt.execute( - new TransactionCallback() { - @Override - public Void doInTransaction(TransactionStatus status) { - reader.open(ec); - reader.close(); - return null; - } - }); + tt.execute(new TransactionCallback() { + @Override + public Void doInTransaction(TransactionStatus status) { + reader.open(ec); + reader.close(); + return null; + } + }); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/HibernateCursorItemReaderBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/HibernateCursorItemReaderBuilderTests.java index f916ae5bf..0e7a43d1d 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/HibernateCursorItemReaderBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/HibernateCursorItemReaderBuilderTests.java @@ -60,27 +60,21 @@ public class HibernateCursorItemReaderBuilderTests { @After public void tearDown() { - if(this.context != null) { + if (this.context != null) { this.context.close(); } } @Test public void testConfiguration() throws Exception { - HibernateCursorItemReader reader = new HibernateCursorItemReaderBuilder() - .name("fooReader") - .sessionFactory(this.sessionFactory) - .fetchSize(2) - .currentItemCount(2) - .maxItemCount(4) - .queryName("allFoos") - .useStatelessSession(true) - .build(); + HibernateCursorItemReader reader = new HibernateCursorItemReaderBuilder().name("fooReader") + .sessionFactory(this.sessionFactory).fetchSize(2).currentItemCount(2).maxItemCount(4) + .queryName("allFoos").useStatelessSession(true).build(); reader.afterPropertiesSet(); ExecutionContext executionContext = new ExecutionContext(); - + reader.open(executionContext); Foo item1 = reader.read(); Foo item2 = reader.read(); @@ -103,13 +97,9 @@ public class HibernateCursorItemReaderBuilderTests { Map parameters = new HashMap<>(); parameters.put("value", 2); - HibernateCursorItemReader reader = new HibernateCursorItemReaderBuilder() - .name("fooReader") - .sessionFactory(this.sessionFactory) - .queryString("from Foo foo where foo.id > :value") - .parameterValues(parameters) - .saveState(false) - .build(); + HibernateCursorItemReader reader = new HibernateCursorItemReaderBuilder().name("fooReader") + .sessionFactory(this.sessionFactory).queryString("from Foo foo where foo.id > :value") + .parameterValues(parameters).saveState(false).build(); reader.afterPropertiesSet(); @@ -118,7 +108,7 @@ public class HibernateCursorItemReaderBuilderTests { reader.open(executionContext); int i = 0; - while(reader.read() != null) { + while (reader.read() != null) { i++; } @@ -137,11 +127,8 @@ public class HibernateCursorItemReaderBuilderTests { provider.setSqlQuery("select * from T_FOOS"); provider.afterPropertiesSet(); - HibernateCursorItemReader reader = new HibernateCursorItemReaderBuilder() - .name("fooReader") - .sessionFactory(this.sessionFactory) - .queryProvider(provider) - .build(); + HibernateCursorItemReader reader = new HibernateCursorItemReaderBuilder().name("fooReader") + .sessionFactory(this.sessionFactory).queryProvider(provider).build(); reader.afterPropertiesSet(); @@ -150,7 +137,7 @@ public class HibernateCursorItemReaderBuilderTests { reader.open(executionContext); int i = 0; - while(reader.read() != null) { + while (reader.read() != null) { i++; } @@ -162,12 +149,8 @@ public class HibernateCursorItemReaderBuilderTests { @Test public void testConfigurationNativeQuery() throws Exception { - HibernateCursorItemReader reader = new HibernateCursorItemReaderBuilder() - .name("fooReader") - .sessionFactory(this.sessionFactory) - .nativeQuery("select * from T_FOOS") - .entityClass(Foo.class) - .build(); + HibernateCursorItemReader reader = new HibernateCursorItemReaderBuilder().name("fooReader") + .sessionFactory(this.sessionFactory).nativeQuery("select * from T_FOOS").entityClass(Foo.class).build(); reader.afterPropertiesSet(); @@ -176,7 +159,7 @@ public class HibernateCursorItemReaderBuilderTests { reader.open(executionContext); int i = 0; - while(reader.read() != null) { + while (reader.read() != null) { i++; } @@ -205,10 +188,7 @@ public class HibernateCursorItemReaderBuilderTests { } try { - new HibernateCursorItemReaderBuilder() - .sessionFactory(this.sessionFactory) - .saveState(true) - .build(); + new HibernateCursorItemReaderBuilder().sessionFactory(this.sessionFactory).saveState(true).build(); fail("name is required when saveState is true"); } catch (IllegalStateException ise) { @@ -216,16 +196,13 @@ public class HibernateCursorItemReaderBuilderTests { } try { - new HibernateCursorItemReaderBuilder() - .sessionFactory(this.sessionFactory) - .saveState(false) - .build(); - fail("A HibernateQueryProvider, queryName, queryString, " + - "or both the nativeQuery and entityClass must be configured"); + new HibernateCursorItemReaderBuilder().sessionFactory(this.sessionFactory).saveState(false).build(); + fail("A HibernateQueryProvider, queryName, queryString, " + + "or both the nativeQuery and entityClass must be configured"); } catch (IllegalStateException ise) { - assertEquals("A HibernateQueryProvider, queryName, queryString, " + - "or both the nativeQuery and entityClass must be configured", ise.getMessage()); + assertEquals("A HibernateQueryProvider, queryName, queryString, " + + "or both the nativeQuery and entityClass must be configured", ise.getMessage()); } } @@ -235,9 +212,7 @@ public class HibernateCursorItemReaderBuilderTests { @Bean public DataSource dataSource() { - return new EmbeddedDatabaseBuilder() - .generateUniqueName(true) - .build(); + return new EmbeddedDatabaseBuilder().generateUniqueName(true).build(); } @Bean @@ -245,7 +220,8 @@ public class HibernateCursorItemReaderBuilderTests { DataSourceInitializer dataSourceInitializer = new DataSourceInitializer(); dataSourceInitializer.setDataSource(dataSource); - Resource create = new ClassPathResource("org/springframework/batch/item/database/init-foo-schema-hsqldb.sql"); + Resource create = new ClassPathResource( + "org/springframework/batch/item/database/init-foo-schema-hsqldb.sql"); dataSourceInitializer.setDatabasePopulator(new ResourceDatabasePopulator(create)); return dataSourceInitializer; @@ -255,11 +231,14 @@ public class HibernateCursorItemReaderBuilderTests { public SessionFactory sessionFactory() throws Exception { LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean(); factoryBean.setDataSource(dataSource()); - factoryBean.setMappingLocations(new ClassPathResource("/org/springframework/batch/item/database/Foo.hbm.xml", getClass())); + factoryBean.setMappingLocations( + new ClassPathResource("/org/springframework/batch/item/database/Foo.hbm.xml", getClass())); factoryBean.afterPropertiesSet(); return factoryBean.getObject(); } + } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/HibernateItemWriterBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/HibernateItemWriterBuilderTests.java index b0999aa54..b3d7770ca 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/HibernateItemWriterBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/HibernateItemWriterBuilderTests.java @@ -56,8 +56,7 @@ public class HibernateItemWriterBuilderTests { @Test public void testConfiguration() { - HibernateItemWriter itemWriter = new HibernateItemWriterBuilder() - .sessionFactory(this.sessionFactory) + HibernateItemWriter itemWriter = new HibernateItemWriterBuilder().sessionFactory(this.sessionFactory) .build(); itemWriter.afterPropertiesSet(); @@ -73,10 +72,8 @@ public class HibernateItemWriterBuilderTests { @Test public void testConfigurationClearSession() { - HibernateItemWriter itemWriter = new HibernateItemWriterBuilder() - .sessionFactory(this.sessionFactory) - .clearSession(false) - .build(); + HibernateItemWriter itemWriter = new HibernateItemWriterBuilder().sessionFactory(this.sessionFactory) + .clearSession(false).build(); itemWriter.afterPropertiesSet(); @@ -93,8 +90,7 @@ public class HibernateItemWriterBuilderTests { @Test public void testValidation() { try { - new HibernateItemWriterBuilder() - .build(); + new HibernateItemWriterBuilder().build(); fail("sessionFactory is required"); } catch (IllegalStateException ise) { @@ -105,7 +101,7 @@ public class HibernateItemWriterBuilderTests { private List getFoos() { List foos = new ArrayList<>(3); - for(int i = 1; i < 4; i++) { + for (int i = 1; i < 4; i++) { Foo foo = new Foo(); foo.setName("foo" + i); foo.setValue(i); @@ -114,4 +110,5 @@ public class HibernateItemWriterBuilderTests { return foos; } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/HibernatePagingItemReaderBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/HibernatePagingItemReaderBuilderTests.java index 98dd872dc..f4b3b1266 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/HibernatePagingItemReaderBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/HibernatePagingItemReaderBuilderTests.java @@ -57,13 +57,14 @@ public class HibernatePagingItemReaderBuilderTests { @Before public void setUp() { - this.context = new AnnotationConfigApplicationContext(HibernatePagingItemReaderBuilderTests.TestDataSourceConfiguration.class); + this.context = new AnnotationConfigApplicationContext( + HibernatePagingItemReaderBuilderTests.TestDataSourceConfiguration.class); this.sessionFactory = (SessionFactory) context.getBean("sessionFactory"); } @After public void tearDown() { - if(this.context != null) { + if (this.context != null) { this.context.close(); } } @@ -71,16 +72,9 @@ public class HibernatePagingItemReaderBuilderTests { @Test @SuppressWarnings("unchecked") public void testConfiguration() throws Exception { - HibernatePagingItemReader reader = new HibernatePagingItemReaderBuilder() - .name("fooReader") - .sessionFactory(this.sessionFactory) - .fetchSize(2) - .currentItemCount(2) - .maxItemCount(4) - .pageSize(5) - .queryName("allFoos") - .useStatelessSession(false) - .build(); + HibernatePagingItemReader reader = new HibernatePagingItemReaderBuilder().name("fooReader") + .sessionFactory(this.sessionFactory).fetchSize(2).currentItemCount(2).maxItemCount(4).pageSize(5) + .queryName("allFoos").useStatelessSession(false).build(); reader.afterPropertiesSet(); @@ -103,7 +97,8 @@ public class HibernatePagingItemReaderBuilderTests { assertEquals(2, executionContext.size()); assertEquals(5, ReflectionTestUtils.getField(reader, "pageSize")); - HibernateItemReaderHelper helper = (HibernateItemReaderHelper) ReflectionTestUtils.getField(reader, "helper"); + HibernateItemReaderHelper helper = (HibernateItemReaderHelper) ReflectionTestUtils.getField(reader, + "helper"); assertEquals(false, ReflectionTestUtils.getField(helper, "useStatelessSession")); } @@ -112,13 +107,9 @@ public class HibernatePagingItemReaderBuilderTests { Map parameters = new HashMap<>(); parameters.put("value", 2); - HibernatePagingItemReader reader = new HibernatePagingItemReaderBuilder() - .name("fooReader") - .sessionFactory(this.sessionFactory) - .queryString("from Foo foo where foo.id > :value") - .parameterValues(parameters) - .saveState(false) - .build(); + HibernatePagingItemReader reader = new HibernatePagingItemReaderBuilder().name("fooReader") + .sessionFactory(this.sessionFactory).queryString("from Foo foo where foo.id > :value") + .parameterValues(parameters).saveState(false).build(); reader.afterPropertiesSet(); @@ -127,7 +118,7 @@ public class HibernatePagingItemReaderBuilderTests { reader.open(executionContext); int i = 0; - while(reader.read() != null) { + while (reader.read() != null) { i++; } @@ -146,11 +137,8 @@ public class HibernatePagingItemReaderBuilderTests { provider.setSqlQuery("select * from T_FOOS"); provider.afterPropertiesSet(); - HibernatePagingItemReader reader = new HibernatePagingItemReaderBuilder() - .name("fooReader") - .sessionFactory(this.sessionFactory) - .queryProvider(provider) - .build(); + HibernatePagingItemReader reader = new HibernatePagingItemReaderBuilder().name("fooReader") + .sessionFactory(this.sessionFactory).queryProvider(provider).build(); reader.afterPropertiesSet(); @@ -159,7 +147,7 @@ public class HibernatePagingItemReaderBuilderTests { reader.open(executionContext); int i = 0; - while(reader.read() != null) { + while (reader.read() != null) { i++; } @@ -172,10 +160,7 @@ public class HibernatePagingItemReaderBuilderTests { @Test public void testValidation() { try { - new HibernatePagingItemReaderBuilder() - .sessionFactory(this.sessionFactory) - .fetchSize(-2) - .build(); + new HibernatePagingItemReaderBuilder().sessionFactory(this.sessionFactory).fetchSize(-2).build(); fail("fetch size must be >= 0"); } catch (IllegalStateException ise) { @@ -191,10 +176,7 @@ public class HibernatePagingItemReaderBuilderTests { } try { - new HibernatePagingItemReaderBuilder() - .sessionFactory(this.sessionFactory) - .saveState(true) - .build(); + new HibernatePagingItemReaderBuilder().sessionFactory(this.sessionFactory).saveState(true).build(); fail("name is required when saveState is set to true"); } catch (IllegalArgumentException ise) { @@ -202,10 +184,7 @@ public class HibernatePagingItemReaderBuilderTests { } try { - new HibernatePagingItemReaderBuilder() - .sessionFactory(this.sessionFactory) - .saveState(false) - .build(); + new HibernatePagingItemReaderBuilder().sessionFactory(this.sessionFactory).saveState(false).build(); fail("queryString or queryName must be set"); } catch (IllegalStateException ise) { @@ -219,9 +198,7 @@ public class HibernatePagingItemReaderBuilderTests { @Bean public DataSource dataSource() { - return new EmbeddedDatabaseBuilder() - .generateUniqueName(true) - .build(); + return new EmbeddedDatabaseBuilder().generateUniqueName(true).build(); } @Bean @@ -229,7 +206,8 @@ public class HibernatePagingItemReaderBuilderTests { DataSourceInitializer dataSourceInitializer = new DataSourceInitializer(); dataSourceInitializer.setDataSource(dataSource); - Resource create = new ClassPathResource("org/springframework/batch/item/database/init-foo-schema-hsqldb.sql"); + Resource create = new ClassPathResource( + "org/springframework/batch/item/database/init-foo-schema-hsqldb.sql"); dataSourceInitializer.setDatabasePopulator(new ResourceDatabasePopulator(create)); return dataSourceInitializer; @@ -239,11 +217,14 @@ public class HibernatePagingItemReaderBuilderTests { public SessionFactory sessionFactory() throws Exception { LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean(); factoryBean.setDataSource(dataSource()); - factoryBean.setMappingLocations(new ClassPathResource("/org/springframework/batch/item/database/Foo.hbm.xml", getClass())); + factoryBean.setMappingLocations( + new ClassPathResource("/org/springframework/batch/item/database/Foo.hbm.xml", getClass())); factoryBean.afterPropertiesSet(); return factoryBean.getObject(); } + } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/JdbcBatchItemWriterBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/JdbcBatchItemWriterBuilderTests.java index 111d9f7ca..69fe072d1 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/JdbcBatchItemWriterBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/JdbcBatchItemWriterBuilderTests.java @@ -64,7 +64,7 @@ public class JdbcBatchItemWriterBuilderTests { @After public void tearDown() { - if(this.context != null) { + if (this.context != null) { this.context.close(); } } @@ -72,10 +72,8 @@ public class JdbcBatchItemWriterBuilderTests { @Test public void testBasicMap() throws Exception { JdbcBatchItemWriter> writer = new JdbcBatchItemWriterBuilder>() - .columnMapped() - .dataSource(this.dataSource) - .sql("INSERT INTO FOO (first, second, third) VALUES (:first, :second, :third)") - .build(); + .columnMapped().dataSource(this.dataSource) + .sql("INSERT INTO FOO (first, second, third) VALUES (:first, :second, :third)").build(); writer.afterPropertiesSet(); @@ -90,10 +88,8 @@ public class JdbcBatchItemWriterBuilderTests { NamedParameterJdbcOperations template = new NamedParameterJdbcTemplate(this.dataSource); JdbcBatchItemWriter> writer = new JdbcBatchItemWriterBuilder>() - .columnMapped() - .namedParametersJdbcTemplate(template) - .sql("INSERT INTO FOO (first, second, third) VALUES (:first, :second, :third)") - .build(); + .columnMapped().namedParametersJdbcTemplate(template) + .sql("INSERT INTO FOO (first, second, third) VALUES (:first, :second, :third)").build(); writer.afterPropertiesSet(); @@ -108,11 +104,8 @@ public class JdbcBatchItemWriterBuilderTests { @Test public void testBasicPojo() throws Exception { - JdbcBatchItemWriter writer = new JdbcBatchItemWriterBuilder() - .beanMapped() - .dataSource(this.dataSource) - .sql("INSERT INTO FOO (first, second, third) VALUES (:first, :second, :third)") - .build(); + JdbcBatchItemWriter writer = new JdbcBatchItemWriterBuilder().beanMapped().dataSource(this.dataSource) + .sql("INSERT INTO FOO (first, second, third) VALUES (:first, :second, :third)").build(); writer.afterPropertiesSet(); @@ -129,11 +122,8 @@ public class JdbcBatchItemWriterBuilderTests { @Test(expected = EmptyResultDataAccessException.class) public void testAssertUpdates() throws Exception { - JdbcBatchItemWriter writer = new JdbcBatchItemWriterBuilder() - .beanMapped() - .dataSource(this.dataSource) - .sql("UPDATE FOO SET second = :second, third = :third WHERE first = :first") - .assertUpdates(true) + JdbcBatchItemWriter writer = new JdbcBatchItemWriterBuilder().beanMapped().dataSource(this.dataSource) + .sql("UPDATE FOO SET second = :second, third = :third WHERE first = :first").assertUpdates(true) .build(); writer.afterPropertiesSet(); @@ -152,10 +142,8 @@ public class JdbcBatchItemWriterBuilderTests { ps.setInt(0, (int) item.get("first")); ps.setString(1, (String) item.get("second")); ps.setString(2, (String) item.get("third")); - }) - .dataSource(this.dataSource) - .sql("INSERT INTO FOO (first, second, third) VALUES (:first, :second, :third)") - .build(); + }).dataSource(this.dataSource) + .sql("INSERT INTO FOO (first, second, third) VALUES (:first, :second, :third)").build(); writer.afterPropertiesSet(); @@ -168,10 +156,8 @@ public class JdbcBatchItemWriterBuilderTests { @Test public void testCustomPSqlParameterSourceProvider() throws Exception { JdbcBatchItemWriter> writer = new JdbcBatchItemWriterBuilder>() - .itemSqlParameterSourceProvider(MapSqlParameterSource::new) - .dataSource(this.dataSource) - .sql("INSERT INTO FOO (first, second, third) VALUES (:first, :second, :third)") - .build(); + .itemSqlParameterSourceProvider(MapSqlParameterSource::new).dataSource(this.dataSource) + .sql("INSERT INTO FOO (first, second, third) VALUES (:first, :second, :third)").build(); writer.afterPropertiesSet(); @@ -185,47 +171,36 @@ public class JdbcBatchItemWriterBuilderTests { public void testBuildAssertions() { try { new JdbcBatchItemWriterBuilder>() - .itemSqlParameterSourceProvider(MapSqlParameterSource::new) - .build(); + .itemSqlParameterSourceProvider(MapSqlParameterSource::new).build(); } catch (IllegalStateException ise) { - assertEquals("Either a DataSource or a NamedParameterJdbcTemplate is required", - ise.getMessage()); + assertEquals("Either a DataSource or a NamedParameterJdbcTemplate is required", ise.getMessage()); } catch (Exception e) { - fail("Incorrect exception was thrown when missing DataSource and JdbcTemplate: " + - e.getMessage()); + fail("Incorrect exception was thrown when missing DataSource and JdbcTemplate: " + e.getMessage()); } try { new JdbcBatchItemWriterBuilder>() - .itemSqlParameterSourceProvider(MapSqlParameterSource::new) - .dataSource(this.dataSource) - .build(); + .itemSqlParameterSourceProvider(MapSqlParameterSource::new).dataSource(this.dataSource).build(); } catch (IllegalArgumentException ise) { assertEquals("A SQL statement is required", ise.getMessage()); } catch (Exception e) { - fail("Incorrect exception was thrown when testing missing SQL: " + - e); + fail("Incorrect exception was thrown when testing missing SQL: " + e); } try { - new JdbcBatchItemWriterBuilder>() - .dataSource(this.dataSource) - .sql("INSERT INTO FOO VALUES (?, ?, ?)") - .columnMapped() - .beanMapped() - .build(); + new JdbcBatchItemWriterBuilder>().dataSource(this.dataSource) + .sql("INSERT INTO FOO VALUES (?, ?, ?)").columnMapped().beanMapped().build(); } catch (IllegalStateException ise) { assertEquals("Either an item can be mapped via db column or via bean spec, can't be both", ise.getMessage()); } catch (Exception e) { - fail("Incorrect exception was thrown both mapping types are used" + - e.getMessage()); + fail("Incorrect exception was thrown both mapping types are used" + e.getMessage()); } } @@ -261,14 +236,17 @@ public class JdbcBatchItemWriterBuilderTests { private void verifyRow(int i, String i1, String nine) { JdbcOperations template = new JdbcTemplate(this.dataSource); - assertEquals(1, (int) template.queryForObject( - "select count(*) from foo where first = ? and second = ? and third = ?", - Integer.class, i, i1, nine)); + assertEquals(1, + (int) template.queryForObject("select count(*) from foo where first = ? and second = ? and third = ?", + Integer.class, i, i1, nine)); } public static class Foo { + private int first; + private String second; + private String third; public Foo(int first, String second, String third) { @@ -300,22 +278,19 @@ public class JdbcBatchItemWriterBuilderTests { public void setThird(String third) { this.third = third; } + } @Configuration public static class TestDataSourceConfiguration { - private static final String CREATE_SQL = "CREATE TABLE FOO (\n" + - "\tID BIGINT IDENTITY NOT NULL PRIMARY KEY ,\n" + - "\tFIRST BIGINT ,\n" + - "\tSECOND VARCHAR(5) NOT NULL,\n" + - "\tTHIRD VARCHAR(5) NOT NULL) ;"; + private static final String CREATE_SQL = "CREATE TABLE FOO (\n" + + "\tID BIGINT IDENTITY NOT NULL PRIMARY KEY ,\n" + "\tFIRST BIGINT ,\n" + + "\tSECOND VARCHAR(5) NOT NULL,\n" + "\tTHIRD VARCHAR(5) NOT NULL) ;"; @Bean public DataSource dataSource() { - return new EmbeddedDatabaseBuilder() - .generateUniqueName(true) - .build(); + return new EmbeddedDatabaseBuilder().generateUniqueName(true).build(); } @Bean @@ -328,5 +303,7 @@ public class JdbcBatchItemWriterBuilderTests { return dataSourceInitializer; } + } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/JdbcCursorItemReaderBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/JdbcCursorItemReaderBuilderTests.java index cc564d9b9..58bdb82ca 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/JdbcCursorItemReaderBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/JdbcCursorItemReaderBuilderTests.java @@ -64,18 +64,15 @@ public class JdbcCursorItemReaderBuilderTests { @After public void tearDown() { - if(this.context != null) { + if (this.context != null) { this.context.close(); } } @Test public void testSimpleScenario() throws Exception { - JdbcCursorItemReader reader = new JdbcCursorItemReaderBuilder() - .dataSource(this.dataSource) - .name("fooReader") - .sql("SELECT * FROM FOO ORDER BY FIRST") - .rowMapper((rs, rowNum) -> { + JdbcCursorItemReader reader = new JdbcCursorItemReaderBuilder().dataSource(this.dataSource) + .name("fooReader").sql("SELECT * FROM FOO ORDER BY FIRST").rowMapper((rs, rowNum) -> { Foo foo = new Foo(); foo.setFirst(rs.getInt("FIRST")); @@ -83,8 +80,7 @@ public class JdbcCursorItemReaderBuilderTests { foo.setThird(rs.getString("THIRD")); return foo; - }) - .build(); + }).build(); ExecutionContext executionContext = new ExecutionContext(); reader.open(executionContext); @@ -98,12 +94,8 @@ public class JdbcCursorItemReaderBuilderTests { @Test public void testMaxRows() throws Exception { - JdbcCursorItemReader reader = new JdbcCursorItemReaderBuilder() - .dataSource(this.dataSource) - .name("fooReader") - .sql("SELECT * FROM FOO ORDER BY FIRST") - .maxRows(2) - .saveState(false) + JdbcCursorItemReader reader = new JdbcCursorItemReaderBuilder().dataSource(this.dataSource) + .name("fooReader").sql("SELECT * FROM FOO ORDER BY FIRST").maxRows(2).saveState(false) .rowMapper((rs, rowNum) -> { Foo foo = new Foo(); @@ -112,8 +104,7 @@ public class JdbcCursorItemReaderBuilderTests { foo.setThird(rs.getString("THIRD")); return foo; - }) - .build(); + }).build(); ExecutionContext executionContext = new ExecutionContext(); reader.open(executionContext); @@ -128,12 +119,9 @@ public class JdbcCursorItemReaderBuilderTests { @Test public void testQueryArgumentsList() throws Exception { - JdbcCursorItemReader reader = new JdbcCursorItemReaderBuilder() - .dataSource(this.dataSource) - .name("fooReader") - .sql("SELECT * FROM FOO WHERE FIRST > ? ORDER BY FIRST") - .queryArguments(Arrays.asList(3)) - .rowMapper((rs, rowNum) -> { + JdbcCursorItemReader reader = new JdbcCursorItemReaderBuilder().dataSource(this.dataSource) + .name("fooReader").sql("SELECT * FROM FOO WHERE FIRST > ? ORDER BY FIRST") + .queryArguments(Arrays.asList(3)).rowMapper((rs, rowNum) -> { Foo foo = new Foo(); foo.setFirst(rs.getInt("FIRST")); @@ -141,8 +129,7 @@ public class JdbcCursorItemReaderBuilderTests { foo.setThird(rs.getString("THIRD")); return foo; - }) - .build(); + }).build(); ExecutionContext executionContext = new ExecutionContext(); reader.open(executionContext); @@ -155,11 +142,8 @@ public class JdbcCursorItemReaderBuilderTests { @Test public void testQueryArgumentsArray() throws Exception { - JdbcCursorItemReader reader = new JdbcCursorItemReaderBuilder() - .dataSource(this.dataSource) - .name("fooReader") - .sql("SELECT * FROM FOO WHERE FIRST > ? ORDER BY FIRST") - .queryArguments(3) + JdbcCursorItemReader reader = new JdbcCursorItemReaderBuilder().dataSource(this.dataSource) + .name("fooReader").sql("SELECT * FROM FOO WHERE FIRST > ? ORDER BY FIRST").queryArguments(3) .rowMapper((rs, rowNum) -> { Foo foo = new Foo(); @@ -168,8 +152,7 @@ public class JdbcCursorItemReaderBuilderTests { foo.setThird(rs.getString("THIRD")); return foo; - }) - .build(); + }).build(); ExecutionContext executionContext = new ExecutionContext(); reader.open(executionContext); @@ -182,12 +165,9 @@ public class JdbcCursorItemReaderBuilderTests { @Test public void testQueryArgumentsTypedArray() throws Exception { - JdbcCursorItemReader reader = new JdbcCursorItemReaderBuilder() - .dataSource(this.dataSource) - .name("fooReader") - .sql("SELECT * FROM FOO WHERE FIRST > ? ORDER BY FIRST") - .queryArguments(new Integer[] {3}, new int[] {Types.BIGINT}) - .rowMapper((rs, rowNum) -> { + JdbcCursorItemReader reader = new JdbcCursorItemReaderBuilder().dataSource(this.dataSource) + .name("fooReader").sql("SELECT * FROM FOO WHERE FIRST > ? ORDER BY FIRST") + .queryArguments(new Integer[] { 3 }, new int[] { Types.BIGINT }).rowMapper((rs, rowNum) -> { Foo foo = new Foo(); foo.setFirst(rs.getInt("FIRST")); @@ -195,8 +175,7 @@ public class JdbcCursorItemReaderBuilderTests { foo.setThird(rs.getString("THIRD")); return foo; - }) - .build(); + }).build(); ExecutionContext executionContext = new ExecutionContext(); reader.open(executionContext); @@ -209,17 +188,14 @@ public class JdbcCursorItemReaderBuilderTests { @Test public void testPreparedStatementSetter() throws Exception { - JdbcCursorItemReader reader = new JdbcCursorItemReaderBuilder() - .dataSource(this.dataSource) - .name("fooReader") - .sql("SELECT * FROM FOO WHERE FIRST > ? ORDER BY FIRST") + JdbcCursorItemReader reader = new JdbcCursorItemReaderBuilder().dataSource(this.dataSource) + .name("fooReader").sql("SELECT * FROM FOO WHERE FIRST > ? ORDER BY FIRST") .preparedStatementSetter(new PreparedStatementSetter() { @Override public void setValues(PreparedStatement ps) throws SQLException { ps.setInt(1, 3); } - }) - .rowMapper((rs, rowNum) -> { + }).rowMapper((rs, rowNum) -> { Foo foo = new Foo(); foo.setFirst(rs.getInt("FIRST")); @@ -227,8 +203,7 @@ public class JdbcCursorItemReaderBuilderTests { foo.setThird(rs.getString("THIRD")); return foo; - }) - .build(); + }).build(); ExecutionContext executionContext = new ExecutionContext(); reader.open(executionContext); @@ -241,12 +216,8 @@ public class JdbcCursorItemReaderBuilderTests { @Test public void testMaxItemCount() throws Exception { - JdbcCursorItemReader reader = new JdbcCursorItemReaderBuilder() - .dataSource(this.dataSource) - .name("fooReader") - .sql("SELECT * FROM FOO ORDER BY FIRST") - .maxItemCount(2) - .rowMapper((rs, rowNum) -> { + JdbcCursorItemReader reader = new JdbcCursorItemReaderBuilder().dataSource(this.dataSource) + .name("fooReader").sql("SELECT * FROM FOO ORDER BY FIRST").maxItemCount(2).rowMapper((rs, rowNum) -> { Foo foo = new Foo(); foo.setFirst(rs.getInt("FIRST")); @@ -254,8 +225,7 @@ public class JdbcCursorItemReaderBuilderTests { foo.setThird(rs.getString("THIRD")); return foo; - }) - .build(); + }).build(); ExecutionContext executionContext = new ExecutionContext(); reader.open(executionContext); @@ -268,11 +238,8 @@ public class JdbcCursorItemReaderBuilderTests { @Test public void testCurrentItemCount() throws Exception { - JdbcCursorItemReader reader = new JdbcCursorItemReaderBuilder() - .dataSource(this.dataSource) - .name("fooReader") - .sql("SELECT * FROM FOO ORDER BY FIRST") - .currentItemCount(1) + JdbcCursorItemReader reader = new JdbcCursorItemReaderBuilder().dataSource(this.dataSource) + .name("fooReader").sql("SELECT * FROM FOO ORDER BY FIRST").currentItemCount(1) .rowMapper((rs, rowNum) -> { Foo foo = new Foo(); @@ -281,8 +248,7 @@ public class JdbcCursorItemReaderBuilderTests { foo.setThird(rs.getString("THIRD")); return foo; - }) - .build(); + }).build(); ExecutionContext executionContext = new ExecutionContext(); reader.open(executionContext); @@ -295,18 +261,10 @@ public class JdbcCursorItemReaderBuilderTests { @Test public void testOtherProperties() { - JdbcCursorItemReader reader = new JdbcCursorItemReaderBuilder() - .dataSource(this.dataSource) - .name("fooReader") - .sql("SELECT * FROM FOO ORDER BY FIRST") - .fetchSize(1) - .queryTimeout(2) - .ignoreWarnings(true) - .driverSupportsAbsolute(true) - .useSharedExtendedConnection(true) - .connectionAutoCommit(true) - .beanRowMapper(Foo.class) - .build(); + JdbcCursorItemReader reader = new JdbcCursorItemReaderBuilder().dataSource(this.dataSource) + .name("fooReader").sql("SELECT * FROM FOO ORDER BY FIRST").fetchSize(1).queryTimeout(2) + .ignoreWarnings(true).driverSupportsAbsolute(true).useSharedExtendedConnection(true) + .connectionAutoCommit(true).beanRowMapper(Foo.class).build(); assertEquals(1, ReflectionTestUtils.getField(reader, "fetchSize")); assertEquals(2, ReflectionTestUtils.getField(reader, "queryTimeout")); @@ -317,12 +275,8 @@ public class JdbcCursorItemReaderBuilderTests { @Test public void testVerifyCursorPositionDefaultToTrue() { - JdbcCursorItemReader reader = new JdbcCursorItemReaderBuilder() - .dataSource(this.dataSource) - .name("fooReader") - .sql("SELECT * FROM FOO ORDER BY FIRST") - .beanRowMapper(Foo.class) - .build(); + JdbcCursorItemReader reader = new JdbcCursorItemReaderBuilder().dataSource(this.dataSource) + .name("fooReader").sql("SELECT * FROM FOO ORDER BY FIRST").beanRowMapper(Foo.class).build(); assertTrue((boolean) ReflectionTestUtils.getField(reader, "verifyCursorPosition")); } @@ -339,9 +293,7 @@ public class JdbcCursorItemReaderBuilderTests { } try { - new JdbcCursorItemReaderBuilder() - .saveState(false) - .build(); + new JdbcCursorItemReaderBuilder().saveState(false).build(); } catch (IllegalArgumentException iae) { assertEquals("A query is required", iae.getMessage()); @@ -351,10 +303,7 @@ public class JdbcCursorItemReaderBuilderTests { } try { - new JdbcCursorItemReaderBuilder() - .saveState(false) - .sql("select 1") - .build(); + new JdbcCursorItemReaderBuilder().saveState(false).sql("select 1").build(); } catch (IllegalArgumentException iae) { assertEquals("A datasource is required", iae.getMessage()); @@ -364,11 +313,7 @@ public class JdbcCursorItemReaderBuilderTests { } try { - new JdbcCursorItemReaderBuilder() - .saveState(false) - .sql("select 1") - .dataSource(this.dataSource) - .build(); + new JdbcCursorItemReaderBuilder().saveState(false).sql("select 1").dataSource(this.dataSource).build(); } catch (IllegalArgumentException iae) { assertEquals("A rowmapper is required", iae.getMessage()); @@ -385,8 +330,11 @@ public class JdbcCursorItemReaderBuilderTests { } public static class Foo { + private int first; + private String second; + private String third; public int getFirst() { @@ -412,27 +360,23 @@ public class JdbcCursorItemReaderBuilderTests { public void setThird(String third) { this.third = third; } + } @Configuration public static class TestDataSourceConfiguration { - private static final String CREATE_SQL = "CREATE TABLE FOO (\n" + - "\tID BIGINT IDENTITY NOT NULL PRIMARY KEY ,\n" + - "\tFIRST BIGINT ,\n" + - "\tSECOND VARCHAR(5) NOT NULL,\n" + - "\tTHIRD VARCHAR(5) NOT NULL) ;"; + private static final String CREATE_SQL = "CREATE TABLE FOO (\n" + + "\tID BIGINT IDENTITY NOT NULL PRIMARY KEY ,\n" + "\tFIRST BIGINT ,\n" + + "\tSECOND VARCHAR(5) NOT NULL,\n" + "\tTHIRD VARCHAR(5) NOT NULL) ;"; - private static final String INSERT_SQL = - "INSERT INTO FOO (FIRST, SECOND, THIRD) VALUES (1, '2', '3');" + - "INSERT INTO FOO (FIRST, SECOND, THIRD) VALUES (4, '5', '6');" + - "INSERT INTO FOO (FIRST, SECOND, THIRD) VALUES (7, '8', '9');"; + private static final String INSERT_SQL = "INSERT INTO FOO (FIRST, SECOND, THIRD) VALUES (1, '2', '3');" + + "INSERT INTO FOO (FIRST, SECOND, THIRD) VALUES (4, '5', '6');" + + "INSERT INTO FOO (FIRST, SECOND, THIRD) VALUES (7, '8', '9');"; @Bean public DataSource dataSource() { - return new EmbeddedDatabaseBuilder() - .generateUniqueName(true) - .build(); + return new EmbeddedDatabaseBuilder().generateUniqueName(true).build(); } @Bean diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/JdbcPagingItemReaderBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/JdbcPagingItemReaderBuilderTests.java index 5721c3194..89ed3babd 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/JdbcPagingItemReaderBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/JdbcPagingItemReaderBuilderTests.java @@ -62,7 +62,7 @@ public class JdbcPagingItemReaderBuilderTests { @After public void tearDown() { - if(this.context != null) { + if (this.context != null) { this.context.close(); } } @@ -77,17 +77,9 @@ public class JdbcPagingItemReaderBuilderTests { provider.setFromClause("FOO"); provider.setSortKeys(sortKeys); - JdbcPagingItemReader reader = new JdbcPagingItemReaderBuilder() - .name("fooReader") - .currentItemCount(1) - .dataSource(this.dataSource) - .queryProvider(provider) - .fetchSize(2) - .maxItemCount(2) - .rowMapper((rs, rowNum) -> new Foo(rs.getInt(1), - rs.getInt(2), - rs.getString(3), - rs.getString(4))) + JdbcPagingItemReader reader = new JdbcPagingItemReaderBuilder().name("fooReader").currentItemCount(1) + .dataSource(this.dataSource).queryProvider(provider).fetchSize(2).maxItemCount(2) + .rowMapper((rs, rowNum) -> new Foo(rs.getInt(1), rs.getInt(2), rs.getString(3), rs.getString(4))) .build(); reader.afterPropertiesSet(); @@ -113,18 +105,10 @@ public class JdbcPagingItemReaderBuilderTests { Map sortKeys = new HashMap<>(1); sortKeys.put("ID", Order.DESCENDING); - JdbcPagingItemReader reader = new JdbcPagingItemReaderBuilder() - .name("fooReader") - .currentItemCount(1) - .dataSource(this.dataSource) - .maxItemCount(2) - .selectClause("SELECT ID, FIRST, SECOND, THIRD") - .fromClause("FOO") - .sortKeys(sortKeys) - .rowMapper((rs, rowNum) -> new Foo(rs.getInt(1), - rs.getInt(2), - rs.getString(3), - rs.getString(4))) + JdbcPagingItemReader reader = new JdbcPagingItemReaderBuilder().name("fooReader").currentItemCount(1) + .dataSource(this.dataSource).maxItemCount(2).selectClause("SELECT ID, FIRST, SECOND, THIRD") + .fromClause("FOO").sortKeys(sortKeys) + .rowMapper((rs, rowNum) -> new Foo(rs.getInt(1), rs.getInt(2), rs.getString(3), rs.getString(4))) .build(); reader.afterPropertiesSet(); @@ -144,18 +128,10 @@ public class JdbcPagingItemReaderBuilderTests { Map sortKeys = new HashMap<>(1); sortKeys.put("ID", Order.DESCENDING); - JdbcPagingItemReader reader = new JdbcPagingItemReaderBuilder() - .name("fooReader") - .dataSource(this.dataSource) - .pageSize(1) - .maxItemCount(2) - .selectClause("SELECT ID, FIRST, SECOND, THIRD") - .fromClause("FOO") - .sortKeys(sortKeys) - .rowMapper((rs, rowNum) -> new Foo(rs.getInt(1), - rs.getInt(2), - rs.getString(3), - rs.getString(4))) + JdbcPagingItemReader reader = new JdbcPagingItemReaderBuilder().name("fooReader") + .dataSource(this.dataSource).pageSize(1).maxItemCount(2).selectClause("SELECT ID, FIRST, SECOND, THIRD") + .fromClause("FOO").sortKeys(sortKeys) + .rowMapper((rs, rowNum) -> new Foo(rs.getInt(1), rs.getInt(2), rs.getString(3), rs.getString(4))) .build(); reader.afterPropertiesSet(); @@ -181,18 +157,10 @@ public class JdbcPagingItemReaderBuilderTests { Map sortKeys = new HashMap<>(1); sortKeys.put("ID", Order.DESCENDING); - JdbcPagingItemReader reader = new JdbcPagingItemReaderBuilder() - .dataSource(this.dataSource) - .pageSize(1) - .maxItemCount(2) - .selectClause("SELECT ID, FIRST, SECOND, THIRD") - .fromClause("FOO") - .sortKeys(sortKeys) - .saveState(false) - .rowMapper((rs, rowNum) -> new Foo(rs.getInt(1), - rs.getInt(2), - rs.getString(3), - rs.getString(4))) + JdbcPagingItemReader reader = new JdbcPagingItemReaderBuilder().dataSource(this.dataSource) + .pageSize(1).maxItemCount(2).selectClause("SELECT ID, FIRST, SECOND, THIRD").fromClause("FOO") + .sortKeys(sortKeys).saveState(false) + .rowMapper((rs, rowNum) -> new Foo(rs.getInt(1), rs.getInt(2), rs.getString(3), rs.getString(4))) .build(); reader.afterPropertiesSet(); @@ -227,20 +195,11 @@ public class JdbcPagingItemReaderBuilderTests { parameterValues.put("min", 1); parameterValues.put("max", 10); - JdbcPagingItemReader reader = new JdbcPagingItemReaderBuilder() - .name("fooReader") - .dataSource(this.dataSource) - .pageSize(1) - .maxItemCount(1) - .selectClause("SELECT ID, FIRST, SECOND, THIRD") - .fromClause("FOO") - .whereClause("FIRST > :min AND FIRST < :max") - .sortKeys(sortKeys) + JdbcPagingItemReader reader = new JdbcPagingItemReaderBuilder().name("fooReader") + .dataSource(this.dataSource).pageSize(1).maxItemCount(1).selectClause("SELECT ID, FIRST, SECOND, THIRD") + .fromClause("FOO").whereClause("FIRST > :min AND FIRST < :max").sortKeys(sortKeys) .parameterValues(parameterValues) - .rowMapper((rs, rowNum) -> new Foo(rs.getInt(1), - rs.getInt(2), - rs.getString(3), - rs.getString(4))) + .rowMapper((rs, rowNum) -> new Foo(rs.getInt(1), rs.getInt(2), rs.getString(3), rs.getString(4))) .build(); reader.afterPropertiesSet(); @@ -260,16 +219,9 @@ public class JdbcPagingItemReaderBuilderTests { Map sortKeys = new HashMap<>(1); sortKeys.put("ID", Order.DESCENDING); - JdbcPagingItemReader reader = new JdbcPagingItemReaderBuilder() - .name("fooReader") - .currentItemCount(1) - .dataSource(this.dataSource) - .maxItemCount(2) - .selectClause("SELECT ID, FIRST, SECOND, THIRD") - .fromClause("FOO") - .sortKeys(sortKeys) - .beanRowMapper(Foo.class) - .build(); + JdbcPagingItemReader reader = new JdbcPagingItemReaderBuilder().name("fooReader").currentItemCount(1) + .dataSource(this.dataSource).maxItemCount(2).selectClause("SELECT ID, FIRST, SECOND, THIRD") + .fromClause("FOO").sortKeys(sortKeys).beanRowMapper(Foo.class).build(); reader.afterPropertiesSet(); @@ -295,9 +247,7 @@ public class JdbcPagingItemReaderBuilderTests { } try { - new JdbcPagingItemReaderBuilder() - .pageSize(-2) - .build(); + new JdbcPagingItemReaderBuilder().pageSize(-2).build(); fail(); } catch (IllegalArgumentException iae) { @@ -305,9 +255,7 @@ public class JdbcPagingItemReaderBuilderTests { } try { - new JdbcPagingItemReaderBuilder() - .pageSize(2) - .build(); + new JdbcPagingItemReaderBuilder().pageSize(2).build(); fail(); } catch (IllegalArgumentException ise) { @@ -315,10 +263,7 @@ public class JdbcPagingItemReaderBuilderTests { } try { - new JdbcPagingItemReaderBuilder() - .pageSize(2) - .dataSource(this.dataSource) - .build(); + new JdbcPagingItemReaderBuilder().pageSize(2).dataSource(this.dataSource).build(); fail(); } catch (IllegalArgumentException ise) { @@ -326,11 +271,7 @@ public class JdbcPagingItemReaderBuilderTests { } try { - new JdbcPagingItemReaderBuilder() - .saveState(false) - .pageSize(2) - .dataSource(this.dataSource) - .build(); + new JdbcPagingItemReaderBuilder().saveState(false).pageSize(2).dataSource(this.dataSource).build(); fail(); } catch (IllegalArgumentException ise) { @@ -338,12 +279,8 @@ public class JdbcPagingItemReaderBuilderTests { } try { - new JdbcPagingItemReaderBuilder() - .name("fooReader") - .pageSize(2) - .dataSource(this.dataSource) - .selectClause("SELECT *") - .build(); + new JdbcPagingItemReaderBuilder().name("fooReader").pageSize(2).dataSource(this.dataSource) + .selectClause("SELECT *").build(); fail(); } catch (IllegalArgumentException ise) { @@ -351,13 +288,8 @@ public class JdbcPagingItemReaderBuilderTests { } try { - new JdbcPagingItemReaderBuilder() - .saveState(false) - .pageSize(2) - .dataSource(this.dataSource) - .selectClause("SELECT *") - .fromClause("FOO") - .build(); + new JdbcPagingItemReaderBuilder().saveState(false).pageSize(2).dataSource(this.dataSource) + .selectClause("SELECT *").fromClause("FOO").build(); fail(); } catch (IllegalArgumentException ise) { @@ -366,12 +298,17 @@ public class JdbcPagingItemReaderBuilderTests { } public static class Foo { + private int id; + private int first; + private String second; + private String third; - public Foo() {} + public Foo() { + } public Foo(int id, int first, String second, String third) { this.id = id; @@ -411,29 +348,25 @@ public class JdbcPagingItemReaderBuilderTests { public void setThird(String third) { this.third = third; } + } @Configuration public static class TestDataSourceConfiguration { - private static final String CREATE_SQL = "CREATE TABLE FOO (\n" + - "\tID BIGINT IDENTITY NOT NULL PRIMARY KEY ,\n" + - "\tFIRST BIGINT ,\n" + - "\tSECOND VARCHAR(5) NOT NULL,\n" + - "\tTHIRD VARCHAR(5) NOT NULL) ;"; + private static final String CREATE_SQL = "CREATE TABLE FOO (\n" + + "\tID BIGINT IDENTITY NOT NULL PRIMARY KEY ,\n" + "\tFIRST BIGINT ,\n" + + "\tSECOND VARCHAR(5) NOT NULL,\n" + "\tTHIRD VARCHAR(5) NOT NULL) ;"; - private static final String INSERT_SQL = - "INSERT INTO FOO (FIRST, SECOND, THIRD) VALUES (1, '2', '3');" + - "INSERT INTO FOO (FIRST, SECOND, THIRD) VALUES (4, '5', '6');" + - "INSERT INTO FOO (FIRST, SECOND, THIRD) VALUES (7, '8', '9');" + - "INSERT INTO FOO (FIRST, SECOND, THIRD) VALUES (10, '11', '12');" + - "INSERT INTO FOO (FIRST, SECOND, THIRD) VALUES (13, '14', '15');"; + private static final String INSERT_SQL = "INSERT INTO FOO (FIRST, SECOND, THIRD) VALUES (1, '2', '3');" + + "INSERT INTO FOO (FIRST, SECOND, THIRD) VALUES (4, '5', '6');" + + "INSERT INTO FOO (FIRST, SECOND, THIRD) VALUES (7, '8', '9');" + + "INSERT INTO FOO (FIRST, SECOND, THIRD) VALUES (10, '11', '12');" + + "INSERT INTO FOO (FIRST, SECOND, THIRD) VALUES (13, '14', '15');"; @Bean public DataSource dataSource() { - return new EmbeddedDatabaseBuilder() - .generateUniqueName(true) - .build(); + return new EmbeddedDatabaseBuilder().generateUniqueName(true).build(); } @Bean @@ -447,5 +380,7 @@ public class JdbcPagingItemReaderBuilderTests { return dataSourceInitializer; } + } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/JpaCursorItemReaderBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/JpaCursorItemReaderBuilderTests.java index 0b98edb3d..def62f286 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/JpaCursorItemReaderBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/JpaCursorItemReaderBuilderTests.java @@ -54,30 +54,28 @@ import static org.junit.Assert.fail; public class JpaCursorItemReaderBuilderTests { private EntityManagerFactory entityManagerFactory; + private ConfigurableApplicationContext context; @Before public void setUp() { - this.context = new AnnotationConfigApplicationContext(JpaCursorItemReaderBuilderTests.TestDataSourceConfiguration.class); + this.context = new AnnotationConfigApplicationContext( + JpaCursorItemReaderBuilderTests.TestDataSourceConfiguration.class); this.entityManagerFactory = (EntityManagerFactory) context.getBean("entityManagerFactory"); } @After public void tearDown() { - if(this.context != null) { + if (this.context != null) { this.context.close(); } } @Test public void testConfiguration() throws Exception { - JpaCursorItemReader reader = new JpaCursorItemReaderBuilder() - .name("fooReader") - .entityManagerFactory(this.entityManagerFactory) - .currentItemCount(2) - .maxItemCount(4) - .queryString("select f from Foo f ") - .build(); + JpaCursorItemReader reader = new JpaCursorItemReaderBuilder().name("fooReader") + .entityManagerFactory(this.entityManagerFactory).currentItemCount(2).maxItemCount(4) + .queryString("select f from Foo f ").build(); reader.afterPropertiesSet(); @@ -105,13 +103,9 @@ public class JpaCursorItemReaderBuilderTests { Map parameters = new HashMap<>(); parameters.put("value", 2); - JpaCursorItemReader reader = new JpaCursorItemReaderBuilder() - .name("fooReader") - .entityManagerFactory(this.entityManagerFactory) - .queryString("select f from Foo f where f.id > :value") - .parameterValues(parameters) - .saveState(false) - .build(); + JpaCursorItemReader reader = new JpaCursorItemReaderBuilder().name("fooReader") + .entityManagerFactory(this.entityManagerFactory).queryString("select f from Foo f where f.id > :value") + .parameterValues(parameters).saveState(false).build(); reader.afterPropertiesSet(); @@ -120,7 +114,7 @@ public class JpaCursorItemReaderBuilderTests { reader.open(executionContext); int i = 0; - while(reader.read() != null) { + while (reader.read() != null) { i++; } @@ -138,11 +132,8 @@ public class JpaCursorItemReaderBuilderTests { namedQueryProvider.setEntityClass(Foo.class); namedQueryProvider.afterPropertiesSet(); - JpaCursorItemReader reader = new JpaCursorItemReaderBuilder() - .name("fooReader") - .entityManagerFactory(this.entityManagerFactory) - .queryProvider(namedQueryProvider) - .build(); + JpaCursorItemReader reader = new JpaCursorItemReaderBuilder().name("fooReader") + .entityManagerFactory(this.entityManagerFactory).queryProvider(namedQueryProvider).build(); reader.afterPropertiesSet(); @@ -152,7 +143,7 @@ public class JpaCursorItemReaderBuilderTests { Foo foo; List foos = new ArrayList<>(); - while((foo = reader.read()) != null) { + while ((foo = reader.read()) != null) { foos.add(foo); } @@ -160,7 +151,7 @@ public class JpaCursorItemReaderBuilderTests { reader.close(); int id = 0; - for (Foo testFoo:foos) { + for (Foo testFoo : foos) { assertEquals(++id, testFoo.getId()); } } @@ -173,11 +164,8 @@ public class JpaCursorItemReaderBuilderTests { provider.setSqlQuery("select * from T_FOOS"); provider.afterPropertiesSet(); - JpaCursorItemReader reader = new JpaCursorItemReaderBuilder() - .name("fooReader") - .entityManagerFactory(this.entityManagerFactory) - .queryProvider(provider) - .build(); + JpaCursorItemReader reader = new JpaCursorItemReaderBuilder().name("fooReader") + .entityManagerFactory(this.entityManagerFactory).queryProvider(provider).build(); reader.afterPropertiesSet(); @@ -186,7 +174,7 @@ public class JpaCursorItemReaderBuilderTests { reader.open(executionContext); int i = 0; - while(reader.read() != null) { + while (reader.read() != null) { i++; } @@ -207,9 +195,7 @@ public class JpaCursorItemReaderBuilderTests { } try { - new JpaCursorItemReaderBuilder() - .entityManagerFactory(this.entityManagerFactory) - .saveState(true) + new JpaCursorItemReaderBuilder().entityManagerFactory(this.entityManagerFactory).saveState(true) .build(); fail("A name is required when saveState is set to true"); } @@ -218,9 +204,7 @@ public class JpaCursorItemReaderBuilderTests { } try { - new JpaCursorItemReaderBuilder() - .entityManagerFactory(this.entityManagerFactory) - .saveState(false) + new JpaCursorItemReaderBuilder().entityManagerFactory(this.entityManagerFactory).saveState(false) .build(); fail("Query string is required when queryProvider is null"); } @@ -234,9 +218,7 @@ public class JpaCursorItemReaderBuilderTests { @Bean public DataSource dataSource() { - return new EmbeddedDatabaseBuilder() - .generateUniqueName(true) - .build(); + return new EmbeddedDatabaseBuilder().generateUniqueName(true).build(); } @Bean @@ -244,7 +226,8 @@ public class JpaCursorItemReaderBuilderTests { DataSourceInitializer dataSourceInitializer = new DataSourceInitializer(); dataSourceInitializer.setDataSource(dataSource); - Resource create = new ClassPathResource("org/springframework/batch/item/database/init-foo-schema-hsqldb.sql"); + Resource create = new ClassPathResource( + "org/springframework/batch/item/database/init-foo-schema-hsqldb.sql"); dataSourceInitializer.setDatabasePopulator(new ResourceDatabasePopulator(create)); return dataSourceInitializer; @@ -252,8 +235,7 @@ public class JpaCursorItemReaderBuilderTests { @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory() { - LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = - new LocalContainerEntityManagerFactoryBean(); + LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean(); entityManagerFactoryBean.setDataSource(dataSource()); entityManagerFactoryBean.setPersistenceUnitName("bar"); @@ -261,5 +243,7 @@ public class JpaCursorItemReaderBuilderTests { return entityManagerFactoryBean; } + } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/JpaItemWriterBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/JpaItemWriterBuilderTests.java index 690d61a51..fc672ea96 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/JpaItemWriterBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/JpaItemWriterBuilderTests.java @@ -63,8 +63,7 @@ public class JpaItemWriterBuilderTests { @Test public void testConfiguration() throws Exception { JpaItemWriter itemWriter = new JpaItemWriterBuilder() - .entityManagerFactory(this.entityManagerFactory) - .build(); + .entityManagerFactory(this.entityManagerFactory).build(); itemWriter.afterPropertiesSet(); @@ -79,8 +78,7 @@ public class JpaItemWriterBuilderTests { @Test public void testValidation() { try { - new JpaItemWriterBuilder() - .build(); + new JpaItemWriterBuilder().build(); fail("Should fail if no EntityManagerFactory is provided"); } catch (IllegalStateException ise) { @@ -91,9 +89,7 @@ public class JpaItemWriterBuilderTests { @Test public void testPersist() throws Exception { JpaItemWriter itemWriter = new JpaItemWriterBuilder() - .entityManagerFactory(this.entityManagerFactory) - .usePersist(true) - .build(); + .entityManagerFactory(this.entityManagerFactory).usePersist(true).build(); itemWriter.afterPropertiesSet(); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/JpaPagingItemReaderBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/JpaPagingItemReaderBuilderTests.java index 08437eed8..feb985709 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/JpaPagingItemReaderBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/JpaPagingItemReaderBuilderTests.java @@ -62,28 +62,23 @@ public class JpaPagingItemReaderBuilderTests { @Before public void setUp() { - this.context = new AnnotationConfigApplicationContext(JpaPagingItemReaderBuilderTests.TestDataSourceConfiguration.class); + this.context = new AnnotationConfigApplicationContext( + JpaPagingItemReaderBuilderTests.TestDataSourceConfiguration.class); this.entityManagerFactory = (EntityManagerFactory) context.getBean("entityManagerFactory"); } @After public void tearDown() { - if(this.context != null) { + if (this.context != null) { this.context.close(); } } @Test public void testConfiguration() throws Exception { - JpaPagingItemReader reader = new JpaPagingItemReaderBuilder() - .name("fooReader") - .entityManagerFactory(this.entityManagerFactory) - .currentItemCount(2) - .maxItemCount(4) - .pageSize(5) - .transacted(false) - .queryString("select f from Foo f ") - .build(); + JpaPagingItemReader reader = new JpaPagingItemReaderBuilder().name("fooReader") + .entityManagerFactory(this.entityManagerFactory).currentItemCount(2).maxItemCount(4).pageSize(5) + .transacted(false).queryString("select f from Foo f ").build(); reader.afterPropertiesSet(); @@ -113,13 +108,9 @@ public class JpaPagingItemReaderBuilderTests { Map parameters = new HashMap<>(); parameters.put("value", 2); - JpaPagingItemReader reader = new JpaPagingItemReaderBuilder() - .name("fooReader") - .entityManagerFactory(this.entityManagerFactory) - .queryString("select f from Foo f where f.id > :value") - .parameterValues(parameters) - .saveState(false) - .build(); + JpaPagingItemReader reader = new JpaPagingItemReaderBuilder().name("fooReader") + .entityManagerFactory(this.entityManagerFactory).queryString("select f from Foo f where f.id > :value") + .parameterValues(parameters).saveState(false).build(); reader.afterPropertiesSet(); @@ -128,7 +119,7 @@ public class JpaPagingItemReaderBuilderTests { reader.open(executionContext); int i = 0; - while(reader.read() != null) { + while (reader.read() != null) { i++; } @@ -146,11 +137,8 @@ public class JpaPagingItemReaderBuilderTests { namedQueryProvider.setEntityClass(Foo.class); namedQueryProvider.afterPropertiesSet(); - JpaPagingItemReader reader = new JpaPagingItemReaderBuilder() - .name("fooReader") - .entityManagerFactory(this.entityManagerFactory) - .queryProvider(namedQueryProvider) - .build(); + JpaPagingItemReader reader = new JpaPagingItemReaderBuilder().name("fooReader") + .entityManagerFactory(this.entityManagerFactory).queryProvider(namedQueryProvider).build(); reader.afterPropertiesSet(); @@ -160,7 +148,7 @@ public class JpaPagingItemReaderBuilderTests { Foo foo; List foos = new ArrayList<>(); - while((foo = reader.read()) != null) { + while ((foo = reader.read()) != null) { foos.add(foo); } @@ -168,7 +156,7 @@ public class JpaPagingItemReaderBuilderTests { reader.close(); int id = 0; - for (Foo testFoo:foos) { + for (Foo testFoo : foos) { assertEquals(++id, testFoo.getId()); } } @@ -181,11 +169,8 @@ public class JpaPagingItemReaderBuilderTests { provider.setSqlQuery("select * from T_FOOS"); provider.afterPropertiesSet(); - JpaPagingItemReader reader = new JpaPagingItemReaderBuilder() - .name("fooReader") - .entityManagerFactory(this.entityManagerFactory) - .queryProvider(provider) - .build(); + JpaPagingItemReader reader = new JpaPagingItemReaderBuilder().name("fooReader") + .entityManagerFactory(this.entityManagerFactory).queryProvider(provider).build(); reader.afterPropertiesSet(); @@ -194,7 +179,7 @@ public class JpaPagingItemReaderBuilderTests { reader.open(executionContext); int i = 0; - while(reader.read() != null) { + while (reader.read() != null) { i++; } @@ -207,10 +192,7 @@ public class JpaPagingItemReaderBuilderTests { @Test public void testValidation() { try { - new JpaPagingItemReaderBuilder() - .entityManagerFactory(this.entityManagerFactory) - .pageSize(-2) - .build(); + new JpaPagingItemReaderBuilder().entityManagerFactory(this.entityManagerFactory).pageSize(-2).build(); fail("pageSize must be >= 0"); } catch (IllegalArgumentException iae) { @@ -226,9 +208,7 @@ public class JpaPagingItemReaderBuilderTests { } try { - new JpaPagingItemReaderBuilder() - .entityManagerFactory(this.entityManagerFactory) - .saveState(true) + new JpaPagingItemReaderBuilder().entityManagerFactory(this.entityManagerFactory).saveState(true) .build(); fail("A name is required when saveState is set to true"); } @@ -237,9 +217,7 @@ public class JpaPagingItemReaderBuilderTests { } try { - new JpaPagingItemReaderBuilder() - .entityManagerFactory(this.entityManagerFactory) - .saveState(false) + new JpaPagingItemReaderBuilder().entityManagerFactory(this.entityManagerFactory).saveState(false) .build(); fail("Query string is required when queryProvider is null"); } @@ -253,9 +231,7 @@ public class JpaPagingItemReaderBuilderTests { @Bean public DataSource dataSource() { - return new EmbeddedDatabaseBuilder() - .generateUniqueName(true) - .build(); + return new EmbeddedDatabaseBuilder().generateUniqueName(true).build(); } @Bean @@ -263,7 +239,8 @@ public class JpaPagingItemReaderBuilderTests { DataSourceInitializer dataSourceInitializer = new DataSourceInitializer(); dataSourceInitializer.setDataSource(dataSource); - Resource create = new ClassPathResource("org/springframework/batch/item/database/init-foo-schema-hsqldb.sql"); + Resource create = new ClassPathResource( + "org/springframework/batch/item/database/init-foo-schema-hsqldb.sql"); dataSourceInitializer.setDatabasePopulator(new ResourceDatabasePopulator(create)); return dataSourceInitializer; @@ -271,8 +248,7 @@ public class JpaPagingItemReaderBuilderTests { @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws Exception { - LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = - new LocalContainerEntityManagerFactoryBean(); + LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean(); entityManagerFactoryBean.setDataSource(dataSource()); entityManagerFactoryBean.setPersistenceUnitName("bar"); @@ -280,5 +256,7 @@ public class JpaPagingItemReaderBuilderTests { return entityManagerFactoryBean; } + } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/StoredProcedureItemReaderBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/StoredProcedureItemReaderBuilderTests.java index 9d97bae3c..6f98d526d 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/StoredProcedureItemReaderBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/StoredProcedureItemReaderBuilderTests.java @@ -67,13 +67,9 @@ public class StoredProcedureItemReaderBuilderTests { @Test public void testSunnyScenario() throws Exception { - StoredProcedureItemReader reader = new StoredProcedureItemReaderBuilder() - .name("foo_reader") - .dataSource(this.dataSource) - .procedureName("read_foos") - .rowMapper(new FooRowMapper()) - .verifyCursorPosition(false) - .build(); + StoredProcedureItemReader reader = new StoredProcedureItemReaderBuilder().name("foo_reader") + .dataSource(this.dataSource).procedureName("read_foos").rowMapper(new FooRowMapper()) + .verifyCursorPosition(false).build(); reader.open(new ExecutionContext()); @@ -91,25 +87,12 @@ public class StoredProcedureItemReaderBuilderTests { SqlParameter[] parameters = new SqlParameter[0]; - StoredProcedureItemReader reader = new StoredProcedureItemReaderBuilder() - .name("foo_reader") - .dataSource(this.dataSource) - .procedureName("read_foos") - .rowMapper(new FooRowMapper()) - .verifyCursorPosition(false) - .refCursorPosition(3) - .useSharedExtendedConnection(true) - .preparedStatementSetter(preparedStatementSetter) - .parameters(parameters) - .function() - .fetchSize(5) - .driverSupportsAbsolute(true) - .currentItemCount(6) - .ignoreWarnings(false) - .maxItemCount(7) - .queryTimeout(8) - .maxRows(9) - .build(); + StoredProcedureItemReader reader = new StoredProcedureItemReaderBuilder().name("foo_reader") + .dataSource(this.dataSource).procedureName("read_foos").rowMapper(new FooRowMapper()) + .verifyCursorPosition(false).refCursorPosition(3).useSharedExtendedConnection(true) + .preparedStatementSetter(preparedStatementSetter).parameters(parameters).function().fetchSize(5) + .driverSupportsAbsolute(true).currentItemCount(6).ignoreWarnings(false).maxItemCount(7).queryTimeout(8) + .maxRows(9).build(); assertEquals(3, ReflectionTestUtils.getField(reader, "refCursorPosition")); assertEquals(preparedStatementSetter, ReflectionTestUtils.getField(reader, "preparedStatementSetter")); @@ -127,12 +110,8 @@ public class StoredProcedureItemReaderBuilderTests { @Test public void testNoSaveState() throws Exception { - StoredProcedureItemReader reader = new StoredProcedureItemReaderBuilder() - .dataSource(this.dataSource) - .procedureName("read_foos") - .rowMapper(new FooRowMapper()) - .verifyCursorPosition(false) - .saveState(false) + StoredProcedureItemReader reader = new StoredProcedureItemReaderBuilder().dataSource(this.dataSource) + .procedureName("read_foos").rowMapper(new FooRowMapper()).verifyCursorPosition(false).saveState(false) .build(); ExecutionContext executionContext = new ExecutionContext(); @@ -151,53 +130,40 @@ public class StoredProcedureItemReaderBuilderTests { @Test public void testValidation() { try { - new StoredProcedureItemReaderBuilder() - .build(); + new StoredProcedureItemReaderBuilder().build(); fail("Exception was not thrown for missing the name"); } catch (IllegalArgumentException iae) { - assertEquals("A name is required when saveSate is set to true", - iae.getMessage()); + assertEquals("A name is required when saveSate is set to true", iae.getMessage()); } try { - new StoredProcedureItemReaderBuilder() - .saveState(false) - .build(); + new StoredProcedureItemReaderBuilder().saveState(false).build(); fail("Exception was not thrown for missing the stored procedure name"); } catch (IllegalArgumentException iae) { - assertEquals("The name of the stored procedure must be provided", - iae.getMessage()); + assertEquals("The name of the stored procedure must be provided", iae.getMessage()); } try { - new StoredProcedureItemReaderBuilder() - .saveState(false) - .procedureName("read_foos") - .build(); + new StoredProcedureItemReaderBuilder().saveState(false).procedureName("read_foos").build(); fail("Exception was not thrown for missing the DataSource"); } catch (IllegalArgumentException iae) { - assertEquals("A datasource is required", - iae.getMessage()); + assertEquals("A datasource is required", iae.getMessage()); } try { - new StoredProcedureItemReaderBuilder() - .saveState(false) - .procedureName("read_foos") - .dataSource(this.dataSource) - .build(); + new StoredProcedureItemReaderBuilder().saveState(false).procedureName("read_foos") + .dataSource(this.dataSource).build(); fail("Exception was not thrown for missing the RowMapper"); } catch (IllegalArgumentException iae) { - assertEquals("A rowmapper is required", - iae.getMessage()); + assertEquals("A rowmapper is required", iae.getMessage()); } } @@ -236,14 +202,14 @@ public class StoredProcedureItemReaderBuilderTests { DataSourceInitializer initializer = new DataSourceInitializer(); initializer.setDataSource(dataSource); - initializer.setInitScripts(new ClassPathResource[]{ - new ClassPathResource("org/springframework/batch/item/database/init-foo-schema-derby.sql") - }); - initializer.setDestroyScripts(new ClassPathResource[]{ - new ClassPathResource("org/springframework/batch/item/database/drop-foo-schema-derby.sql") - }); + initializer.setInitScripts(new ClassPathResource[] { + new ClassPathResource("org/springframework/batch/item/database/init-foo-schema-derby.sql") }); + initializer.setDestroyScripts(new ClassPathResource[] { + new ClassPathResource("org/springframework/batch/item/database/drop-foo-schema-derby.sql") }); return initializer; } + } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/orm/JpaNamedQueryProviderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/orm/JpaNamedQueryProviderTests.java index 049a2539d..3bae8657a 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/orm/JpaNamedQueryProviderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/orm/JpaNamedQueryProviderTests.java @@ -84,4 +84,5 @@ public class JpaNamedQueryProviderTests { Assert.notNull(result, "Result query must not be null"); verify(entityManager).createNamedQuery(namedQuery, Foo.class); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/AbstractSqlPagingQueryProviderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/AbstractSqlPagingQueryProviderTests.java index b157ab7be..c4f99774f 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/AbstractSqlPagingQueryProviderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/AbstractSqlPagingQueryProviderTests.java @@ -33,8 +33,8 @@ import org.springframework.batch.item.database.Order; public abstract class AbstractSqlPagingQueryProviderTests { protected AbstractSqlPagingQueryProvider pagingQueryProvider; - protected int pageSize; + protected int pageSize; @Before public void setUp() { @@ -44,7 +44,7 @@ public abstract class AbstractSqlPagingQueryProviderTests { pagingQueryProvider.setSelectClause("id, name, age"); pagingQueryProvider.setFromClause("foo"); pagingQueryProvider.setWhereClause("bar = 1"); - + Map sortKeys = new LinkedHashMap<>(); sortKeys.put("id", Order.ASCENDING); pagingQueryProvider.setSortKeys(sortKeys); @@ -53,16 +53,16 @@ public abstract class AbstractSqlPagingQueryProviderTests { } @Test - public void testQueryContainsSortKey(){ + public void testQueryContainsSortKey() { String s = pagingQueryProvider.generateFirstPageQuery(pageSize).toLowerCase(); - assertTrue("Wrong query: "+s, s.contains("id asc")); + assertTrue("Wrong query: " + s, s.contains("id asc")); } @Test - public void testQueryContainsSortKeyDesc(){ + public void testQueryContainsSortKeyDesc() { pagingQueryProvider.getSortKeys().put("id", Order.DESCENDING); String s = pagingQueryProvider.generateFirstPageQuery(pageSize).toLowerCase(); - assertTrue("Wrong query: "+s, s.contains("id desc")); + assertTrue("Wrong query: " + s, s.contains("id desc")); } @Test @@ -104,7 +104,7 @@ public abstract class AbstractSqlPagingQueryProviderTests { String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); assertEquals(getJumpToItemQueryForFirstPageWithMultipleSortKeys(), s); } - + @Test public void testRemoveKeyWordsFollowedBySpaceChar() { String selectClause = "SELECT id, 'yes', false"; @@ -113,7 +113,7 @@ public abstract class AbstractSqlPagingQueryProviderTests { pagingQueryProvider.setSelectClause(selectClause); pagingQueryProvider.setFromClause(fromClause); pagingQueryProvider.setWhereClause(whereClause); - + assertEquals("id, 'yes', false", pagingQueryProvider.getSelectClause()); assertEquals("test.verification_table", pagingQueryProvider.getFromClause()); assertEquals("TRUE", pagingQueryProvider.getWhereClause()); @@ -146,7 +146,7 @@ public abstract class AbstractSqlPagingQueryProviderTests { assertEquals("test.verification_table", pagingQueryProvider.getFromClause()); assertEquals("TRUE", pagingQueryProvider.getWhereClause()); } - + @Test public abstract void testGenerateFirstPageQuery(); @@ -158,24 +158,25 @@ public abstract class AbstractSqlPagingQueryProviderTests { @Test public abstract void testGenerateJumpToItemQueryForFirstPage(); - + @Test public abstract void testGenerateFirstPageQueryWithGroupBy(); - + @Test public abstract void testGenerateRemainingPagesQueryWithGroupBy(); - + @Test public abstract void testGenerateJumpToItemQueryWithGroupBy(); - + @Test public abstract void testGenerateJumpToItemQueryForFirstPageWithGroupBy(); public abstract String getFirstPageSqlWithMultipleSortKeys(); - + public abstract String getRemainingSqlWithMultipleSortKeys(); - + public abstract String getJumpToItemQueryWithMultipleSortKeys(); - + public abstract String getJumpToItemQueryForFirstPageWithMultipleSortKeys(); + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/ColumnMapExecutionContextRowMapperTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/ColumnMapExecutionContextRowMapperTests.java index d501b23b2..c5fe749d0 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/ColumnMapExecutionContextRowMapperTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/ColumnMapExecutionContextRowMapperTests.java @@ -30,33 +30,33 @@ import junit.framework.TestCase; public class ColumnMapExecutionContextRowMapperTests extends TestCase { private ColumnMapItemPreparedStatementSetter mapper; - + private Map key; - + private PreparedStatement ps; - - @Override + + @Override protected void setUp() throws Exception { super.setUp(); - + ps = mock(PreparedStatement.class); mapper = new ColumnMapItemPreparedStatementSetter(); - + key = new LinkedHashMap<>(2); key.put("1", Integer.valueOf(1)); key.put("2", Integer.valueOf(2)); } - + public void testCreateExecutionContextFromEmptyKeys() throws Exception { - + mapper.setValues(new HashMap<>(), ps); } - + public void testCreateSetter() throws Exception { - + ps.setObject(1, Integer.valueOf(1)); ps.setObject(2, Integer.valueOf(2)); - mapper.setValues(key, ps); + mapper.setValues(key, ps); } - + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/Db2PagingQueryProviderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/Db2PagingQueryProviderTests.java index 01018c1e5..a835e8d0e 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/Db2PagingQueryProviderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/Db2PagingQueryProviderTests.java @@ -37,7 +37,7 @@ public class Db2PagingQueryProviderTests extends AbstractSqlPagingQueryProviderT assertEquals(sql, s); } - @Test + @Test @Override public void testGenerateRemainingPagesQuery() { String sql = "SELECT id, name, age FROM foo WHERE (bar = 1) AND ((id > ?)) ORDER BY id ASC FETCH FIRST 100 ROWS ONLY"; @@ -45,7 +45,7 @@ public class Db2PagingQueryProviderTests extends AbstractSqlPagingQueryProviderT assertEquals(sql, s); } - @Test + @Test @Override public void testGenerateJumpToItemQuery() { String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 100 ORDER BY id ASC"; @@ -53,7 +53,7 @@ public class Db2PagingQueryProviderTests extends AbstractSqlPagingQueryProviderT assertEquals(sql, s); } - @Test + @Test @Override public void testGenerateJumpToItemQueryForFirstPage() { String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 1 ORDER BY id ASC"; @@ -116,4 +116,5 @@ public class Db2PagingQueryProviderTests extends AbstractSqlPagingQueryProviderT public String getJumpToItemQueryForFirstPageWithMultipleSortKeys() { return "SELECT name, id FROM ( SELECT name, id, ROW_NUMBER() OVER ( ORDER BY name ASC, id DESC) AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 1 ORDER BY name ASC, id DESC"; } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/DefaultDataFieldMaxValueIncrementerFactoryTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/DefaultDataFieldMaxValueIncrementerFactoryTests.java index 96604f412..f88c97d4d 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/DefaultDataFieldMaxValueIncrementerFactoryTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/DefaultDataFieldMaxValueIncrementerFactoryTests.java @@ -41,19 +41,21 @@ import org.springframework.jdbc.support.incrementer.SybaseMaxValueIncrementer; public class DefaultDataFieldMaxValueIncrementerFactoryTests extends TestCase { private DefaultDataFieldMaxValueIncrementerFactory factory; - - /* (non-Javadoc) + + /* + * (non-Javadoc) + * * @see junit.framework.TestCase#setUp() */ - @Override + @Override protected void setUp() throws Exception { super.setUp(); - + DataSource dataSource = mock(DataSource.class); factory = new DefaultDataFieldMaxValueIncrementerFactory(dataSource); } - - public void testSupportedDatabaseType(){ + + public void testSupportedDatabaseType() { assertTrue(factory.isSupportedIncrementerType("db2")); assertTrue(factory.isSupportedIncrementerType("db2zos")); assertTrue(factory.isSupportedIncrementerType("mysql")); @@ -66,73 +68,73 @@ public class DefaultDataFieldMaxValueIncrementerFactoryTests extends TestCase { assertTrue(factory.isSupportedIncrementerType("sqlite")); assertTrue(factory.isSupportedIncrementerType("hana")); } - - public void testUnsupportedDatabaseType(){ + + public void testUnsupportedDatabaseType() { assertFalse(factory.isSupportedIncrementerType("invalidtype")); } - - public void testInvalidDatabaseType(){ - try{ + + public void testInvalidDatabaseType() { + try { factory.getIncrementer("invalidtype", "NAME"); fail(); } - catch(IllegalArgumentException ex){ - //expected + catch (IllegalArgumentException ex) { + // expected } } - - public void testNullIncrementerName(){ - try{ + + public void testNullIncrementerName() { + try { factory.getIncrementer("db2", null); fail(); } - catch(IllegalArgumentException ex){ - //expected + catch (IllegalArgumentException ex) { + // expected } } - - public void testDb2(){ + + public void testDb2() { assertTrue(factory.getIncrementer("db2", "NAME") instanceof Db2LuwMaxValueIncrementer); } - - public void testDb2zos(){ + + public void testDb2zos() { assertTrue(factory.getIncrementer("db2zos", "NAME") instanceof Db2MainframeMaxValueIncrementer); } - public void testMysql(){ + public void testMysql() { assertTrue(factory.getIncrementer("mysql", "NAME") instanceof MySQLMaxValueIncrementer); } - public void testOracle(){ + public void testOracle() { factory.setIncrementerColumnName("ID"); assertTrue(factory.getIncrementer("oracle", "NAME") instanceof OracleSequenceMaxValueIncrementer); } - public void testDerby(){ + public void testDerby() { assertTrue(factory.getIncrementer("derby", "NAME") instanceof DerbyMaxValueIncrementer); } - public void testHsql(){ + public void testHsql() { assertTrue(factory.getIncrementer("hsql", "NAME") instanceof HsqlMaxValueIncrementer); } - - public void testPostgres(){ + + public void testPostgres() { assertTrue(factory.getIncrementer("postgres", "NAME") instanceof PostgresSequenceMaxValueIncrementer); } - public void testMsSqlServer(){ + public void testMsSqlServer() { assertTrue(factory.getIncrementer("sqlserver", "NAME") instanceof SqlServerSequenceMaxValueIncrementer); } - public void testSybase(){ + public void testSybase() { assertTrue(factory.getIncrementer("sybase", "NAME") instanceof SybaseMaxValueIncrementer); } - public void testSqlite(){ + public void testSqlite() { assertTrue(factory.getIncrementer("sqlite", "NAME") instanceof SqliteMaxValueIncrementer); } - - public void testHana(){ + + public void testHana() { assertTrue(factory.getIncrementer("hana", "NAME") instanceof HanaSequenceMaxValueIncrementer); } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/DerbyPagingQueryProviderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/DerbyPagingQueryProviderTests.java index 3583cd5d3..33d906d44 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/DerbyPagingQueryProviderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/DerbyPagingQueryProviderTests.java @@ -1,192 +1,195 @@ -/* - * Copyright 2006-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.database.support; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.sql.Connection; -import java.sql.DatabaseMetaData; - -import javax.sql.DataSource; - -import org.junit.Assert; -import org.junit.Test; -import org.springframework.batch.item.database.Order; -import org.springframework.dao.InvalidDataAccessResourceUsageException; - -/** - * @author Thomas Risberg - * @author Michael Minella - * @author Will Schipp - */ -public class DerbyPagingQueryProviderTests extends AbstractSqlPagingQueryProviderTests { - - public DerbyPagingQueryProviderTests() { - pagingQueryProvider = new DerbyPagingQueryProvider(); - } - - @Test - public void testInit() throws Exception { - DataSource ds = mock(DataSource.class); - Connection con = mock(Connection.class); - DatabaseMetaData dmd = mock(DatabaseMetaData.class); - when(dmd.getDatabaseProductVersion()).thenReturn("10.4.1.3"); - when(con.getMetaData()).thenReturn(dmd); - when(ds.getConnection()).thenReturn(con); - pagingQueryProvider.init(ds); - } - - @Test - public void testInitWithRecentVersion() throws Exception { - DataSource ds = mock(DataSource.class); - Connection con = mock(Connection.class); - DatabaseMetaData dmd = mock(DatabaseMetaData.class); - when(dmd.getDatabaseProductVersion()).thenReturn("10.10.1.1"); - when(con.getMetaData()).thenReturn(dmd); - when(ds.getConnection()).thenReturn(con); - pagingQueryProvider.init(ds); - } - - @Test - public void testInitWithUnsupportedVersion() throws Exception { - DataSource ds = mock(DataSource.class); - Connection con = mock(Connection.class); - DatabaseMetaData dmd = mock(DatabaseMetaData.class); - when(dmd.getDatabaseProductVersion()).thenReturn("10.2.9.9"); - when(con.getMetaData()).thenReturn(dmd); - when(ds.getConnection()).thenReturn(con); - try { - pagingQueryProvider.init(ds); - fail(); - } - catch (InvalidDataAccessResourceUsageException e) { - // expected - } - } - - @Test - @Override - public void testGenerateFirstPageQuery() { - String sql = "SELECT * FROM ( SELECT TMP_ORDERED.*, ROW_NUMBER() OVER () AS ROW_NUMBER FROM (SELECT id, name, age FROM foo WHERE bar = 1 ) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100 ORDER BY id ASC"; - String s = pagingQueryProvider.generateFirstPageQuery(pageSize); - Assert.assertEquals(sql, s); - } - - @Test - @Override - public void testGenerateRemainingPagesQuery() { - String sql = "SELECT * FROM ( SELECT TMP_ORDERED.*, ROW_NUMBER() OVER () AS ROW_NUMBER FROM (SELECT id, name, age FROM foo WHERE bar = 1 ) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100 AND ((id > ?)) ORDER BY id ASC"; - String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); - Assert.assertEquals(sql, s); - } - - @Test - @Override - public void testGenerateJumpToItemQuery() { - String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER () AS ROW_NUMBER FROM (SELECT id, name, age FROM foo WHERE bar = 1 ) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 100 ORDER BY id ASC"; - String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); - Assert.assertEquals(sql, s); - } - - @Test - @Override - public void testGenerateJumpToItemQueryForFirstPage() { - String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER () AS ROW_NUMBER FROM (SELECT id, name, age FROM foo WHERE bar = 1 ) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 1 ORDER BY id ASC"; - String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); - Assert.assertEquals(sql, s); - } - - /** - * Older versions of Derby don't allow order by in the sub select. This should work with 10.6.1 and above. - */ - @Test - @Override - public void testQueryContainsSortKey() { - String s = pagingQueryProvider.generateFirstPageQuery(pageSize).toLowerCase(); - assertTrue("Wrong query: " + s, s.contains("id asc")); - } - - /** - * Older versions of Derby don't allow order by in the sub select. This should work with 10.6.1 and above. - */ - @Test - @Override - public void testQueryContainsSortKeyDesc() { - pagingQueryProvider.getSortKeys().put("id", Order.DESCENDING); - String s = pagingQueryProvider.generateFirstPageQuery(pageSize).toLowerCase(); - assertTrue("Wrong query: " + s, s.contains("id desc")); - } - - @Override - @Test - public void testGenerateFirstPageQueryWithGroupBy() { - pagingQueryProvider.setGroupClause("dep"); - String sql = "SELECT * FROM ( SELECT TMP_ORDERED.*, ROW_NUMBER() OVER () AS ROW_NUMBER FROM (SELECT id, name, age FROM foo WHERE bar = 1 GROUP BY dep ) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100 ORDER BY id ASC"; - String s = pagingQueryProvider.generateFirstPageQuery(pageSize); - assertEquals(sql, s); - } - - @Override - @Test - public void testGenerateRemainingPagesQueryWithGroupBy() { - pagingQueryProvider.setGroupClause("dep"); - String sql = "SELECT * FROM ( SELECT TMP_ORDERED.*, ROW_NUMBER() OVER () AS ROW_NUMBER FROM (SELECT id, name, age FROM foo WHERE bar = 1 GROUP BY dep ) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100 AND ((id > ?)) ORDER BY id ASC"; - String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); - assertEquals(sql, s); - } - - @Override - @Test - public void testGenerateJumpToItemQueryWithGroupBy() { - pagingQueryProvider.setGroupClause("dep"); - String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER () AS ROW_NUMBER FROM (SELECT id, name, age FROM foo WHERE bar = 1 GROUP BY dep ) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 100 ORDER BY id ASC"; - String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); - assertEquals(sql, s); - } - - @Override - @Test - public void testGenerateJumpToItemQueryForFirstPageWithGroupBy() { - pagingQueryProvider.setGroupClause("dep"); - String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER () AS ROW_NUMBER FROM (SELECT id, name, age FROM foo WHERE bar = 1 GROUP BY dep ) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 1 ORDER BY id ASC"; - String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); - assertEquals(sql, s); - } - - @Override - public String getFirstPageSqlWithMultipleSortKeys() { - return "SELECT * FROM ( SELECT TMP_ORDERED.*, ROW_NUMBER() OVER () AS ROW_NUMBER FROM (SELECT id, name, age FROM foo WHERE bar = 1 ) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100 ORDER BY name ASC, id DESC"; - } - - @Override - public String getRemainingSqlWithMultipleSortKeys() { - return "SELECT * FROM ( SELECT TMP_ORDERED.*, ROW_NUMBER() OVER () AS ROW_NUMBER FROM (SELECT id, name, age FROM foo WHERE bar = 1 ) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100 AND ((name > ?) OR (name = ? AND id < ?)) ORDER BY name ASC, id DESC"; - } - - @Override - public String getJumpToItemQueryWithMultipleSortKeys() { - return "SELECT name, id FROM ( SELECT name, id, ROW_NUMBER() OVER () AS ROW_NUMBER FROM (SELECT id, name, age FROM foo WHERE bar = 1 ) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 100 ORDER BY name ASC, id DESC"; - } - - @Override - public String getJumpToItemQueryForFirstPageWithMultipleSortKeys() { - return "SELECT name, id FROM ( SELECT name, id, ROW_NUMBER() OVER () AS ROW_NUMBER FROM (SELECT id, name, age FROM foo WHERE bar = 1 ) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 1 ORDER BY name ASC, id DESC"; - } -} +/* + * Copyright 2006-2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item.database.support; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.sql.Connection; +import java.sql.DatabaseMetaData; + +import javax.sql.DataSource; + +import org.junit.Assert; +import org.junit.Test; +import org.springframework.batch.item.database.Order; +import org.springframework.dao.InvalidDataAccessResourceUsageException; + +/** + * @author Thomas Risberg + * @author Michael Minella + * @author Will Schipp + */ +public class DerbyPagingQueryProviderTests extends AbstractSqlPagingQueryProviderTests { + + public DerbyPagingQueryProviderTests() { + pagingQueryProvider = new DerbyPagingQueryProvider(); + } + + @Test + public void testInit() throws Exception { + DataSource ds = mock(DataSource.class); + Connection con = mock(Connection.class); + DatabaseMetaData dmd = mock(DatabaseMetaData.class); + when(dmd.getDatabaseProductVersion()).thenReturn("10.4.1.3"); + when(con.getMetaData()).thenReturn(dmd); + when(ds.getConnection()).thenReturn(con); + pagingQueryProvider.init(ds); + } + + @Test + public void testInitWithRecentVersion() throws Exception { + DataSource ds = mock(DataSource.class); + Connection con = mock(Connection.class); + DatabaseMetaData dmd = mock(DatabaseMetaData.class); + when(dmd.getDatabaseProductVersion()).thenReturn("10.10.1.1"); + when(con.getMetaData()).thenReturn(dmd); + when(ds.getConnection()).thenReturn(con); + pagingQueryProvider.init(ds); + } + + @Test + public void testInitWithUnsupportedVersion() throws Exception { + DataSource ds = mock(DataSource.class); + Connection con = mock(Connection.class); + DatabaseMetaData dmd = mock(DatabaseMetaData.class); + when(dmd.getDatabaseProductVersion()).thenReturn("10.2.9.9"); + when(con.getMetaData()).thenReturn(dmd); + when(ds.getConnection()).thenReturn(con); + try { + pagingQueryProvider.init(ds); + fail(); + } + catch (InvalidDataAccessResourceUsageException e) { + // expected + } + } + + @Test + @Override + public void testGenerateFirstPageQuery() { + String sql = "SELECT * FROM ( SELECT TMP_ORDERED.*, ROW_NUMBER() OVER () AS ROW_NUMBER FROM (SELECT id, name, age FROM foo WHERE bar = 1 ) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100 ORDER BY id ASC"; + String s = pagingQueryProvider.generateFirstPageQuery(pageSize); + Assert.assertEquals(sql, s); + } + + @Test + @Override + public void testGenerateRemainingPagesQuery() { + String sql = "SELECT * FROM ( SELECT TMP_ORDERED.*, ROW_NUMBER() OVER () AS ROW_NUMBER FROM (SELECT id, name, age FROM foo WHERE bar = 1 ) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100 AND ((id > ?)) ORDER BY id ASC"; + String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); + Assert.assertEquals(sql, s); + } + + @Test + @Override + public void testGenerateJumpToItemQuery() { + String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER () AS ROW_NUMBER FROM (SELECT id, name, age FROM foo WHERE bar = 1 ) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 100 ORDER BY id ASC"; + String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); + Assert.assertEquals(sql, s); + } + + @Test + @Override + public void testGenerateJumpToItemQueryForFirstPage() { + String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER () AS ROW_NUMBER FROM (SELECT id, name, age FROM foo WHERE bar = 1 ) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 1 ORDER BY id ASC"; + String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); + Assert.assertEquals(sql, s); + } + + /** + * Older versions of Derby don't allow order by in the sub select. This should work + * with 10.6.1 and above. + */ + @Test + @Override + public void testQueryContainsSortKey() { + String s = pagingQueryProvider.generateFirstPageQuery(pageSize).toLowerCase(); + assertTrue("Wrong query: " + s, s.contains("id asc")); + } + + /** + * Older versions of Derby don't allow order by in the sub select. This should work + * with 10.6.1 and above. + */ + @Test + @Override + public void testQueryContainsSortKeyDesc() { + pagingQueryProvider.getSortKeys().put("id", Order.DESCENDING); + String s = pagingQueryProvider.generateFirstPageQuery(pageSize).toLowerCase(); + assertTrue("Wrong query: " + s, s.contains("id desc")); + } + + @Override + @Test + public void testGenerateFirstPageQueryWithGroupBy() { + pagingQueryProvider.setGroupClause("dep"); + String sql = "SELECT * FROM ( SELECT TMP_ORDERED.*, ROW_NUMBER() OVER () AS ROW_NUMBER FROM (SELECT id, name, age FROM foo WHERE bar = 1 GROUP BY dep ) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100 ORDER BY id ASC"; + String s = pagingQueryProvider.generateFirstPageQuery(pageSize); + assertEquals(sql, s); + } + + @Override + @Test + public void testGenerateRemainingPagesQueryWithGroupBy() { + pagingQueryProvider.setGroupClause("dep"); + String sql = "SELECT * FROM ( SELECT TMP_ORDERED.*, ROW_NUMBER() OVER () AS ROW_NUMBER FROM (SELECT id, name, age FROM foo WHERE bar = 1 GROUP BY dep ) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100 AND ((id > ?)) ORDER BY id ASC"; + String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); + assertEquals(sql, s); + } + + @Override + @Test + public void testGenerateJumpToItemQueryWithGroupBy() { + pagingQueryProvider.setGroupClause("dep"); + String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER () AS ROW_NUMBER FROM (SELECT id, name, age FROM foo WHERE bar = 1 GROUP BY dep ) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 100 ORDER BY id ASC"; + String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); + assertEquals(sql, s); + } + + @Override + @Test + public void testGenerateJumpToItemQueryForFirstPageWithGroupBy() { + pagingQueryProvider.setGroupClause("dep"); + String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER () AS ROW_NUMBER FROM (SELECT id, name, age FROM foo WHERE bar = 1 GROUP BY dep ) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 1 ORDER BY id ASC"; + String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); + assertEquals(sql, s); + } + + @Override + public String getFirstPageSqlWithMultipleSortKeys() { + return "SELECT * FROM ( SELECT TMP_ORDERED.*, ROW_NUMBER() OVER () AS ROW_NUMBER FROM (SELECT id, name, age FROM foo WHERE bar = 1 ) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100 ORDER BY name ASC, id DESC"; + } + + @Override + public String getRemainingSqlWithMultipleSortKeys() { + return "SELECT * FROM ( SELECT TMP_ORDERED.*, ROW_NUMBER() OVER () AS ROW_NUMBER FROM (SELECT id, name, age FROM foo WHERE bar = 1 ) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100 AND ((name > ?) OR (name = ? AND id < ?)) ORDER BY name ASC, id DESC"; + } + + @Override + public String getJumpToItemQueryWithMultipleSortKeys() { + return "SELECT name, id FROM ( SELECT name, id, ROW_NUMBER() OVER () AS ROW_NUMBER FROM (SELECT id, name, age FROM foo WHERE bar = 1 ) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 100 ORDER BY name ASC, id DESC"; + } + + @Override + public String getJumpToItemQueryForFirstPageWithMultipleSortKeys() { + return "SELECT name, id FROM ( SELECT name, id, ROW_NUMBER() OVER () AS ROW_NUMBER FROM (SELECT id, name, age FROM foo WHERE bar = 1 ) AS TMP_ORDERED) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 1 ORDER BY name ASC, id DESC"; + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/H2PagingQueryProviderIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/H2PagingQueryProviderIntegrationTests.java index eeaf8463b..ce7b4f466 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/H2PagingQueryProviderIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/H2PagingQueryProviderIntegrationTests.java @@ -72,31 +72,23 @@ public class H2PagingQueryProviderIntegrationTests { sortKeys.put("ID", Order.ASCENDING); queryProvider.setSortKeys(sortKeys); - List firstPage = jdbcTemplate.queryForList( - queryProvider.generateFirstPageQuery(2), - String.class - ); - assertArrayEquals("firstPage", new String[]{"Spring", "Batch"}, firstPage.toArray()); + List firstPage = jdbcTemplate.queryForList(queryProvider.generateFirstPageQuery(2), String.class); + assertArrayEquals("firstPage", new String[] { "Spring", "Batch" }, firstPage.toArray()); - List secondPage = jdbcTemplate.queryForList( - queryProvider.generateRemainingPagesQuery(2), - String.class, - 2 - ); - assertArrayEquals("secondPage", new String[]{"Infrastructure"}, secondPage.toArray()); + List secondPage = jdbcTemplate.queryForList(queryProvider.generateRemainingPagesQuery(2), + String.class, 2); + assertArrayEquals("secondPage", new String[] { "Infrastructure" }, secondPage.toArray()); - Integer secondItem = jdbcTemplate.queryForObject( - queryProvider.generateJumpToItemQuery(3, 2), - Integer.class - ); + Integer secondItem = jdbcTemplate.queryForObject(queryProvider.generateJumpToItemQuery(3, 2), + Integer.class); assertEquals(Integer.valueOf(2), secondItem); }); } @Parameters public static List data() throws Exception { - return Arrays.stream(org.h2.engine.Mode.ModeEnum.values()) - .map(mode -> new Object[]{mode.toString()}) + return Arrays.stream(org.h2.engine.Mode.ModeEnum.values()).map(mode -> new Object[] { mode.toString() }) .collect(Collectors.toList()); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/H2PagingQueryProviderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/H2PagingQueryProviderTests.java index 308edfeba..f69f7025c 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/H2PagingQueryProviderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/H2PagingQueryProviderTests.java @@ -39,22 +39,25 @@ public class H2PagingQueryProviderTests extends AbstractSqlPagingQueryProviderTe assertEquals(sql, s); } - @Test @Override + @Test + @Override public void testGenerateRemainingPagesQuery() { String sql = "SELECT id, name, age FROM foo WHERE (bar = 1) AND ((id > ?)) " - + "ORDER BY id ASC FETCH NEXT 100 ROWS ONLY"; + + "ORDER BY id ASC FETCH NEXT 100 ROWS ONLY"; String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); assertEquals(sql, s); } - @Test @Override + @Test + @Override public void testGenerateJumpToItemQuery() { String sql = "SELECT id FROM foo WHERE bar = 1 ORDER BY id ASC OFFSET 99 ROWS FETCH NEXT 1 ROWS ONLY"; String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); assertEquals(sql, s); } - @Test @Override + @Test + @Override public void testGenerateJumpToItemQueryForFirstPage() { String sql = "SELECT id FROM foo WHERE bar = 1 ORDER BY id ASC OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY"; String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); @@ -118,4 +121,5 @@ public class H2PagingQueryProviderTests extends AbstractSqlPagingQueryProviderTe public String getJumpToItemQueryForFirstPageWithMultipleSortKeys() { return "SELECT name, id FROM foo WHERE bar = 1 ORDER BY name ASC, id DESC OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY"; } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/HanaPagingQueryProviderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/HanaPagingQueryProviderTests.java index 63ab3f6be..8e2d4ea75 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/HanaPagingQueryProviderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/HanaPagingQueryProviderTests.java @@ -42,21 +42,24 @@ public class HanaPagingQueryProviderTests extends AbstractSqlPagingQueryProvider assertEquals(sql, s); } - @Test @Override + @Test + @Override public void testGenerateRemainingPagesQuery() { String sql = "SELECT id, name, age FROM foo WHERE (bar = 1) AND ((id > ?)) ORDER BY id ASC LIMIT 100"; String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); assertEquals(sql, s); } - @Test @Override + @Test + @Override public void testGenerateJumpToItemQuery() { String sql = "SELECT id FROM foo WHERE bar = 1 ORDER BY id ASC LIMIT 1 OFFSET 99"; String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); assertEquals(sql, s); } - - @Test @Override + + @Test + @Override public void testGenerateJumpToItemQueryForFirstPage() { String sql = "SELECT id FROM foo WHERE bar = 1 ORDER BY id ASC LIMIT 1 OFFSET 0"; String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); @@ -113,9 +116,15 @@ public class HanaPagingQueryProviderTests extends AbstractSqlPagingQueryProvider String jumpToItemQuery = this.pagingQueryProvider.generateJumpToItemQuery(7, 5); String remainingPagesQuery = this.pagingQueryProvider.generateRemainingPagesQuery(5); - assertEquals("SELECT owner.id as ownerid, first_name, last_name, dog_name FROM dog_owner owner INNER JOIN dog ON owner.id = dog.id ORDER BY owner.id ASC LIMIT 5", firstPage); - assertEquals("SELECT owner.id FROM dog_owner owner INNER JOIN dog ON owner.id = dog.id ORDER BY owner.id ASC LIMIT 1 OFFSET 4", jumpToItemQuery); - assertEquals("SELECT owner.id as ownerid, first_name, last_name, dog_name FROM dog_owner owner INNER JOIN dog ON owner.id = dog.id WHERE ((owner.id > ?)) ORDER BY owner.id ASC LIMIT 5", remainingPagesQuery); + assertEquals( + "SELECT owner.id as ownerid, first_name, last_name, dog_name FROM dog_owner owner INNER JOIN dog ON owner.id = dog.id ORDER BY owner.id ASC LIMIT 5", + firstPage); + assertEquals( + "SELECT owner.id FROM dog_owner owner INNER JOIN dog ON owner.id = dog.id ORDER BY owner.id ASC LIMIT 1 OFFSET 4", + jumpToItemQuery); + assertEquals( + "SELECT owner.id as ownerid, first_name, last_name, dog_name FROM dog_owner owner INNER JOIN dog ON owner.id = dog.id WHERE ((owner.id > ?)) ORDER BY owner.id ASC LIMIT 5", + remainingPagesQuery); } @Override @@ -137,4 +146,5 @@ public class HanaPagingQueryProviderTests extends AbstractSqlPagingQueryProvider public String getJumpToItemQueryForFirstPageWithMultipleSortKeys() { return "SELECT name, id FROM foo WHERE bar = 1 ORDER BY name ASC, id DESC LIMIT 1 OFFSET 0"; } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/HibernateNativeQueryProviderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/HibernateNativeQueryProviderTests.java index d2ff37ce1..6f46be7ba 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/HibernateNativeQueryProviderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/HibernateNativeQueryProviderTests.java @@ -76,6 +76,7 @@ public class HibernateNativeQueryProviderTests { } private static class Foo { + } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/HsqlPagingQueryProviderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/HsqlPagingQueryProviderTests.java index 33be0b46d..0231ec272 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/HsqlPagingQueryProviderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/HsqlPagingQueryProviderTests.java @@ -37,21 +37,24 @@ public class HsqlPagingQueryProviderTests extends AbstractSqlPagingQueryProvider assertEquals(sql, s); } - @Test @Override + @Test + @Override public void testGenerateRemainingPagesQuery() { String sql = "SELECT TOP 100 id, name, age FROM foo WHERE (bar = 1) AND ((id > ?)) ORDER BY id ASC"; String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); assertEquals(sql, s); } - @Test @Override + @Test + @Override public void testGenerateJumpToItemQuery() { String sql = "SELECT LIMIT 99 1 id FROM foo WHERE bar = 1 ORDER BY id ASC"; String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); assertEquals(sql, s); } - @Test @Override + @Test + @Override public void testGenerateJumpToItemQueryForFirstPage() { String sql = "SELECT LIMIT 0 1 id FROM foo WHERE bar = 1 ORDER BY id ASC"; String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); @@ -113,4 +116,5 @@ public class HsqlPagingQueryProviderTests extends AbstractSqlPagingQueryProvider public String getJumpToItemQueryForFirstPageWithMultipleSortKeys() { return "SELECT LIMIT 0 1 name, id FROM foo WHERE bar = 1 ORDER BY name ASC, id DESC"; } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/JpaNativeQueryProviderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/JpaNativeQueryProviderTests.java index bd311c414..f656d6627 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/JpaNativeQueryProviderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/JpaNativeQueryProviderTests.java @@ -57,4 +57,5 @@ public class JpaNativeQueryProviderTests { jpaQueryProvider.setEntityManager(entityManager); Assert.notNull(jpaQueryProvider.createQuery(), "Query was null"); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/MySqlPagingQueryProviderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/MySqlPagingQueryProviderTests.java index 4593b94d9..f28797014 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/MySqlPagingQueryProviderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/MySqlPagingQueryProviderTests.java @@ -42,21 +42,24 @@ public class MySqlPagingQueryProviderTests extends AbstractSqlPagingQueryProvide assertEquals(sql, s); } - @Test @Override + @Test + @Override public void testGenerateRemainingPagesQuery() { String sql = "SELECT id, name, age FROM foo WHERE (bar = 1) AND ((id > ?)) ORDER BY id ASC LIMIT 100"; String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); assertEquals(sql, s); } - @Test @Override + @Test + @Override public void testGenerateJumpToItemQuery() { String sql = "SELECT id FROM foo WHERE bar = 1 ORDER BY id ASC LIMIT 99, 1"; String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); assertEquals(sql, s); } - - @Test @Override + + @Test + @Override public void testGenerateJumpToItemQueryForFirstPage() { String sql = "SELECT id FROM foo WHERE bar = 1 ORDER BY id ASC LIMIT 0, 1"; String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); @@ -113,9 +116,15 @@ public class MySqlPagingQueryProviderTests extends AbstractSqlPagingQueryProvide String jumpToItemQuery = this.pagingQueryProvider.generateJumpToItemQuery(7, 5); String remainingPagesQuery = this.pagingQueryProvider.generateRemainingPagesQuery(5); - assertEquals("SELECT owner.id as ownerid, first_name, last_name, dog_name FROM dog_owner owner INNER JOIN dog ON owner.id = dog.id ORDER BY owner.id ASC LIMIT 5", firstPage); - assertEquals("SELECT owner.id FROM dog_owner owner INNER JOIN dog ON owner.id = dog.id ORDER BY owner.id ASC LIMIT 4, 1", jumpToItemQuery); - assertEquals("SELECT owner.id as ownerid, first_name, last_name, dog_name FROM dog_owner owner INNER JOIN dog ON owner.id = dog.id WHERE ((owner.id > ?)) ORDER BY owner.id ASC LIMIT 5", remainingPagesQuery); + assertEquals( + "SELECT owner.id as ownerid, first_name, last_name, dog_name FROM dog_owner owner INNER JOIN dog ON owner.id = dog.id ORDER BY owner.id ASC LIMIT 5", + firstPage); + assertEquals( + "SELECT owner.id FROM dog_owner owner INNER JOIN dog ON owner.id = dog.id ORDER BY owner.id ASC LIMIT 4, 1", + jumpToItemQuery); + assertEquals( + "SELECT owner.id as ownerid, first_name, last_name, dog_name FROM dog_owner owner INNER JOIN dog ON owner.id = dog.id WHERE ((owner.id > ?)) ORDER BY owner.id ASC LIMIT 5", + remainingPagesQuery); } @Override @@ -137,4 +146,5 @@ public class MySqlPagingQueryProviderTests extends AbstractSqlPagingQueryProvide public String getJumpToItemQueryForFirstPageWithMultipleSortKeys() { return "SELECT name, id FROM foo WHERE bar = 1 ORDER BY name ASC, id DESC LIMIT 0, 1"; } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/OraclePagingQueryProviderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/OraclePagingQueryProviderTests.java index 1eb9260e9..52b7f367b 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/OraclePagingQueryProviderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/OraclePagingQueryProviderTests.java @@ -41,21 +41,24 @@ public class OraclePagingQueryProviderTests extends AbstractSqlPagingQueryProvid assertEquals(sql2, s2); } - @Test @Override + @Test + @Override public void testGenerateRemainingPagesQuery() { String sql = "SELECT * FROM (SELECT id, name, age FROM foo WHERE bar = 1 ORDER BY id ASC) WHERE ROWNUM <= 100 AND ((id > ?))"; String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); assertEquals(sql, s); } - @Test @Override + @Test + @Override public void testGenerateJumpToItemQuery() { String sql = "SELECT id FROM (SELECT id, ROWNUM as TMP_ROW_NUM FROM (SELECT id FROM foo WHERE bar = 1 ORDER BY id ASC)) WHERE TMP_ROW_NUM = 100"; String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); assertEquals(sql, s); } - - @Test @Override + + @Test + @Override public void testGenerateJumpToItemQueryForFirstPage() { String sql = "SELECT id FROM (SELECT id, ROWNUM as TMP_ROW_NUM FROM (SELECT id FROM foo WHERE bar = 1 ORDER BY id ASC)) WHERE TMP_ROW_NUM = 1"; String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); @@ -117,4 +120,5 @@ public class OraclePagingQueryProviderTests extends AbstractSqlPagingQueryProvid public String getJumpToItemQueryForFirstPageWithMultipleSortKeys() { return "SELECT name, id FROM (SELECT name, id, ROWNUM as TMP_ROW_NUM FROM (SELECT name, id FROM foo WHERE bar = 1 ORDER BY name ASC, id DESC)) WHERE TMP_ROW_NUM = 1"; } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/PostgresPagingQueryProviderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/PostgresPagingQueryProviderTests.java index d43ea4c8e..7a9822c08 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/PostgresPagingQueryProviderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/PostgresPagingQueryProviderTests.java @@ -37,21 +37,24 @@ public class PostgresPagingQueryProviderTests extends AbstractSqlPagingQueryProv assertEquals(sql, s); } - @Test @Override + @Test + @Override public void testGenerateRemainingPagesQuery() { String sql = "SELECT id, name, age FROM foo WHERE (bar = 1) AND ((id > ?)) ORDER BY id ASC LIMIT 100"; String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); assertEquals(sql, s); } - @Test @Override + @Test + @Override public void testGenerateJumpToItemQuery() { String sql = "SELECT id FROM foo WHERE bar = 1 ORDER BY id ASC LIMIT 1 OFFSET 99"; String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); assertEquals("Wrong SQL for jump to", sql, s); } - @Test @Override + @Test + @Override public void testGenerateJumpToItemQueryForFirstPage() { String sql = "SELECT id FROM foo WHERE bar = 1 ORDER BY id ASC LIMIT 1 OFFSET 0"; String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); @@ -113,4 +116,5 @@ public class PostgresPagingQueryProviderTests extends AbstractSqlPagingQueryProv public String getJumpToItemQueryForFirstPageWithMultipleSortKeys() { return "SELECT name, id FROM foo WHERE bar = 1 ORDER BY name ASC, id DESC LIMIT 1 OFFSET 0"; } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlPagingQueryProviderFactoryBeanTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlPagingQueryProviderFactoryBeanTests.java index f10d67435..717096053 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlPagingQueryProviderFactoryBeanTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlPagingQueryProviderFactoryBeanTests.java @@ -1,121 +1,121 @@ -/* - * Copyright 2006-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.database.support; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.util.LinkedHashMap; -import java.util.Map; - -import javax.sql.DataSource; - -import org.junit.Test; -import org.springframework.batch.item.database.Order; -import org.springframework.batch.item.database.PagingQueryProvider; -import org.springframework.batch.support.DatabaseType; -import org.springframework.batch.support.DatabaseTypeTestUtils; -import org.springframework.jdbc.support.MetaDataAccessException; - -/** - * @author Dave Syer - * @author Michael Minella - */ -public class SqlPagingQueryProviderFactoryBeanTests { - - private SqlPagingQueryProviderFactoryBean factory = new SqlPagingQueryProviderFactoryBean(); - - public SqlPagingQueryProviderFactoryBeanTests() throws Exception { - factory.setSelectClause("id, name, age"); - factory.setFromClause("foo"); - factory.setWhereClause("bar = 1"); - Map sortKeys = new LinkedHashMap<>(); - sortKeys.put("id", Order.ASCENDING); - factory.setSortKeys(sortKeys); - DataSource dataSource = DatabaseTypeTestUtils.getMockDataSource(DatabaseType.HSQL.getProductName(), "100.0.0"); - factory.setDataSource(dataSource); - } - - @Test - public void testFactory() throws Exception { - PagingQueryProvider provider = factory.getObject(); - assertNotNull(provider); - } - - @Test - public void testType() throws Exception { - assertEquals(PagingQueryProvider.class, factory.getObjectType()); - } - - @Test - public void testSingleton() throws Exception { - assertEquals(true, factory.isSingleton()); - } - - @Test(expected=IllegalArgumentException.class) - public void testNoDataSource() throws Exception { - factory.setDataSource(null); - PagingQueryProvider provider = factory.getObject(); - assertNotNull(provider); - } - - @Test(expected=IllegalArgumentException.class) - public void testNoSortKey() throws Exception { - factory.setSortKeys(null); - PagingQueryProvider provider = factory.getObject(); - assertNotNull(provider); - } - - @Test - public void testWhereClause() throws Exception { - factory.setWhereClause("x=y"); - PagingQueryProvider provider = factory.getObject(); - String query = provider.generateFirstPageQuery(100); - assertTrue("Wrong query: "+query, query.contains("x=y")); - } - - @Test - public void testAscending() throws Exception { - PagingQueryProvider provider = factory.getObject(); - String query = provider.generateFirstPageQuery(100); - assertTrue("Wrong query: "+query, query.contains("ASC")); - } - - @Test(expected=IllegalArgumentException.class) - public void testWrongDatabaseType() throws Exception { - factory.setDatabaseType("NoSuchDb"); - PagingQueryProvider provider = factory.getObject(); - assertNotNull(provider); - } - - @Test(expected=IllegalArgumentException.class) - public void testMissingMetaData() throws Exception { - factory.setDataSource(DatabaseTypeTestUtils.getMockDataSource(new MetaDataAccessException("foo"))); - PagingQueryProvider provider = factory.getObject(); - assertNotNull(provider); - } - - @Test - public void testAllDatabaseTypes() throws Exception { - for (DatabaseType type : DatabaseType.values()) { - factory.setDatabaseType(type.name()); - PagingQueryProvider provider = factory.getObject(); - assertNotNull(provider); - } - } - -} +/* + * Copyright 2006-2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item.database.support; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.LinkedHashMap; +import java.util.Map; + +import javax.sql.DataSource; + +import org.junit.Test; +import org.springframework.batch.item.database.Order; +import org.springframework.batch.item.database.PagingQueryProvider; +import org.springframework.batch.support.DatabaseType; +import org.springframework.batch.support.DatabaseTypeTestUtils; +import org.springframework.jdbc.support.MetaDataAccessException; + +/** + * @author Dave Syer + * @author Michael Minella + */ +public class SqlPagingQueryProviderFactoryBeanTests { + + private SqlPagingQueryProviderFactoryBean factory = new SqlPagingQueryProviderFactoryBean(); + + public SqlPagingQueryProviderFactoryBeanTests() throws Exception { + factory.setSelectClause("id, name, age"); + factory.setFromClause("foo"); + factory.setWhereClause("bar = 1"); + Map sortKeys = new LinkedHashMap<>(); + sortKeys.put("id", Order.ASCENDING); + factory.setSortKeys(sortKeys); + DataSource dataSource = DatabaseTypeTestUtils.getMockDataSource(DatabaseType.HSQL.getProductName(), "100.0.0"); + factory.setDataSource(dataSource); + } + + @Test + public void testFactory() throws Exception { + PagingQueryProvider provider = factory.getObject(); + assertNotNull(provider); + } + + @Test + public void testType() throws Exception { + assertEquals(PagingQueryProvider.class, factory.getObjectType()); + } + + @Test + public void testSingleton() throws Exception { + assertEquals(true, factory.isSingleton()); + } + + @Test(expected = IllegalArgumentException.class) + public void testNoDataSource() throws Exception { + factory.setDataSource(null); + PagingQueryProvider provider = factory.getObject(); + assertNotNull(provider); + } + + @Test(expected = IllegalArgumentException.class) + public void testNoSortKey() throws Exception { + factory.setSortKeys(null); + PagingQueryProvider provider = factory.getObject(); + assertNotNull(provider); + } + + @Test + public void testWhereClause() throws Exception { + factory.setWhereClause("x=y"); + PagingQueryProvider provider = factory.getObject(); + String query = provider.generateFirstPageQuery(100); + assertTrue("Wrong query: " + query, query.contains("x=y")); + } + + @Test + public void testAscending() throws Exception { + PagingQueryProvider provider = factory.getObject(); + String query = provider.generateFirstPageQuery(100); + assertTrue("Wrong query: " + query, query.contains("ASC")); + } + + @Test(expected = IllegalArgumentException.class) + public void testWrongDatabaseType() throws Exception { + factory.setDatabaseType("NoSuchDb"); + PagingQueryProvider provider = factory.getObject(); + assertNotNull(provider); + } + + @Test(expected = IllegalArgumentException.class) + public void testMissingMetaData() throws Exception { + factory.setDataSource(DatabaseTypeTestUtils.getMockDataSource(new MetaDataAccessException("foo"))); + PagingQueryProvider provider = factory.getObject(); + assertNotNull(provider); + } + + @Test + public void testAllDatabaseTypes() throws Exception { + for (DatabaseType type : DatabaseType.values()) { + factory.setDatabaseType(type.name()); + PagingQueryProvider provider = factory.getObject(); + assertNotNull(provider); + } + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlPagingQueryUtilsTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlPagingQueryUtilsTests.java index e8b6d9084..1cf0992ee 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlPagingQueryUtilsTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlPagingQueryUtilsTests.java @@ -34,9 +34,9 @@ import org.springframework.util.StringUtils; * @since 2.0 */ public class SqlPagingQueryUtilsTests { - + private Map sortKeys; - + @Before public void setUp() { sortKeys = new LinkedHashMap<>(); @@ -46,13 +46,13 @@ public class SqlPagingQueryUtilsTests { @Test public void testGenerateLimitSqlQuery() { AbstractSqlPagingQueryProvider qp = new TestSqlPagingQueryProvider("FOO", "BAR", sortKeys); - assertEquals("SELECT FOO FROM BAR ORDER BY ID ASC LIMIT 100", SqlPagingQueryUtils.generateLimitSqlQuery(qp, - false, "LIMIT 100")); - assertEquals("SELECT FOO FROM BAR WHERE ((ID > ?)) ORDER BY ID ASC LIMIT 100", SqlPagingQueryUtils - .generateLimitSqlQuery(qp, true, "LIMIT 100")); + assertEquals("SELECT FOO FROM BAR ORDER BY ID ASC LIMIT 100", + SqlPagingQueryUtils.generateLimitSqlQuery(qp, false, "LIMIT 100")); + assertEquals("SELECT FOO FROM BAR WHERE ((ID > ?)) ORDER BY ID ASC LIMIT 100", + SqlPagingQueryUtils.generateLimitSqlQuery(qp, true, "LIMIT 100")); qp.setWhereClause("BAZ IS NOT NULL"); - assertEquals("SELECT FOO FROM BAR WHERE BAZ IS NOT NULL ORDER BY ID ASC LIMIT 100", SqlPagingQueryUtils - .generateLimitSqlQuery(qp, false, "LIMIT 100")); + assertEquals("SELECT FOO FROM BAR WHERE BAZ IS NOT NULL ORDER BY ID ASC LIMIT 100", + SqlPagingQueryUtils.generateLimitSqlQuery(qp, false, "LIMIT 100")); assertEquals("SELECT FOO FROM BAR WHERE (BAZ IS NOT NULL) AND ((ID > ?)) ORDER BY ID ASC LIMIT 100", SqlPagingQueryUtils.generateLimitSqlQuery(qp, true, "LIMIT 100")); } @@ -60,13 +60,13 @@ public class SqlPagingQueryUtilsTests { @Test public void testGenerateTopSqlQuery() { AbstractSqlPagingQueryProvider qp = new TestSqlPagingQueryProvider("FOO", "BAR", sortKeys); - assertEquals("SELECT TOP 100 FOO FROM BAR ORDER BY ID ASC", SqlPagingQueryUtils.generateTopSqlQuery(qp, false, - "TOP 100")); - assertEquals("SELECT TOP 100 FOO FROM BAR WHERE ((ID > ?)) ORDER BY ID ASC", SqlPagingQueryUtils - .generateTopSqlQuery(qp, true, "TOP 100")); + assertEquals("SELECT TOP 100 FOO FROM BAR ORDER BY ID ASC", + SqlPagingQueryUtils.generateTopSqlQuery(qp, false, "TOP 100")); + assertEquals("SELECT TOP 100 FOO FROM BAR WHERE ((ID > ?)) ORDER BY ID ASC", + SqlPagingQueryUtils.generateTopSqlQuery(qp, true, "TOP 100")); qp.setWhereClause("BAZ IS NOT NULL"); - assertEquals("SELECT TOP 100 FOO FROM BAR WHERE BAZ IS NOT NULL ORDER BY ID ASC", SqlPagingQueryUtils - .generateTopSqlQuery(qp, false, "TOP 100")); + assertEquals("SELECT TOP 100 FOO FROM BAR WHERE BAZ IS NOT NULL ORDER BY ID ASC", + SqlPagingQueryUtils.generateTopSqlQuery(qp, false, "TOP 100")); assertEquals("SELECT TOP 100 FOO FROM BAR WHERE (BAZ IS NOT NULL) AND ((ID > ?)) ORDER BY ID ASC", SqlPagingQueryUtils.generateTopSqlQuery(qp, true, "TOP 100")); } @@ -74,15 +74,12 @@ public class SqlPagingQueryUtilsTests { @Test public void testGenerateRowNumSqlQuery() { AbstractSqlPagingQueryProvider qp = new TestSqlPagingQueryProvider("FOO", "BAR", sortKeys); - assertEquals( - "SELECT * FROM (SELECT FOO FROM BAR ORDER BY ID ASC) WHERE ROWNUMBER <= 100", + assertEquals("SELECT * FROM (SELECT FOO FROM BAR ORDER BY ID ASC) WHERE ROWNUMBER <= 100", SqlPagingQueryUtils.generateRowNumSqlQuery(qp, false, "ROWNUMBER <= 100")); - assertEquals( - "SELECT * FROM (SELECT FOO FROM BAR ORDER BY ID ASC) WHERE ROWNUMBER <= 100 AND ((ID > ?))", + assertEquals("SELECT * FROM (SELECT FOO FROM BAR ORDER BY ID ASC) WHERE ROWNUMBER <= 100 AND ((ID > ?))", SqlPagingQueryUtils.generateRowNumSqlQuery(qp, true, "ROWNUMBER <= 100")); qp.setWhereClause("BAZ IS NOT NULL"); - assertEquals( - "SELECT * FROM (SELECT FOO FROM BAR WHERE BAZ IS NOT NULL ORDER BY ID ASC) WHERE ROWNUMBER <= 100", + assertEquals("SELECT * FROM (SELECT FOO FROM BAR WHERE BAZ IS NOT NULL ORDER BY ID ASC) WHERE ROWNUMBER <= 100", SqlPagingQueryUtils.generateRowNumSqlQuery(qp, false, "ROWNUMBER <= 100")); assertEquals( "SELECT * FROM (SELECT FOO FROM BAR WHERE BAZ IS NOT NULL ORDER BY ID ASC) WHERE ROWNUMBER <= 100 AND ((ID > ?))", @@ -101,13 +98,13 @@ public class SqlPagingQueryUtilsTests { public void testGenerateTopSqlQueryDescending() { sortKeys.put("ID", Order.DESCENDING); AbstractSqlPagingQueryProvider qp = new TestSqlPagingQueryProvider("FOO", "BAR", sortKeys); - assertEquals("SELECT TOP 100 FOO FROM BAR ORDER BY ID DESC", SqlPagingQueryUtils.generateTopSqlQuery(qp, false, - "TOP 100")); - assertEquals("SELECT TOP 100 FOO FROM BAR WHERE ((ID < ?)) ORDER BY ID DESC", SqlPagingQueryUtils - .generateTopSqlQuery(qp, true, "TOP 100")); + assertEquals("SELECT TOP 100 FOO FROM BAR ORDER BY ID DESC", + SqlPagingQueryUtils.generateTopSqlQuery(qp, false, "TOP 100")); + assertEquals("SELECT TOP 100 FOO FROM BAR WHERE ((ID < ?)) ORDER BY ID DESC", + SqlPagingQueryUtils.generateTopSqlQuery(qp, true, "TOP 100")); qp.setWhereClause("BAZ IS NOT NULL"); - assertEquals("SELECT TOP 100 FOO FROM BAR WHERE BAZ IS NOT NULL ORDER BY ID DESC", SqlPagingQueryUtils - .generateTopSqlQuery(qp, false, "TOP 100")); + assertEquals("SELECT TOP 100 FOO FROM BAR WHERE BAZ IS NOT NULL ORDER BY ID DESC", + SqlPagingQueryUtils.generateTopSqlQuery(qp, false, "TOP 100")); assertEquals("SELECT TOP 100 FOO FROM BAR WHERE (BAZ IS NOT NULL) AND ((ID < ?)) ORDER BY ID DESC", SqlPagingQueryUtils.generateTopSqlQuery(qp, true, "TOP 100")); } @@ -116,11 +113,9 @@ public class SqlPagingQueryUtilsTests { public void testGenerateRowNumSqlQueryDescending() { sortKeys.put("ID", Order.DESCENDING); AbstractSqlPagingQueryProvider qp = new TestSqlPagingQueryProvider("FOO", "BAR", sortKeys); - assertEquals( - "SELECT * FROM (SELECT FOO FROM BAR ORDER BY ID DESC) WHERE ROWNUMBER <= 100", + assertEquals("SELECT * FROM (SELECT FOO FROM BAR ORDER BY ID DESC) WHERE ROWNUMBER <= 100", SqlPagingQueryUtils.generateRowNumSqlQuery(qp, false, "ROWNUMBER <= 100")); - assertEquals( - "SELECT * FROM (SELECT FOO FROM BAR ORDER BY ID DESC) WHERE ROWNUMBER <= 100 AND ((ID < ?))", + assertEquals("SELECT * FROM (SELECT FOO FROM BAR ORDER BY ID DESC) WHERE ROWNUMBER <= 100 AND ((ID < ?))", SqlPagingQueryUtils.generateRowNumSqlQuery(qp, true, "ROWNUMBER <= 100")); qp.setWhereClause("BAZ IS NOT NULL"); assertEquals( @@ -134,8 +129,8 @@ public class SqlPagingQueryUtilsTests { @Test public void testGenerateLimitJumpToQuery() { AbstractSqlPagingQueryProvider qp = new TestSqlPagingQueryProvider("FOO", "BAR", sortKeys); - assertEquals("SELECT ID FROM BAR ORDER BY ID ASC LIMIT 100, 1", SqlPagingQueryUtils - .generateLimitJumpToQuery(qp, "LIMIT 100, 1")); + assertEquals("SELECT ID FROM BAR ORDER BY ID ASC LIMIT 100, 1", + SqlPagingQueryUtils.generateLimitJumpToQuery(qp, "LIMIT 100, 1")); qp.setWhereClause("BAZ IS NOT NULL"); assertEquals("SELECT ID FROM BAR WHERE BAZ IS NOT NULL ORDER BY ID ASC LIMIT 100, 1", SqlPagingQueryUtils.generateLimitJumpToQuery(qp, "LIMIT 100, 1")); @@ -144,8 +139,8 @@ public class SqlPagingQueryUtilsTests { @Test public void testGenerateTopJumpToQuery() { AbstractSqlPagingQueryProvider qp = new TestSqlPagingQueryProvider("FOO", "BAR", sortKeys); - assertEquals("SELECT TOP 100, 1 ID FROM BAR ORDER BY ID ASC", SqlPagingQueryUtils - .generateTopJumpToQuery(qp, "TOP 100, 1")); + assertEquals("SELECT TOP 100, 1 ID FROM BAR ORDER BY ID ASC", + SqlPagingQueryUtils.generateTopJumpToQuery(qp, "TOP 100, 1")); qp.setWhereClause("BAZ IS NOT NULL"); assertEquals("SELECT TOP 100, 1 ID FROM BAR WHERE BAZ IS NOT NULL ORDER BY ID ASC", SqlPagingQueryUtils.generateTopJumpToQuery(qp, "TOP 100, 1")); @@ -183,17 +178,17 @@ public class SqlPagingQueryUtilsTests { setSortKeys(sortKeys); } - @Override + @Override public String generateFirstPageQuery(int pageSize) { return null; } - @Override + @Override public String generateRemainingPagesQuery(int pageSize) { return null; } - @Override + @Override public String generateJumpToItemQuery(int itemIndex, int pageSize) { return null; } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlServerPagingQueryProviderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlServerPagingQueryProviderTests.java index f18dcac8e..8267490bc 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlServerPagingQueryProviderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlServerPagingQueryProviderTests.java @@ -37,7 +37,7 @@ public class SqlServerPagingQueryProviderTests extends AbstractSqlPagingQueryPro assertEquals(sql, s); } - @Test + @Test @Override public void testGenerateRemainingPagesQuery() { String sql = "SELECT TOP 100 id, name, age FROM foo WHERE (bar = 1) AND ((id > ?)) ORDER BY id ASC"; @@ -45,7 +45,7 @@ public class SqlServerPagingQueryProviderTests extends AbstractSqlPagingQueryPro assertEquals(sql, s); } - @Test + @Test @Override public void testGenerateJumpToItemQuery() { String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 100 ORDER BY id ASC"; @@ -53,7 +53,7 @@ public class SqlServerPagingQueryProviderTests extends AbstractSqlPagingQueryPro assertEquals(sql, s); } - @Test + @Test @Override public void testGenerateJumpToItemQueryForFirstPage() { String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 1 ORDER BY id ASC"; @@ -116,4 +116,5 @@ public class SqlServerPagingQueryProviderTests extends AbstractSqlPagingQueryPro public String getJumpToItemQueryForFirstPageWithMultipleSortKeys() { return "SELECT name, id FROM ( SELECT name, id, ROW_NUMBER() OVER ( ORDER BY name ASC, id DESC) AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 1 ORDER BY name ASC, id DESC"; } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlServerSequenceMaxValueIncrementerTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlServerSequenceMaxValueIncrementerTests.java index c6e23939e..0f271397c 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlServerSequenceMaxValueIncrementerTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlServerSequenceMaxValueIncrementerTests.java @@ -31,20 +31,21 @@ import static org.junit.Assert.assertEquals; @RunWith(MockitoJUnitRunner.class) public class SqlServerSequenceMaxValueIncrementerTests { - @Mock - private DataSource dataSource; + @Mock + private DataSource dataSource; - private SqlServerSequenceMaxValueIncrementer incrementer; + private SqlServerSequenceMaxValueIncrementer incrementer; - @Test - public void testGetSequenceQuery() { - // given - this.incrementer = new SqlServerSequenceMaxValueIncrementer(this.dataSource, "BATCH_JOB_SEQ"); + @Test + public void testGetSequenceQuery() { + // given + this.incrementer = new SqlServerSequenceMaxValueIncrementer(this.dataSource, "BATCH_JOB_SEQ"); - // when - String sequenceQuery = this.incrementer.getSequenceQuery(); + // when + String sequenceQuery = this.incrementer.getSequenceQuery(); + + // then + Assert.assertEquals("select next value for BATCH_JOB_SEQ", sequenceQuery); + } - // then - Assert.assertEquals("select next value for BATCH_JOB_SEQ", sequenceQuery); - } } \ No newline at end of file diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlWindowingPagingQueryProviderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlWindowingPagingQueryProviderTests.java index 06e504d1e..a110b5695 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlWindowingPagingQueryProviderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlWindowingPagingQueryProviderTests.java @@ -1,138 +1,139 @@ -/* - * Copyright 2006-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.database.support; - -import org.junit.Assert; -import org.junit.Test; -import org.springframework.batch.item.database.Order; - -import java.util.HashMap; -import java.util.Map; - -import static org.junit.Assert.assertEquals; - -/** - * @author Thomas Risberg - * @author Michael Minella - */ -public class SqlWindowingPagingQueryProviderTests extends AbstractSqlPagingQueryProviderTests { - - public SqlWindowingPagingQueryProviderTests() { - pagingQueryProvider = new SqlWindowingPagingQueryProvider(); - } - - @Test - @Override - public void testGenerateFirstPageQuery() { - String sql = "SELECT * FROM ( SELECT *, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100 ORDER BY id ASC"; - String s = pagingQueryProvider.generateFirstPageQuery(pageSize); - assertEquals("", sql, s); - } - - @Test - @Override - public void testGenerateRemainingPagesQuery() { - String sql = "SELECT * FROM ( SELECT *, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100 AND ((id > ?)) ORDER BY id ASC"; - String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); - assertEquals("", sql, s); - } - - @Test - @Override - public void testGenerateJumpToItemQuery() { - String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 100 ORDER BY id ASC"; - String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); - assertEquals("", sql, s); - } - - @Test - @Override - public void testGenerateJumpToItemQueryForFirstPage() { - String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 1 ORDER BY id ASC"; - String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); - Assert.assertEquals("", sql, s); - } - - @Test - @Override - public void testGenerateFirstPageQueryWithGroupBy() { - pagingQueryProvider.setGroupClause("dep"); - String sql = "SELECT * FROM ( SELECT *, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1 GROUP BY dep) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100 ORDER BY id ASC"; - String s = pagingQueryProvider.generateFirstPageQuery(pageSize); - assertEquals(sql, s); - } - - @Test - @Override - public void testGenerateRemainingPagesQueryWithGroupBy() { - pagingQueryProvider.setGroupClause("dep"); - String sql = "SELECT * FROM ( SELECT *, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1 GROUP BY dep) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100 AND ((id > ?)) ORDER BY id ASC"; - String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); - assertEquals(sql, s); - } - - @Test - @Override - public void testGenerateJumpToItemQueryWithGroupBy() { - pagingQueryProvider.setGroupClause("dep"); - String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1 GROUP BY dep) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 100 ORDER BY id ASC"; - String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); - assertEquals(sql, s); - } - - @Test - @Override - public void testGenerateJumpToItemQueryForFirstPageWithGroupBy() { - pagingQueryProvider.setGroupClause("dep"); - String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1 GROUP BY dep) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 1 ORDER BY id ASC"; - String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); - assertEquals(sql, s); - } - - @Test - public void testGenerateJumpToItemQueryForTableQualifierReplacement() { - pagingQueryProvider.setFromClause("foo_e E, foo_i I"); - pagingQueryProvider.setWhereClause("E.id=I.id"); - - Map sortKeys = new HashMap<>(); - sortKeys.put("E.id", Order.DESCENDING); - pagingQueryProvider.setSortKeys(sortKeys); - - String sql="SELECT TMP_SUB.id FROM ( SELECT E.id, ROW_NUMBER() OVER ( ORDER BY id DESC) AS ROW_NUMBER FROM foo_e E, foo_i I WHERE E.id=I.id) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 1 ORDER BY TMP_SUB.id DESC"; - String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); - assertEquals(sql, s); - } - - @Override - public String getFirstPageSqlWithMultipleSortKeys() { - return "SELECT * FROM ( SELECT *, ROW_NUMBER() OVER ( ORDER BY name ASC, id DESC) AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100 ORDER BY name ASC, id DESC"; - } - - @Override - public String getRemainingSqlWithMultipleSortKeys() { - return "SELECT * FROM ( SELECT *, ROW_NUMBER() OVER ( ORDER BY name ASC, id DESC) AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100 AND ((name > ?) OR (name = ? AND id < ?)) ORDER BY name ASC, id DESC"; - } - - @Override - public String getJumpToItemQueryWithMultipleSortKeys() { - return "SELECT name, id FROM ( SELECT name, id, ROW_NUMBER() OVER ( ORDER BY name ASC, id DESC) AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 100 ORDER BY name ASC, id DESC"; - } - - @Override - public String getJumpToItemQueryForFirstPageWithMultipleSortKeys() { - return "SELECT name, id FROM ( SELECT name, id, ROW_NUMBER() OVER ( ORDER BY name ASC, id DESC) AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 1 ORDER BY name ASC, id DESC"; - } -} +/* + * Copyright 2006-2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item.database.support; + +import org.junit.Assert; +import org.junit.Test; +import org.springframework.batch.item.database.Order; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; + +/** + * @author Thomas Risberg + * @author Michael Minella + */ +public class SqlWindowingPagingQueryProviderTests extends AbstractSqlPagingQueryProviderTests { + + public SqlWindowingPagingQueryProviderTests() { + pagingQueryProvider = new SqlWindowingPagingQueryProvider(); + } + + @Test + @Override + public void testGenerateFirstPageQuery() { + String sql = "SELECT * FROM ( SELECT *, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100 ORDER BY id ASC"; + String s = pagingQueryProvider.generateFirstPageQuery(pageSize); + assertEquals("", sql, s); + } + + @Test + @Override + public void testGenerateRemainingPagesQuery() { + String sql = "SELECT * FROM ( SELECT *, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100 AND ((id > ?)) ORDER BY id ASC"; + String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); + assertEquals("", sql, s); + } + + @Test + @Override + public void testGenerateJumpToItemQuery() { + String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 100 ORDER BY id ASC"; + String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); + assertEquals("", sql, s); + } + + @Test + @Override + public void testGenerateJumpToItemQueryForFirstPage() { + String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 1 ORDER BY id ASC"; + String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); + Assert.assertEquals("", sql, s); + } + + @Test + @Override + public void testGenerateFirstPageQueryWithGroupBy() { + pagingQueryProvider.setGroupClause("dep"); + String sql = "SELECT * FROM ( SELECT *, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1 GROUP BY dep) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100 ORDER BY id ASC"; + String s = pagingQueryProvider.generateFirstPageQuery(pageSize); + assertEquals(sql, s); + } + + @Test + @Override + public void testGenerateRemainingPagesQueryWithGroupBy() { + pagingQueryProvider.setGroupClause("dep"); + String sql = "SELECT * FROM ( SELECT *, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1 GROUP BY dep) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100 AND ((id > ?)) ORDER BY id ASC"; + String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); + assertEquals(sql, s); + } + + @Test + @Override + public void testGenerateJumpToItemQueryWithGroupBy() { + pagingQueryProvider.setGroupClause("dep"); + String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1 GROUP BY dep) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 100 ORDER BY id ASC"; + String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); + assertEquals(sql, s); + } + + @Test + @Override + public void testGenerateJumpToItemQueryForFirstPageWithGroupBy() { + pagingQueryProvider.setGroupClause("dep"); + String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1 GROUP BY dep) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 1 ORDER BY id ASC"; + String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); + assertEquals(sql, s); + } + + @Test + public void testGenerateJumpToItemQueryForTableQualifierReplacement() { + pagingQueryProvider.setFromClause("foo_e E, foo_i I"); + pagingQueryProvider.setWhereClause("E.id=I.id"); + + Map sortKeys = new HashMap<>(); + sortKeys.put("E.id", Order.DESCENDING); + pagingQueryProvider.setSortKeys(sortKeys); + + String sql = "SELECT TMP_SUB.id FROM ( SELECT E.id, ROW_NUMBER() OVER ( ORDER BY id DESC) AS ROW_NUMBER FROM foo_e E, foo_i I WHERE E.id=I.id) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 1 ORDER BY TMP_SUB.id DESC"; + String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); + assertEquals(sql, s); + } + + @Override + public String getFirstPageSqlWithMultipleSortKeys() { + return "SELECT * FROM ( SELECT *, ROW_NUMBER() OVER ( ORDER BY name ASC, id DESC) AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100 ORDER BY name ASC, id DESC"; + } + + @Override + public String getRemainingSqlWithMultipleSortKeys() { + return "SELECT * FROM ( SELECT *, ROW_NUMBER() OVER ( ORDER BY name ASC, id DESC) AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER <= 100 AND ((name > ?) OR (name = ? AND id < ?)) ORDER BY name ASC, id DESC"; + } + + @Override + public String getJumpToItemQueryWithMultipleSortKeys() { + return "SELECT name, id FROM ( SELECT name, id, ROW_NUMBER() OVER ( ORDER BY name ASC, id DESC) AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 100 ORDER BY name ASC, id DESC"; + } + + @Override + public String getJumpToItemQueryForFirstPageWithMultipleSortKeys() { + return "SELECT name, id FROM ( SELECT name, id, ROW_NUMBER() OVER ( ORDER BY name ASC, id DESC) AS ROW_NUMBER FROM foo WHERE bar = 1) AS TMP_SUB WHERE TMP_SUB.ROW_NUMBER = 1 ORDER BY name ASC, id DESC"; + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqliteMaxValueIncrementerTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqliteMaxValueIncrementerTests.java index e252fce61..758947768 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqliteMaxValueIncrementerTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqliteMaxValueIncrementerTests.java @@ -31,6 +31,7 @@ import org.springframework.test.jdbc.JdbcTestUtils; * @author Mahmoud Ben Hassine */ public class SqliteMaxValueIncrementerTests { + static String dbFile; static SimpleDriverDataSource dataSource; static JdbcTemplate template; @@ -63,4 +64,5 @@ public class SqliteMaxValueIncrementerTests { assertEquals(3, mvi.getNextKey()); assertEquals(1, JdbcTestUtils.countRowsInTable(template, "max_value")); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlitePagingQueryProviderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlitePagingQueryProviderTests.java index 7ff6becfb..6f461750e 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlitePagingQueryProviderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SqlitePagingQueryProviderTests.java @@ -38,21 +38,24 @@ public class SqlitePagingQueryProviderTests extends AbstractSqlPagingQueryProvid assertEquals(sql, s); } - @Test @Override + @Test + @Override public void testGenerateRemainingPagesQuery() { String sql = "SELECT id, name, age FROM foo WHERE (bar = 1) AND ((id > ?)) ORDER BY id ASC LIMIT 100"; String s = pagingQueryProvider.generateRemainingPagesQuery(pageSize); assertEquals(sql, s); } - @Test @Override + @Test + @Override public void testGenerateJumpToItemQuery() { String sql = "SELECT id FROM foo WHERE bar = 1 ORDER BY id ASC LIMIT 99, 1"; String s = pagingQueryProvider.generateJumpToItemQuery(145, pageSize); assertEquals(sql, s); } - @Test @Override + @Test + @Override public void testGenerateJumpToItemQueryForFirstPage() { String sql = "SELECT id FROM foo WHERE bar = 1 ORDER BY id ASC LIMIT 0, 1"; String s = pagingQueryProvider.generateJumpToItemQuery(45, pageSize); @@ -114,4 +117,5 @@ public class SqlitePagingQueryProviderTests extends AbstractSqlPagingQueryProvid public String getJumpToItemQueryForFirstPageWithMultipleSortKeys() { return "SELECT name, id FROM foo WHERE bar = 1 ORDER BY name ASC, id DESC LIMIT 0, 1"; } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SybasePagingQueryProviderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SybasePagingQueryProviderTests.java index 3600a2a2e..9c72fb293 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SybasePagingQueryProviderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/SybasePagingQueryProviderTests.java @@ -37,7 +37,7 @@ public class SybasePagingQueryProviderTests extends AbstractSqlPagingQueryProvid assertEquals("", sql, s); } - @Test + @Test @Override public void testGenerateRemainingPagesQuery() { String sql = "SELECT TOP 100 id, name, age FROM foo WHERE (bar = 1) AND ((id > ?)) ORDER BY id ASC"; @@ -45,7 +45,7 @@ public class SybasePagingQueryProviderTests extends AbstractSqlPagingQueryProvid assertEquals("", sql, s); } - @Test + @Test @Override public void testGenerateJumpToItemQuery() { String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1) WHERE ROW_NUMBER = 100 ORDER BY id ASC"; @@ -53,7 +53,7 @@ public class SybasePagingQueryProviderTests extends AbstractSqlPagingQueryProvid assertEquals("", sql, s); } - @Test + @Test @Override public void testGenerateJumpToItemQueryForFirstPage() { String sql = "SELECT id FROM ( SELECT id, ROW_NUMBER() OVER ( ORDER BY id ASC) AS ROW_NUMBER FROM foo WHERE bar = 1) WHERE ROW_NUMBER = 1 ORDER BY id ASC"; @@ -116,4 +116,5 @@ public class SybasePagingQueryProviderTests extends AbstractSqlPagingQueryProvid public String getJumpToItemQueryForFirstPageWithMultipleSortKeys() { return "SELECT name, id FROM ( SELECT name, id, ROW_NUMBER() OVER ( ORDER BY name ASC, id DESC) AS ROW_NUMBER FROM foo WHERE bar = 1) WHERE ROW_NUMBER = 1 ORDER BY name ASC, id DESC"; } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/AbstractMultiResourceItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/AbstractMultiResourceItemWriterTests.java index 08ca568b3..614cf13c0 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/AbstractMultiResourceItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/AbstractMultiResourceItemWriterTests.java @@ -24,7 +24,7 @@ import org.springframework.core.io.FileSystemResource; /** * Tests for {@link MultiResourceItemWriter}. - * + * * @see MultiResourceItemWriterFlatFileTests * @see MultiResourceItemReaderXmlTests */ @@ -68,4 +68,5 @@ public class AbstractMultiResourceItemWriterTests { } return result.toString(); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/FlatFileItemReaderCommonTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/FlatFileItemReaderCommonTests.java index 3499ab823..6f9571145 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/FlatFileItemReaderCommonTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/FlatFileItemReaderCommonTests.java @@ -1,65 +1,63 @@ -/* - * Copyright 2008-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.file; - -import org.springframework.batch.item.AbstractItemStreamItemReaderTests; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.sample.Foo; -import org.springframework.core.io.ByteArrayResource; -import org.springframework.core.io.Resource; - -/** - * Tests for {@link FlatFileItemReader}. - */ -public class FlatFileItemReaderCommonTests extends AbstractItemStreamItemReaderTests{ - - private static final String FOOS = "1 \n 2 \n 3 \n 4 \n 5 \n"; - - @Override - protected ItemReader getItemReader() throws Exception { - FlatFileItemReader tested = new FlatFileItemReader<>(); - Resource resource = new ByteArrayResource(FOOS.getBytes()); - tested.setResource(resource); - tested.setLineMapper(new LineMapper() { - @Override - public Foo mapLine(String line, int lineNumber) { - Foo foo = new Foo(); - foo.setValue(Integer.valueOf(line.trim())); - return foo; - } - }); - - tested.setSaveState(true); - tested.afterPropertiesSet(); - return tested; - } - - @Override - protected void pointToEmptyInput(ItemReader tested) throws Exception { - FlatFileItemReader reader = (FlatFileItemReader) tested; - reader.close(); - - reader.setResource(new ByteArrayResource("".getBytes())); - reader.afterPropertiesSet(); - - reader.open(new ExecutionContext()); - - } - - - -} +/* + * Copyright 2008-2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item.file; + +import org.springframework.batch.item.AbstractItemStreamItemReaderTests; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.sample.Foo; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.core.io.Resource; + +/** + * Tests for {@link FlatFileItemReader}. + */ +public class FlatFileItemReaderCommonTests extends AbstractItemStreamItemReaderTests { + + private static final String FOOS = "1 \n 2 \n 3 \n 4 \n 5 \n"; + + @Override + protected ItemReader getItemReader() throws Exception { + FlatFileItemReader tested = new FlatFileItemReader<>(); + Resource resource = new ByteArrayResource(FOOS.getBytes()); + tested.setResource(resource); + tested.setLineMapper(new LineMapper() { + @Override + public Foo mapLine(String line, int lineNumber) { + Foo foo = new Foo(); + foo.setValue(Integer.valueOf(line.trim())); + return foo; + } + }); + + tested.setSaveState(true); + tested.afterPropertiesSet(); + return tested; + } + + @Override + protected void pointToEmptyInput(ItemReader tested) throws Exception { + FlatFileItemReader reader = (FlatFileItemReader) tested; + reader.close(); + + reader.setResource(new ByteArrayResource("".getBytes())); + reader.afterPropertiesSet(); + + reader.open(new ExecutionContext()); + + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/FlatFileItemReaderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/FlatFileItemReaderTests.java index fcbbfb536..811c03460 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/FlatFileItemReaderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/FlatFileItemReaderTests.java @@ -56,9 +56,11 @@ public class FlatFileItemReaderTests { private ExecutionContext executionContext = new ExecutionContext(); - private Resource inputResource2 = getInputResource("testLine1\ntestLine2\ntestLine3\ntestLine4\ntestLine5\ntestLine6"); + private Resource inputResource2 = getInputResource( + "testLine1\ntestLine2\ntestLine3\ntestLine4\ntestLine5\ntestLine6"); - private Resource inputResource1 = getInputResource("testLine1\ntestLine2\ntestLine3\ntestLine4\ntestLine5\ntestLine6"); + private Resource inputResource1 = getInputResource( + "testLine1\ntestLine2\ntestLine3\ntestLine4\ntestLine5\ntestLine6"); @Before public void setUp() { @@ -224,7 +226,7 @@ public class FlatFileItemReaderTests { } }; reader.setResource(getInputResource("#testLine1\ntestLine2\n//testLine3\ntestLine4\n")); - reader.setComments(new String[] {"#", "//"}); + reader.setComments(new String[] { "#", "//" }); reader.setLineMapper(new PassThroughLineMapper()); reader.open(executionContext); @@ -253,7 +255,8 @@ public class FlatFileItemReaderTests { // close input reader.close(); - reader.setResource(getInputResource("header\nignoreme\ntestLine1\ntestLine2\ntestLine3\ntestLine4\ntestLine5\ntestLine6")); + reader.setResource( + getInputResource("header\nignoreme\ntestLine1\ntestLine2\ntestLine3\ntestLine4\ntestLine5\ntestLine6")); // init for restart reader.open(executionContext); @@ -444,8 +447,8 @@ public class FlatFileItemReaderTests { } /** - * Exceptions from {@link LineMapper} are wrapped as {@link FlatFileParseException} containing contextual info about - * the problematic line and its line number. + * Exceptions from {@link LineMapper} are wrapped as {@link FlatFileParseException} + * containing contextual info about the problematic line and its line number. */ @Test public void testMappingExceptionWrapping() throws Exception { @@ -560,6 +563,7 @@ public class FlatFileItemReaderTests { public InputStream getInputStream() throws IOException { return null; } + } private static class Item implements ItemCountAware { @@ -592,7 +596,7 @@ public class FlatFileItemReaderTests { } - private static final class ItemLineMapper implements LineMapper { + private static final class ItemLineMapper implements LineMapper { @Override public Item mapLine(String line, int lineNumber) throws Exception { @@ -600,4 +604,5 @@ public class FlatFileItemReaderTests { } } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/FlatFileItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/FlatFileItemWriterTests.java index 24231672d..152c10725 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/FlatFileItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/FlatFileItemWriterTests.java @@ -54,8 +54,9 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; /** - * Tests of regular usage for {@link FlatFileItemWriter} Exception cases will be in separate TestCase classes with - * different setUp and tearDown methods + * Tests of regular usage for {@link FlatFileItemWriter} Exception cases will be in + * separate TestCase classes with different setUp and tearDown + * methods * * @author Robert Kasanicky * @author Dave Syer @@ -78,7 +79,8 @@ public class FlatFileItemWriterTests { private ExecutionContext executionContext; /** - * Create temporary output file, define mock behaviour, set dependencies and initialize the object under test + * Create temporary output file, define mock behaviour, set dependencies and + * initialize the object under test */ @Before public void setUp() throws Exception { @@ -107,16 +109,18 @@ public class FlatFileItemWriterTests { } /* - * Read a line from the output file, if the reader has not been created, recreate. This method is only necessary - * because running the tests in a UNIX environment locks the file if it's open for writing. + * Read a line from the output file, if the reader has not been created, recreate. + * This method is only necessary because running the tests in a UNIX environment locks + * the file if it's open for writing. */ private String readLine() throws IOException { return readLine("UTF-8"); } /* - * Read a line from the output file, if the reader has not been created, recreate. This method is only necessary - * because running the tests in a UNIX environment locks the file if it's open for writing. + * Read a line from the output file, if the reader has not been created, recreate. + * This method is only necessary because running the tests in a UNIX environment locks + * the file if it's open for writing. */ private String readLine(String encoding) throws IOException { @@ -213,7 +217,6 @@ public class FlatFileItemWriterTests { /** * Regular usage of write(String) method - * * @throws Exception */ @Test @@ -239,7 +242,6 @@ public class FlatFileItemWriterTests { /** * Regular usage of write(String) method - * * @throws Exception */ @Test @@ -260,7 +262,6 @@ public class FlatFileItemWriterTests { /** * Regular usage of write(String) method - * * @throws Exception */ @Test @@ -279,7 +280,6 @@ public class FlatFileItemWriterTests { /** * Regular usage of write(String[], LineDescriptor) method - * * @throws Exception */ @Test @@ -835,12 +835,14 @@ public class FlatFileItemWriterTests { @Test /** - * If append=true a new output file should still be created on the first run (not restart). + * If append=true a new output file should still be created on the first run (not + * restart). */ public void testAppendToNotYetExistingFile() throws Exception { WritableResource toBeCreated = new FileSystemResource("target/FlatFileItemWriterTests.out"); - outputFile = toBeCreated.getFile(); //enable easy content reading and auto-delete the file + outputFile = toBeCreated.getFile(); // enable easy content reading and auto-delete + // the file assertFalse("output file does not exist yet", toBeCreated.exists()); writer.setResource(toBeCreated); @@ -854,4 +856,5 @@ public class FlatFileItemWriterTests { writer.close(); assertEquals("test1", readLine()); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/FlatFileParseExceptionTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/FlatFileParseExceptionTests.java index 4d934defa..eb8ca0f0b 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/FlatFileParseExceptionTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/FlatFileParseExceptionTests.java @@ -18,24 +18,23 @@ package org.springframework.batch.item.file; import org.springframework.batch.support.AbstractExceptionTests; - public class FlatFileParseExceptionTests extends AbstractExceptionTests { - @Override + @Override public Exception getException(String msg) throws Exception { return new FlatFileParseException(msg, "bar"); } - @Override + @Override public Exception getException(String msg, Throwable t) throws Exception { return new FlatFileParseException(msg, t, "bar", 100); } - + public void testMessageInputLineCount() throws Exception { FlatFileParseException exception = new FlatFileParseException("foo", "bar", 100); assertEquals("foo", exception.getMessage()); assertEquals("bar", exception.getInput()); assertEquals(100, exception.getLineNumber()); } - + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/MultiResourceItemReaderFlatFileTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/MultiResourceItemReaderFlatFileTests.java index 70f5124e0..bdf721d70 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/MultiResourceItemReaderFlatFileTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/MultiResourceItemReaderFlatFileTests.java @@ -1,80 +1,78 @@ -/* - * Copyright 2008-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.file; - -import java.util.Comparator; - -import org.junit.runners.JUnit4; -import org.junit.runner.RunWith; -import org.springframework.batch.item.AbstractItemStreamItemReaderTests; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.sample.Foo; -import org.springframework.core.io.ByteArrayResource; -import org.springframework.core.io.Resource; - -@RunWith(JUnit4.class) -public class MultiResourceItemReaderFlatFileTests extends - AbstractItemStreamItemReaderTests { - - @Override - protected ItemReader getItemReader() throws Exception { - - MultiResourceItemReader multiReader = new MultiResourceItemReader<>(); - FlatFileItemReader fileReader = new FlatFileItemReader<>(); - - fileReader.setLineMapper(new LineMapper() { - - @Override - public Foo mapLine(String line, int lineNumber) throws Exception { - Foo foo = new Foo(); - foo.setValue(Integer.valueOf(line)); - return foo; - } - - }); - fileReader.setSaveState(true); - - multiReader.setDelegate(fileReader); - - Resource r1 = new ByteArrayResource("1\n2\n".getBytes()); - Resource r2 = new ByteArrayResource("".getBytes()); - Resource r3 = new ByteArrayResource("3\n".getBytes()); - Resource r4 = new ByteArrayResource("4\n5\n".getBytes()); - - multiReader.setResources(new Resource[] { r1, r2, r3, r4 }); - multiReader.setSaveState(true); - multiReader.setComparator(new Comparator() { - @Override - public int compare(Resource arg0, Resource arg1) { - return 0; // preserve original ordering - } - - }); - - return multiReader; - } - - @Override - protected void pointToEmptyInput(ItemReader tested) throws Exception { - MultiResourceItemReader multiReader = (MultiResourceItemReader) tested; - multiReader.close(); - multiReader.setResources(new Resource[] { new ByteArrayResource("" - .getBytes()) }); - multiReader.open(new ExecutionContext()); - } - -} +/* + * Copyright 2008-2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item.file; + +import java.util.Comparator; + +import org.junit.runners.JUnit4; +import org.junit.runner.RunWith; +import org.springframework.batch.item.AbstractItemStreamItemReaderTests; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.sample.Foo; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.core.io.Resource; + +@RunWith(JUnit4.class) +public class MultiResourceItemReaderFlatFileTests extends AbstractItemStreamItemReaderTests { + + @Override + protected ItemReader getItemReader() throws Exception { + + MultiResourceItemReader multiReader = new MultiResourceItemReader<>(); + FlatFileItemReader fileReader = new FlatFileItemReader<>(); + + fileReader.setLineMapper(new LineMapper() { + + @Override + public Foo mapLine(String line, int lineNumber) throws Exception { + Foo foo = new Foo(); + foo.setValue(Integer.valueOf(line)); + return foo; + } + + }); + fileReader.setSaveState(true); + + multiReader.setDelegate(fileReader); + + Resource r1 = new ByteArrayResource("1\n2\n".getBytes()); + Resource r2 = new ByteArrayResource("".getBytes()); + Resource r3 = new ByteArrayResource("3\n".getBytes()); + Resource r4 = new ByteArrayResource("4\n5\n".getBytes()); + + multiReader.setResources(new Resource[] { r1, r2, r3, r4 }); + multiReader.setSaveState(true); + multiReader.setComparator(new Comparator() { + @Override + public int compare(Resource arg0, Resource arg1) { + return 0; // preserve original ordering + } + + }); + + return multiReader; + } + + @Override + protected void pointToEmptyInput(ItemReader tested) throws Exception { + MultiResourceItemReader multiReader = (MultiResourceItemReader) tested; + multiReader.close(); + multiReader.setResources(new Resource[] { new ByteArrayResource("".getBytes()) }); + multiReader.open(new ExecutionContext()); + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/MultiResourceItemReaderIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/MultiResourceItemReaderIntegrationTests.java index e7831a960..145db1766 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/MultiResourceItemReaderIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/MultiResourceItemReaderIntegrationTests.java @@ -1,476 +1,481 @@ -/* - * Copyright 2008-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.file; - -import static org.junit.Assert.*; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Comparator; - -import org.junit.Before; -import org.junit.Test; - -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemStreamException; -import org.springframework.batch.item.NonTransientResourceException; -import org.springframework.batch.item.ParseException; -import org.springframework.batch.item.UnexpectedInputException; -import org.springframework.batch.item.file.mapping.PassThroughLineMapper; -import org.springframework.core.io.AbstractResource; -import org.springframework.core.io.ByteArrayResource; -import org.springframework.core.io.FileSystemResource; -import org.springframework.core.io.Resource; -import org.springframework.lang.Nullable; -import org.springframework.test.util.ReflectionTestUtils; - -/** - * Tests for {@link MultiResourceItemReader}. - */ -public class MultiResourceItemReaderIntegrationTests { - - private MultiResourceItemReader tested = new MultiResourceItemReader<>(); - - private FlatFileItemReader itemReader = new FlatFileItemReader<>(); - - private ExecutionContext ctx = new ExecutionContext(); - - // test input spans several resources - private Resource r1 = new ByteArrayResource("1\n2\n3\n".getBytes()); - - private Resource r2 = new ByteArrayResource("4\n5\n".getBytes()); - - private Resource r3 = new ByteArrayResource("".getBytes()); - - private Resource r4 = new ByteArrayResource("6\n".getBytes()); - - private Resource r5 = new ByteArrayResource("7\n8\n".getBytes()); - - /** - * Setup the tested reader to read from the test resources. - */ - @Before - public void setUp() throws Exception { - - itemReader.setLineMapper(new PassThroughLineMapper()); - - tested.setDelegate(itemReader); - tested.setComparator(new Comparator() { - @Override - public int compare(Resource o1, Resource o2) { - return 0; // do not change ordering - } - }); - tested.setResources(new Resource[] { r1, r2, r3, r4, r5 }); - } - - /** - * Read input from start to end. - */ - @Test - public void testRead() throws Exception { - - tested.open(ctx); - - assertEquals("1", tested.read()); - assertEquals("2", tested.read()); - assertEquals("3", tested.read()); - assertEquals("4", tested.read()); - assertEquals("5", tested.read()); - assertEquals("6", tested.read()); - assertEquals("7", tested.read()); - assertEquals("8", tested.read()); - assertEquals(null, tested.read()); - - tested.close(); - } - - @Test - public void testRestartWhenStateNotSaved() throws Exception { - - tested.setSaveState(false); - - tested.open(ctx); - - assertEquals("1", tested.read()); - - tested.update(ctx); - - assertEquals("2", tested.read()); - assertEquals("3", tested.read()); - - tested.close(); - - tested.open(ctx); - - assertEquals("1", tested.read()); - } - - /** - * - * Read items with a couple of rollbacks, requiring to jump back to items from previous resources. - */ - @Test - public void testRestartAcrossResourceBoundary() throws Exception { - - tested.open(ctx); - - assertEquals("1", tested.read()); - - tested.update(ctx); - - assertEquals("2", tested.read()); - assertEquals("3", tested.read()); - - tested.close(); - - tested.open(ctx); - - assertEquals("2", tested.read()); - assertEquals("3", tested.read()); - assertEquals("4", tested.read()); - - tested.close(); - - tested.open(ctx); - - assertEquals("2", tested.read()); - assertEquals("3", tested.read()); - assertEquals("4", tested.read()); - assertEquals("5", tested.read()); - - tested.update(ctx); - - assertEquals("6", tested.read()); - assertEquals("7", tested.read()); - - tested.close(); - - tested.open(ctx); - - assertEquals("6", tested.read()); - assertEquals("7", tested.read()); - - assertEquals("8", tested.read()); - assertEquals(null, tested.read()); - - tested.close(); - } - - /** - * Restore from saved state. - */ - @Test - public void testRestart() throws Exception { - - tested.open(ctx); - - assertEquals("1", tested.read()); - assertEquals("2", tested.read()); - assertEquals("3", tested.read()); - assertEquals("4", tested.read()); - - tested.update(ctx); - - assertEquals("5", tested.read()); - assertEquals("6", tested.read()); - - tested.close(); - - tested.open(ctx); - - assertEquals("5", tested.read()); - assertEquals("6", tested.read()); - assertEquals("7", tested.read()); - assertEquals("8", tested.read()); - assertEquals(null, tested.read()); - } - - /** - * Resources are ordered according to injected comparator. - */ - @Test - public void testResourceOrderingWithCustomComparator() { - - Resource r1 = new ByteArrayResource("".getBytes(), "b"); - Resource r2 = new ByteArrayResource("".getBytes(), "a"); - Resource r3 = new ByteArrayResource("".getBytes(), "c"); - - Resource[] resources = new Resource[] { r1, r2, r3 }; - - Comparator comp = new Comparator() { - - /** - * Reversed ordering by filename. - */ - @Override - public int compare(Resource o1, Resource o2) { - Resource r1 = o1; - Resource r2 = o2; - return -r1.getDescription().compareTo(r2.getDescription()); - } - - }; - - tested.setComparator(comp); - tested.setResources(resources); - tested.open(ctx); - - resources = (Resource[]) ReflectionTestUtils.getField(tested, "resources"); - - assertSame(r3, resources[0]); - assertSame(r1, resources[1]); - assertSame(r2, resources[2]); - } - - /** - * Empty resource list is OK. - */ - @Test - public void testNoResourcesFound() throws Exception { - tested.setResources(new Resource[] {}); - tested.open(new ExecutionContext()); - - assertNull(tested.read()); - - tested.close(); - } - - /** - * Missing resource is OK. - */ - @Test - public void testNonExistentResources() throws Exception { - tested.setResources(new Resource[] { new FileSystemResource("no/such/file.txt") }); - itemReader.setStrict(false); - tested.open(new ExecutionContext()); - - assertNull(tested.read()); - - tested.close(); - } - - /** - * Test {@link org.springframework.batch.item.ItemStream} lifecycle symmetry - */ - @Test - public void testNonExistentResourcesItemStreamLifecycle() throws Exception { - ItemStreamReaderImpl delegate = new ItemStreamReaderImpl(); - tested.setDelegate(delegate); - tested.setResources(new Resource[] { }); - itemReader.setStrict(false); - tested.open(new ExecutionContext()); - - assertNull(tested.read()); - assertFalse(delegate.openCalled); - assertFalse(delegate.closeCalled); - assertFalse(delegate.updateCalled); - - tested.close(); - } - - /** - * Directory resource behaves as if it was empty. - */ - @Test - public void testDirectoryResources() throws Exception { - FileSystemResource resource = new FileSystemResource("target/data"); - resource.getFile().mkdirs(); - assertTrue(resource.getFile().isDirectory()); - tested.setResources(new Resource[] { resource }); - itemReader.setStrict(false); - tested.open(new ExecutionContext()); - - assertNull(tested.read()); - - tested.close(); - } - - @Test - public void testMiddleResourceThrowsException() throws Exception { - - Resource badResource = new AbstractResource() { - - @Override - public InputStream getInputStream() throws IOException { - throw new RuntimeException(); - } - - @Override - public String getDescription() { - return null; - } - }; - - tested.setResources(new Resource[] { r1, badResource, r3, r4, r5 }); - - tested.open(ctx); - - assertEquals("1", tested.read()); - assertEquals("2", tested.read()); - assertEquals("3", tested.read()); - try { - assertEquals("4", tested.read()); - fail(); - } - catch (ItemStreamException ex) { - // a try/catch was used to ensure the exception was thrown when reading - // the 4th item, rather than on open - } - } - - @Test - public void testFirstResourceThrowsExceptionOnRead() throws Exception { - - Resource badResource = new AbstractResource() { - - @Override - public InputStream getInputStream() throws IOException { - throw new RuntimeException(); - } - - @Override - public String getDescription() { - return null; - } - }; - - tested.setResources(new Resource[] { badResource, r2, r3, r4, r5 }); - - tested.open(ctx); - - try { - assertEquals("1", tested.read()); - fail(); - } - catch (ItemStreamException ex) { - // a try/catch was used to ensure the exception was thrown when reading - // the 1st item, rather than on open - } - } - - @Test - public void testBadIOInput() throws Exception { - - Resource badResource = new AbstractResource() { - - @Override - public boolean exists() { - // Looks good ... - return true; - } - - @Override - public InputStream getInputStream() throws IOException { - // ... but fails during read - throw new RuntimeException(); - } - - @Override - public String getDescription() { - return null; - } - }; - - tested.setResources(new Resource[] { badResource, r2, r3, r4, r5 }); - - tested.open(ctx); - - try { - assertEquals("1", tested.read()); - fail(); - } - catch (ItemStreamException ex) { - // expected - } - - // Now check the next read gets the next resource - assertEquals("4", tested.read()); - - } - - /** - * No resources to read should result in error in strict mode. - */ - @Test(expected = IllegalStateException.class) - public void testStrictModeEnabled() throws Exception { - tested.setResources(new Resource[] {}); - tested.setStrict(true); - - tested.open(ctx); - } - - /** - * No resources to read is OK when strict=false. - */ - @Test - public void testStrictModeDisabled() throws Exception { - tested.setResources(new Resource[] {}); - tested.setStrict(false); - - tested.open(ctx); - assertTrue("empty input doesn't cause an error", true); - } - - /** - * E.g. when using the reader in the processing phase reading might not have been attempted at all before the job - * crashed (BATCH-1798). - */ - @Test - public void testRestartAfterFailureWithoutRead() throws Exception { - - // save reader state without calling read - tested.open(ctx); - tested.update(ctx); - tested.close(); - - // restart should work OK - tested.open(ctx); - assertEquals("1", tested.read()); - } - - private static class ItemStreamReaderImpl implements ResourceAwareItemReaderItemStream { - - private boolean openCalled = false; - private boolean updateCalled = false; - private boolean closeCalled = false; - - @Nullable - @Override - public String read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException { - return null; - } - - @Override - public void open(ExecutionContext executionContext) throws ItemStreamException { - openCalled = true; - } - - @Override - public void update(ExecutionContext executionContext) throws ItemStreamException { - updateCalled = true; - } - - @Override - public void close() throws ItemStreamException { - closeCalled = true; - } - - @Override - public void setResource(Resource resource) { - } - } -} +/* + * Copyright 2008-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item.file; + +import static org.junit.Assert.*; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Comparator; + +import org.junit.Before; +import org.junit.Test; + +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ItemStreamException; +import org.springframework.batch.item.NonTransientResourceException; +import org.springframework.batch.item.ParseException; +import org.springframework.batch.item.UnexpectedInputException; +import org.springframework.batch.item.file.mapping.PassThroughLineMapper; +import org.springframework.core.io.AbstractResource; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.core.io.FileSystemResource; +import org.springframework.core.io.Resource; +import org.springframework.lang.Nullable; +import org.springframework.test.util.ReflectionTestUtils; + +/** + * Tests for {@link MultiResourceItemReader}. + */ +public class MultiResourceItemReaderIntegrationTests { + + private MultiResourceItemReader tested = new MultiResourceItemReader<>(); + + private FlatFileItemReader itemReader = new FlatFileItemReader<>(); + + private ExecutionContext ctx = new ExecutionContext(); + + // test input spans several resources + private Resource r1 = new ByteArrayResource("1\n2\n3\n".getBytes()); + + private Resource r2 = new ByteArrayResource("4\n5\n".getBytes()); + + private Resource r3 = new ByteArrayResource("".getBytes()); + + private Resource r4 = new ByteArrayResource("6\n".getBytes()); + + private Resource r5 = new ByteArrayResource("7\n8\n".getBytes()); + + /** + * Setup the tested reader to read from the test resources. + */ + @Before + public void setUp() throws Exception { + + itemReader.setLineMapper(new PassThroughLineMapper()); + + tested.setDelegate(itemReader); + tested.setComparator(new Comparator() { + @Override + public int compare(Resource o1, Resource o2) { + return 0; // do not change ordering + } + }); + tested.setResources(new Resource[] { r1, r2, r3, r4, r5 }); + } + + /** + * Read input from start to end. + */ + @Test + public void testRead() throws Exception { + + tested.open(ctx); + + assertEquals("1", tested.read()); + assertEquals("2", tested.read()); + assertEquals("3", tested.read()); + assertEquals("4", tested.read()); + assertEquals("5", tested.read()); + assertEquals("6", tested.read()); + assertEquals("7", tested.read()); + assertEquals("8", tested.read()); + assertEquals(null, tested.read()); + + tested.close(); + } + + @Test + public void testRestartWhenStateNotSaved() throws Exception { + + tested.setSaveState(false); + + tested.open(ctx); + + assertEquals("1", tested.read()); + + tested.update(ctx); + + assertEquals("2", tested.read()); + assertEquals("3", tested.read()); + + tested.close(); + + tested.open(ctx); + + assertEquals("1", tested.read()); + } + + /** + * + * Read items with a couple of rollbacks, requiring to jump back to items from + * previous resources. + */ + @Test + public void testRestartAcrossResourceBoundary() throws Exception { + + tested.open(ctx); + + assertEquals("1", tested.read()); + + tested.update(ctx); + + assertEquals("2", tested.read()); + assertEquals("3", tested.read()); + + tested.close(); + + tested.open(ctx); + + assertEquals("2", tested.read()); + assertEquals("3", tested.read()); + assertEquals("4", tested.read()); + + tested.close(); + + tested.open(ctx); + + assertEquals("2", tested.read()); + assertEquals("3", tested.read()); + assertEquals("4", tested.read()); + assertEquals("5", tested.read()); + + tested.update(ctx); + + assertEquals("6", tested.read()); + assertEquals("7", tested.read()); + + tested.close(); + + tested.open(ctx); + + assertEquals("6", tested.read()); + assertEquals("7", tested.read()); + + assertEquals("8", tested.read()); + assertEquals(null, tested.read()); + + tested.close(); + } + + /** + * Restore from saved state. + */ + @Test + public void testRestart() throws Exception { + + tested.open(ctx); + + assertEquals("1", tested.read()); + assertEquals("2", tested.read()); + assertEquals("3", tested.read()); + assertEquals("4", tested.read()); + + tested.update(ctx); + + assertEquals("5", tested.read()); + assertEquals("6", tested.read()); + + tested.close(); + + tested.open(ctx); + + assertEquals("5", tested.read()); + assertEquals("6", tested.read()); + assertEquals("7", tested.read()); + assertEquals("8", tested.read()); + assertEquals(null, tested.read()); + } + + /** + * Resources are ordered according to injected comparator. + */ + @Test + public void testResourceOrderingWithCustomComparator() { + + Resource r1 = new ByteArrayResource("".getBytes(), "b"); + Resource r2 = new ByteArrayResource("".getBytes(), "a"); + Resource r3 = new ByteArrayResource("".getBytes(), "c"); + + Resource[] resources = new Resource[] { r1, r2, r3 }; + + Comparator comp = new Comparator() { + + /** + * Reversed ordering by filename. + */ + @Override + public int compare(Resource o1, Resource o2) { + Resource r1 = o1; + Resource r2 = o2; + return -r1.getDescription().compareTo(r2.getDescription()); + } + + }; + + tested.setComparator(comp); + tested.setResources(resources); + tested.open(ctx); + + resources = (Resource[]) ReflectionTestUtils.getField(tested, "resources"); + + assertSame(r3, resources[0]); + assertSame(r1, resources[1]); + assertSame(r2, resources[2]); + } + + /** + * Empty resource list is OK. + */ + @Test + public void testNoResourcesFound() throws Exception { + tested.setResources(new Resource[] {}); + tested.open(new ExecutionContext()); + + assertNull(tested.read()); + + tested.close(); + } + + /** + * Missing resource is OK. + */ + @Test + public void testNonExistentResources() throws Exception { + tested.setResources(new Resource[] { new FileSystemResource("no/such/file.txt") }); + itemReader.setStrict(false); + tested.open(new ExecutionContext()); + + assertNull(tested.read()); + + tested.close(); + } + + /** + * Test {@link org.springframework.batch.item.ItemStream} lifecycle symmetry + */ + @Test + public void testNonExistentResourcesItemStreamLifecycle() throws Exception { + ItemStreamReaderImpl delegate = new ItemStreamReaderImpl(); + tested.setDelegate(delegate); + tested.setResources(new Resource[] {}); + itemReader.setStrict(false); + tested.open(new ExecutionContext()); + + assertNull(tested.read()); + assertFalse(delegate.openCalled); + assertFalse(delegate.closeCalled); + assertFalse(delegate.updateCalled); + + tested.close(); + } + + /** + * Directory resource behaves as if it was empty. + */ + @Test + public void testDirectoryResources() throws Exception { + FileSystemResource resource = new FileSystemResource("target/data"); + resource.getFile().mkdirs(); + assertTrue(resource.getFile().isDirectory()); + tested.setResources(new Resource[] { resource }); + itemReader.setStrict(false); + tested.open(new ExecutionContext()); + + assertNull(tested.read()); + + tested.close(); + } + + @Test + public void testMiddleResourceThrowsException() throws Exception { + + Resource badResource = new AbstractResource() { + + @Override + public InputStream getInputStream() throws IOException { + throw new RuntimeException(); + } + + @Override + public String getDescription() { + return null; + } + }; + + tested.setResources(new Resource[] { r1, badResource, r3, r4, r5 }); + + tested.open(ctx); + + assertEquals("1", tested.read()); + assertEquals("2", tested.read()); + assertEquals("3", tested.read()); + try { + assertEquals("4", tested.read()); + fail(); + } + catch (ItemStreamException ex) { + // a try/catch was used to ensure the exception was thrown when reading + // the 4th item, rather than on open + } + } + + @Test + public void testFirstResourceThrowsExceptionOnRead() throws Exception { + + Resource badResource = new AbstractResource() { + + @Override + public InputStream getInputStream() throws IOException { + throw new RuntimeException(); + } + + @Override + public String getDescription() { + return null; + } + }; + + tested.setResources(new Resource[] { badResource, r2, r3, r4, r5 }); + + tested.open(ctx); + + try { + assertEquals("1", tested.read()); + fail(); + } + catch (ItemStreamException ex) { + // a try/catch was used to ensure the exception was thrown when reading + // the 1st item, rather than on open + } + } + + @Test + public void testBadIOInput() throws Exception { + + Resource badResource = new AbstractResource() { + + @Override + public boolean exists() { + // Looks good ... + return true; + } + + @Override + public InputStream getInputStream() throws IOException { + // ... but fails during read + throw new RuntimeException(); + } + + @Override + public String getDescription() { + return null; + } + }; + + tested.setResources(new Resource[] { badResource, r2, r3, r4, r5 }); + + tested.open(ctx); + + try { + assertEquals("1", tested.read()); + fail(); + } + catch (ItemStreamException ex) { + // expected + } + + // Now check the next read gets the next resource + assertEquals("4", tested.read()); + + } + + /** + * No resources to read should result in error in strict mode. + */ + @Test(expected = IllegalStateException.class) + public void testStrictModeEnabled() throws Exception { + tested.setResources(new Resource[] {}); + tested.setStrict(true); + + tested.open(ctx); + } + + /** + * No resources to read is OK when strict=false. + */ + @Test + public void testStrictModeDisabled() throws Exception { + tested.setResources(new Resource[] {}); + tested.setStrict(false); + + tested.open(ctx); + assertTrue("empty input doesn't cause an error", true); + } + + /** + * E.g. when using the reader in the processing phase reading might not have been + * attempted at all before the job crashed (BATCH-1798). + */ + @Test + public void testRestartAfterFailureWithoutRead() throws Exception { + + // save reader state without calling read + tested.open(ctx); + tested.update(ctx); + tested.close(); + + // restart should work OK + tested.open(ctx); + assertEquals("1", tested.read()); + } + + private static class ItemStreamReaderImpl implements ResourceAwareItemReaderItemStream { + + private boolean openCalled = false; + + private boolean updateCalled = false; + + private boolean closeCalled = false; + + @Nullable + @Override + public String read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException { + return null; + } + + @Override + public void open(ExecutionContext executionContext) throws ItemStreamException { + openCalled = true; + } + + @Override + public void update(ExecutionContext executionContext) throws ItemStreamException { + updateCalled = true; + } + + @Override + public void close() throws ItemStreamException { + closeCalled = true; + } + + @Override + public void setResource(Resource resource) { + } + + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/MultiResourceItemReaderResourceAwareTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/MultiResourceItemReaderResourceAwareTests.java index 2aad05b34..093d1ab64 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/MultiResourceItemReaderResourceAwareTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/MultiResourceItemReaderResourceAwareTests.java @@ -1,118 +1,123 @@ -/* - * Copyright 2012-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.file; - -import org.junit.Before; -import org.junit.Test; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ResourceAware; -import org.springframework.core.io.ByteArrayResource; -import org.springframework.core.io.Resource; -import java.util.Comparator; - -import static org.junit.Assert.*; - -/** - * Tests to ensure that the current Resource is correctly being set on items that implement ResourceAware. - * Because it there are extensive tests the reader in general, this will only test ResourceAware related - * use cases. - */ -public class MultiResourceItemReaderResourceAwareTests { - - private MultiResourceItemReader tested = new MultiResourceItemReader<>(); - - private FlatFileItemReader itemReader = new FlatFileItemReader<>(); - - private ExecutionContext ctx = new ExecutionContext(); - - // test input spans several resources - private Resource r1 = new ByteArrayResource("1\n2\n3\n".getBytes()); - - private Resource r2 = new ByteArrayResource("4\n5\n".getBytes()); - - private Resource r3 = new ByteArrayResource("".getBytes()); - - private Resource r4 = new ByteArrayResource("6\n".getBytes()); - - private Resource r5 = new ByteArrayResource("7\n8\n".getBytes()); - - /** - * Setup the tested reader to read from the test resources. - */ - @Before - public void setUp() throws Exception { - - itemReader.setLineMapper(new FooLineMapper()); - - tested.setDelegate(itemReader); - tested.setComparator(new Comparator() { - @Override - public int compare(Resource o1, Resource o2) { - return 0; // do not change ordering - } - }); - tested.setResources(new Resource[] { r1, r2, r3, r4, r5 }); - } - - /** - * Read input from start to end. - */ - @Test - public void testRead() throws Exception { - - tested.open(ctx); - - assertValueAndResource(r1, "1"); - assertValueAndResource(r1, "2"); - assertValueAndResource(r1, "3"); - assertValueAndResource(r2, "4"); - assertValueAndResource(r2, "5"); - assertValueAndResource(r4, "6"); - assertValueAndResource(r5, "7"); - assertValueAndResource(r5, "8"); - assertEquals(null, tested.read()); - - tested.close(); - } - - private void assertValueAndResource(Resource expectedResource, String expectedValue) throws Exception { - Foo foo = tested.read(); - assertEquals(expectedValue, foo.value); - assertEquals(expectedResource, foo.resource); - } - - static final class FooLineMapper implements LineMapper { - @Override - public Foo mapLine(String line, int lineNumber) throws Exception { - return new Foo(line); - } - } - - static final class Foo implements ResourceAware { - - String value; - Resource resource; - - Foo(String value) { - this.value = value; - } - - @Override - public void setResource(Resource resource) { - this.resource = resource; - } - } -} +/* + * Copyright 2012-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item.file; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ResourceAware; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.core.io.Resource; +import java.util.Comparator; + +import static org.junit.Assert.*; + +/** + * Tests to ensure that the current Resource is correctly being set on items that + * implement ResourceAware. Because it there are extensive tests the reader in general, + * this will only test ResourceAware related use cases. + */ +public class MultiResourceItemReaderResourceAwareTests { + + private MultiResourceItemReader tested = new MultiResourceItemReader<>(); + + private FlatFileItemReader itemReader = new FlatFileItemReader<>(); + + private ExecutionContext ctx = new ExecutionContext(); + + // test input spans several resources + private Resource r1 = new ByteArrayResource("1\n2\n3\n".getBytes()); + + private Resource r2 = new ByteArrayResource("4\n5\n".getBytes()); + + private Resource r3 = new ByteArrayResource("".getBytes()); + + private Resource r4 = new ByteArrayResource("6\n".getBytes()); + + private Resource r5 = new ByteArrayResource("7\n8\n".getBytes()); + + /** + * Setup the tested reader to read from the test resources. + */ + @Before + public void setUp() throws Exception { + + itemReader.setLineMapper(new FooLineMapper()); + + tested.setDelegate(itemReader); + tested.setComparator(new Comparator() { + @Override + public int compare(Resource o1, Resource o2) { + return 0; // do not change ordering + } + }); + tested.setResources(new Resource[] { r1, r2, r3, r4, r5 }); + } + + /** + * Read input from start to end. + */ + @Test + public void testRead() throws Exception { + + tested.open(ctx); + + assertValueAndResource(r1, "1"); + assertValueAndResource(r1, "2"); + assertValueAndResource(r1, "3"); + assertValueAndResource(r2, "4"); + assertValueAndResource(r2, "5"); + assertValueAndResource(r4, "6"); + assertValueAndResource(r5, "7"); + assertValueAndResource(r5, "8"); + assertEquals(null, tested.read()); + + tested.close(); + } + + private void assertValueAndResource(Resource expectedResource, String expectedValue) throws Exception { + Foo foo = tested.read(); + assertEquals(expectedValue, foo.value); + assertEquals(expectedResource, foo.resource); + } + + static final class FooLineMapper implements LineMapper { + + @Override + public Foo mapLine(String line, int lineNumber) throws Exception { + return new Foo(line); + } + + } + + static final class Foo implements ResourceAware { + + String value; + + Resource resource; + + Foo(String value) { + this.value = value; + } + + @Override + public void setResource(Resource resource) { + this.resource = resource; + } + + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/MultiResourceItemReaderXmlTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/MultiResourceItemReaderXmlTests.java index 11bcd3ac6..c486e7924 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/MultiResourceItemReaderXmlTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/MultiResourceItemReaderXmlTests.java @@ -1,107 +1,105 @@ -/* - * Copyright 2008-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.file; - -import static org.junit.Assert.assertTrue; - -import java.io.IOException; -import java.util.Comparator; - -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.events.Attribute; -import javax.xml.stream.events.StartElement; -import javax.xml.transform.Source; - -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.springframework.batch.item.AbstractItemStreamItemReaderTests; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.sample.Foo; -import org.springframework.batch.item.xml.StaxEventItemReader; -import org.springframework.batch.item.xml.StaxTestUtils; -import org.springframework.core.io.ByteArrayResource; -import org.springframework.core.io.Resource; -import org.springframework.oxm.Unmarshaller; -import org.springframework.oxm.XmlMappingException; - -@RunWith(JUnit4.class) -public class MultiResourceItemReaderXmlTests extends AbstractItemStreamItemReaderTests { - - @Override - protected ItemReader getItemReader() throws Exception { - MultiResourceItemReader multiReader = new MultiResourceItemReader<>(); - - StaxEventItemReader reader = new StaxEventItemReader<>(); - - reader.setFragmentRootElementName("foo"); - reader.setUnmarshaller(new Unmarshaller() { - @Override - public Object unmarshal(Source source) throws XmlMappingException, IOException { - - - Attribute attr; - try { - XMLEventReader eventReader = StaxTestUtils.getXmlEventReader(source ); - assertTrue(eventReader.nextEvent().isStartDocument()); - StartElement event = eventReader.nextEvent().asStartElement(); - attr = (Attribute) event.getAttributes().next(); - } - catch ( Exception e) { - throw new RuntimeException(e); - } - Foo foo = new Foo(); - foo.setValue(Integer.parseInt(attr.getValue())); - return foo; - } - - @Override - public boolean supports(Class clazz) { - return true; - } - - }); - - reader.setSaveState(true); - - Resource r1 = new ByteArrayResource(" ".getBytes()); - Resource r2 = new ByteArrayResource(" ".getBytes()); - Resource r3 = new ByteArrayResource(" ".getBytes()); - Resource r4 = new ByteArrayResource(" ".getBytes()); - - multiReader.setDelegate(reader); - multiReader.setResources(new Resource[] { r1, r2, r3, r4 }); - multiReader.setSaveState(true); - multiReader.setComparator(new Comparator() { - @Override - public int compare(Resource arg0, Resource arg1) { - return 0; // preserve original ordering - } - }); - - return multiReader; - } - - @Override - protected void pointToEmptyInput(ItemReader tested) throws Exception { - MultiResourceItemReader multiReader = (MultiResourceItemReader) tested; - multiReader.close(); - multiReader.setResources(new Resource[] { new ByteArrayResource("" - .getBytes()) }); - multiReader.open(new ExecutionContext()); - } - -} +/* + * Copyright 2008-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item.file; + +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.util.Comparator; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.events.Attribute; +import javax.xml.stream.events.StartElement; +import javax.xml.transform.Source; + +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.springframework.batch.item.AbstractItemStreamItemReaderTests; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.sample.Foo; +import org.springframework.batch.item.xml.StaxEventItemReader; +import org.springframework.batch.item.xml.StaxTestUtils; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.core.io.Resource; +import org.springframework.oxm.Unmarshaller; +import org.springframework.oxm.XmlMappingException; + +@RunWith(JUnit4.class) +public class MultiResourceItemReaderXmlTests extends AbstractItemStreamItemReaderTests { + + @Override + protected ItemReader getItemReader() throws Exception { + MultiResourceItemReader multiReader = new MultiResourceItemReader<>(); + + StaxEventItemReader reader = new StaxEventItemReader<>(); + + reader.setFragmentRootElementName("foo"); + reader.setUnmarshaller(new Unmarshaller() { + @Override + public Object unmarshal(Source source) throws XmlMappingException, IOException { + + Attribute attr; + try { + XMLEventReader eventReader = StaxTestUtils.getXmlEventReader(source); + assertTrue(eventReader.nextEvent().isStartDocument()); + StartElement event = eventReader.nextEvent().asStartElement(); + attr = (Attribute) event.getAttributes().next(); + } + catch (Exception e) { + throw new RuntimeException(e); + } + Foo foo = new Foo(); + foo.setValue(Integer.parseInt(attr.getValue())); + return foo; + } + + @Override + public boolean supports(Class clazz) { + return true; + } + + }); + + reader.setSaveState(true); + + Resource r1 = new ByteArrayResource(" ".getBytes()); + Resource r2 = new ByteArrayResource(" ".getBytes()); + Resource r3 = new ByteArrayResource(" ".getBytes()); + Resource r4 = new ByteArrayResource(" ".getBytes()); + + multiReader.setDelegate(reader); + multiReader.setResources(new Resource[] { r1, r2, r3, r4 }); + multiReader.setSaveState(true); + multiReader.setComparator(new Comparator() { + @Override + public int compare(Resource arg0, Resource arg1) { + return 0; // preserve original ordering + } + }); + + return multiReader; + } + + @Override + protected void pointToEmptyInput(ItemReader tested) throws Exception { + MultiResourceItemReader multiReader = (MultiResourceItemReader) tested; + multiReader.close(); + multiReader.setResources(new Resource[] { new ByteArrayResource("".getBytes()) }); + multiReader.open(new ExecutionContext()); + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/MultiResourceItemWriterFlatFileTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/MultiResourceItemWriterFlatFileTests.java index 51c606675..38b206d1e 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/MultiResourceItemWriterFlatFileTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/MultiResourceItemWriterFlatFileTests.java @@ -33,8 +33,7 @@ import org.springframework.transaction.support.TransactionCallback; import org.springframework.transaction.support.TransactionTemplate; /** - * Tests for {@link MultiResourceItemWriter} delegating to - * {@link FlatFileItemWriter}. + * Tests for {@link MultiResourceItemWriter} delegating to {@link FlatFileItemWriter}. */ public class MultiResourceItemWriterFlatFileTests extends AbstractMultiResourceItemWriterTests { @@ -43,6 +42,7 @@ public class MultiResourceItemWriterFlatFileTests extends AbstractMultiResourceI * */ private final class WriterCallback implements TransactionCallback { + private List list; public WriterCallback(List list) { @@ -50,7 +50,7 @@ public class MultiResourceItemWriterFlatFileTests extends AbstractMultiResourceI this.list = list; } - @Override + @Override public Void doInTransaction(TransactionStatus status) { try { tested.write(list); @@ -60,6 +60,7 @@ public class MultiResourceItemWriterFlatFileTests extends AbstractMultiResourceI } return null; } + } private FlatFileItemWriter delegate; @@ -117,7 +118,7 @@ public class MultiResourceItemWriterFlatFileTests extends AbstractMultiResourceI public void testMultiResourceWriteScenarioWithFooter() throws Exception { delegate.setFooterCallback(new FlatFileFooterCallback() { - @Override + @Override public void writeFooter(Writer writer) throws IOException { writer.write("f"); } @@ -145,7 +146,7 @@ public class MultiResourceItemWriterFlatFileTests extends AbstractMultiResourceI public void testTransactionalMultiResourceWriteScenarioWithFooter() throws Exception { delegate.setFooterCallback(new FlatFileFooterCallback() { - @Override + @Override public void writeFooter(Writer writer) throws IOException { writer.write("f"); } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/MultiResourceItemWriterXmlTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/MultiResourceItemWriterXmlTests.java index 9b8730fda..cc103f1cb 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/MultiResourceItemWriterXmlTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/MultiResourceItemWriterXmlTests.java @@ -14,6 +14,7 @@ * limitations under the License. */ package org.springframework.batch.item.file; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -34,8 +35,7 @@ import org.springframework.oxm.XmlMappingException; import org.springframework.util.Assert; /** - * Tests for {@link MultiResourceItemWriter} delegating to - * {@link StaxEventItemWriter}. + * Tests for {@link MultiResourceItemWriter} delegating to {@link StaxEventItemWriter}. */ public class MultiResourceItemWriterXmlTests extends AbstractMultiResourceItemWriterTests { @@ -56,8 +56,8 @@ public class MultiResourceItemWriterXmlTests extends AbstractMultiResourceItemWr * Writes object's toString representation as tag. */ private static class SimpleMarshaller implements Marshaller { - - @Override + + @Override public void marshal(Object graph, Result result) throws XmlMappingException, IOException { Assert.isInstanceOf(Result.class, result); @@ -69,21 +69,23 @@ public class MultiResourceItemWriterXmlTests extends AbstractMultiResourceItemWr writer.add(factory.createEndElement("prefix", "namespace", graph.toString())); writer.add(factory.createEndDocument()); } - catch ( Exception e) { + catch (Exception e) { throw new RuntimeException("Exception while writing to output file", e); } } - @Override + @Override public boolean supports(Class clazz) { return true; } + } @Override protected String readFile(File f) throws Exception { String content = super.readFile(f); - //skip the header to avoid platform issues with single vs. double quotes + // skip the header to avoid platform issues with single vs. double + // quotes return content.substring(content.indexOf("?>") + 2); } @@ -105,10 +107,8 @@ public class MultiResourceItemWriterXmlTests extends AbstractMultiResourceItemWr tested.update(executionContext); tested.close(); - assertEquals(xmlDocStart + "" + xmlDocEnd, readFile(part2)); - assertEquals(xmlDocStart + "" + xmlDocEnd, - readFile(part1)); + assertEquals(xmlDocStart + "" + xmlDocEnd, readFile(part1)); tested.open(executionContext); @@ -121,9 +121,7 @@ public class MultiResourceItemWriterXmlTests extends AbstractMultiResourceItemWr tested.close(); assertEquals(xmlDocStart + "" + xmlDocEnd, readFile(part2)); - assertEquals(xmlDocStart - + "" + xmlDocEnd, - readFile(part3)); + assertEquals(xmlDocStart + "" + xmlDocEnd, readFile(part3)); } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/ResourcesItemReaderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/ResourcesItemReaderTests.java index b35351f3a..70ee71ed3 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/ResourcesItemReaderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/ResourcesItemReaderTests.java @@ -1,67 +1,67 @@ -/* - * Copyright 2009-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.file; - -import static org.junit.Assert.*; - -import org.junit.Before; -import org.junit.Test; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.core.io.ByteArrayResource; -import org.springframework.core.io.Resource; - -public class ResourcesItemReaderTests { - - private ResourcesItemReader reader = new ResourcesItemReader(); - - @Before - public void init() { - reader.setResources(new Resource[] { new ByteArrayResource("foo".getBytes()), - new ByteArrayResource("bar".getBytes()) }); - } - - @Test - public void testRead() throws Exception { - assertNotNull(reader.read()); - } - - @Test - public void testExhaustRead() throws Exception { - for (int i = 0; i < 2; i++) { - assertNotNull(reader.read()); - } - assertNull(reader.read()); - } - - @Test - public void testReadAfterOpen() throws Exception { - ExecutionContext executionContext = new ExecutionContext(); - executionContext.putInt(reader.getExecutionContextKey("COUNT"), 1); - reader.open(executionContext); - assertNotNull(reader.read()); - assertNull(reader.read()); - } - - @Test - public void testReadAndUpdate() throws Exception { - ExecutionContext executionContext = new ExecutionContext(); - assertNotNull(reader.read()); - - reader.update(executionContext); - assertEquals(1, executionContext.getInt(reader.getExecutionContextKey("COUNT"))); - } - -} +/* + * Copyright 2009-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item.file; + +import static org.junit.Assert.*; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.core.io.Resource; + +public class ResourcesItemReaderTests { + + private ResourcesItemReader reader = new ResourcesItemReader(); + + @Before + public void init() { + reader.setResources( + new Resource[] { new ByteArrayResource("foo".getBytes()), new ByteArrayResource("bar".getBytes()) }); + } + + @Test + public void testRead() throws Exception { + assertNotNull(reader.read()); + } + + @Test + public void testExhaustRead() throws Exception { + for (int i = 0; i < 2; i++) { + assertNotNull(reader.read()); + } + assertNull(reader.read()); + } + + @Test + public void testReadAfterOpen() throws Exception { + ExecutionContext executionContext = new ExecutionContext(); + executionContext.putInt(reader.getExecutionContextKey("COUNT"), 1); + reader.open(executionContext); + assertNotNull(reader.read()); + assertNull(reader.read()); + } + + @Test + public void testReadAndUpdate() throws Exception { + ExecutionContext executionContext = new ExecutionContext(); + assertNotNull(reader.read()); + + reader.update(executionContext); + assertEquals(1, executionContext.getInt(reader.getExecutionContextKey("COUNT"))); + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/SimpleResourceSuffixCreatorTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/SimpleResourceSuffixCreatorTests.java index 23bdf5ba6..323b8d939 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/SimpleResourceSuffixCreatorTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/SimpleResourceSuffixCreatorTests.java @@ -1,35 +1,36 @@ -/* - * Copyright 2008 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.file; - -import static org.junit.Assert.*; - -import org.junit.Test; - -/** - * Tests for {@link SimpleResourceSuffixCreator}. - */ -public class SimpleResourceSuffixCreatorTests { - - private SimpleResourceSuffixCreator tested = new SimpleResourceSuffixCreator(); - - @Test - public void testGetSuffix() { - assertEquals(".0", tested.getSuffix(0)); - assertEquals(".1", tested.getSuffix(1)); - assertEquals(".3463457", tested.getSuffix(3463457)); - } -} +/* + * Copyright 2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item.file; + +import static org.junit.Assert.*; + +import org.junit.Test; + +/** + * Tests for {@link SimpleResourceSuffixCreator}. + */ +public class SimpleResourceSuffixCreatorTests { + + private SimpleResourceSuffixCreator tested = new SimpleResourceSuffixCreator(); + + @Test + public void testGetSuffix() { + assertEquals(".0", tested.getSuffix(0)); + assertEquals(".1", tested.getSuffix(1)); + assertEquals(".3463457", tested.getSuffix(3463457)); + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/builder/FlatFileItemReaderBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/builder/FlatFileItemReaderBuilderTests.java index 7643a785d..b3eb2a5e9 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/builder/FlatFileItemReaderBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/builder/FlatFileItemReaderBuilderTests.java @@ -54,14 +54,9 @@ public class FlatFileItemReaderBuilderTests { @Test public void testSimpleFixedLength() throws Exception { - FlatFileItemReader reader = new FlatFileItemReaderBuilder() - .name("fooReader") - .resource(getResource("1 2 3")) - .fixedLength() - .columns(new Range(1, 3), new Range(4, 6), new Range(7)) - .names("first", "second", "third") - .targetType(Foo.class) - .build(); + FlatFileItemReader reader = new FlatFileItemReaderBuilder().name("fooReader") + .resource(getResource("1 2 3")).fixedLength().columns(new Range(1, 3), new Range(4, 6), new Range(7)) + .names("first", "second", "third").targetType(Foo.class).build(); reader.open(new ExecutionContext()); Foo item = reader.read(); @@ -73,12 +68,8 @@ public class FlatFileItemReaderBuilderTests { @Test public void testSimpleDelimited() throws Exception { - FlatFileItemReader reader = new FlatFileItemReaderBuilder() - .name("fooReader") - .resource(getResource("1,2,3")) - .delimited() - .names("first", "second", "third") - .targetType(Foo.class) + FlatFileItemReader reader = new FlatFileItemReaderBuilder().name("fooReader") + .resource(getResource("1,2,3")).delimited().names("first", "second", "third").targetType(Foo.class) .build(); reader.open(new ExecutionContext()); @@ -91,14 +82,9 @@ public class FlatFileItemReaderBuilderTests { @Test public void testSimpleDelimitedWithWhitespaceCharacter() throws Exception { - FlatFileItemReader reader = new FlatFileItemReaderBuilder() - .name("fooReader") - .resource(getResource("1 2 3")) - .delimited() - .delimiter(" ") - .names("first", "second", "third") - .targetType(Foo.class) - .build(); + FlatFileItemReader reader = new FlatFileItemReaderBuilder().name("fooReader") + .resource(getResource("1 2 3")).delimited().delimiter(" ").names("first", "second", "third") + .targetType(Foo.class).build(); reader.open(new ExecutionContext()); Foo item = reader.read(); @@ -110,14 +96,9 @@ public class FlatFileItemReaderBuilderTests { @Test public void testSimpleDelimitedWithTabCharacter() throws Exception { - FlatFileItemReader reader = new FlatFileItemReaderBuilder() - .name("fooReader") - .resource(getResource("1\t2\t3")) - .delimited() - .delimiter(DelimitedLineTokenizer.DELIMITER_TAB) - .names("first", "second", "third") - .targetType(Foo.class) - .build(); + FlatFileItemReader reader = new FlatFileItemReaderBuilder().name("fooReader") + .resource(getResource("1\t2\t3")).delimited().delimiter(DelimitedLineTokenizer.DELIMITER_TAB) + .names("first", "second", "third").targetType(Foo.class).build(); reader.open(new ExecutionContext()); Foo item = reader.read(); @@ -131,17 +112,10 @@ public class FlatFileItemReaderBuilderTests { public void testAdvancedDelimited() throws Exception { final List skippedLines = new ArrayList<>(); - FlatFileItemReader reader = new FlatFileItemReaderBuilder() - .name("fooReader") - .resource(getResource("1,2,3\n4,5,$1,2,3$\n@this is a comment\n6,7, 8")) - .delimited() - .quoteCharacter('$') - .names("first", "second", "third") - .targetType(Foo.class) - .linesToSkip(1) - .skippedLinesCallback(skippedLines::add) - .addComment("@") - .build(); + FlatFileItemReader reader = new FlatFileItemReaderBuilder().name("fooReader") + .resource(getResource("1,2,3\n4,5,$1,2,3$\n@this is a comment\n6,7, 8")).delimited().quoteCharacter('$') + .names("first", "second", "third").targetType(Foo.class).linesToSkip(1) + .skippedLinesCallback(skippedLines::add).addComment("@").build(); ExecutionContext executionContext = new ExecutionContext(); reader.open(executionContext); @@ -168,19 +142,13 @@ public class FlatFileItemReaderBuilderTests { @Test public void testAdvancedFixedLength() throws Exception { - FlatFileItemReader reader = new FlatFileItemReaderBuilder() - .name("fooReader") - .resource(getResource("1 2%\n 3\n4 5%\n 6\n@this is a comment\n7 8%\n 9\n")) - .fixedLength() - .columns(new Range(1, 2), new Range(3, 5), new Range(6)) - .names("first", "second", "third") - .targetType(Foo.class) - .recordSeparatorPolicy(new DefaultRecordSeparatorPolicy("\"", "%")) - .bufferedReaderFactory((resource, encoding) -> - new LineNumberReader(new InputStreamReader(resource.getInputStream(), encoding))) - .maxItemCount(2) - .saveState(false) - .build(); + FlatFileItemReader reader = new FlatFileItemReaderBuilder().name("fooReader") + .resource(getResource("1 2%\n 3\n4 5%\n 6\n@this is a comment\n7 8%\n 9\n")).fixedLength() + .columns(new Range(1, 2), new Range(3, 5), new Range(6)).names("first", "second", "third") + .targetType(Foo.class).recordSeparatorPolicy(new DefaultRecordSeparatorPolicy("\"", "%")) + .bufferedReaderFactory((resource, + encoding) -> new LineNumberReader(new InputStreamReader(resource.getInputStream(), encoding))) + .maxItemCount(2).saveState(false).build(); ExecutionContext executionContext = new ExecutionContext(); @@ -203,14 +171,9 @@ public class FlatFileItemReaderBuilderTests { @Test public void testStrict() throws Exception { - FlatFileItemReader reader = new FlatFileItemReaderBuilder() - .name("fooReader") - .resource(new FileSystemResource("this/file/does/not/exist")) - .delimited() - .names("first", "second", "third") - .targetType(Foo.class) - .strict(false) - .build(); + FlatFileItemReader reader = new FlatFileItemReaderBuilder().name("fooReader") + .resource(new FileSystemResource("this/file/does/not/exist")).delimited() + .names("first", "second", "third").targetType(Foo.class).strict(false).build(); reader.open(new ExecutionContext()); @@ -219,11 +182,9 @@ public class FlatFileItemReaderBuilderTests { @Test public void testCustomLineTokenizerFieldSetMapper() throws Exception { - FlatFileItemReader reader = new FlatFileItemReaderBuilder() - .name("fooReader") + FlatFileItemReader reader = new FlatFileItemReaderBuilder().name("fooReader") .resource(getResource("|1|&|2|&| 3|\n|4|&|5|&|foo|")) - .lineTokenizer(line -> new DefaultFieldSet(line.split("&"))) - .fieldSetMapper(fieldSet -> { + .lineTokenizer(line -> new DefaultFieldSet(line.split("&"))).fieldSetMapper(fieldSet -> { Foo item = new Foo(); item.setFirst(Integer.valueOf(fieldSet.readString(0).replaceAll("\\|", ""))); @@ -231,8 +192,7 @@ public class FlatFileItemReaderBuilderTests { item.setThird(fieldSet.readString(2).replaceAll("\\|", "")); return item; - }) - .build(); + }).build(); reader.open(new ExecutionContext()); Foo item = reader.read(); @@ -252,14 +212,9 @@ public class FlatFileItemReaderBuilderTests { @Test public void testComments() throws Exception { - FlatFileItemReader reader = new FlatFileItemReaderBuilder() - .name("fooReader") - .resource(getResource("1,2,3\n@this is a comment\n+so is this\n4,5,6")) - .comments("@", "+") - .delimited() - .names("first", "second", "third") - .targetType(Foo.class) - .build(); + FlatFileItemReader reader = new FlatFileItemReaderBuilder().name("fooReader") + .resource(getResource("1,2,3\n@this is a comment\n+so is this\n4,5,6")).comments("@", "+").delimited() + .names("first", "second", "third").targetType(Foo.class).build(); reader.open(new ExecutionContext()); Foo item = reader.read(); @@ -275,14 +230,9 @@ public class FlatFileItemReaderBuilderTests { @Test public void testEmptyComments() throws Exception { - FlatFileItemReader reader = new FlatFileItemReaderBuilder() - .name("fooReader") - .resource(getResource("1,2,3\n4,5,6")) - .comments(new String[]{}) - .delimited() - .names("first", "second", "third") - .targetType(Foo.class) - .build(); + FlatFileItemReader reader = new FlatFileItemReaderBuilder().name("fooReader") + .resource(getResource("1,2,3\n4,5,6")).comments(new String[] {}).delimited() + .names("first", "second", "third").targetType(Foo.class).build(); reader.open(new ExecutionContext()); Foo item = reader.read(); @@ -298,13 +248,9 @@ public class FlatFileItemReaderBuilderTests { @Test public void testDefaultComments() throws Exception { - FlatFileItemReader reader = new FlatFileItemReaderBuilder() - .name("fooReader") - .resource(getResource("1,2,3\n4,5,6\n#this is a default comment")) - .delimited() - .names("first", "second", "third") - .targetType(Foo.class) - .build(); + FlatFileItemReader reader = new FlatFileItemReaderBuilder().name("fooReader") + .resource(getResource("1,2,3\n4,5,6\n#this is a default comment")).delimited() + .names("first", "second", "third").targetType(Foo.class).build(); reader.open(new ExecutionContext()); Foo item = reader.read(); @@ -322,14 +268,9 @@ public class FlatFileItemReaderBuilderTests { public void testPrototypeBean() throws Exception { BeanFactory factory = new AnnotationConfigApplicationContext(Beans.class); - FlatFileItemReader reader = new FlatFileItemReaderBuilder() - .name("fooReader") - .resource(getResource("1,2,3")) - .delimited() - .names("first", "second", "third") - .prototypeBeanName("foo") - .beanFactory(factory) - .build(); + FlatFileItemReader reader = new FlatFileItemReaderBuilder().name("fooReader") + .resource(getResource("1,2,3")).delimited().names("first", "second", "third").prototypeBeanName("foo") + .beanFactory(factory).build(); reader.open(new ExecutionContext()); Foo item = reader.read(); @@ -341,14 +282,9 @@ public class FlatFileItemReaderBuilderTests { @Test public void testBeanWrapperFieldSetMapperStrict() throws Exception { - FlatFileItemReader reader = new FlatFileItemReaderBuilder() - .name("fooReader") - .resource(getResource("1,2,3")) - .delimited() - .names("setFirst", "setSecond", "setThird") - .targetType(Foo.class) - .beanMapperStrict(true) - .build(); + FlatFileItemReader reader = new FlatFileItemReaderBuilder().name("fooReader") + .resource(getResource("1,2,3")).delimited().names("setFirst", "setSecond", "setThird") + .targetType(Foo.class).beanMapperStrict(true).build(); reader.open(new ExecutionContext()); Foo item = reader.read(); @@ -360,15 +296,9 @@ public class FlatFileItemReaderBuilderTests { @Test public void testDelimitedIncludedFields() throws Exception { - FlatFileItemReader reader = new FlatFileItemReaderBuilder() - .name("fooReader") - .resource(getResource("1,2,3")) - .delimited() - .includedFields(0, 2) - .addIncludedField(1) - .names("first", "second", "third") - .targetType(Foo.class) - .build(); + FlatFileItemReader reader = new FlatFileItemReaderBuilder().name("fooReader") + .resource(getResource("1,2,3")).delimited().includedFields(0, 2).addIncludedField(1) + .names("first", "second", "third").targetType(Foo.class).build(); reader.open(new ExecutionContext()); Foo item = reader.read(); @@ -380,14 +310,11 @@ public class FlatFileItemReaderBuilderTests { @Test public void testDelimitedFieldSetFactory() throws Exception { - String[] names = {"first", "second", "third"}; + String[] names = { "first", "second", "third" }; - FlatFileItemReader reader = new FlatFileItemReaderBuilder() - .name("fooReader") - .resource(getResource("1,2,3")) - .delimited() - .fieldSetFactory(new FieldSetFactory() { - private FieldSet fieldSet = new DefaultFieldSet(new String[] {"1", "3", "foo"}, names); + FlatFileItemReader reader = new FlatFileItemReaderBuilder().name("fooReader") + .resource(getResource("1,2,3")).delimited().fieldSetFactory(new FieldSetFactory() { + private FieldSet fieldSet = new DefaultFieldSet(new String[] { "1", "3", "foo" }, names); @Override public FieldSet create(String[] values, String[] names) { @@ -398,10 +325,7 @@ public class FlatFileItemReaderBuilderTests { public FieldSet create(String[] values) { return fieldSet; } - }) - .names(names) - .targetType(Foo.class) - .build(); + }).names(names).targetType(Foo.class).build(); reader.open(new ExecutionContext()); Foo item = reader.read(); @@ -413,14 +337,11 @@ public class FlatFileItemReaderBuilderTests { @Test public void testFixedLengthFieldSetFactory() throws Exception { - String[] names = {"first", "second", "third"}; + String[] names = { "first", "second", "third" }; - FlatFileItemReader reader = new FlatFileItemReaderBuilder() - .name("fooReader") - .resource(getResource("1 2 3")) - .fixedLength() - .fieldSetFactory(new FieldSetFactory() { - private FieldSet fieldSet = new DefaultFieldSet(new String[] {"1", "3", "foo"}, names); + FlatFileItemReader reader = new FlatFileItemReaderBuilder().name("fooReader") + .resource(getResource("1 2 3")).fixedLength().fieldSetFactory(new FieldSetFactory() { + private FieldSet fieldSet = new DefaultFieldSet(new String[] { "1", "3", "foo" }, names); @Override public FieldSet create(String[] values, String[] names) { @@ -431,11 +352,8 @@ public class FlatFileItemReaderBuilderTests { public FieldSet create(String[] values) { return fieldSet; } - }) - .columns(new Range(1, 3), new Range(4, 6), new Range(7)) - .names("first", "second", "third") - .targetType(Foo.class) - .build(); + }).columns(new Range(1, 3), new Range(4, 6), new Range(7)).names("first", "second", "third") + .targetType(Foo.class).build(); reader.open(new ExecutionContext()); Foo item = reader.read(); @@ -445,64 +363,42 @@ public class FlatFileItemReaderBuilderTests { assertNull(reader.read()); } - @Test public void testName() throws Exception { try { - new FlatFileItemReaderBuilder() - .resource(getResource("1 2 3")) - .fixedLength() - .columns(new Range(1, 3), new Range(4, 6), new Range(7)) - .names("first", "second", "third") - .targetType(Foo.class) - .build(); + new FlatFileItemReaderBuilder().resource(getResource("1 2 3")).fixedLength() + .columns(new Range(1, 3), new Range(4, 6), new Range(7)).names("first", "second", "third") + .targetType(Foo.class).build(); fail("null name should throw exception"); } catch (IllegalStateException iae) { assertEquals("A name is required when saveState is set to true.", iae.getMessage()); } try { - new FlatFileItemReaderBuilder() - .resource(getResource("1 2 3")) - .fixedLength() - .columns(new Range(1, 3), new Range(4, 6), new Range(7)) - .names("first", "second", "third") - .targetType(Foo.class) - .name(null) - .build(); + new FlatFileItemReaderBuilder().resource(getResource("1 2 3")).fixedLength() + .columns(new Range(1, 3), new Range(4, 6), new Range(7)).names("first", "second", "third") + .targetType(Foo.class).name(null).build(); } catch (IllegalStateException iae) { assertEquals("A name is required when saveState is set to true.", iae.getMessage()); } - assertNotNull("builder should return new instance of FlatFileItemReader", new FlatFileItemReaderBuilder() - .resource(getResource("1 2 3")) - .fixedLength() - .columns(new Range(1, 3), new Range(4, 6), new Range(7)) - .names("first", "second", "third") - .targetType(Foo.class) - .saveState(false) - .build()); + assertNotNull("builder should return new instance of FlatFileItemReader", + new FlatFileItemReaderBuilder().resource(getResource("1 2 3")).fixedLength() + .columns(new Range(1, 3), new Range(4, 6), new Range(7)).names("first", "second", "third") + .targetType(Foo.class).saveState(false).build()); - assertNotNull("builder should return new instance of FlatFileItemReader", new FlatFileItemReaderBuilder() - .resource(getResource("1 2 3")) - .fixedLength() - .columns(new Range(1, 3), new Range(4, 6), new Range(7)) - .names("first", "second", "third") - .targetType(Foo.class) - .name("foobar") - .build()); + assertNotNull("builder should return new instance of FlatFileItemReader", + new FlatFileItemReaderBuilder().resource(getResource("1 2 3")).fixedLength() + .columns(new Range(1, 3), new Range(4, 6), new Range(7)).names("first", "second", "third") + .targetType(Foo.class).name("foobar").build()); } @Test public void testDefaultEncoding() { String encoding = FlatFileItemReader.DEFAULT_CHARSET; - FlatFileItemReader reader = new FlatFileItemReaderBuilder() - .name("fooReader") - .resource(getResource("1,2,3")) - .delimited() - .names("first", "second", "third") - .targetType(Foo.class) + FlatFileItemReader reader = new FlatFileItemReaderBuilder().name("fooReader") + .resource(getResource("1,2,3")).delimited().names("first", "second", "third").targetType(Foo.class) .build(); assertEquals(encoding, ReflectionTestUtils.getField(reader, "encoding")); @@ -511,15 +407,10 @@ public class FlatFileItemReaderBuilderTests { @Test public void testCustomEncoding() { String encoding = "UTF-8"; - FlatFileItemReader reader = new FlatFileItemReaderBuilder() - .name("fooReader") - .resource(getResource("1 2 3")) - .encoding(encoding) - .fixedLength() - .columns(new Range(1, 3), new Range(4, 6), new Range(7)) - .names("first", "second", "third") - .targetType(Foo.class) - .build(); + FlatFileItemReader reader = new FlatFileItemReaderBuilder().name("fooReader") + .resource(getResource("1 2 3")).encoding(encoding).fixedLength() + .columns(new Range(1, 3), new Range(4, 6), new Range(7)).names("first", "second", "third") + .targetType(Foo.class).build(); assertEquals(encoding, ReflectionTestUtils.getField(reader, "encoding")); } @@ -527,28 +418,25 @@ public class FlatFileItemReaderBuilderTests { @Test public void testErrorMessageWhenNoFieldSetMapperIsProvided() { try { - new FlatFileItemReaderBuilder() - .name("fooReader") - .resource(getResource("1;2;3")) - .lineTokenizer(line -> new DefaultFieldSet(line.split(";"))) - .build(); - } catch (IllegalStateException exception) { + new FlatFileItemReaderBuilder().name("fooReader").resource(getResource("1;2;3")) + .lineTokenizer(line -> new DefaultFieldSet(line.split(";"))).build(); + } + catch (IllegalStateException exception) { String exceptionMessage = exception.getMessage(); if (exceptionMessage.equals("No LineTokenizer implementation was provided.")) { - fail("Error message should not be 'No LineTokenizer implementation was provided.'" + - " when a LineTokenizer is provided"); + fail("Error message should not be 'No LineTokenizer implementation was provided.'" + + " when a LineTokenizer is provided"); } assertEquals("No FieldSetMapper implementation was provided.", exceptionMessage); } } + @Test public void testErrorMessageWhenNoLineTokenizerWasProvided() { try { - new FlatFileItemReaderBuilder() - .name("fooReader") - .resource(getResource("1;2;3")) - .build(); - } catch (IllegalStateException exception) { + new FlatFileItemReaderBuilder().name("fooReader").resource(getResource("1;2;3")).build(); + } + catch (IllegalStateException exception) { String exceptionMessage = exception.getMessage(); assertEquals("No LineTokenizer implementation was provided.", exceptionMessage); } @@ -559,8 +447,11 @@ public class FlatFileItemReaderBuilderTests { } public static class Foo { + private int first; + private int second; + private String third; public int getFirst() { @@ -586,6 +477,7 @@ public class FlatFileItemReaderBuilderTests { public void setThird(String third) { this.third = third; } + } @Configuration @@ -596,6 +488,7 @@ public class FlatFileItemReaderBuilderTests { public Foo foo() { return new Foo(); } + } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/builder/FlatFileItemWriterBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/builder/FlatFileItemWriterBuilderTests.java index 888ad363d..2c175eec8 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/builder/FlatFileItemWriterBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/builder/FlatFileItemWriterBuilderTests.java @@ -50,24 +50,15 @@ public class FlatFileItemWriterBuilderTests { @Test(expected = IllegalArgumentException.class) public void testMissingLineAggregator() { - new FlatFileItemWriterBuilder() - .build(); + new FlatFileItemWriterBuilder().build(); } @Test(expected = IllegalStateException.class) public void testMultipleLineAggregators() throws IOException { WritableResource output = new FileSystemResource(File.createTempFile("foo", "txt")); - new FlatFileItemWriterBuilder() - .name("itemWriter") - .resource(output) - .delimited() - .delimiter(";") - .names("foo", "bar") - .formatted() - .format("%2s%2s") - .names("foo", "bar") - .build(); + new FlatFileItemWriterBuilder().name("itemWriter").resource(output).delimited().delimiter(";") + .names("foo", "bar").formatted().format("%2s%2s").names("foo", "bar").build(); } @Test @@ -75,15 +66,10 @@ public class FlatFileItemWriterBuilderTests { WritableResource output = new FileSystemResource(File.createTempFile("foo", "txt")); - FlatFileItemWriter writer = new FlatFileItemWriterBuilder() - .name("foo") - .resource(output) - .lineSeparator("$") - .lineAggregator(new PassThroughLineAggregator<>()) - .encoding("UTF-16LE") + FlatFileItemWriter writer = new FlatFileItemWriterBuilder().name("foo").resource(output) + .lineSeparator("$").lineAggregator(new PassThroughLineAggregator<>()).encoding("UTF-16LE") .headerCallback(writer1 -> writer1.append("HEADER")) - .footerCallback(writer12 -> writer12.append("FOOTER")) - .build(); + .footerCallback(writer12 -> writer12.append("FOOTER")).build(); ExecutionContext executionContext = new ExecutionContext(); @@ -93,7 +79,8 @@ public class FlatFileItemWriterBuilderTests { writer.close(); - assertEquals("HEADER$Foo{first=1, second=2, third='3'}$Foo{first=4, second=5, third='6'}$FOOTER", readLine("UTF-16LE", output)); + assertEquals("HEADER$Foo{first=1, second=2, third='3'}$Foo{first=4, second=5, third='6'}$FOOTER", + readLine("UTF-16LE", output)); } @Test @@ -101,16 +88,10 @@ public class FlatFileItemWriterBuilderTests { WritableResource output = new FileSystemResource(File.createTempFile("foo", "txt")); - FlatFileItemWriter writer = new FlatFileItemWriterBuilder() - .name("foo") - .resource(output) - .lineSeparator("$") - .delimited() - .names("first", "second", "third") - .encoding("UTF-16LE") + FlatFileItemWriter writer = new FlatFileItemWriterBuilder().name("foo").resource(output) + .lineSeparator("$").delimited().names("first", "second", "third").encoding("UTF-16LE") .headerCallback(writer1 -> writer1.append("HEADER")) - .footerCallback(writer12 -> writer12.append("FOOTER")) - .build(); + .footerCallback(writer12 -> writer12.append("FOOTER")).build(); ExecutionContext executionContext = new ExecutionContext(); @@ -128,17 +109,10 @@ public class FlatFileItemWriterBuilderTests { WritableResource output = new FileSystemResource(File.createTempFile("foo", "txt")); - FlatFileItemWriter writer = new FlatFileItemWriterBuilder() - .name("foo") - .resource(output) - .lineSeparator("$") - .delimited() - .delimiter("") - .names("first", "second", "third") - .encoding("UTF-16LE") + FlatFileItemWriter writer = new FlatFileItemWriterBuilder().name("foo").resource(output) + .lineSeparator("$").delimited().delimiter("").names("first", "second", "third").encoding("UTF-16LE") .headerCallback(writer1 -> writer1.append("HEADER")) - .footerCallback(writer12 -> writer12.append("FOOTER")) - .build(); + .footerCallback(writer12 -> writer12.append("FOOTER")).build(); ExecutionContext executionContext = new ExecutionContext(); @@ -156,17 +130,10 @@ public class FlatFileItemWriterBuilderTests { WritableResource output = new FileSystemResource(File.createTempFile("foo", "txt")); - FlatFileItemWriter writer = new FlatFileItemWriterBuilder() - .name("foo") - .resource(output) - .lineSeparator("$") - .delimited() - .delimiter(";") - .names("first", "second", "third") - .encoding("UTF-16LE") + FlatFileItemWriter writer = new FlatFileItemWriterBuilder().name("foo").resource(output) + .lineSeparator("$").delimited().delimiter(";").names("first", "second", "third").encoding("UTF-16LE") .headerCallback(writer1 -> writer1.append("HEADER")) - .footerCallback(writer12 -> writer12.append("FOOTER")) - .build(); + .footerCallback(writer12 -> writer12.append("FOOTER")).build(); ExecutionContext executionContext = new ExecutionContext(); @@ -184,17 +151,11 @@ public class FlatFileItemWriterBuilderTests { WritableResource output = new FileSystemResource(File.createTempFile("foo", "txt")); - FlatFileItemWriter writer = new FlatFileItemWriterBuilder() - .name("foo") - .resource(output) - .lineSeparator("$") - .delimited() - .delimiter(" ") - .fieldExtractor(item -> new Object[] {item.getFirst(), item.getThird()}) - .encoding("UTF-16LE") + FlatFileItemWriter writer = new FlatFileItemWriterBuilder().name("foo").resource(output) + .lineSeparator("$").delimited().delimiter(" ") + .fieldExtractor(item -> new Object[] { item.getFirst(), item.getThird() }).encoding("UTF-16LE") .headerCallback(writer1 -> writer1.append("HEADER")) - .footerCallback(writer12 -> writer12.append("FOOTER")) - .build(); + .footerCallback(writer12 -> writer12.append("FOOTER")).build(); ExecutionContext executionContext = new ExecutionContext(); @@ -212,17 +173,10 @@ public class FlatFileItemWriterBuilderTests { WritableResource output = new FileSystemResource(File.createTempFile("foo", "txt")); - FlatFileItemWriter writer = new FlatFileItemWriterBuilder() - .name("foo") - .resource(output) - .lineSeparator("$") - .formatted() - .format("%2s%2s%2s") - .names("first", "second", "third") - .encoding("UTF-16LE") - .headerCallback(writer1 -> writer1.append("HEADER")) - .footerCallback(writer12 -> writer12.append("FOOTER")) - .build(); + FlatFileItemWriter writer = new FlatFileItemWriterBuilder().name("foo").resource(output) + .lineSeparator("$").formatted().format("%2s%2s%2s").names("first", "second", "third") + .encoding("UTF-16LE").headerCallback(writer1 -> writer1.append("HEADER")) + .footerCallback(writer12 -> writer12.append("FOOTER")).build(); ExecutionContext executionContext = new ExecutionContext(); @@ -240,17 +194,11 @@ public class FlatFileItemWriterBuilderTests { WritableResource output = new FileSystemResource(File.createTempFile("foo", "txt")); - FlatFileItemWriter writer = new FlatFileItemWriterBuilder() - .name("foo") - .resource(output) - .lineSeparator("$") - .formatted() - .format("%3s%3s") - .fieldExtractor(item -> new Object[] {item.getFirst(), item.getThird()}) - .encoding("UTF-16LE") + FlatFileItemWriter writer = new FlatFileItemWriterBuilder().name("foo").resource(output) + .lineSeparator("$").formatted().format("%3s%3s") + .fieldExtractor(item -> new Object[] { item.getFirst(), item.getThird() }).encoding("UTF-16LE") .headerCallback(writer1 -> writer1.append("HEADER")) - .footerCallback(writer12 -> writer12.append("FOOTER")) - .build(); + .footerCallback(writer12 -> writer12.append("FOOTER")).build(); ExecutionContext executionContext = new ExecutionContext(); @@ -270,17 +218,9 @@ public class FlatFileItemWriterBuilderTests { String encoding = Charset.defaultCharset().name(); - FlatFileItemWriter writer = new FlatFileItemWriterBuilder() - .name("foo") - .resource(output) - .shouldDeleteIfEmpty(true) - .shouldDeleteIfExists(false) - .saveState(false) - .forceSync(true) - .append(true) - .transactional(false) - .lineAggregator(new PassThroughLineAggregator<>()) - .build(); + FlatFileItemWriter writer = new FlatFileItemWriterBuilder().name("foo").resource(output) + .shouldDeleteIfEmpty(true).shouldDeleteIfExists(false).saveState(false).forceSync(true).append(true) + .transactional(false).lineAggregator(new PassThroughLineAggregator<>()).build(); validateBuilderFlags(writer, encoding); } @@ -290,18 +230,9 @@ public class FlatFileItemWriterBuilderTests { WritableResource output = new FileSystemResource(File.createTempFile("foo", "txt")); String encoding = "UTF-8"; - FlatFileItemWriter writer = new FlatFileItemWriterBuilder() - .name("foo") - .encoding(encoding) - .resource(output) - .shouldDeleteIfEmpty(true) - .shouldDeleteIfExists(false) - .saveState(false) - .forceSync(true) - .append(true) - .transactional(false) - .lineAggregator(new PassThroughLineAggregator<>()) - .build(); + FlatFileItemWriter writer = new FlatFileItemWriterBuilder().name("foo").encoding(encoding) + .resource(output).shouldDeleteIfEmpty(true).shouldDeleteIfExists(false).saveState(false).forceSync(true) + .append(true).transactional(false).lineAggregator(new PassThroughLineAggregator<>()).build(); validateBuilderFlags(writer, encoding); } @@ -312,11 +243,10 @@ public class FlatFileItemWriterBuilderTests { assertTrue((Boolean) ReflectionTestUtils.getField(writer, "shouldDeleteIfEmpty")); assertFalse((Boolean) ReflectionTestUtils.getField(writer, "shouldDeleteIfExists")); assertTrue((Boolean) ReflectionTestUtils.getField(writer, "forceSync")); - assertEquals( encoding, ReflectionTestUtils.getField(writer, "encoding")); + assertEquals(encoding, ReflectionTestUtils.getField(writer, "encoding")); } - - private String readLine(String encoding, Resource outputFile ) throws IOException { + private String readLine(String encoding, Resource outputFile) throws IOException { if (reader == null) { reader = new BufferedReader(new InputStreamReader(outputFile.getInputStream(), encoding)); @@ -326,8 +256,11 @@ public class FlatFileItemWriterBuilderTests { } public static class Foo { + private int first; + private int second; + private String third; public Foo(int first, int second, String third) { @@ -362,11 +295,9 @@ public class FlatFileItemWriterBuilderTests { @Override public String toString() { - return "Foo{" + - "first=" + first + - ", second=" + second + - ", third='" + third + '\'' + - '}'; + return "Foo{" + "first=" + first + ", second=" + second + ", third='" + third + '\'' + '}'; } + } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/builder/MultiResourceItemReaderBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/builder/MultiResourceItemReaderBuilderTests.java index 95905bbf8..e03c964d7 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/builder/MultiResourceItemReaderBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/builder/MultiResourceItemReaderBuilderTests.java @@ -66,12 +66,12 @@ public class MultiResourceItemReaderBuilderTests extends AbstractItemStreamItemR @Test public void testNullDelegate() { try { - new MultiResourceItemReaderBuilder().resources(new Resource[]{}).build(); + new MultiResourceItemReaderBuilder().resources(new Resource[] {}).build(); fail("IllegalArgumentException should have been thrown"); } catch (IllegalArgumentException ise) { - assertEquals("IllegalArgumentException message did not match the expected result.", - "delegate is required.", ise.getMessage()); + assertEquals("IllegalArgumentException message did not match the expected result.", "delegate is required.", + ise.getMessage()); } } @@ -95,4 +95,5 @@ public class MultiResourceItemReaderBuilderTests extends AbstractItemStreamItemR multiReader.setResources(new Resource[] { new ByteArrayResource("".getBytes()) }); multiReader.open(new ExecutionContext()); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/BeanWrapperFieldSetMapperConcurrentTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/BeanWrapperFieldSetMapperConcurrentTests.java index f83d7d64f..58067bce0 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/BeanWrapperFieldSetMapperConcurrentTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/BeanWrapperFieldSetMapperConcurrentTests.java @@ -45,7 +45,7 @@ public class BeanWrapperFieldSetMapperConcurrentTests { Collection> results = new ArrayList<>(); for (int i = 0; i < 10; i++) { Future result = executorService.submit(new Callable() { - @Override + @Override public Boolean call() throws Exception { for (int i = 0; i < 10; i++) { GreenBean bean = mapper.mapFieldSet(lineTokenizer.tokenize("blue,green")); @@ -62,6 +62,7 @@ public class BeanWrapperFieldSetMapperConcurrentTests { } public static class GreenBean { + private String green; private String blue; @@ -83,4 +84,5 @@ public class BeanWrapperFieldSetMapperConcurrentTests { } } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/BeanWrapperFieldSetMapperFuzzyMatchingTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/BeanWrapperFieldSetMapperFuzzyMatchingTests.java index fb2e7455b..13cfd7b9d 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/BeanWrapperFieldSetMapperFuzzyMatchingTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/BeanWrapperFieldSetMapperFuzzyMatchingTests.java @@ -64,6 +64,7 @@ public class BeanWrapperFieldSetMapperFuzzyMatchingTests { } public static class GreenBean { + private String green; public String getGreen() { @@ -77,6 +78,7 @@ public class BeanWrapperFieldSetMapperFuzzyMatchingTests { } public static class BlueBean { + private String blue; private String bleu; diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/BeanWrapperFieldSetMapperTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/BeanWrapperFieldSetMapperTests.java index 867225007..be029609f 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/BeanWrapperFieldSetMapperTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/BeanWrapperFieldSetMapperTests.java @@ -56,9 +56,9 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; public class BeanWrapperFieldSetMapperTests { - + private static final TimeZone UTC_TIME_ZONE = TimeZone.getTimeZone("UTC"); - + private TimeZone defaultTimeZone = TimeZone.getDefault(); @Before @@ -104,7 +104,7 @@ public class BeanWrapperFieldSetMapperTests { fail(); } -} + } @Test public void testVanillaBeanCreatedFromType() throws Exception { @@ -126,8 +126,8 @@ public class BeanWrapperFieldSetMapperTests { mapper.setTargetType(TestNestedA.class); mapper.afterPropertiesSet(); - FieldSet fieldSet = new DefaultFieldSet(new String[] { "Foo", "Bar" }, new String[] { "valueA", - "testObjectB.valueA" }); + FieldSet fieldSet = new DefaultFieldSet(new String[] { "Foo", "Bar" }, + new String[] { "valueA", "testObjectB.valueA" }); TestNestedA result = mapper.mapFieldSet(fieldSet); assertEquals("Bar", result.getTestObjectB().getValueA()); } @@ -168,7 +168,7 @@ public class BeanWrapperFieldSetMapperTests { } @Test - @SuppressWarnings({"unchecked", "resource"}) + @SuppressWarnings({ "unchecked", "resource" }) public void testMapperWithPrototype() throws Exception { ApplicationContext context = new ClassPathXmlApplicationContext("bean-wrapper.xml", getClass()); @@ -198,9 +198,8 @@ public class BeanWrapperFieldSetMapperTests { context.getBeanFactory().registerSingleton("bean", testNestedA); mapper.setPrototypeBeanName("bean"); - FieldSet fieldSet = new DefaultFieldSet( - new String[] { "This is some dummy string", "1", "Another dummy", "2" }, new String[] { "valueA", - "valueB", "testObjectB.valueA", "testObjectB.testObjectC.value" }); + FieldSet fieldSet = new DefaultFieldSet(new String[] { "This is some dummy string", "1", "Another dummy", "2" }, + new String[] { "valueA", "valueB", "testObjectB.valueA", "testObjectB.testObjectC.value" }); TestNestedA result = mapper.mapFieldSet(fieldSet); @@ -222,8 +221,8 @@ public class BeanWrapperFieldSetMapperTests { context.getBeanFactory().registerSingleton("bean", testNestedA); mapper.setPrototypeBeanName("bean"); - FieldSet fieldSet = new DefaultFieldSet(new String[] { "This is some dummy string", "1" }, new String[] { - "VALUE_A", "VALUE_B" }); + FieldSet fieldSet = new DefaultFieldSet(new String[] { "This is some dummy string", "1" }, + new String[] { "VALUE_A", "VALUE_B" }); TestNestedA result = mapper.mapFieldSet(fieldSet); @@ -266,8 +265,8 @@ public class BeanWrapperFieldSetMapperTests { mapper.setDistanceLimit(2); mapper.setPrototypeBeanName("bean"); - FieldSet fieldSet = new DefaultFieldSet(new String[] { "Another dummy", "2" }, new String[] { - "TestObjectB.ValueA", "TestObjectB.TestObjectC.Value" }); + FieldSet fieldSet = new DefaultFieldSet(new String[] { "Another dummy", "2" }, + new String[] { "TestObjectB.ValueA", "TestObjectB.TestObjectC.Value" }); TestNestedA result = mapper.mapFieldSet(fieldSet); @@ -353,8 +352,8 @@ public class BeanWrapperFieldSetMapperTests { context.getBeanFactory().registerSingleton("bean", nestedList); mapper.setPrototypeBeanName("bean"); - FieldSet fieldSet = new DefaultFieldSet(new String[] { "1", "2", "3" }, new String[] { "NestedC[0].Value", - "NestedC[1].Value", "NestedC[2].Value" }); + FieldSet fieldSet = new DefaultFieldSet(new String[] { "1", "2", "3" }, + new String[] { "NestedC[0].Value", "NestedC[1].Value", "NestedC[2].Value" }); mapper.mapFieldSet(fieldSet); @@ -381,8 +380,8 @@ public class BeanWrapperFieldSetMapperTests { context.getBeanFactory().registerSingleton("bean", nestedList); mapper.setPrototypeBeanName("bean"); - FieldSet fieldSet = new DefaultFieldSet(new String[] { "1", "2", "3" }, new String[] { "NestedC[0].Value", - "NestedC[1].Value", "NestedC[2].Value" }); + FieldSet fieldSet = new DefaultFieldSet(new String[] { "1", "2", "3" }, + new String[] { "NestedC[0].Value", "NestedC[1].Value", "NestedC[2].Value" }); mapper.mapFieldSet(fieldSet); @@ -412,8 +411,8 @@ public class BeanWrapperFieldSetMapperTests { FieldSet fieldSet = new DefaultFieldSet(new String[] { "00009" }, new String[] { "varLong" }); - mapper.setCustomEditors(Collections.singletonMap(Long.TYPE, new CustomNumberEditor(Long.class, NumberFormat - .getNumberInstance(), true))); + mapper.setCustomEditors(Collections.singletonMap(Long.TYPE, + new CustomNumberEditor(Long.class, NumberFormat.getNumberInstance(), true))); TestObject bean = mapper.mapFieldSet(fieldSet); assertEquals(9, bean.getVarLong()); @@ -427,8 +426,8 @@ public class BeanWrapperFieldSetMapperTests { FieldSet fieldSet = new DefaultFieldSet(new String[] { "00009", "78" }, new String[] { "varLong", "varInt" }); - mapper.setCustomEditors(Collections.singletonMap(Long.TYPE, new CustomNumberEditor(Long.class, NumberFormat - .getNumberInstance(), true))); + mapper.setCustomEditors(Collections.singletonMap(Long.TYPE, + new CustomNumberEditor(Long.class, NumberFormat.getNumberInstance(), true))); TestObject bean = mapper.mapFieldSet(fieldSet); assertEquals(9, bean.getVarLong()); @@ -441,8 +440,8 @@ public class BeanWrapperFieldSetMapperTests { BeanWrapperFieldSetMapper mapper = new BeanWrapperFieldSetMapper<>(); mapper.setTargetType(TestObject.class); - FieldSet fieldSet = new DefaultFieldSet(new String[] { "9.876,1", "7,890.1" }, new String[] { "varDouble", - "varFloat" }); + FieldSet fieldSet = new DefaultFieldSet(new String[] { "9.876,1", "7,890.1" }, + new String[] { "varDouble", "varFloat" }); Map, PropertyEditor> editors = new HashMap<>(); editors.put(Double.TYPE, new CustomNumberEditor(Double.class, NumberFormat.getInstance(Locale.GERMAN), true)); @@ -455,7 +454,6 @@ public class BeanWrapperFieldSetMapperTests { assertEquals(7890.1, bean.getVarFloat(), 0.01); } - @Test public void testConversionWithTestConverter() throws Exception { @@ -482,9 +480,11 @@ public class BeanWrapperFieldSetMapperTests { BigDecimal bigDecimal = new BigDecimal(12345L); String dateString = date.toString(); - - FieldSet fieldSet = new DefaultFieldSet(new String[] { "12", "12345", "true", "Z", "123", "12345", "12345", "12", dateString, "12345", sampleString}, - new String[] { "varInt", "varLong", "varBoolean", "varChar","varByte","varFloat", "varDouble", "varShort", "varDate", "varBigDecimal", "varString" }); + FieldSet fieldSet = new DefaultFieldSet( + new String[] { "12", "12345", "true", "Z", "123", "12345", "12345", "12", dateString, "12345", + sampleString }, + new String[] { "varInt", "varLong", "varBoolean", "varChar", "varByte", "varFloat", "varDouble", + "varShort", "varDate", "varBigDecimal", "varString" }); mapper.setConversionService(new DefaultConversionService()); mapper.afterPropertiesSet(); @@ -513,8 +513,8 @@ public class BeanWrapperFieldSetMapperTests { mapper.setTargetType(TestObject.class); mapper.setConversionService(new TestConversion()); - mapper.setCustomEditors(Collections.singletonMap(Long.TYPE, new CustomNumberEditor(Long.class, NumberFormat - .getNumberInstance(), true))); + mapper.setCustomEditors(Collections.singletonMap(Long.TYPE, + new CustomNumberEditor(Long.class, NumberFormat.getNumberInstance(), true))); try { mapper.afterPropertiesSet(); } @@ -533,8 +533,8 @@ public class BeanWrapperFieldSetMapperTests { BeanWrapperFieldSetMapper mapper = new BeanWrapperFieldSetMapper<>(); mapper.setTargetType(TestObject.class); - FieldSet fieldSet = new DefaultFieldSet(new String[] { "foo", "7890.1" }, new String[] { "varDouble", - "varFloat" }); + FieldSet fieldSet = new DefaultFieldSet(new String[] { "foo", "7890.1" }, + new String[] { "varDouble", "varFloat" }); try { mapper.mapFieldSet(fieldSet); fail("Expected BindException"); @@ -552,13 +552,14 @@ public class BeanWrapperFieldSetMapperTests { BeanWrapperFieldSetMapper mapper = new BeanWrapperFieldSetMapper() { @Override protected void initBinder(DataBinder binder) { - binder.registerCustomEditor(Double.TYPE, "value", new CustomNumberEditor(Double.class, NumberFormat - .getNumberInstance(Locale.GERMAN), true)); + binder.registerCustomEditor(Double.TYPE, "value", + new CustomNumberEditor(Double.class, NumberFormat.getNumberInstance(Locale.GERMAN), true)); } }; mapper.setTargetType(TestTwoDoubles.class); - FieldSet fieldSet = new DefaultFieldSet(new String[] { "9.876,1", "7890.1" }, new String[] { "value", "other" }); + FieldSet fieldSet = new DefaultFieldSet(new String[] { "9.876,1", "7890.1" }, + new String[] { "value", "other" }); TestTwoDoubles bean = mapper.mapFieldSet(fieldSet); assertEquals(9876.1, bean.getValue(), 0.01); @@ -572,13 +573,14 @@ public class BeanWrapperFieldSetMapperTests { @Override public void registerCustomEditors(PropertyEditorRegistry registry) { super.registerCustomEditors(registry); - registry.registerCustomEditor(Double.TYPE, "value", new CustomNumberEditor(Double.class, NumberFormat - .getNumberInstance(Locale.GERMAN), true)); + registry.registerCustomEditor(Double.TYPE, "value", + new CustomNumberEditor(Double.class, NumberFormat.getNumberInstance(Locale.GERMAN), true)); } }; mapper.setTargetType(TestTwoDoubles.class); - FieldSet fieldSet = new DefaultFieldSet(new String[] { "9.876,1", "7890.1" }, new String[] { "value", "other" }); + FieldSet fieldSet = new DefaultFieldSet(new String[] { "9.876,1", "7890.1" }, + new String[] { "value", "other" }); TestTwoDoubles bean = mapper.mapFieldSet(fieldSet); assertEquals(9876.1, bean.getValue(), 0.01); @@ -592,8 +594,9 @@ public class BeanWrapperFieldSetMapperTests { mapper.setTargetType(TestObject.class); mapper.afterPropertiesSet(); - FieldSet fieldSet = new DefaultFieldSet(new String[] { "This is some dummy string", "This won't be mapped", - "true", "C" }, new String[] { "varString", "illegalPropertyName", "varBoolean", "varChar" }); + FieldSet fieldSet = new DefaultFieldSet( + new String[] { "This is some dummy string", "This won't be mapped", "true", "C" }, + new String[] { "varString", "illegalPropertyName", "varBoolean", "varChar" }); try { mapper.mapFieldSet(fieldSet); fail("expected error"); @@ -610,8 +613,9 @@ public class BeanWrapperFieldSetMapperTests { mapper.setTargetType(TestObject.class); mapper.afterPropertiesSet(); - FieldSet fieldSet = new DefaultFieldSet(new String[] { "This is some dummy string", "This won't be mapped", - "true", "C" }, new String[] { "varString", "illegalPropertyName", "varBoolean", "varChar" }); + FieldSet fieldSet = new DefaultFieldSet( + new String[] { "This is some dummy string", "This won't be mapped", "true", "C" }, + new String[] { "varString", "illegalPropertyName", "varBoolean", "varChar" }); TestObject result = mapper.mapFieldSet(fieldSet); assertEquals("This is some dummy string", result.getVarString()); assertEquals(true, result.isVarBoolean()); @@ -633,6 +637,7 @@ public class BeanWrapperFieldSetMapperTests { } public static class TestNestedA { + private String valueA; private int valueB; @@ -666,6 +671,7 @@ public class BeanWrapperFieldSetMapperTests { } public static class TestNestedB { + private String valueA; private TestNestedC testObjectC; @@ -689,6 +695,7 @@ public class BeanWrapperFieldSetMapperTests { } public static class TestNestedC { + private int value; public int getValue() { @@ -698,9 +705,11 @@ public class BeanWrapperFieldSetMapperTests { public void setValue(int value) { this.value = value; } + } public static class TestTwoDoubles { + private double value; private double other; @@ -724,6 +733,7 @@ public class BeanWrapperFieldSetMapperTests { } public static class TestObject { + String varString; boolean varBoolean; @@ -836,9 +846,10 @@ public class BeanWrapperFieldSetMapperTests { public void setVarInt(int varInt) { this.varInt = varInt; } + } - public static class TestConversion implements ConversionService{ + public static class TestConversion implements ConversionService { @Override public boolean canConvert(@Nullable Class sourceType, Class targetType) { @@ -854,7 +865,7 @@ public class BeanWrapperFieldSetMapperTests { @Override @SuppressWarnings("unchecked") public T convert(@Nullable Object source, Class targetType) { - return (T)"CONVERTED"; + return (T) "CONVERTED"; } @Nullable @@ -862,5 +873,7 @@ public class BeanWrapperFieldSetMapperTests { public Object convert(@Nullable Object source, @Nullable TypeDescriptor sourceType, TypeDescriptor targetType) { return "CONVERTED"; } + } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/DefaultLineMapperTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/DefaultLineMapperTests.java index 12fdb2c59..0e76fe540 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/DefaultLineMapperTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/DefaultLineMapperTests.java @@ -1,68 +1,68 @@ -/* - * Copyright 2008-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.file.mapping; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.junit.Assert.assertSame; - -import org.junit.Test; -import org.springframework.batch.item.file.transform.DefaultFieldSet; -import org.springframework.batch.item.file.transform.DelimitedLineTokenizer; -import org.springframework.batch.item.file.transform.FieldSet; -import org.springframework.batch.item.file.transform.LineTokenizer; - -/** - * Tests for {@link DefaultLineMapper}. - */ -public class DefaultLineMapperTests { - - private DefaultLineMapper tested = new DefaultLineMapper<>(); - - @Test(expected=IllegalArgumentException.class) - public void testMandatoryTokenizer() throws Exception { - tested.afterPropertiesSet(); - tested.mapLine("foo", 1); - } - - @Test(expected=IllegalArgumentException.class) - public void testMandatoryMapper() throws Exception { - tested.setLineTokenizer(new DelimitedLineTokenizer()); - tested.afterPropertiesSet(); - tested.mapLine("foo", 1); - } - - @Test - public void testMapping() throws Exception { - final String line = "TEST"; - final FieldSet fs = new DefaultFieldSet(new String[]{"token1", "token2"}); - final String item = "ITEM"; - - LineTokenizer tokenizer = mock(LineTokenizer.class); - when(tokenizer.tokenize(line)).thenReturn(fs); - - @SuppressWarnings("unchecked") - FieldSetMapper fsMapper = mock(FieldSetMapper.class); - when(fsMapper.mapFieldSet(fs)).thenReturn(item); - - tested.setLineTokenizer(tokenizer); - tested.setFieldSetMapper(fsMapper); - - assertSame(item, tested.mapLine(line, 1)); - - } - -} +/* + * Copyright 2008-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item.file.mapping; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.junit.Assert.assertSame; + +import org.junit.Test; +import org.springframework.batch.item.file.transform.DefaultFieldSet; +import org.springframework.batch.item.file.transform.DelimitedLineTokenizer; +import org.springframework.batch.item.file.transform.FieldSet; +import org.springframework.batch.item.file.transform.LineTokenizer; + +/** + * Tests for {@link DefaultLineMapper}. + */ +public class DefaultLineMapperTests { + + private DefaultLineMapper tested = new DefaultLineMapper<>(); + + @Test(expected = IllegalArgumentException.class) + public void testMandatoryTokenizer() throws Exception { + tested.afterPropertiesSet(); + tested.mapLine("foo", 1); + } + + @Test(expected = IllegalArgumentException.class) + public void testMandatoryMapper() throws Exception { + tested.setLineTokenizer(new DelimitedLineTokenizer()); + tested.afterPropertiesSet(); + tested.mapLine("foo", 1); + } + + @Test + public void testMapping() throws Exception { + final String line = "TEST"; + final FieldSet fs = new DefaultFieldSet(new String[] { "token1", "token2" }); + final String item = "ITEM"; + + LineTokenizer tokenizer = mock(LineTokenizer.class); + when(tokenizer.tokenize(line)).thenReturn(fs); + + @SuppressWarnings("unchecked") + FieldSetMapper fsMapper = mock(FieldSetMapper.class); + when(fsMapper.mapFieldSet(fs)).thenReturn(item); + + tested.setLineTokenizer(tokenizer); + tested.setFieldSetMapper(fsMapper); + + assertSame(item, tested.mapLine(line, 1)); + + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/JsonLineMapperTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/JsonLineMapperTests.java index 5d68be2c8..6ff2d2584 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/JsonLineMapperTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/JsonLineMapperTests.java @@ -1,49 +1,49 @@ -/* - * Copyright 2009-2010 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.file.mapping; - -import java.util.Map; - -import com.fasterxml.jackson.core.JsonParseException; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -public class JsonLineMapperTests { - - private JsonLineMapper mapper = new JsonLineMapper(); - - @Test - public void testMapLine() throws Exception { - Map map = mapper.mapLine("{\"foo\": 1}", 1); - assertEquals(1, map.get("foo")); - } - - @SuppressWarnings("unchecked") - @Test - public void testMapNested() throws Exception { - Map map = mapper.mapLine("{\"foo\": 1, \"bar\" : {\"foo\": 2}}", 1); - assertEquals(1, map.get("foo")); - assertEquals(2, ((Map) map.get("bar")).get("foo")); - } - - @Test(expected=JsonParseException.class) - public void testMappingError() throws Exception { - Map map = mapper.mapLine("{\"foo\": 1", 1); - assertEquals(1, map.get("foo")); - } - -} +/* + * Copyright 2009-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item.file.mapping; + +import java.util.Map; + +import com.fasterxml.jackson.core.JsonParseException; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class JsonLineMapperTests { + + private JsonLineMapper mapper = new JsonLineMapper(); + + @Test + public void testMapLine() throws Exception { + Map map = mapper.mapLine("{\"foo\": 1}", 1); + assertEquals(1, map.get("foo")); + } + + @SuppressWarnings("unchecked") + @Test + public void testMapNested() throws Exception { + Map map = mapper.mapLine("{\"foo\": 1, \"bar\" : {\"foo\": 2}}", 1); + assertEquals(1, map.get("foo")); + assertEquals(2, ((Map) map.get("bar")).get("foo")); + } + + @Test(expected = JsonParseException.class) + public void testMappingError() throws Exception { + Map map = mapper.mapLine("{\"foo\": 1", 1); + assertEquals(1, map.get("foo")); + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/PassThroughFieldSetMapperTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/PassThroughFieldSetMapperTests.java index 3b6b80c35..59b34ffb1 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/PassThroughFieldSetMapperTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/PassThroughFieldSetMapperTests.java @@ -22,7 +22,7 @@ import junit.framework.TestCase; /** * @author Dave Syer - * + * */ public class PassThroughFieldSetMapperTests extends TestCase { @@ -37,5 +37,4 @@ public class PassThroughFieldSetMapperTests extends TestCase { assertEquals(fieldSet, mapper.mapFieldSet(fieldSet)); } - } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/PassThroughLineMapperTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/PassThroughLineMapperTests.java index 7c45f5375..e66b2a2e5 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/PassThroughLineMapperTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/PassThroughLineMapperTests.java @@ -1,33 +1,34 @@ -/* - * Copyright 2008 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.file.mapping; - -import static org.junit.Assert.*; - -import org.junit.Test; - -/** - * Tests for {@link PassThroughLineMapper}. - */ -public class PassThroughLineMapperTests { - - private PassThroughLineMapper tested = new PassThroughLineMapper(); - - @Test - public void testMapLine() throws Exception { - assertSame("line", tested.mapLine("line", 1)); - } -} +/* + * Copyright 2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item.file.mapping; + +import static org.junit.Assert.*; + +import org.junit.Test; + +/** + * Tests for {@link PassThroughLineMapper}. + */ +public class PassThroughLineMapperTests { + + private PassThroughLineMapper tested = new PassThroughLineMapper(); + + @Test + public void testMapLine() throws Exception { + assertSame("line", tested.mapLine("line", 1)); + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/PatternMatchingCompositeLineMapperTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/PatternMatchingCompositeLineMapperTests.java index 1cffddc2f..cf6c41de0 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/PatternMatchingCompositeLineMapperTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/PatternMatchingCompositeLineMapperTests.java @@ -51,13 +51,13 @@ public class PatternMatchingCompositeLineMapperTests { public void testKeyFound() throws Exception { Map tokenizers = new HashMap<>(); tokenizers.put("foo*", new LineTokenizer() { - @Override + @Override public FieldSet tokenize(@Nullable String line) { return new DefaultFieldSet(new String[] { "a", "b" }); } }); tokenizers.put("bar*", new LineTokenizer() { - @Override + @Override public FieldSet tokenize(@Nullable String line) { return new DefaultFieldSet(new String[] { "c", "d" }); } @@ -66,13 +66,13 @@ public class PatternMatchingCompositeLineMapperTests { Map> fieldSetMappers = new HashMap<>(); fieldSetMappers.put("foo*", new FieldSetMapper() { - @Override + @Override public Name mapFieldSet(FieldSet fs) { return new Name(fs.readString(0), fs.readString(1), 0); } }); fieldSetMappers.put("bar*", new FieldSetMapper() { - @Override + @Override public Name mapFieldSet(FieldSet fs) { return new Name(fs.readString(1), fs.readString(0), 0); } @@ -87,13 +87,13 @@ public class PatternMatchingCompositeLineMapperTests { public void testMapperKeyNotFound() throws Exception { Map tokenizers = new HashMap<>(); tokenizers.put("foo*", new LineTokenizer() { - @Override + @Override public FieldSet tokenize(@Nullable String line) { return new DefaultFieldSet(new String[] { "a", "b" }); } }); tokenizers.put("bar*", new LineTokenizer() { - @Override + @Override public FieldSet tokenize(@Nullable String line) { return new DefaultFieldSet(new String[] { "c", "d" }); } @@ -102,7 +102,7 @@ public class PatternMatchingCompositeLineMapperTests { Map> fieldSetMappers = new HashMap<>(); fieldSetMappers.put("foo*", new FieldSetMapper() { - @Override + @Override public Name mapFieldSet(FieldSet fs) { return new Name(fs.readString(0), fs.readString(1), 0); } @@ -112,4 +112,5 @@ public class PatternMatchingCompositeLineMapperTests { Name name = mapper.mapLine("bar", 1); assertEquals(new Name("d", "c", 0), name); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/PropertyMatchesTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/PropertyMatchesTests.java index c50955883..5d948b86f 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/PropertyMatchesTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/PropertyMatchesTests.java @@ -19,10 +19,10 @@ package org.springframework.batch.item.file.mapping; import junit.framework.TestCase; public class PropertyMatchesTests extends TestCase { - + public void setDuckSoup(String duckSoup) { } - + public void setDuckPate(String duckPate) { } @@ -33,7 +33,7 @@ public class PropertyMatchesTests extends TestCase { String[] matches = PropertyMatches.forProperty("DUCK_SOUP", getClass(), 2).getPossibleMatches(); assertEquals(1, matches.length); } - + public void testPropertyMatchesWithDefault() throws Exception { String[] matches = PropertyMatches.forProperty("DUCK_SOUP", getClass()).getPossibleMatches(); assertEquals(1, matches.length); @@ -41,25 +41,26 @@ public class PropertyMatchesTests extends TestCase { public void testBuildErrorMessageNoMatches() throws Exception { String msg = PropertyMatches.forProperty("foo", getClass(), 2).buildErrorMessage(); - assertTrue(msg.indexOf("foo")>=0); + assertTrue(msg.indexOf("foo") >= 0); } public void testBuildErrorMessagePossibleMatch() throws Exception { String msg = PropertyMatches.forProperty("DUCKSOUP", getClass(), 1).buildErrorMessage(); - // the message contains the close match - assertTrue(msg.indexOf("duckSoup")>=0); + // the message contains the close match + assertTrue(msg.indexOf("duckSoup") >= 0); } public void testBuildErrorMessageMultiplePossibleMatches() throws Exception { String msg = PropertyMatches.forProperty("DUCKCRAP", getClass(), 4).buildErrorMessage(); // the message contains the close matches - assertTrue(msg.indexOf("duckSoup")>=0); - assertTrue(msg.indexOf("duckPate")>=0); + assertTrue(msg.indexOf("duckSoup") >= 0); + assertTrue(msg.indexOf("duckPate") >= 0); } - + public void testEmptyString() throws Exception { String[] matches = PropertyMatches.forProperty("", getClass(), 4).getPossibleMatches(); // TestCase base class has a name property assertEquals("name", matches[0]); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/RecordFieldSetMapperTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/RecordFieldSetMapperTests.java index d715ca924..5a94a1a0d 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/RecordFieldSetMapperTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/RecordFieldSetMapperTests.java @@ -32,7 +32,7 @@ public class RecordFieldSetMapperTests { public void testMapFieldSet() { // given RecordFieldSetMapper recordFieldSetMapper = new RecordFieldSetMapper<>(Person.class); - FieldSet fieldSet = new DefaultFieldSet(new String[]{"1", "foo"}, new String[] {"id", "name"}); + FieldSet fieldSet = new DefaultFieldSet(new String[] { "1", "foo" }, new String[] { "id", "name" }); // when Person person = recordFieldSetMapper.mapFieldSet(fieldSet); @@ -47,13 +47,14 @@ public class RecordFieldSetMapperTests { public void testMapFieldSetWhenFieldCountIsIncorrect() { // given RecordFieldSetMapper recordFieldSetMapper = new RecordFieldSetMapper<>(Person.class); - FieldSet fieldSet = new DefaultFieldSet(new String[]{"1"}, new String[] {"id"}); + FieldSet fieldSet = new DefaultFieldSet(new String[] { "1" }, new String[] { "id" }); // when try { recordFieldSetMapper.mapFieldSet(fieldSet); fail("Should fail when fields count is not equal to record components count"); - } catch (IllegalArgumentException e) { + } + catch (IllegalArgumentException e) { // then Assert.assertEquals("Fields count must be equal to record components count", e.getMessage()); } @@ -63,20 +64,24 @@ public class RecordFieldSetMapperTests { public void testMapFieldSetWhenFieldNamesAreNotSpecified() { // given RecordFieldSetMapper recordFieldSetMapper = new RecordFieldSetMapper<>(Person.class); - FieldSet fieldSet = new DefaultFieldSet(new String[]{"1", "foo"}); + FieldSet fieldSet = new DefaultFieldSet(new String[] { "1", "foo" }); // when try { recordFieldSetMapper.mapFieldSet(fieldSet); fail("Should fail when field names are not specified"); - } catch (IllegalArgumentException e) { + } + catch (IllegalArgumentException e) { // then Assert.assertEquals("Field names must specified", e.getMessage()); } } - public static class Person { // TODO change to record in v5 + public static class Person { + + // TODO change to record in v5 private int id; + private String name; public Person(int id, String name) { @@ -91,5 +96,7 @@ public class RecordFieldSetMapperTests { public String name() { return name; } + } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/separator/DefaultRecordSeparatorPolicyTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/separator/DefaultRecordSeparatorPolicyTests.java index 99584bd47..c20bcd151 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/separator/DefaultRecordSeparatorPolicyTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/separator/DefaultRecordSeparatorPolicyTests.java @@ -21,7 +21,7 @@ import junit.framework.TestCase; public class DefaultRecordSeparatorPolicyTests extends TestCase { DefaultRecordSeparatorPolicy policy = new DefaultRecordSeparatorPolicy(); - + public void testNormalLine() throws Exception { assertTrue(policy.isEndOfRecord("a string")); } @@ -37,41 +37,42 @@ public class DefaultRecordSeparatorPolicyTests extends TestCase { public void testNullLine() throws Exception { assertTrue(policy.isEndOfRecord(null)); } - + public void testPostProcess() throws Exception { String line = "foo\nbar"; assertEquals(line, policy.postProcess(line)); } - + public void testPreProcessWithQuote() throws Exception { String line = "foo\"bar"; - assertEquals(line+"\n", policy.preProcess(line)); + assertEquals(line + "\n", policy.preProcess(line)); } public void testPreProcessWithNotDefaultQuote() throws Exception { String line = "foo'bar"; policy.setQuoteCharacter("'"); - assertEquals(line+"\n", policy.preProcess(line)); + assertEquals(line + "\n", policy.preProcess(line)); } - + public void testPreProcessWithoutQuote() throws Exception { String line = "foo"; - assertEquals(line, policy.preProcess(line)); + assertEquals(line, policy.preProcess(line)); } public void testContinuationMarkerNotEnd() throws Exception { String line = "foo\\"; - assertFalse(policy.isEndOfRecord(line)); + assertFalse(policy.isEndOfRecord(line)); } public void testNotDefaultContinuationMarkerNotEnd() throws Exception { String line = "foo bar"; policy.setContinuation("bar"); - assertFalse(policy.isEndOfRecord(line)); + assertFalse(policy.isEndOfRecord(line)); } public void testContinuationMarkerRemoved() throws Exception { String line = "foo\\"; - assertEquals("foo", policy.preProcess(line)); + assertEquals("foo", policy.preProcess(line)); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/separator/JsonRecordSeparatorPolicyTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/separator/JsonRecordSeparatorPolicyTests.java index 290d189a8..4c99b963b 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/separator/JsonRecordSeparatorPolicyTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/separator/JsonRecordSeparatorPolicyTests.java @@ -1,38 +1,38 @@ -/* - * Copyright 2009 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.file.separator; - -import static org.junit.Assert.*; - -import org.junit.Test; - -public class JsonRecordSeparatorPolicyTests { - - private JsonRecordSeparatorPolicy policy = new JsonRecordSeparatorPolicy(); - - @Test - public void testIsEndOfRecord() { - assertFalse(policy.isEndOfRecord("{\"a\":\"b\"")); - assertTrue(policy.isEndOfRecord("{\"a\":\"b\"} ")); - } - - @Test - public void testNestedObject() { - assertFalse(policy.isEndOfRecord("{\"a\": {\"b\": 2}")); - assertTrue(policy.isEndOfRecord("{\"a\": {\"b\": 2}} ")); - } - -} +/* + * Copyright 2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item.file.separator; + +import static org.junit.Assert.*; + +import org.junit.Test; + +public class JsonRecordSeparatorPolicyTests { + + private JsonRecordSeparatorPolicy policy = new JsonRecordSeparatorPolicy(); + + @Test + public void testIsEndOfRecord() { + assertFalse(policy.isEndOfRecord("{\"a\":\"b\"")); + assertTrue(policy.isEndOfRecord("{\"a\":\"b\"} ")); + } + + @Test + public void testNestedObject() { + assertFalse(policy.isEndOfRecord("{\"a\": {\"b\": 2}")); + assertTrue(policy.isEndOfRecord("{\"a\": {\"b\": 2}} ")); + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/separator/SimpleRecordSeparatorPolicyTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/separator/SimpleRecordSeparatorPolicyTests.java index 36ce460fa..be8b58dd9 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/separator/SimpleRecordSeparatorPolicyTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/separator/SimpleRecordSeparatorPolicyTests.java @@ -21,7 +21,7 @@ import junit.framework.TestCase; public class SimpleRecordSeparatorPolicyTests extends TestCase { SimpleRecordSeparatorPolicy policy = new SimpleRecordSeparatorPolicy(); - + public void testNormalLine() throws Exception { assertTrue(policy.isEndOfRecord("a string")); } @@ -33,7 +33,7 @@ public class SimpleRecordSeparatorPolicyTests extends TestCase { public void testNullLine() throws Exception { assertTrue(policy.isEndOfRecord(null)); } - + public void testPostProcess() throws Exception { String line = "foo\nbar"; assertEquals(line, policy.postProcess(line)); @@ -43,4 +43,5 @@ public class SimpleRecordSeparatorPolicyTests extends TestCase { String line = "foo\nbar"; assertEquals(line, policy.preProcess(line)); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/separator/SuffixRecordSeparatorPolicyTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/separator/SuffixRecordSeparatorPolicyTests.java index 6c4f716a3..c6de1354b 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/separator/SuffixRecordSeparatorPolicyTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/separator/SuffixRecordSeparatorPolicyTests.java @@ -21,28 +21,29 @@ import junit.framework.TestCase; public class SuffixRecordSeparatorPolicyTests extends TestCase { private static final String LINE = "a string"; + SuffixRecordSeparatorPolicy policy = new SuffixRecordSeparatorPolicy(); - + public void testNormalLine() throws Exception { assertFalse(policy.isEndOfRecord(LINE)); } public void testNormalLineWithDefaultSuffix() throws Exception { - assertTrue(policy.isEndOfRecord(LINE+SuffixRecordSeparatorPolicy.DEFAULT_SUFFIX)); + assertTrue(policy.isEndOfRecord(LINE + SuffixRecordSeparatorPolicy.DEFAULT_SUFFIX)); } public void testNormalLineWithNonDefaultSuffix() throws Exception { policy.setSuffix(":foo"); - assertTrue(policy.isEndOfRecord(LINE+ ":foo")); + assertTrue(policy.isEndOfRecord(LINE + ":foo")); } public void testNormalLineWithDefaultSuffixAndWhitespace() throws Exception { - assertTrue(policy.isEndOfRecord(LINE+SuffixRecordSeparatorPolicy.DEFAULT_SUFFIX+" ")); + assertTrue(policy.isEndOfRecord(LINE + SuffixRecordSeparatorPolicy.DEFAULT_SUFFIX + " ")); } public void testNormalLineWithDefaultSuffixWithIgnoreWhitespace() throws Exception { policy.setIgnoreWhitespace(false); - assertFalse(policy.isEndOfRecord(LINE+SuffixRecordSeparatorPolicy.DEFAULT_SUFFIX+" ")); + assertFalse(policy.isEndOfRecord(LINE + SuffixRecordSeparatorPolicy.DEFAULT_SUFFIX + " ")); } public void testEmptyLine() throws Exception { @@ -52,16 +53,16 @@ public class SuffixRecordSeparatorPolicyTests extends TestCase { public void testNullLineIsEndOfRecord() throws Exception { assertTrue(policy.isEndOfRecord(null)); } - + public void testPostProcessSunnyDay() throws Exception { String line = LINE; - String record = line+SuffixRecordSeparatorPolicy.DEFAULT_SUFFIX; - assertEquals(line, policy.postProcess(record)); + String record = line + SuffixRecordSeparatorPolicy.DEFAULT_SUFFIX; + assertEquals(line, policy.postProcess(record)); } public void testPostProcessNullLine() throws Exception { String line = null; - assertEquals(null, policy.postProcess(line)); + assertEquals(null, policy.postProcess(line)); } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/BeanWrapperFieldExtractorTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/BeanWrapperFieldExtractorTests.java index 834db7785..100bc351d 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/BeanWrapperFieldExtractorTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/BeanWrapperFieldExtractorTests.java @@ -74,4 +74,5 @@ public class BeanWrapperFieldExtractorTests { extractor.setNames(null); extractor.afterPropertiesSet(); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/CommonLineTokenizerTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/CommonLineTokenizerTests.java index 2f383783e..0a04c9833 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/CommonLineTokenizerTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/CommonLineTokenizerTests.java @@ -22,33 +22,34 @@ import junit.framework.TestCase; /** * Tests for {@link AbstractLineTokenizer}. - * + * * @author Robert Kasanicky * @author Dave Syer */ public class CommonLineTokenizerTests extends TestCase { - + /** - * Columns names are considered to be specified if they are not null or empty. + * Columns names are considered to be specified if they are not null or + * empty. */ public void testHasNames() { AbstractLineTokenizer tokenizer = new AbstractLineTokenizer() { - @Override + @Override protected List doTokenize(String line) { return null; } }; - + assertFalse(tokenizer.hasNames()); - + tokenizer.setNames((String) null); assertFalse(tokenizer.hasNames()); - + tokenizer.setNames(new ArrayList().toArray(new String[0])); assertFalse(tokenizer.hasNames()); - + tokenizer.setNames("name1", "name2"); assertTrue(tokenizer.hasNames()); } - + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/DefaultFieldSetFactoryTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/DefaultFieldSetFactoryTests.java index dd0e5c7b9..b68cd4b3a 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/DefaultFieldSetFactoryTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/DefaultFieldSetFactoryTests.java @@ -25,7 +25,7 @@ import org.junit.Test; /** * @author Dave Syer - * + * */ public class DefaultFieldSetFactoryTests { @@ -33,13 +33,13 @@ public class DefaultFieldSetFactoryTests { @Test public void testVanillaFieldSet() throws Exception { - FieldSet fieldSet = factory.create(new String[] {"foo", "bar"} ); + FieldSet fieldSet = factory.create(new String[] { "foo", "bar" }); assertEquals("foo", fieldSet.readString(0)); } @Test public void testVanillaFieldSetWithNames() throws Exception { - FieldSet fieldSet = factory.create(new String[] {"1", "bar"}, new String[] {"foo", "bar"} ); + FieldSet fieldSet = factory.create(new String[] { "1", "bar" }, new String[] { "foo", "bar" }); assertEquals(1, fieldSet.readInt("foo")); } @@ -47,14 +47,14 @@ public class DefaultFieldSetFactoryTests { public void testFieldSetWithDateFormat() throws Exception { SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd"); factory.setDateFormat(format); - FieldSet fieldSet = factory.create(new String[] {"1999/12/18", "bar"} ); + FieldSet fieldSet = factory.create(new String[] { "1999/12/18", "bar" }); assertEquals(format.parse("1999/12/18"), fieldSet.readDate(0)); } @Test public void testFieldSetWithNumberFormat() throws Exception { factory.setNumberFormat(NumberFormat.getNumberInstance(Locale.GERMAN)); - FieldSet fieldSet = factory.create(new String[] {"19.991.218", "bar"} ); + FieldSet fieldSet = factory.create(new String[] { "19.991.218", "bar" }); assertEquals(19991218, fieldSet.readInt(0)); } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/DefaultFieldSetTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/DefaultFieldSetTests.java index 13110fce7..e99825a57 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/DefaultFieldSetTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/DefaultFieldSetTests.java @@ -156,7 +156,7 @@ public class DefaultFieldSetTests { @Test public void testReadBigBigDecimal() throws Exception { - fieldSet = new DefaultFieldSet(new String[] {"12345678901234567890"}); + fieldSet = new DefaultFieldSet(new String[] { "12345678901234567890" }); BigDecimal bd = new BigDecimal("12345678901234567890"); assertEquals(bd, fieldSet.readBigDecimal(0)); @@ -264,13 +264,13 @@ public class DefaultFieldSetTests { @Test public void testReadIntWithSeparator() throws Exception { - fieldSet = new DefaultFieldSet(new String[] {"354,224"}); + fieldSet = new DefaultFieldSet(new String[] { "354,224" }); assertEquals(354224, fieldSet.readInt(0)); } @Test public void testReadIntWithSeparatorAndFormat() throws Exception { - fieldSet = new DefaultFieldSet(new String[] {"354.224"}); + fieldSet = new DefaultFieldSet(new String[] { "354.224" }); fieldSet.setNumberFormat(NumberFormat.getInstance(Locale.GERMAN)); assertEquals(354224, fieldSet.readInt(0)); } @@ -379,7 +379,7 @@ public class DefaultFieldSetTests { @Test public void testReadDateWithFormat() throws Exception { - fieldSet = new DefaultFieldSet(new String[] {"13/01/1999"}); + fieldSet = new DefaultFieldSet(new String[] { "13/01/1999" }); SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy"); fieldSet.setDateFormat(dateFormat); assertEquals(dateFormat.parse("13/01/1999"), fieldSet.readDate(0)); @@ -436,35 +436,39 @@ public class DefaultFieldSetTests { try { fieldSet.readDate(1, defaultDate); fail("Should throw IllegalArgumentException"); - } catch (IllegalArgumentException e) { + } + catch (IllegalArgumentException e) { assertTrue(e.getMessage().indexOf("yyyy-MM-dd") > 0); } try { fieldSet.readDate("String", defaultDate); fail("Should throw IllegalArgumentException"); - } catch (IllegalArgumentException e) { + } + catch (IllegalArgumentException e) { assertTrue(e.getMessage().indexOf("yyyy-MM-dd") > 0); assertTrue(e.getMessage().indexOf("name: [String]") > 0); } try { fieldSet.readDate(1, "dd-MM-yyyy", defaultDate); fail("Should throw IllegalArgumentException"); - } catch (IllegalArgumentException e) { + } + catch (IllegalArgumentException e) { assertTrue(e.getMessage().indexOf("dd-MM-yyyy") > 0); } try { fieldSet.readDate("String", "dd-MM-yyyy", defaultDate); fail("Should throw IllegalArgumentException"); - } catch (IllegalArgumentException e) { + } + catch (IllegalArgumentException e) { assertTrue(e.getMessage().indexOf("dd-MM-yyyy") > 0); assertTrue(e.getMessage().indexOf("name: [String]") > 0); } } - + @Test public void testStrictReadDateWithPattern() throws Exception { - fieldSet = new DefaultFieldSet(new String[] {"50-2-13"}); + fieldSet = new DefaultFieldSet(new String[] { "50-2-13" }); try { fieldSet.readDate(0, "dd-MM-yyyy"); fail("field value is not a valid date for strict parser, exception expected"); @@ -478,7 +482,7 @@ public class DefaultFieldSetTests { @Test public void testStrictReadDateWithPatternAndStrangeDate() throws Exception { - fieldSet = new DefaultFieldSet(new String[] {"5550212"}); + fieldSet = new DefaultFieldSet(new String[] { "5550212" }); try { System.err.println(fieldSet.readDate(0, "yyyyMMdd")); fail("field value is not a valid date for strict parser, exception expected"); @@ -649,4 +653,5 @@ public class DefaultFieldSetTests { assertEquals(value, fs.readRawString(0)); assertEquals(value, fs.readRawString(name)); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/DelimitedLineAggregatorTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/DelimitedLineAggregatorTests.java index 94ca082ee..a86b26a29 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/DelimitedLineAggregatorTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/DelimitedLineAggregatorTests.java @@ -22,14 +22,14 @@ import org.junit.Test; /** * @author Dave Syer - * + * */ public class DelimitedLineAggregatorTests { private static DelimitedLineAggregator aggregator; private FieldExtractor defaultFieldExtractor = new FieldExtractor() { - @Override + @Override public Object[] extract(String[] item) { return item; } @@ -56,4 +56,5 @@ public class DelimitedLineAggregatorTests { public void testAggregateWithNull() { assertEquals("foo,,bar", aggregator.aggregate(new String[] { "foo", null, "bar" })); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/DelimitedLineTokenizerTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/DelimitedLineTokenizerTests.java index 588b93a20..053217d8c 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/DelimitedLineTokenizerTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/DelimitedLineTokenizerTests.java @@ -22,7 +22,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; - public class DelimitedLineTokenizerTests { private static final String TOKEN_MATCHES = "token equals the expected string"; @@ -46,17 +45,17 @@ public class DelimitedLineTokenizerTests { assertTrue(TOKEN_MATCHES, tokens.readString(1).equals("")); } - @Test - public void testBlankString() { - FieldSet tokens = tokenizer.tokenize(" "); - assertTrue(TOKEN_MATCHES, tokens.readString(0).equals("")); - } + @Test + public void testBlankString() { + FieldSet tokens = tokenizer.tokenize(" "); + assertTrue(TOKEN_MATCHES, tokens.readString(0).equals("")); + } - @Test - public void testEmptyString() { - FieldSet tokens = tokenizer.tokenize("\"\""); - assertTrue(TOKEN_MATCHES, tokens.readString(0).equals("")); - } + @Test + public void testEmptyString() { + FieldSet tokens = tokenizer.tokenize("\"\""); + assertTrue(TOKEN_MATCHES, tokens.readString(0).equals("")); + } @Test public void testInvalidConstructorArgument() { @@ -77,7 +76,7 @@ public class DelimitedLineTokenizerTests { @Test public void testNames() { - tokenizer.setNames(new String[] {"A", "B", "C"}); + tokenizer.setNames(new String[] { "A", "B", "C" }); FieldSet line = tokenizer.tokenize("a,b,c"); assertEquals(3, line.getFieldCount()); assertEquals("a", line.readString("A")); @@ -85,7 +84,7 @@ public class DelimitedLineTokenizerTests { @Test public void testTooFewNames() { - tokenizer.setNames(new String[] {"A", "B"}); + tokenizer.setNames(new String[] { "A", "B" }); try { tokenizer.tokenize("a,b,c"); fail("Expected IncorrectTokenCountException"); @@ -99,7 +98,7 @@ public class DelimitedLineTokenizerTests { @Test public void testTooFewNamesNotStrict() { - tokenizer.setNames(new String[] {"A", "B"}); + tokenizer.setNames(new String[] { "A", "B" }); tokenizer.setStrict(false); FieldSet tokens = tokenizer.tokenize("a,b,c"); @@ -110,11 +109,11 @@ public class DelimitedLineTokenizerTests { @Test public void testTooManyNames() { - tokenizer.setNames(new String[] {"A", "B", "C", "D"}); - try{ + tokenizer.setNames(new String[] { "A", "B", "C", "D" }); + try { tokenizer.tokenize("a,b,c"); } - catch(IncorrectTokenCountException e){ + catch (IncorrectTokenCountException e) { assertEquals(4, e.getExpectedCount()); assertEquals(3, e.getActualCount()); assertEquals("a,b,c", e.getInput()); @@ -124,8 +123,8 @@ public class DelimitedLineTokenizerTests { @Test public void testTooManyNamesNotStrict() { - tokenizer.setNames(new String[] {"A", "B", "C", "D","E"}); - tokenizer.setStrict( false ); + tokenizer.setNames(new String[] { "A", "B", "C", "D", "E" }); + tokenizer.setStrict(false); FieldSet tokens = tokenizer.tokenize("a,b,c"); @@ -143,13 +142,13 @@ public class DelimitedLineTokenizerTests { assertEquals(3, line.getFieldCount()); } - @Test(expected=IllegalArgumentException.class) + @Test(expected = IllegalArgumentException.class) public void testDelimitedLineTokenizerNullDelimiter() { AbstractLineTokenizer tokenizer = new DelimitedLineTokenizer(null); tokenizer.tokenize("a b c"); } - @Test(expected=IllegalArgumentException.class) + @Test(expected = IllegalArgumentException.class) public void testDelimitedLineTokenizerEmptyString() throws Exception { DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer(""); tokenizer.afterPropertiesSet(); @@ -297,13 +296,13 @@ public class DelimitedLineTokenizerTests { } @Test - public void testEmptyLineWithNames(){ + public void testEmptyLineWithNames() { - tokenizer.setNames(new String[]{"A", "B"}); - try{ + tokenizer.setNames(new String[] { "A", "B" }); + try { tokenizer.tokenize(""); } - catch(IncorrectTokenCountException ex){ + catch (IncorrectTokenCountException ex) { assertEquals(2, ex.getExpectedCount()); assertEquals(0, ex.getActualCount()); assertEquals("", ex.getInput()); @@ -349,7 +348,7 @@ public class DelimitedLineTokenizerTests { @Test public void testTokenizeWithIncludedFields() { - tokenizer.setIncludedFields(new int[] {1,2}); + tokenizer.setIncludedFields(new int[] { 1, 2 }); FieldSet line = tokenizer.tokenize("\"a\",\"b\",\"c\",\"d\""); assertEquals(2, line.getFieldCount()); assertEquals("c", line.readString(1)); @@ -357,7 +356,7 @@ public class DelimitedLineTokenizerTests { @Test public void testTokenizeWithIncludedFieldsAndEmptyEnd() { - tokenizer.setIncludedFields(new int[] {1,3}); + tokenizer.setIncludedFields(new int[] { 1, 3 }); FieldSet line = tokenizer.tokenize("\"a\",\"b\",\"c\","); assertEquals(2, line.getFieldCount()); assertEquals("", line.readString(1)); @@ -365,26 +364,26 @@ public class DelimitedLineTokenizerTests { @Test public void testTokenizeWithIncludedFieldsAndNames() { - tokenizer.setIncludedFields(new int[] {1,2}); - tokenizer.setNames(new String[] {"foo", "bar"}); + tokenizer.setIncludedFields(new int[] { 1, 2 }); + tokenizer.setNames(new String[] { "foo", "bar" }); FieldSet line = tokenizer.tokenize("\"a\",\"b\",\"c\",\"d\""); assertEquals(2, line.getFieldCount()); assertEquals("c", line.readString("bar")); } - @Test(expected=IncorrectTokenCountException.class) + @Test(expected = IncorrectTokenCountException.class) public void testTokenizeWithIncludedFieldsAndTooFewNames() { - tokenizer.setIncludedFields(new int[] {1,2}); - tokenizer.setNames(new String[] {"foo"}); + tokenizer.setIncludedFields(new int[] { 1, 2 }); + tokenizer.setNames(new String[] { "foo" }); FieldSet line = tokenizer.tokenize("\"a\",\"b\",\"c\",\"d\""); assertEquals(2, line.getFieldCount()); assertEquals("c", line.readString("bar")); } - @Test(expected=IncorrectTokenCountException.class) + @Test(expected = IncorrectTokenCountException.class) public void testTokenizeWithIncludedFieldsAndTooManyNames() { - tokenizer.setIncludedFields(new int[] {1,2}); - tokenizer.setNames(new String[] {"foo", "bar", "spam"}); + tokenizer.setIncludedFields(new int[] { 1, 2 }); + tokenizer.setNames(new String[] { "foo", "bar", "spam" }); FieldSet line = tokenizer.tokenize("\"a\",\"b\",\"c\",\"d\""); assertEquals(2, line.getFieldCount()); assertEquals("c", line.readString("bar")); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/FixedLengthTokenizerTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/FixedLengthTokenizerTests.java index 9d08c104c..00f465081 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/FixedLengthTokenizerTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/FixedLengthTokenizerTests.java @@ -28,8 +28,8 @@ public class FixedLengthTokenizerTests { private String line = null; /** - * if null or empty string is tokenized, tokenizer returns empty fieldset - * (with no tokens). + * if null or empty string is tokenized, tokenizer returns empty fieldset (with no + * tokens). */ @Test public void testTokenizeEmptyString() { @@ -154,7 +154,7 @@ public class FixedLengthTokenizerTests { @Test public void testLongerLinesNotStrict() throws Exception { - tokenizer.setColumns(new Range[] { new Range(1, 10), new Range(11, 25), new Range(26,30) }); + tokenizer.setColumns(new Range[] { new Range(1, 10), new Range(11, 25), new Range(26, 30) }); line = "H1 12345678 1234567890"; tokenizer.setStrict(false); FieldSet tokens = tokenizer.tokenize(line); @@ -190,8 +190,8 @@ public class FixedLengthTokenizerTests { @Test public void testFillerAtEnd() throws Exception { - tokenizer.setColumns(new Range[] { new Range(1, 5), new Range(6, 15), new Range(16, 25), new Range(26, 27), - new Range(34) }); + tokenizer.setColumns( + new Range[] { new Range(1, 5), new Range(6, 15), new Range(16, 25), new Range(26, 27), new Range(34) }); // test another type of record line = "H2 123456 12345 12-123456"; FieldSet tokens = tokenizer.tokenize(line); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/FormatterLineAggregatorTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/FormatterLineAggregatorTests.java index 4b4c368fd..28859fddb 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/FormatterLineAggregatorTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/FormatterLineAggregatorTests.java @@ -24,7 +24,7 @@ import org.junit.Test; /** * Unit tests for {@link FormatterLineAggregator} - * + * * @author Dave Syer */ public class FormatterLineAggregatorTests { @@ -33,7 +33,7 @@ public class FormatterLineAggregatorTests { private FormatterLineAggregator aggregator; private FieldExtractor defaultFieldExtractor = new FieldExtractor() { - @Override + @Override public Object[] extract(String[] item) { return item; } @@ -126,7 +126,7 @@ public class FormatterLineAggregatorTests { aggregator.setFieldExtractor(new FieldExtractor() { private int[] widths = new int[] { 13, 12 }; - @Override + @Override public Object[] extract(String[] item) { String[] strings = new String[item.length]; for (int i = 0; i < strings.length; i++) { @@ -161,7 +161,7 @@ public class FormatterLineAggregatorTests { aggregator.setFieldExtractor(new FieldExtractor() { private int[] widths = new int[] { 13, 11 }; - @Override + @Override public Object[] extract(String[] item) { String[] strings = new String[item.length]; for (int i = 0; i < strings.length; i++) { @@ -194,8 +194,8 @@ public class FormatterLineAggregatorTests { } /** - * If one of the passed arguments is null, string filled with spaces should - * be returned + * If one of the passed arguments is null, string filled with spaces should be + * returned */ @Test public void testAggregateNullArgument() { diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/Name.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/Name.java index 493ff48b9..024d52058 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/Name.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/Name.java @@ -15,10 +15,12 @@ */ package org.springframework.batch.item.file.transform; - public class Name { + private String first; + private String last; + private int born; public Name() { @@ -91,5 +93,4 @@ public class Name { return true; } - } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/PassThroughFieldExtractorTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/PassThroughFieldExtractorTests.java index 6c2b58898..9c4389a82 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/PassThroughFieldExtractorTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/PassThroughFieldExtractorTests.java @@ -1,73 +1,73 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.file.transform; - -import static org.junit.Assert.assertTrue; - -import java.util.Arrays; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import org.junit.Test; - -/** - * @author Dan Garrette - * @since 2.0 - */ -public class PassThroughFieldExtractorTests { - - @Test - public void testExtractString() { - PassThroughFieldExtractor extractor = new PassThroughFieldExtractor<>(); - Object[] result = extractor.extract("abc"); - assertTrue(Arrays.equals(new Object[] { "abc" }, result)); - } - - @Test - public void testExtractArray() { - PassThroughFieldExtractor extractor = new PassThroughFieldExtractor<>(); - Object[] result = extractor.extract(new String[] { "a", "b", null, "d" }); - assertTrue(Arrays.equals(new Object[] { "a", "b", null, "d" }, result)); - } - - @Test - public void testExtractFieldSet() { - PassThroughFieldExtractor
      extractor = new PassThroughFieldExtractor<>(); - Object[] result = extractor.extract(new DefaultFieldSet(new String[] { "a", "b", "", "d" })); - assertTrue(Arrays.equals(new Object[] { "a", "b", "", "d" }, result)); - } - - @Test - public void testExtractCollection() { - PassThroughFieldExtractor> extractor = new PassThroughFieldExtractor<>(); - Object[] result = extractor.extract(Arrays.asList("a", "b", null, "d")); - assertTrue(Arrays.equals(new Object[] { "a", "b", null, "d" }, result)); - } - - @Test - public void testExtractMap() { - PassThroughFieldExtractor> extractor = new PassThroughFieldExtractor<>(); - Map map = new LinkedHashMap<>(); - map.put("A", "a"); - map.put("B", "b"); - map.put("C", null); - map.put("D", "d"); - Object[] result = extractor.extract(map); - assertTrue(Arrays.equals(new Object[] { "a", "b", null, "d" }, result)); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item.file.transform; + +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.junit.Test; + +/** + * @author Dan Garrette + * @since 2.0 + */ +public class PassThroughFieldExtractorTests { + + @Test + public void testExtractString() { + PassThroughFieldExtractor extractor = new PassThroughFieldExtractor<>(); + Object[] result = extractor.extract("abc"); + assertTrue(Arrays.equals(new Object[] { "abc" }, result)); + } + + @Test + public void testExtractArray() { + PassThroughFieldExtractor extractor = new PassThroughFieldExtractor<>(); + Object[] result = extractor.extract(new String[] { "a", "b", null, "d" }); + assertTrue(Arrays.equals(new Object[] { "a", "b", null, "d" }, result)); + } + + @Test + public void testExtractFieldSet() { + PassThroughFieldExtractor
      extractor = new PassThroughFieldExtractor<>(); + Object[] result = extractor.extract(new DefaultFieldSet(new String[] { "a", "b", "", "d" })); + assertTrue(Arrays.equals(new Object[] { "a", "b", "", "d" }, result)); + } + + @Test + public void testExtractCollection() { + PassThroughFieldExtractor> extractor = new PassThroughFieldExtractor<>(); + Object[] result = extractor.extract(Arrays.asList("a", "b", null, "d")); + assertTrue(Arrays.equals(new Object[] { "a", "b", null, "d" }, result)); + } + + @Test + public void testExtractMap() { + PassThroughFieldExtractor> extractor = new PassThroughFieldExtractor<>(); + Map map = new LinkedHashMap<>(); + map.put("A", "a"); + map.put("B", "b"); + map.put("C", null); + map.put("D", "d"); + Object[] result = extractor.extract(map); + assertTrue(Arrays.equals(new Object[] { "a", "b", null, "d" }, result)); + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/PassThroughLineAggregatorTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/PassThroughLineAggregatorTests.java index 44b9361c8..e46ea4e7f 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/PassThroughLineAggregatorTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/PassThroughLineAggregatorTests.java @@ -1,36 +1,36 @@ -/* - * Copyright 2008 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.file.transform; - -import junit.framework.TestCase; - -import org.springframework.batch.item.file.transform.LineAggregator; -import org.springframework.batch.item.file.transform.PassThroughLineAggregator; - -public class PassThroughLineAggregatorTests extends TestCase { - - private LineAggregator mapper = new PassThroughLineAggregator<>(); - - public void testUnmapItemAsFieldSet() throws Exception { - Object item = new Object(); - assertEquals(item.toString(), mapper.aggregate(item)); - } - - public void testUnmapItemAsString() throws Exception { - assertEquals("foo", mapper.aggregate("foo")); - } - -} +/* + * Copyright 2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item.file.transform; + +import junit.framework.TestCase; + +import org.springframework.batch.item.file.transform.LineAggregator; +import org.springframework.batch.item.file.transform.PassThroughLineAggregator; + +public class PassThroughLineAggregatorTests extends TestCase { + + private LineAggregator mapper = new PassThroughLineAggregator<>(); + + public void testUnmapItemAsFieldSet() throws Exception { + Object item = new Object(); + assertEquals(item.toString(), mapper.aggregate(item)); + } + + public void testUnmapItemAsString() throws Exception { + assertEquals("foo", mapper.aggregate("foo")); + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/PatternMatchingCompositeLineTokenizerTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/PatternMatchingCompositeLineTokenizerTests.java index 76cde5cf8..790dca73d 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/PatternMatchingCompositeLineTokenizerTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/PatternMatchingCompositeLineTokenizerTests.java @@ -46,7 +46,7 @@ public class PatternMatchingCompositeLineTokenizerTests { Map map = new HashMap<>(); map.put("*", new DelimitedLineTokenizer()); map.put("foo", new LineTokenizer() { - @Override + @Override public FieldSet tokenize(@Nullable String line) { return null; } @@ -62,7 +62,7 @@ public class PatternMatchingCompositeLineTokenizerTests { Map map = new LinkedHashMap<>(); map.put("*", new LineTokenizer() { - @Override + @Override public FieldSet tokenize(@Nullable String line) { return null; } @@ -84,7 +84,7 @@ public class PatternMatchingCompositeLineTokenizerTests { @Test public void testMatchWithPrefix() throws Exception { tokenizer.setTokenizers(Collections.singletonMap("foo*", (LineTokenizer) new LineTokenizer() { - @Override + @Override public FieldSet tokenize(@Nullable String line) { return new DefaultFieldSet(new String[] { line }); } @@ -94,4 +94,5 @@ public class PatternMatchingCompositeLineTokenizerTests { assertEquals(1, fields.getFieldCount()); assertEquals("foo bar", fields.readString(0)); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/RangeArrayPropertyEditorTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/RangeArrayPropertyEditorTests.java index 017acb68a..3ed073429 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/RangeArrayPropertyEditorTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/RangeArrayPropertyEditorTests.java @@ -20,20 +20,21 @@ import junit.framework.TestCase; public class RangeArrayPropertyEditorTests extends TestCase { private Range[] ranges; + private RangeArrayPropertyEditor pe; - @Override + @Override public void setUp() { ranges = null; pe = new RangeArrayPropertyEditor() { - @Override + @Override public void setValue(Object value) { ranges = (Range[]) value; } - @Override + @Override public Object getValue() { return ranges; } @@ -68,8 +69,7 @@ public class RangeArrayPropertyEditorTests extends TestCase { public void testGetAsText() { - ranges = new Range[] { new Range(20), new Range(6, 15), new Range(2), - new Range(26, 95) }; + ranges = new Range[] { new Range(20), new Range(6, 15), new Range(2), new Range(26, 95) }; assertEquals("20, 6-15, 2, 26-95", pe.getAsText()); } @@ -95,7 +95,8 @@ public class RangeArrayPropertyEditorTests extends TestCase { try { pe.setAsText("1-10, 5-15"); fail("Exception expected: ranges are not disjoint"); - } catch (IllegalArgumentException iae) { + } + catch (IllegalArgumentException iae) { // expected } } @@ -117,8 +118,10 @@ public class RangeArrayPropertyEditorTests extends TestCase { try { pe.setAsText("1-5, b"); fail("Exception expected: 2nd range is invalid"); - } catch (IllegalArgumentException iae) { + } + catch (IllegalArgumentException iae) { // expected } } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/RecursiveCollectionItemTransformerTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/RecursiveCollectionItemTransformerTests.java index d31822ece..3633f3edd 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/RecursiveCollectionItemTransformerTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/RecursiveCollectionItemTransformerTests.java @@ -24,7 +24,7 @@ import org.springframework.util.StringUtils; /** * @author Dave Syer - * + * */ public class RecursiveCollectionItemTransformerTests extends TestCase { @@ -34,7 +34,7 @@ public class RecursiveCollectionItemTransformerTests extends TestCase { public void testSetDelegateAndPassInString() throws Exception { aggregator.setDelegate(new LineAggregator() { - @Override + @Override public String aggregate(String item) { return "bar"; } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/RegexLineTokenizerTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/RegexLineTokenizerTests.java index f2b518e94..bec27cea0 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/RegexLineTokenizerTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/RegexLineTokenizerTests.java @@ -1,12 +1,12 @@ /* * Copyright 2006-2012 the original author or authors. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * https://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -28,7 +28,8 @@ public class RegexLineTokenizerTests { @Test public void testCapturingGroups() { String line = "Liverpool, England: 53d 25m 0s N 3d 0m 0s"; - tokenizer.setRegex("([a-zA-Z]+), ([a-zA-Z]+): ([0-9]+). ([0-9]+). ([0-9]+). ([A-Z]) ([0-9]+). ([0-9]+). ([0-9]+)."); + tokenizer.setRegex( + "([a-zA-Z]+), ([a-zA-Z]+): ([0-9]+). ([0-9]+). ([0-9]+). ([A-Z]) ([0-9]+). ([0-9]+). ([0-9]+)."); List tokens = tokenizer.doTokenize(line); assertEquals(9, tokens.size()); assertEquals("England", tokens.get(1)); @@ -51,4 +52,5 @@ public class RegexLineTokenizerTests { List tokens = tokenizer.doTokenize("noNumber"); assertEquals(0, tokens.size()); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/function/FunctionItemProcessorTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/function/FunctionItemProcessorTests.java index 01ca7e95a..a6b13ffc5 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/function/FunctionItemProcessorTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/function/FunctionItemProcessorTests.java @@ -43,15 +43,16 @@ public class FunctionItemProcessorTests { new FunctionItemProcessor<>(null); fail("null should not be accepted as a constructor arg"); } - catch (IllegalArgumentException iae) {} + catch (IllegalArgumentException iae) { + } } @Test public void testFunctionItemProcessor() throws Exception { - ItemProcessor itemProcessor = - new FunctionItemProcessor<>(this.function); + ItemProcessor itemProcessor = new FunctionItemProcessor<>(this.function); assertEquals("1", itemProcessor.process(1L)); assertEquals("foo", itemProcessor.process("foo")); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/JmsItemReaderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/JmsItemReaderTests.java index ac9ada385..daaf9cd07 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/JmsItemReaderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/JmsItemReaderTests.java @@ -98,18 +98,18 @@ public class JmsItemReaderTests { assertEquals(message, itemReader.read()); } - @Test(expected=IllegalArgumentException.class) + @Test(expected = IllegalArgumentException.class) public void testTemplateWithNoDefaultDestination() throws Exception { JmsTemplate jmsTemplate = new JmsTemplate(); jmsTemplate.setReceiveTimeout(100L); - itemReader.setJmsTemplate(jmsTemplate); + itemReader.setJmsTemplate(jmsTemplate); } - @Test(expected=IllegalArgumentException.class) + @Test(expected = IllegalArgumentException.class) public void testTemplateWithNoTimeout() throws Exception { JmsTemplate jmsTemplate = new JmsTemplate(); jmsTemplate.setDefaultDestinationName("foo"); - itemReader.setJmsTemplate(jmsTemplate); + itemReader.setJmsTemplate(jmsTemplate); } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/JmsItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/JmsItemWriterTests.java index f21dd65c9..5138921af 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/JmsItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/JmsItemWriterTests.java @@ -37,11 +37,11 @@ public class JmsItemWriterTests { itemWriter.setJmsTemplate(jmsTemplate); itemWriter.write(Arrays.asList("foo", "bar")); } - - @Test(expected=IllegalArgumentException.class) + + @Test(expected = IllegalArgumentException.class) public void testTemplateWithNoDefaultDestination() throws Exception { JmsTemplate jmsTemplate = new JmsTemplate(); - itemWriter.setJmsTemplate(jmsTemplate); + itemWriter.setJmsTemplate(jmsTemplate); } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/JmsMethodArgumentsKeyGeneratorTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/JmsMethodArgumentsKeyGeneratorTests.java index e911df4e7..3710e91a9 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/JmsMethodArgumentsKeyGeneratorTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/JmsMethodArgumentsKeyGeneratorTests.java @@ -23,7 +23,6 @@ import jakarta.jms.Message; import org.junit.Test; - /** * @author Dave Syer * @author Will Schipp @@ -31,8 +30,8 @@ import org.junit.Test; * */ public class JmsMethodArgumentsKeyGeneratorTests { - - private JmsMethodArgumentsKeyGenerator methodArgumentsKeyGenerator = new JmsMethodArgumentsKeyGenerator(); + + private JmsMethodArgumentsKeyGenerator methodArgumentsKeyGenerator = new JmsMethodArgumentsKeyGenerator(); @Test public void testGetKeyFromMessage() throws Exception { @@ -41,13 +40,13 @@ public class JmsMethodArgumentsKeyGeneratorTests { JmsItemReader itemReader = new JmsItemReader<>(); itemReader.setItemType(Message.class); - assertEquals("foo", methodArgumentsKeyGenerator.getKey(new Object[]{message})); + assertEquals("foo", methodArgumentsKeyGenerator.getKey(new Object[] { message })); } @Test public void testGetKeyFromNonMessage() throws Exception { - assertEquals("foo", methodArgumentsKeyGenerator.getKey(new Object[]{"foo"})); + assertEquals("foo", methodArgumentsKeyGenerator.getKey(new Object[] { "foo" })); } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/JmsNewMethodArgumentsIdentifierTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/JmsNewMethodArgumentsIdentifierTests.java index 2150cc540..139e0a06a 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/JmsNewMethodArgumentsIdentifierTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/JmsNewMethodArgumentsIdentifierTests.java @@ -23,7 +23,6 @@ import jakarta.jms.Message; import org.junit.Test; - /** * @author Dave Syer * @author Will Schipp @@ -31,19 +30,20 @@ import org.junit.Test; * */ public class JmsNewMethodArgumentsIdentifierTests { - + private JmsNewMethodArgumentsIdentifier newMethodArgumentsIdentifier = new JmsNewMethodArgumentsIdentifier<>(); @Test public void testIsNewForMessage() throws Exception { Message message = mock(Message.class); when(message.getJMSRedelivered()).thenReturn(true); - assertEquals(false, newMethodArgumentsIdentifier.isNew(new Object[]{message})); - + assertEquals(false, newMethodArgumentsIdentifier.isNew(new Object[] { message })); + } @Test public void testIsNewForNonMessage() throws Exception { - assertEquals(false, newMethodArgumentsIdentifier.isNew(new Object[]{"foo"})); + assertEquals(false, newMethodArgumentsIdentifier.isNew(new Object[] { "foo" })); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/builder/JmsItemReaderBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/builder/JmsItemReaderBuilderTests.java index 002c29ef8..cfa938bce 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/builder/JmsItemReaderBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/builder/JmsItemReaderBuilderTests.java @@ -101,4 +101,5 @@ public class JmsItemReaderBuilderTests { "jmsTemplate is required.", ise.getMessage()); } } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/builder/JmsItemWriterBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/builder/JmsItemWriterBuilderTests.java index 42c891faa..cd1a7b703 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/builder/JmsItemWriterBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/builder/JmsItemWriterBuilderTests.java @@ -46,7 +46,7 @@ public class JmsItemWriterBuilderTests { assertEquals("Expected foo", "foo", argCaptor.getAllValues().get(0)); assertEquals("Expected bar", "bar", argCaptor.getAllValues().get(1)); } - + @Test public void testNullJmsTemplate() { try { @@ -58,4 +58,5 @@ public class JmsItemWriterBuilderTests { "jmsTemplate is required.", ise.getMessage()); } } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/GsonJsonObjectMarshallerTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/GsonJsonObjectMarshallerTests.java index 50030139c..f29f97bfc 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/GsonJsonObjectMarshallerTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/GsonJsonObjectMarshallerTests.java @@ -37,7 +37,9 @@ public class GsonJsonObjectMarshallerTests { } public static class Foo { + private int id; + private String name; public Foo(int id, String name) { @@ -60,6 +62,7 @@ public class GsonJsonObjectMarshallerTests { public void setName(String name) { this.name = name; } + } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/JacksonJsonObjectMarshallerTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/JacksonJsonObjectMarshallerTests.java index e541fdc8b..00f85aa8b 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/JacksonJsonObjectMarshallerTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/JacksonJsonObjectMarshallerTests.java @@ -37,7 +37,9 @@ public class JacksonJsonObjectMarshallerTests { } public static class Foo { + private int id; + private String name; public Foo(int id, String name) { @@ -60,6 +62,7 @@ public class JacksonJsonObjectMarshallerTests { public void setName(String name) { this.name = name; } + } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/JsonFileItemWriterFunctionalTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/JsonFileItemWriterFunctionalTests.java index 84bbdb554..06056c25d 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/JsonFileItemWriterFunctionalTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/JsonFileItemWriterFunctionalTests.java @@ -50,25 +50,28 @@ public abstract class JsonFileItemWriterFunctionalTests { private static final String EXPECTED_FILE_DIRECTORY = "src/test/resources/org/springframework/batch/item/json/"; private Trade trade1 = new Trade("123", 5, new BigDecimal("10.5"), "foo"); + private Trade trade2 = new Trade("456", 10, new BigDecimal("20.5"), "bar"); + private Trade trade3 = new Trade("789", 15, new BigDecimal("30.5"), "foobar"); + private Trade trade4 = new Trade("987", 20, new BigDecimal("40.5"), "barfoo"); protected abstract JsonObjectMarshaller getJsonObjectMarshaller(); + protected abstract JsonObjectMarshaller getJsonObjectMarshallerWithPrettyPrint(); + protected abstract String getExpectedPrettyPrintedFile(); + protected abstract String getMarshallerName(); @Test public void testJsonWriting() throws Exception { - //given + // given Path outputFilePath = Paths.get("target", "trades-" + getMarshallerName() + ".json"); FileSystemResource resource = new FileSystemResource(outputFilePath); - JsonFileItemWriter writer = new JsonFileItemWriterBuilder() - .name("tradesItemWriter") - .resource(resource) - .jsonObjectMarshaller(getJsonObjectMarshaller()) - .build(); + JsonFileItemWriter writer = new JsonFileItemWriterBuilder().name("tradesItemWriter") + .resource(resource).jsonObjectMarshaller(getJsonObjectMarshaller()).build(); // when writer.open(new ExecutionContext()); @@ -76,21 +79,16 @@ public abstract class JsonFileItemWriterFunctionalTests { writer.close(); // then - assertFileEquals( - new File(EXPECTED_FILE_DIRECTORY + "expected-trades.json"), - resource.getFile()); + assertFileEquals(new File(EXPECTED_FILE_DIRECTORY + "expected-trades.json"), resource.getFile()); } @Test public void testJsonWritingWithMultipleWrite() throws Exception { - //given + // given Path outputFilePath = Paths.get("target", "testJsonWritingWithMultipleWrite-" + getMarshallerName() + ".json"); FileSystemResource resource = new FileSystemResource(outputFilePath); - JsonFileItemWriter writer = new JsonFileItemWriterBuilder() - .name("tradesItemWriter") - .resource(resource) - .jsonObjectMarshaller(getJsonObjectMarshaller()) - .build(); + JsonFileItemWriter writer = new JsonFileItemWriterBuilder().name("tradesItemWriter") + .resource(resource).jsonObjectMarshaller(getJsonObjectMarshaller()).build(); // when writer.open(new ExecutionContext()); @@ -99,8 +97,7 @@ public abstract class JsonFileItemWriterFunctionalTests { writer.close(); // then - assertFileEquals( - new File(EXPECTED_FILE_DIRECTORY + "expected-trades-with-multiple-writes.json"), + assertFileEquals(new File(EXPECTED_FILE_DIRECTORY + "expected-trades-with-multiple-writes.json"), resource.getFile()); } @@ -109,11 +106,8 @@ public abstract class JsonFileItemWriterFunctionalTests { // given Path outputFilePath = Paths.get("target", "testJsonWritingWithPrettyPrinting-" + getMarshallerName() + ".json"); FileSystemResource resource = new FileSystemResource(outputFilePath); - JsonFileItemWriter writer = new JsonFileItemWriterBuilder() - .name("tradesItemWriter") - .resource(resource) - .jsonObjectMarshaller(getJsonObjectMarshallerWithPrettyPrint()) - .build(); + JsonFileItemWriter writer = new JsonFileItemWriterBuilder().name("tradesItemWriter") + .resource(resource).jsonObjectMarshaller(getJsonObjectMarshallerWithPrettyPrint()).build(); // when writer.open(new ExecutionContext()); @@ -121,20 +115,17 @@ public abstract class JsonFileItemWriterFunctionalTests { writer.close(); // when - assertFileEquals( - new File(EXPECTED_FILE_DIRECTORY + getExpectedPrettyPrintedFile()), - resource.getFile()); + assertFileEquals(new File(EXPECTED_FILE_DIRECTORY + getExpectedPrettyPrintedFile()), resource.getFile()); } @Test public void testJsonWritingWithEnclosingObject() throws Exception { // given - Path outputFilePath = Paths.get("target", "testJsonWritingWithEnclosingObject-" + getMarshallerName() + ".json"); + Path outputFilePath = Paths.get("target", + "testJsonWritingWithEnclosingObject-" + getMarshallerName() + ".json"); FileSystemResource resource = new FileSystemResource(outputFilePath); - JsonFileItemWriter writer = new JsonFileItemWriterBuilder() - .name("tradesItemWriter") - .resource(resource) - .jsonObjectMarshaller(getJsonObjectMarshaller()) + JsonFileItemWriter writer = new JsonFileItemWriterBuilder().name("tradesItemWriter") + .resource(resource).jsonObjectMarshaller(getJsonObjectMarshaller()) .headerCallback(headerWriter -> headerWriter.write("{\"trades\":[")) .footerCallback(footerWriter -> footerWriter.write(JsonFileItemWriter.DEFAULT_LINE_SEPARATOR + "]}")) .build(); @@ -145,8 +136,7 @@ public abstract class JsonFileItemWriterFunctionalTests { writer.close(); // then - assertFileEquals( - new File(EXPECTED_FILE_DIRECTORY + "expected-trades-with-wrapper-object.json"), + assertFileEquals(new File(EXPECTED_FILE_DIRECTORY + "expected-trades-with-wrapper-object.json"), resource.getFile()); } @@ -155,12 +145,8 @@ public abstract class JsonFileItemWriterFunctionalTests { // given Path outputFilePath = Paths.get("target", "testForcedWrite-" + getMarshallerName() + ".json"); FileSystemResource resource = new FileSystemResource(outputFilePath); - JsonFileItemWriter writer = new JsonFileItemWriterBuilder() - .name("tradesItemWriter") - .resource(resource) - .jsonObjectMarshaller(getJsonObjectMarshaller()) - .forceSync(true) - .build(); + JsonFileItemWriter writer = new JsonFileItemWriterBuilder().name("tradesItemWriter") + .resource(resource).jsonObjectMarshaller(getJsonObjectMarshaller()).forceSync(true).build(); // when writer.open(new ExecutionContext()); @@ -168,9 +154,7 @@ public abstract class JsonFileItemWriterFunctionalTests { writer.close(); // then - assertFileEquals( - new File(EXPECTED_FILE_DIRECTORY + "expected-trades1.json"), - resource.getFile()); + assertFileEquals(new File(EXPECTED_FILE_DIRECTORY + "expected-trades1.json"), resource.getFile()); } @Test @@ -179,12 +163,8 @@ public abstract class JsonFileItemWriterFunctionalTests { ExecutionContext executionContext = new ExecutionContext(); Path outputFilePath = Paths.get("target", "testWriteWithDelete-" + getMarshallerName() + ".json"); FileSystemResource resource = new FileSystemResource(outputFilePath); - JsonFileItemWriter writer = new JsonFileItemWriterBuilder() - .name("tradesItemWriter") - .resource(resource) - .jsonObjectMarshaller(getJsonObjectMarshaller()) - .shouldDeleteIfExists(true) - .build(); + JsonFileItemWriter writer = new JsonFileItemWriterBuilder().name("tradesItemWriter") + .resource(resource).jsonObjectMarshaller(getJsonObjectMarshaller()).shouldDeleteIfExists(true).build(); // when writer.open(executionContext); @@ -195,9 +175,7 @@ public abstract class JsonFileItemWriterFunctionalTests { writer.close(); // then - assertFileEquals( - new File(EXPECTED_FILE_DIRECTORY + "expected-trades2.json"), - resource.getFile()); + assertFileEquals(new File(EXPECTED_FILE_DIRECTORY + "expected-trades2.json"), resource.getFile()); } @Test @@ -206,11 +184,8 @@ public abstract class JsonFileItemWriterFunctionalTests { ExecutionContext executionContext = new ExecutionContext(); Path outputFilePath = Paths.get("target", "testRestart-" + getMarshallerName() + ".json"); FileSystemResource resource = new FileSystemResource(outputFilePath); - JsonFileItemWriter writer = new JsonFileItemWriterBuilder() - .name("tradesItemWriter") - .resource(resource) - .jsonObjectMarshaller(getJsonObjectMarshaller()) - .build(); + JsonFileItemWriter writer = new JsonFileItemWriterBuilder().name("tradesItemWriter") + .resource(resource).jsonObjectMarshaller(getJsonObjectMarshaller()).build(); // when writer.open(executionContext); @@ -231,9 +206,7 @@ public abstract class JsonFileItemWriterFunctionalTests { writer.close(); // verify what was written to the file - assertFileEquals( - new File(EXPECTED_FILE_DIRECTORY+ "expected-trades.json"), - resource.getFile()); + assertFileEquals(new File(EXPECTED_FILE_DIRECTORY + "expected-trades.json"), resource.getFile()); // 2 lines were written to the file in total assertEquals(2, executionContext.getLong("tradesItemWriter.written")); @@ -246,11 +219,8 @@ public abstract class JsonFileItemWriterFunctionalTests { ExecutionContext executionContext = new ExecutionContext(); Path outputFilePath = Paths.get("target", "testTransactionalRestart-" + getMarshallerName() + ".json"); FileSystemResource resource = new FileSystemResource(outputFilePath); - JsonFileItemWriter writer = new JsonFileItemWriterBuilder() - .name("tradesItemWriter") - .resource(resource) - .jsonObjectMarshaller(getJsonObjectMarshaller()) - .build(); + JsonFileItemWriter writer = new JsonFileItemWriterBuilder().name("tradesItemWriter") + .resource(resource).jsonObjectMarshaller(getJsonObjectMarshaller()).build(); // when writer.open(executionContext); @@ -289,9 +259,7 @@ public abstract class JsonFileItemWriterFunctionalTests { writer.close(); // verify what was written to the file - assertFileEquals( - new File(EXPECTED_FILE_DIRECTORY+ "expected-trades.json"), - resource.getFile()); + assertFileEquals(new File(EXPECTED_FILE_DIRECTORY + "expected-trades.json"), resource.getFile()); // 2 lines were written to the file in total assertEquals(2, executionContext.getLong("tradesItemWriter.written")); @@ -303,11 +271,10 @@ public abstract class JsonFileItemWriterFunctionalTests { ExecutionContext executionContext = new ExecutionContext(); Path outputFilePath = Paths.get("target", "testItemMarshallingFailure-" + getMarshallerName() + ".json"); FileSystemResource resource = new FileSystemResource(outputFilePath); - JsonFileItemWriter writer = new JsonFileItemWriterBuilder() - .name("tradesItemWriter") - .resource(resource) - .jsonObjectMarshaller(item -> { throw new IllegalArgumentException("Bad item"); }) - .build(); + JsonFileItemWriter writer = new JsonFileItemWriterBuilder().name("tradesItemWriter") + .resource(resource).jsonObjectMarshaller(item -> { + throw new IllegalArgumentException("Bad item"); + }).build(); // when writer.open(executionContext); @@ -322,14 +289,13 @@ public abstract class JsonFileItemWriterFunctionalTests { writer.close(); } - assertFileEquals( - new File(EXPECTED_FILE_DIRECTORY + "empty-trades.json"), - resource.getFile()); + assertFileEquals(new File(EXPECTED_FILE_DIRECTORY + "empty-trades.json"), resource.getFile()); } @Test /* - * If append=true a new output file should still be created on the first run (not restart). + * If append=true a new output file should still be created on the first run (not + * restart). */ public void testAppendToNotYetExistingFile() throws Exception { // given @@ -337,22 +303,17 @@ public abstract class JsonFileItemWriterFunctionalTests { Path outputFilePath = Paths.get("target", "testAppendToNotYetExistingFile-" + getMarshallerName() + ".json"); FileSystemResource resource = new FileSystemResource(outputFilePath); Files.deleteIfExists(outputFilePath); - JsonFileItemWriter writer = new JsonFileItemWriterBuilder() - .name("tradesItemWriter") - .resource(new FileSystemResource(outputFilePath)) - .jsonObjectMarshaller(getJsonObjectMarshaller()) - .append(true) - .build(); + JsonFileItemWriter writer = new JsonFileItemWriterBuilder().name("tradesItemWriter") + .resource(new FileSystemResource(outputFilePath)).jsonObjectMarshaller(getJsonObjectMarshaller()) + .append(true).build(); // when writer.open(executionContext); writer.write(Collections.singletonList(this.trade1)); writer.close(); - + // then - assertFileEquals( - new File(EXPECTED_FILE_DIRECTORY + "expected-trades1.json"), - resource.getFile()); + assertFileEquals(new File(EXPECTED_FILE_DIRECTORY + "expected-trades1.json"), resource.getFile()); } private void assertFileEquals(File expected, File actual) throws Exception { diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/JsonFileItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/JsonFileItemWriterTests.java index b644dfb44..803279e4f 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/JsonFileItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/JsonFileItemWriterTests.java @@ -38,6 +38,7 @@ import org.springframework.core.io.WritableResource; public class JsonFileItemWriterTests { private WritableResource resource; + @Mock private JsonObjectMarshaller jsonObjectMarshaller; @@ -71,4 +72,5 @@ public class JsonFileItemWriterTests { Mockito.verify(this.jsonObjectMarshaller).marshal("foo"); Mockito.verify(this.jsonObjectMarshaller).marshal("bar"); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/JsonItemReaderCommonTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/JsonItemReaderCommonTests.java index fad5d1e94..828f2d63c 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/JsonItemReaderCommonTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/JsonItemReaderCommonTests.java @@ -27,13 +27,8 @@ import org.springframework.core.io.ByteArrayResource; */ public abstract class JsonItemReaderCommonTests extends AbstractItemStreamItemReaderTests { - private static final String FOOS = "[" + - " {\"value\":1}," + - " {\"value\":2}," + - " {\"value\":3}," + - " {\"value\":4}," + - " {\"value\":5}" + - "]"; + private static final String FOOS = "[" + " {\"value\":1}," + " {\"value\":2}," + " {\"value\":3}," + + " {\"value\":4}," + " {\"value\":5}" + "]"; protected abstract JsonObjectReader getJsonObjectReader(); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/JsonItemReaderFunctionalTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/JsonItemReaderFunctionalTests.java index 1991b2a40..857b787a5 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/JsonItemReaderFunctionalTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/JsonItemReaderFunctionalTests.java @@ -44,11 +44,9 @@ public abstract class JsonItemReaderFunctionalTests { @Test public void testJsonReading() throws Exception { - JsonItemReader itemReader = new JsonItemReaderBuilder() - .jsonObjectReader(getJsonObjectReader()) + JsonItemReader itemReader = new JsonItemReaderBuilder().jsonObjectReader(getJsonObjectReader()) .resource(new ClassPathResource("org/springframework/batch/item/json/trades.json")) - .name("tradeJsonItemReader") - .build(); + .name("tradeJsonItemReader").build(); itemReader.open(new ExecutionContext()); @@ -86,11 +84,8 @@ public abstract class JsonItemReaderFunctionalTests { @Test public void testEmptyResource() throws Exception { - JsonItemReader itemReader = new JsonItemReaderBuilder() - .jsonObjectReader(getJsonObjectReader()) - .resource(new ByteArrayResource("[]".getBytes())) - .name("tradeJsonItemReader") - .build(); + JsonItemReader itemReader = new JsonItemReaderBuilder().jsonObjectReader(getJsonObjectReader()) + .resource(new ByteArrayResource("[]".getBytes())).name("tradeJsonItemReader").build(); itemReader.open(new ExecutionContext()); @@ -101,14 +96,12 @@ public abstract class JsonItemReaderFunctionalTests { @Test public void testInvalidResourceFormat() { // given - JsonItemReader itemReader = new JsonItemReaderBuilder() - .jsonObjectReader(getJsonObjectReader()) - .resource(new ByteArrayResource("{}, {}".getBytes())) - .name("tradeJsonItemReader") - .build(); + JsonItemReader itemReader = new JsonItemReaderBuilder().jsonObjectReader(getJsonObjectReader()) + .resource(new ByteArrayResource("{}, {}".getBytes())).name("tradeJsonItemReader").build(); // when - final Exception expectedException = assertThrows(ItemStreamException.class, () -> itemReader.open(new ExecutionContext())); + final Exception expectedException = assertThrows(ItemStreamException.class, + () -> itemReader.open(new ExecutionContext())); // then assertEquals("Failed to initialize the reader", expectedException.getMessage()); @@ -118,18 +111,15 @@ public abstract class JsonItemReaderFunctionalTests { @Test public void testInvalidResourceContent() { // given - JsonItemReader itemReader = new JsonItemReaderBuilder() - .jsonObjectReader(getJsonObjectReader()) - .resource(new ByteArrayResource("[{]".getBytes())) - .name("tradeJsonItemReader") - .build(); + JsonItemReader itemReader = new JsonItemReaderBuilder().jsonObjectReader(getJsonObjectReader()) + .resource(new ByteArrayResource("[{]".getBytes())).name("tradeJsonItemReader").build(); itemReader.open(new ExecutionContext()); // when final Exception expectedException = assertThrows(ParseException.class, itemReader::read); - // then assertTrue(getJsonParsingException().isInstance(expectedException.getCause())); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/JsonItemReaderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/JsonItemReaderTests.java index 7d7313834..fae5dfaf1 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/JsonItemReaderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/JsonItemReaderTests.java @@ -51,14 +51,16 @@ public class JsonItemReaderTests { try { new JsonItemReader<>(null, this.jsonObjectReader); fail("A resource is required."); - } catch (IllegalArgumentException iae) { + } + catch (IllegalArgumentException iae) { assertEquals("The resource must not be null.", iae.getMessage()); } try { new JsonItemReader<>(new ByteArrayResource("[{}]".getBytes()), null); fail("A json object reader is required."); - } catch (IllegalArgumentException iae) { + } + catch (IllegalArgumentException iae) { assertEquals("The json object reader must not be null.", iae.getMessage()); } } @@ -124,6 +126,7 @@ public class JsonItemReaderTests { public InputStream getInputStream() { return null; } + } private static class NonReadableResource extends AbstractResource { @@ -150,5 +153,7 @@ public class JsonItemReaderTests { public InputStream getInputStream() { return null; } + } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/builder/JsonFileItemWriterBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/builder/JsonFileItemWriterBuilderTests.java index 977a9f45b..b258452cb 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/builder/JsonFileItemWriterBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/builder/JsonFileItemWriterBuilderTests.java @@ -42,6 +42,7 @@ import static org.junit.Assert.assertTrue; public class JsonFileItemWriterBuilderTests { private WritableResource resource; + private JsonObjectMarshaller jsonObjectMarshaller; @Before @@ -53,23 +54,17 @@ public class JsonFileItemWriterBuilderTests { @Test(expected = IllegalArgumentException.class) public void testMissingResource() { - new JsonFileItemWriterBuilder() - .jsonObjectMarshaller(this.jsonObjectMarshaller) - .build(); + new JsonFileItemWriterBuilder().jsonObjectMarshaller(this.jsonObjectMarshaller).build(); } @Test(expected = IllegalArgumentException.class) public void testMissingJsonObjectMarshaller() { - new JsonFileItemWriterBuilder() - .resource(this.resource) - .build(); + new JsonFileItemWriterBuilder().resource(this.resource).build(); } @Test(expected = IllegalArgumentException.class) public void testMandatoryNameWhenSaveStateIsSet() { - new JsonFileItemWriterBuilder() - .resource(this.resource) - .jsonObjectMarshaller(this.jsonObjectMarshaller) + new JsonFileItemWriterBuilder().resource(this.resource).jsonObjectMarshaller(this.jsonObjectMarshaller) .build(); } @@ -87,22 +82,13 @@ public class JsonFileItemWriterBuilderTests { FlatFileFooterCallback footerCallback = Mockito.mock(FlatFileFooterCallback.class); // when - JsonFileItemWriter writer = new JsonFileItemWriterBuilder() - .name("jsonFileItemWriter") - .resource(this.resource) - .jsonObjectMarshaller(this.jsonObjectMarshaller) - .append(append) - .encoding(encoding) - .forceSync(forceSync) - .headerCallback(headerCallback) - .footerCallback(footerCallback) - .lineSeparator(lineSeparator) - .shouldDeleteIfEmpty(shouldDeleteIfEmpty) - .shouldDeleteIfExists(shouldDeleteIfExists) - .transactional(transactional) - .build(); + JsonFileItemWriter writer = new JsonFileItemWriterBuilder().name("jsonFileItemWriter") + .resource(this.resource).jsonObjectMarshaller(this.jsonObjectMarshaller).append(append) + .encoding(encoding).forceSync(forceSync).headerCallback(headerCallback).footerCallback(footerCallback) + .lineSeparator(lineSeparator).shouldDeleteIfEmpty(shouldDeleteIfEmpty) + .shouldDeleteIfExists(shouldDeleteIfExists).transactional(transactional).build(); - //then + // then validateBuilderFlags(writer, encoding, lineSeparator, headerCallback, footerCallback); } @@ -120,27 +106,18 @@ public class JsonFileItemWriterBuilderTests { FlatFileFooterCallback footerCallback = Mockito.mock(FlatFileFooterCallback.class); // when - JsonFileItemWriter writer = new JsonFileItemWriterBuilder() - .name("jsonFileItemWriter") - .resource(this.resource) - .jsonObjectMarshaller(this.jsonObjectMarshaller) - .append(append) - .forceSync(forceSync) - .headerCallback(headerCallback) - .footerCallback(footerCallback) - .lineSeparator(lineSeparator) - .shouldDeleteIfEmpty(shouldDeleteIfEmpty) - .shouldDeleteIfExists(shouldDeleteIfExists) - .transactional(transactional) - .build(); + JsonFileItemWriter writer = new JsonFileItemWriterBuilder().name("jsonFileItemWriter") + .resource(this.resource).jsonObjectMarshaller(this.jsonObjectMarshaller).append(append) + .forceSync(forceSync).headerCallback(headerCallback).footerCallback(footerCallback) + .lineSeparator(lineSeparator).shouldDeleteIfEmpty(shouldDeleteIfEmpty) + .shouldDeleteIfExists(shouldDeleteIfExists).transactional(transactional).build(); - //then + // then validateBuilderFlags(writer, encoding, lineSeparator, headerCallback, footerCallback); } - private void validateBuilderFlags(JsonFileItemWriter writer, String encoding, - String lineSeparator, FlatFileHeaderCallback headerCallback, - FlatFileFooterCallback footerCallback) { + private void validateBuilderFlags(JsonFileItemWriter writer, String encoding, String lineSeparator, + FlatFileHeaderCallback headerCallback, FlatFileFooterCallback footerCallback) { assertTrue((Boolean) ReflectionTestUtils.getField(writer, "saveState")); assertTrue((Boolean) ReflectionTestUtils.getField(writer, "append")); assertTrue((Boolean) ReflectionTestUtils.getField(writer, "transactional")); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/builder/JsonItemReaderBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/builder/JsonItemReaderBuilderTests.java index ffa5979af..12c047a06 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/builder/JsonItemReaderBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/builder/JsonItemReaderBuilderTests.java @@ -40,44 +40,34 @@ public class JsonItemReaderBuilderTests { @Mock private Resource resource; + @Mock private JsonObjectReader jsonObjectReader; @Test public void testValidation() { try { - new JsonItemReaderBuilder() - .build(); + new JsonItemReaderBuilder().build(); fail("A json object reader is required."); } catch (IllegalArgumentException iae) { - assertEquals("A json object reader is required.", - iae.getMessage()); + assertEquals("A json object reader is required.", iae.getMessage()); } try { - new JsonItemReaderBuilder() - .jsonObjectReader(this.jsonObjectReader) - .build(); + new JsonItemReaderBuilder().jsonObjectReader(this.jsonObjectReader).build(); fail("A name is required when saveState is set to true."); } catch (IllegalStateException iae) { - assertEquals("A name is required when saveState is set to true.", - iae.getMessage()); + assertEquals("A name is required when saveState is set to true.", iae.getMessage()); } } @Test public void testConfiguration() { - JsonItemReader itemReader = new JsonItemReaderBuilder() - .jsonObjectReader(this.jsonObjectReader) - .resource(this.resource) - .saveState(true) - .strict(true) - .name("jsonItemReader") - .maxItemCount(100) - .currentItemCount(50) - .build(); + JsonItemReader itemReader = new JsonItemReaderBuilder().jsonObjectReader(this.jsonObjectReader) + .resource(this.resource).saveState(true).strict(true).name("jsonItemReader").maxItemCount(100) + .currentItemCount(50).build(); Assert.assertEquals(this.jsonObjectReader, getField(itemReader, "jsonObjectReader")); Assert.assertEquals(this.resource, getField(itemReader, "resource")); @@ -90,15 +80,9 @@ public class JsonItemReaderBuilderTests { } @Test - public void shouldBuildJsonItemReaderWhenResourceIsNotProvided(){ - JsonItemReader itemReader = new JsonItemReaderBuilder() - .jsonObjectReader(this.jsonObjectReader) - .saveState(true) - .strict(true) - .name("jsonItemReader") - .maxItemCount(100) - .currentItemCount(50) - .build(); + public void shouldBuildJsonItemReaderWhenResourceIsNotProvided() { + JsonItemReader itemReader = new JsonItemReaderBuilder().jsonObjectReader(this.jsonObjectReader) + .saveState(true).strict(true).name("jsonItemReader").maxItemCount(100).currentItemCount(50).build(); Assert.assertEquals(this.jsonObjectReader, getField(itemReader, "jsonObjectReader")); Assert.assertEquals(100, getField(itemReader, "maxItemCount")); @@ -108,4 +92,5 @@ public class JsonItemReaderBuilderTests { Object executionContext = getField(itemReader, "executionContextUserSupport"); Assert.assertEquals("jsonItemReader", getField(executionContext, "name")); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/kafka/KafkaItemReaderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/kafka/KafkaItemReaderTests.java index de14357ca..d847fb4ba 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/kafka/KafkaItemReaderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/kafka/KafkaItemReaderTests.java @@ -60,19 +60,17 @@ public class KafkaItemReaderTests { public static EmbeddedKafkaRule embeddedKafka = new EmbeddedKafkaRule(1); private KafkaItemReader reader; + private KafkaTemplate template; + private Properties consumerProperties; @BeforeClass public static void setUpTopics() { - embeddedKafka.getEmbeddedKafka().addTopics( - new NewTopic("topic1", 1, (short) 1), - new NewTopic("topic2", 2, (short) 1), - new NewTopic("topic3", 1, (short) 1), - new NewTopic("topic4", 2, (short) 1), - new NewTopic("topic5", 1, (short) 1), - new NewTopic("topic6", 1, (short) 1) - ); + embeddedKafka.getEmbeddedKafka().addTopics(new NewTopic("topic1", 1, (short) 1), + new NewTopic("topic2", 2, (short) 1), new NewTopic("topic3", 1, (short) 1), + new NewTopic("topic4", 2, (short) 1), new NewTopic("topic5", 1, (short) 1), + new NewTopic("topic6", 1, (short) 1)); } @Before @@ -281,19 +279,19 @@ public class KafkaItemReaderTests { this.reader.close(); // The offset stored in Kafka should be equal to 2 at this point - OffsetAndMetadata currentOffset = KafkaTestUtils.getCurrentOffset( - embeddedKafka.getEmbeddedKafka().getBrokersAsString(), - "1", "topic6", - 0); + OffsetAndMetadata currentOffset = KafkaTestUtils + .getCurrentOffset(embeddedKafka.getEmbeddedKafka().getBrokersAsString(), "1", "topic6", 0); assertEquals(2, currentOffset.offset()); - - // second run (with same consumer group ID): new messages arrived since the last run. + + // second run (with same consumer group ID): new messages arrived since the last + // run. this.template.sendDefault("val2"); // <-- offset 2 this.template.sendDefault("val3"); // <-- offset 3 this.reader = new KafkaItemReader<>(this.consumerProperties, "topic6", 0); - // Passing an empty map means the reader should start from the offset stored in Kafka (offset 2 in this case) + // Passing an empty map means the reader should start from the offset stored in + // Kafka (offset 2 in this case) this.reader.setPartitionOffsets(new HashMap<>()); this.reader.setPollTimeout(Duration.ofSeconds(1)); this.reader.open(new ExecutionContext()); @@ -356,9 +354,9 @@ public class KafkaItemReaderTests { executionContext.put("topic.partition.offsets", offsets); // topic3-0: val0, val1, val2, val3, val4 - // ^ - // | - // last committed offset = 1 (should restart from offset = 2) + // ^ + // | + // last committed offset = 1 (should restart from offset = 2) this.reader = new KafkaItemReader<>(this.consumerProperties, "topic3", 0); this.reader.setPollTimeout(Duration.ofSeconds(1)); @@ -398,13 +396,13 @@ public class KafkaItemReaderTests { executionContext.put("topic.partition.offsets", offsets); // topic4-0: val0, val2, val4, val6 - // ^ - // | - // last committed offset = 1 (should restart from offset = 2) + // ^ + // | + // last committed offset = 1 (should restart from offset = 2) // topic4-1: val1, val3, val5, val7 - // ^ - // | - // last committed offset = 2 (should restart from offset = 3) + // ^ + // | + // last committed offset = 2 (should restart from offset = 3) this.reader = new KafkaItemReader<>(this.consumerProperties, "topic4", 0, 1); this.reader.setPollTimeout(Duration.ofSeconds(1)); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/kafka/KafkaItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/kafka/KafkaItemWriterTests.java index 5d6a3b3a6..374b4f2e0 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/kafka/KafkaItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/kafka/KafkaItemWriterTests.java @@ -41,6 +41,7 @@ public class KafkaItemWriterTests { @Rule public MockitoRule rule = MockitoJUnit.rule().silent(); + @Mock private KafkaTemplate kafkaTemplate; @@ -138,5 +139,7 @@ public class KafkaItemWriterTests { public String convert(String source) { return source; } + } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/kafka/builder/KafkaItemReaderBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/kafka/builder/KafkaItemReaderBuilderTests.java index 71310d3fe..02cf4a925 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/kafka/builder/KafkaItemReaderBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/kafka/builder/KafkaItemReaderBuilderTests.java @@ -61,8 +61,7 @@ public class KafkaItemReaderBuilderTests { @Test public void testNullConsumerProperties() { // given - final KafkaItemReaderBuilder builder = new KafkaItemReaderBuilder<>() - .name("kafkaItemReader") + final KafkaItemReaderBuilder builder = new KafkaItemReaderBuilder<>().name("kafkaItemReader") .consumerProperties(null); // when @@ -75,58 +74,47 @@ public class KafkaItemReaderBuilderTests { @Test public void testConsumerPropertiesValidation() { try { - new KafkaItemReaderBuilder<>() - .name("kafkaItemReader") - .consumerProperties(new Properties()) - .build(); + new KafkaItemReaderBuilder<>().name("kafkaItemReader").consumerProperties(new Properties()).build(); fail("Expected exception was not thrown"); - } catch (IllegalArgumentException exception) { + } + catch (IllegalArgumentException exception) { assertEquals("bootstrap.servers property must be provided", exception.getMessage()); } Properties consumerProperties = new Properties(); consumerProperties.put("bootstrap.servers", "foo"); try { - new KafkaItemReaderBuilder<>() - .name("kafkaItemReader") - .consumerProperties(consumerProperties) - .build(); + new KafkaItemReaderBuilder<>().name("kafkaItemReader").consumerProperties(consumerProperties).build(); fail("Expected exception was not thrown"); - } catch (IllegalArgumentException exception) { + } + catch (IllegalArgumentException exception) { assertEquals("group.id property must be provided", exception.getMessage()); } consumerProperties.put("group.id", "1"); try { - new KafkaItemReaderBuilder<>() - .name("kafkaItemReader") - .consumerProperties(consumerProperties) - .build(); + new KafkaItemReaderBuilder<>().name("kafkaItemReader").consumerProperties(consumerProperties).build(); fail("Expected exception was not thrown"); - } catch (IllegalArgumentException exception) { + } + catch (IllegalArgumentException exception) { assertEquals("key.deserializer property must be provided", exception.getMessage()); } consumerProperties.put("key.deserializer", StringDeserializer.class.getName()); try { - new KafkaItemReaderBuilder<>() - .name("kafkaItemReader") - .consumerProperties(consumerProperties) - .build(); + new KafkaItemReaderBuilder<>().name("kafkaItemReader").consumerProperties(consumerProperties).build(); fail("Expected exception was not thrown"); - } catch (IllegalArgumentException exception) { + } + catch (IllegalArgumentException exception) { assertEquals("value.deserializer property must be provided", exception.getMessage()); } consumerProperties.put("value.deserializer", StringDeserializer.class.getName()); try { - new KafkaItemReaderBuilder<>() - .name("kafkaItemReader") - .consumerProperties(consumerProperties) - .topic("test") - .partitions(0, 1) - .build(); - } catch (Exception exception) { + new KafkaItemReaderBuilder<>().name("kafkaItemReader").consumerProperties(consumerProperties).topic("test") + .partitions(0, 1).build(); + } + catch (Exception exception) { fail("Must not throw an exception when configuration is valid"); } } @@ -134,10 +122,8 @@ public class KafkaItemReaderBuilderTests { @Test public void testNullTopicName() { // given - final KafkaItemReaderBuilder builder = new KafkaItemReaderBuilder<>() - .name("kafkaItemReader") - .consumerProperties(this.consumerProperties) - .topic(null); + final KafkaItemReaderBuilder builder = new KafkaItemReaderBuilder<>().name("kafkaItemReader") + .consumerProperties(this.consumerProperties).topic(null); // when final Exception expectedException = Assert.assertThrows(IllegalArgumentException.class, builder::build); @@ -149,10 +135,8 @@ public class KafkaItemReaderBuilderTests { @Test public void testEmptyTopicName() { // given - final KafkaItemReaderBuilder builder = new KafkaItemReaderBuilder<>() - .name("kafkaItemReader") - .consumerProperties(this.consumerProperties) - .topic(""); + final KafkaItemReaderBuilder builder = new KafkaItemReaderBuilder<>().name("kafkaItemReader") + .consumerProperties(this.consumerProperties).topic(""); // when final Exception expectedException = Assert.assertThrows(IllegalArgumentException.class, builder::build); @@ -164,11 +148,8 @@ public class KafkaItemReaderBuilderTests { @Test public void testNullPollTimeout() { // given - final KafkaItemReaderBuilder builder = new KafkaItemReaderBuilder<>() - .name("kafkaItemReader") - .consumerProperties(this.consumerProperties) - .topic("test") - .pollTimeout(null); + final KafkaItemReaderBuilder builder = new KafkaItemReaderBuilder<>().name("kafkaItemReader") + .consumerProperties(this.consumerProperties).topic("test").pollTimeout(null); // when final Exception expectedException = Assert.assertThrows(IllegalArgumentException.class, builder::build); @@ -180,11 +161,8 @@ public class KafkaItemReaderBuilderTests { @Test public void testNegativePollTimeout() { // given - final KafkaItemReaderBuilder builder = new KafkaItemReaderBuilder<>() - .name("kafkaItemReader") - .consumerProperties(this.consumerProperties) - .topic("test") - .pollTimeout(Duration.ofSeconds(-1)); + final KafkaItemReaderBuilder builder = new KafkaItemReaderBuilder<>().name("kafkaItemReader") + .consumerProperties(this.consumerProperties).topic("test").pollTimeout(Duration.ofSeconds(-1)); // when final Exception expectedException = Assert.assertThrows(IllegalArgumentException.class, builder::build); @@ -196,11 +174,8 @@ public class KafkaItemReaderBuilderTests { @Test public void testZeroPollTimeout() { // given - final KafkaItemReaderBuilder builder = new KafkaItemReaderBuilder<>() - .name("kafkaItemReader") - .consumerProperties(this.consumerProperties) - .topic("test") - .pollTimeout(Duration.ZERO); + final KafkaItemReaderBuilder builder = new KafkaItemReaderBuilder<>().name("kafkaItemReader") + .consumerProperties(this.consumerProperties).topic("test").pollTimeout(Duration.ZERO); // when final Exception expectedException = Assert.assertThrows(IllegalArgumentException.class, builder::build); @@ -212,11 +187,8 @@ public class KafkaItemReaderBuilderTests { @Test public void testEmptyPartitions() { // given - final KafkaItemReaderBuilder builder = new KafkaItemReaderBuilder<>() - .name("kafkaItemReader") - .consumerProperties(this.consumerProperties) - .topic("test") - .pollTimeout(Duration.ofSeconds(10)); + final KafkaItemReaderBuilder builder = new KafkaItemReaderBuilder<>().name("kafkaItemReader") + .consumerProperties(this.consumerProperties).topic("test").pollTimeout(Duration.ofSeconds(10)); // when final Exception expectedException = Assert.assertThrows(IllegalArgumentException.class, builder::build); @@ -238,29 +210,26 @@ public class KafkaItemReaderBuilderTests { partitionOffsets.put(new TopicPartition(topic, partitions.get(1)), 15L); // when - KafkaItemReader reader = new KafkaItemReaderBuilder() - .name("kafkaItemReader") - .consumerProperties(this.consumerProperties) - .topic(topic) - .partitions(partitions) - .partitionOffsets(partitionOffsets) - .pollTimeout(pollTimeout) - .saveState(saveState) - .build(); + KafkaItemReader reader = new KafkaItemReaderBuilder().name("kafkaItemReader") + .consumerProperties(this.consumerProperties).topic(topic).partitions(partitions) + .partitionOffsets(partitionOffsets).pollTimeout(pollTimeout).saveState(saveState).build(); // then assertNotNull(reader); assertFalse((Boolean) ReflectionTestUtils.getField(reader, "saveState")); assertEquals(pollTimeout, ReflectionTestUtils.getField(reader, "pollTimeout")); - List topicPartitions = (List) ReflectionTestUtils.getField(reader, "topicPartitions"); + List topicPartitions = (List) ReflectionTestUtils.getField(reader, + "topicPartitions"); assertEquals(2, topicPartitions.size()); assertEquals(topic, topicPartitions.get(0).topic()); assertEquals(partitions.get(0).intValue(), topicPartitions.get(0).partition()); assertEquals(topic, topicPartitions.get(1).topic()); assertEquals(partitions.get(1).intValue(), topicPartitions.get(1).partition()); - Map partitionOffsetsMap = (Map) ReflectionTestUtils.getField(reader, "partitionOffsets"); + Map partitionOffsetsMap = (Map) ReflectionTestUtils.getField(reader, + "partitionOffsets"); assertEquals(2, partitionOffsetsMap.size()); assertEquals(Long.valueOf(10L), partitionOffsetsMap.get(new TopicPartition(topic, partitions.get(0)))); assertEquals(Long.valueOf(15L), partitionOffsetsMap.get(new TopicPartition(topic, partitions.get(1)))); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/kafka/builder/KafkaItemWriterBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/kafka/builder/KafkaItemWriterBuilderTests.java index a0047faac..d85de7eb6 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/kafka/builder/KafkaItemWriterBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/kafka/builder/KafkaItemWriterBuilderTests.java @@ -54,7 +54,8 @@ public class KafkaItemWriterBuilderTests { @Test public void testNullKafkaTemplate() { // given - final KafkaItemWriterBuilder builder = new KafkaItemWriterBuilder().itemKeyMapper(this.itemKeyMapper); + final KafkaItemWriterBuilder builder = new KafkaItemWriterBuilder() + .itemKeyMapper(this.itemKeyMapper); // when final Exception expectedException = Assert.assertThrows(IllegalArgumentException.class, builder::build); @@ -66,7 +67,8 @@ public class KafkaItemWriterBuilderTests { @Test public void testNullItemKeyMapper() { // given - final KafkaItemWriterBuilder builder = new KafkaItemWriterBuilder().kafkaTemplate(this.kafkaTemplate); + final KafkaItemWriterBuilder builder = new KafkaItemWriterBuilder() + .kafkaTemplate(this.kafkaTemplate); // when final Exception expectedException = Assert.assertThrows(IllegalArgumentException.class, builder::build); @@ -83,10 +85,7 @@ public class KafkaItemWriterBuilderTests { // when KafkaItemWriter writer = new KafkaItemWriterBuilder() - .kafkaTemplate(this.kafkaTemplate) - .itemKeyMapper(this.itemKeyMapper) - .delete(delete) - .timeout(timeout) + .kafkaTemplate(this.kafkaTemplate).itemKeyMapper(this.itemKeyMapper).delete(delete).timeout(timeout) .build(); // then @@ -102,6 +101,7 @@ public class KafkaItemWriterBuilderTests { public String convert(String source) { return source; } + } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/mail/DefaultMailErrorHandlerTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/mail/DefaultMailErrorHandlerTests.java index 33d968ece..d00d99599 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/mail/DefaultMailErrorHandlerTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/mail/DefaultMailErrorHandlerTests.java @@ -28,12 +28,11 @@ import org.springframework.mail.SimpleMailMessage; /** * @author Dave Syer * @author Mahmoud Ben Hassine - * * @since 2.1 * */ public class DefaultMailErrorHandlerTests { - + private DefaultMailErrorHandler handler = new DefaultMailErrorHandler(); /** @@ -46,16 +45,17 @@ public class DefaultMailErrorHandlerTests { SimpleMailMessage message = new SimpleMailMessage(); handler.handle(message, new MessagingException()); fail("Expected MailException"); - } catch (MailException e) { + } + catch (MailException e) { String msg = e.getMessage(); - assertTrue("Wrong message: "+msg, msg.matches(".*SimpleMailMessage: f;.*")); + assertTrue("Wrong message: " + msg, msg.matches(".*SimpleMailMessage: f;.*")); } } /** * Test method for {@link DefaultMailErrorHandler#handle(MailMessage, Exception)}. */ - @Test(expected=MailSendException.class) + @Test(expected = MailSendException.class) public void testHandle() { handler.handle(new SimpleMailMessage(), new MessagingException()); } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/mail/SimpleMailMessageItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/mail/SimpleMailMessageItemWriterTests.java index ac7213346..92b30545a 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/mail/SimpleMailMessageItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/mail/SimpleMailMessageItemWriterTests.java @@ -41,9 +41,8 @@ import org.springframework.util.ReflectionUtils; * @author Dave Syer * @author Will Schipp * @author Mahmoud Ben Hassine - * * @since 2.1 - * + * */ public class SimpleMailMessageItemWriterTests { @@ -66,7 +65,7 @@ public class SimpleMailMessageItemWriterTests { writer.write(Arrays.asList(items)); // Spring 4.1 changed the send method to be vargs instead of an array - if(ReflectionUtils.findMethod(SimpleMailMessage.class, "send", SimpleMailMessage[].class) != null) { + if (ReflectionUtils.findMethod(SimpleMailMessage.class, "send", SimpleMailMessage[].class) != null) { verify(mailSender).send(aryEq(items)); } else { @@ -82,14 +81,15 @@ public class SimpleMailMessageItemWriterTests { SimpleMailMessage[] items = new SimpleMailMessage[] { foo, bar }; // Spring 4.1 changed the send method to be vargs instead of an array - if(ReflectionUtils.findMethod(SimpleMailMessage.class, "send", SimpleMailMessage[].class) != null) { + if (ReflectionUtils.findMethod(SimpleMailMessage.class, "send", SimpleMailMessage[].class) != null) { mailSender.send(aryEq(items)); } else { mailSender.send(items); } - when(mailSender).thenThrow(new MailSendException(Collections.singletonMap((Object)foo, (Exception)new MessagingException("FOO")))); + when(mailSender).thenThrow(new MailSendException( + Collections.singletonMap((Object) foo, (Exception) new MessagingException("FOO")))); writer.write(Arrays.asList(items)); } @@ -99,7 +99,7 @@ public class SimpleMailMessageItemWriterTests { final AtomicReference content = new AtomicReference<>(); writer.setMailErrorHandler(new MailErrorHandler() { - @Override + @Override public void handle(MailMessage message, Exception exception) throws MailException { content.set(exception.getMessage()); } @@ -110,14 +110,15 @@ public class SimpleMailMessageItemWriterTests { SimpleMailMessage[] items = new SimpleMailMessage[] { foo, bar }; // Spring 4.1 changed the send method to be vargs instead of an array - if(ReflectionUtils.findMethod(SimpleMailMessage.class, "send", SimpleMailMessage[].class) != null) { + if (ReflectionUtils.findMethod(SimpleMailMessage.class, "send", SimpleMailMessage[].class) != null) { mailSender.send(aryEq(items)); } else { mailSender.send(items); } - when(mailSender).thenThrow(new MailSendException(Collections.singletonMap((Object)foo, (Exception)new MessagingException("FOO")))); + when(mailSender).thenThrow(new MailSendException( + Collections.singletonMap((Object) foo, (Exception) new MessagingException("FOO")))); writer.write(Arrays.asList(items)); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/mail/javamail/MimeMessageItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/mail/javamail/MimeMessageItemWriterTests.java index fe203c976..7221a70ab 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/mail/javamail/MimeMessageItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/mail/javamail/MimeMessageItemWriterTests.java @@ -43,16 +43,15 @@ import org.springframework.util.ReflectionUtils; * @author Dave Syer * @author Will Schipp * @author Mahmoud Ben Hassine - * * @since 2.1 - * + * */ public class MimeMessageItemWriterTests { private MimeMessageItemWriter writer = new MimeMessageItemWriter(); private JavaMailSender mailSender = mock(JavaMailSender.class); - + private Session session = Session.getDefaultInstance(new Properties()); @Before @@ -71,7 +70,6 @@ public class MimeMessageItemWriterTests { writer.write(Arrays.asList(items)); - } @Test(expected = MailSendException.class) @@ -82,14 +80,15 @@ public class MimeMessageItemWriterTests { MimeMessage[] items = new MimeMessage[] { foo, bar }; // Spring 4.1 changed the send method to be vargs instead of an array - if(ReflectionUtils.findMethod(MailSender.class, "send", MimeMessage[].class) != null) { + if (ReflectionUtils.findMethod(MailSender.class, "send", MimeMessage[].class) != null) { mailSender.send(aryEq(items)); } else { mailSender.send(items); } - when(mailSender).thenThrow(new MailSendException(Collections.singletonMap((Object)foo, (Exception)new MessagingException("FOO")))); + when(mailSender).thenThrow(new MailSendException( + Collections.singletonMap((Object) foo, (Exception) new MessagingException("FOO")))); writer.write(Arrays.asList(items)); } @@ -99,7 +98,7 @@ public class MimeMessageItemWriterTests { final AtomicReference content = new AtomicReference<>(); writer.setMailErrorHandler(new MailErrorHandler() { - @Override + @Override public void handle(MailMessage message, Exception exception) throws MailException { content.set(exception.getMessage()); } @@ -109,22 +108,21 @@ public class MimeMessageItemWriterTests { MimeMessage bar = new MimeMessage(session); MimeMessage[] items = new MimeMessage[] { foo, bar }; - // Spring 4.1 changed the send method to be vargs instead of an array - if(ReflectionUtils.findMethod(MailSender.class, "send", MimeMessage[].class) != null) { + if (ReflectionUtils.findMethod(MailSender.class, "send", MimeMessage[].class) != null) { mailSender.send(aryEq(items)); } else { mailSender.send(items); } - when(mailSender).thenThrow(new MailSendException(Collections.singletonMap((Object)foo, (Exception)new MessagingException("FOO")))); + when(mailSender).thenThrow(new MailSendException( + Collections.singletonMap((Object) foo, (Exception) new MessagingException("FOO")))); writer.write(Arrays.asList(items)); assertEquals("FOO", content.get()); - } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/Customer.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/Customer.java index 41d3ef22c..bd0136ddc 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/Customer.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/Customer.java @@ -16,13 +16,13 @@ package org.springframework.batch.item.sample; - /** * An XML customer. - * + * * This is a complex type. */ public class Customer { + private String name; private String address; diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/Foo.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/Foo.java index fd4f07d3e..9f122ef56 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/Foo.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/Foo.java @@ -25,48 +25,56 @@ import jakarta.persistence.Table; @Entity @Table(name = "T_FOOS") public class Foo { - + public static final String FAILURE_MESSAGE = "Foo Failure!"; - + public static final String UGLY_FAILURE_MESSAGE = "Ugly Foo Failure!"; - + @Id private int id; + private String name; + private int value; - - public Foo(){} - + + public Foo() { + } + public Foo(int id, String name, int value) { this.id = id; this.name = name; this.value = value; } - + public String getName() { return name; } + public void setName(String name) { this.name = name; } + public int getValue() { return value; } + public void setValue(int value) { this.value = value; } + public int getId() { return id; } + public void setId(int id) { this.id = id; } - - @Override + + @Override public String toString() { - return "Foo[id=" +id +",name=" + name + ",value=" + value + "]"; + return "Foo[id=" + id + ",name=" + name + ",value=" + value + "]"; } - + @Override public int hashCode() { final int prime = 31; @@ -102,7 +110,7 @@ public class Foo { public void fail() throws Exception { throw new Exception(FAILURE_MESSAGE); } - + public void failUgly() throws Throwable { throw new Throwable(UGLY_FAILURE_MESSAGE); } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/FooService.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/FooService.java index 673c723f2..ee2c1662a 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/FooService.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/FooService.java @@ -18,41 +18,44 @@ package org.springframework.batch.item.sample; import java.util.ArrayList; import java.util.List; - /** - * Custom class that contains the logic of providing and processing {@link Foo} - * objects. It serves the purpose to show how providing/processing logic contained in a - * custom class can be reused by the framework. - * + * Custom class that contains the logic of providing and processing {@link Foo} objects. + * It serves the purpose to show how providing/processing logic contained in a custom + * class can be reused by the framework. + * * @author Robert Kasanicky */ public class FooService { public static final int GENERATION_LIMIT = 10; - + private int counter = 0; + private List generatedFoos = new ArrayList<>(GENERATION_LIMIT); + private List processedFoos = new ArrayList<>(GENERATION_LIMIT); + private List processedFooNameValuePairs = new ArrayList<>(GENERATION_LIMIT); - + public Foo generateFoo() { - if (counter++ >= GENERATION_LIMIT) return null; - + if (counter++ >= GENERATION_LIMIT) + return null; + Foo foo = new Foo(counter, "foo" + counter, counter); generatedFoos.add(foo); return foo; - + } - + public void processFoo(Foo foo) { processedFoos.add(foo); } - + public String extractName(Foo foo) { processedFoos.add(foo); return foo.getName(); } - + public void processNameValuePair(String name, int value) { processedFooNameValuePairs.add(new Foo(0, name, value)); } @@ -67,6 +70,6 @@ public class FooService { public List getProcessedFooNameValuePairs() { return processedFooNameValuePairs; - } - + } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/LineItem.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/LineItem.java index 4ab0e6250..fcd0d743a 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/LineItem.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/LineItem.java @@ -16,13 +16,13 @@ package org.springframework.batch.item.sample; - /** * An XML line-item. - * + * * This is a complex type. */ public class LineItem { + private String description; private double perUnitOunces; diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/Order.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/Order.java index 54df93525..6fa2fc68c 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/Order.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/Order.java @@ -21,10 +21,11 @@ import java.util.List; /** * An XML order. - * + * * This is a complex type. */ public class Order { + private Customer customer; private Date date; @@ -42,11 +43,11 @@ public class Order { } public Date getDate() { - return (Date)date.clone(); + return (Date) date.clone(); } public void setDate(Date date) { - this.date = date == null ? null : (Date)date.clone(); + this.date = date == null ? null : (Date) date.clone(); } public List getLineItems() { diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/Person.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/Person.java index db50eb9b8..ca77bfd98 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/Person.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/Person.java @@ -26,6 +26,7 @@ public class Person { @Id private int id; + private String name; private Person() { @@ -54,15 +55,17 @@ public class Person { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; Person person = (Person) o; - return id == person.id && - Objects.equals(name, person.name); + return id == person.id && Objects.equals(name, person.name); } @Override public int hashCode() { return Objects.hash(id, name); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/Shipper.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/Shipper.java index c10794242..5685d5e78 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/Shipper.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/Shipper.java @@ -16,13 +16,13 @@ package org.springframework.batch.item.sample; - /** * An XML shipper. - * + * * This is a complex type. */ public class Shipper { + private String name; private double perOunceRate; diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/books/Author.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/books/Author.java index 9a40f6a8a..0c3717cb1 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/books/Author.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/books/Author.java @@ -34,38 +34,41 @@ import java.util.Objects; @Table(name = "T_AUTHORS") public class Author { - @Id - private int id; + @Id + private int id; - @Basic - private String name; + @Basic + private String name; - @OneToMany - @JoinColumn(name = "AUTHOR_ID") - private List books; + @OneToMany + @JoinColumn(name = "AUTHOR_ID") + private List books; - public int getId() { - return id; - } - public String getName() { - return name; - } - public List getBooks() { - return books; - } + public int getId() { + return id; + } - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Author author = (Author) o; - return id == author.id && - Objects.equals(name, author.name) && - Objects.equals(books, author.books); - } + public String getName() { + return name; + } + + public List getBooks() { + return books; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + Author author = (Author) o; + return id == author.id && Objects.equals(name, author.name) && Objects.equals(books, author.books); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, books); + } - @Override - public int hashCode() { - return Objects.hash(id, name, books); - } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/books/Book.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/books/Book.java index c895fadf2..c2ef54cf3 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/books/Book.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/books/Book.java @@ -30,28 +30,32 @@ import java.util.Objects; @Table(name = "T_BOOKS") public class Book { - @Id - private int id; - private String name; + @Id + private int id; - public int getId() { - return id; - } - public String getName() { - return name; - } + private String name; - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Book book = (Book) o; - return id == book.id && - Objects.equals(name, book.name); - } + public int getId() { + return id; + } + + public String getName() { + return name; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + Book book = (Book) o; + return id == book.id && Objects.equals(name, book.name); + } + + @Override + public int hashCode() { + return Objects.hash(id, name); + } - @Override - public int hashCode() { - return Objects.hash(id, name); - } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/books/data/AuthorRepository.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/books/data/AuthorRepository.java index 472cc28e9..1fdb08f39 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/books/data/AuthorRepository.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/sample/books/data/AuthorRepository.java @@ -19,7 +19,7 @@ import org.springframework.batch.item.sample.books.Author; import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.stereotype.Repository; - @Repository public interface AuthorRepository extends PagingAndSortingRepository { + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/AbstractSynchronizedItemStreamWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/AbstractSynchronizedItemStreamWriterTests.java index 1d70d7947..42534d611 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/AbstractSynchronizedItemStreamWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/AbstractSynchronizedItemStreamWriterTests.java @@ -46,7 +46,9 @@ public abstract class AbstractSynchronizedItemStreamWriterTests { protected ItemStreamWriter delegate; private SynchronizedItemStreamWriter synchronizedItemStreamWriter; + private final List testList = Collections.unmodifiableList(new ArrayList<>()); + private final ExecutionContext testExecutionContext = new ExecutionContext(); abstract protected SynchronizedItemStreamWriter createNewSynchronizedItemStreamWriter(); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/ClassifierCompositeItemProcessorTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/ClassifierCompositeItemProcessorTests.java index e47e0eb76..e6a5067b5 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/ClassifierCompositeItemProcessorTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/ClassifierCompositeItemProcessorTests.java @@ -1,108 +1,106 @@ -/* - * Copyright 2014-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.support; - -import static org.junit.Assert.assertEquals; - -import java.util.HashMap; -import java.util.Map; - -import org.junit.Test; -import org.springframework.batch.item.ItemProcessor; -import org.springframework.classify.PatternMatchingClassifier; -import org.springframework.classify.SubclassClassifier; -import org.springframework.lang.Nullable; - -/** - * @author Jimmy Praet - */ -public class ClassifierCompositeItemProcessorTests { - - @Test - public void testBasicClassifierCompositeItemProcessor() throws Exception { - ClassifierCompositeItemProcessor processor = new ClassifierCompositeItemProcessor<>(); - - ItemProcessor fooProcessor = new ItemProcessor() { - @Nullable - @Override - public String process(String item) throws Exception { - return "foo: " + item; - } - }; - ItemProcessor defaultProcessor = new ItemProcessor() { - @Nullable - @Override - public String process(String item) throws Exception { - return item; - } - }; - - Map> routingConfiguration = - new HashMap<>(); - routingConfiguration.put("foo", fooProcessor); - routingConfiguration.put("*", defaultProcessor); - processor.setClassifier(new PatternMatchingClassifier<>(routingConfiguration)); - - assertEquals("bar", processor.process("bar")); - assertEquals("foo: foo", processor.process("foo")); - assertEquals("baz", processor.process("baz")); - } - - /** - * Test the ClassifierCompositeItemProcessor with delegates that have more specific generic types for input as well as output. - */ - @Test - public void testGenericsClassifierCompositeItemProcessor() throws Exception { - ClassifierCompositeItemProcessor processor = new ClassifierCompositeItemProcessor<>(); - - ItemProcessor intProcessor = new ItemProcessor() { - @Nullable - @Override - public String process(Integer item) throws Exception { - return "int: " + item; - } - }; - ItemProcessor longProcessor = new ItemProcessor() { - @Nullable - @Override - public StringBuffer process(Long item) throws Exception { - return new StringBuffer("long: " + item); - } - }; - ItemProcessor defaultProcessor = new ItemProcessor() { - @Nullable - @Override - public StringBuilder process(Number item) throws Exception { - return new StringBuilder("number: " + item); - } - }; - - SubclassClassifier> classifier = - new SubclassClassifier<>(); - Map, ItemProcessor> typeMap = - new HashMap<>(); - typeMap.put(Integer.class, intProcessor); - typeMap.put(Long.class, longProcessor); - typeMap.put(Number.class, defaultProcessor); - classifier.setTypeMap(typeMap); - processor.setClassifier(classifier); - - assertEquals("int: 1", processor.process(Integer.valueOf(1)).toString()); - assertEquals("long: 2", processor.process(Long.valueOf(2)).toString()); - assertEquals("number: 3", processor.process(Byte.valueOf((byte) 3)).toString()); - } - -} +/* + * Copyright 2014-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item.support; + +import static org.junit.Assert.assertEquals; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Test; +import org.springframework.batch.item.ItemProcessor; +import org.springframework.classify.PatternMatchingClassifier; +import org.springframework.classify.SubclassClassifier; +import org.springframework.lang.Nullable; + +/** + * @author Jimmy Praet + */ +public class ClassifierCompositeItemProcessorTests { + + @Test + public void testBasicClassifierCompositeItemProcessor() throws Exception { + ClassifierCompositeItemProcessor processor = new ClassifierCompositeItemProcessor<>(); + + ItemProcessor fooProcessor = new ItemProcessor() { + @Nullable + @Override + public String process(String item) throws Exception { + return "foo: " + item; + } + }; + ItemProcessor defaultProcessor = new ItemProcessor() { + @Nullable + @Override + public String process(String item) throws Exception { + return item; + } + }; + + Map> routingConfiguration = new HashMap<>(); + routingConfiguration.put("foo", fooProcessor); + routingConfiguration.put("*", defaultProcessor); + processor.setClassifier(new PatternMatchingClassifier<>(routingConfiguration)); + + assertEquals("bar", processor.process("bar")); + assertEquals("foo: foo", processor.process("foo")); + assertEquals("baz", processor.process("baz")); + } + + /** + * Test the ClassifierCompositeItemProcessor with delegates that have more specific + * generic types for input as well as output. + */ + @Test + public void testGenericsClassifierCompositeItemProcessor() throws Exception { + ClassifierCompositeItemProcessor processor = new ClassifierCompositeItemProcessor<>(); + + ItemProcessor intProcessor = new ItemProcessor() { + @Nullable + @Override + public String process(Integer item) throws Exception { + return "int: " + item; + } + }; + ItemProcessor longProcessor = new ItemProcessor() { + @Nullable + @Override + public StringBuffer process(Long item) throws Exception { + return new StringBuffer("long: " + item); + } + }; + ItemProcessor defaultProcessor = new ItemProcessor() { + @Nullable + @Override + public StringBuilder process(Number item) throws Exception { + return new StringBuilder("number: " + item); + } + }; + + SubclassClassifier> classifier = new SubclassClassifier<>(); + Map, ItemProcessor> typeMap = new HashMap<>(); + typeMap.put(Integer.class, intProcessor); + typeMap.put(Long.class, longProcessor); + typeMap.put(Number.class, defaultProcessor); + classifier.setTypeMap(typeMap); + processor.setClassifier(classifier); + + assertEquals("int: 1", processor.process(Integer.valueOf(1)).toString()); + assertEquals("long: 2", processor.process(Long.valueOf(2)).toString()); + assertEquals("number: 3", processor.process(Byte.valueOf((byte) 3)).toString()); + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/ClassifierCompositeItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/ClassifierCompositeItemWriterTests.java index ffd3c6f48..403e45087 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/ClassifierCompositeItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/ClassifierCompositeItemWriterTests.java @@ -1,78 +1,81 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.support; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.junit.Test; - -import org.springframework.batch.item.ItemWriter; -import org.springframework.classify.PatternMatchingClassifier; - -import static junit.framework.TestCase.fail; -import static org.junit.Assert.assertEquals; - -/** - * @author Dave Syer - * @author Glenn Renfro - * - */ -public class ClassifierCompositeItemWriterTests { - - private ClassifierCompositeItemWriter writer = new ClassifierCompositeItemWriter<>(); - private List defaults = new ArrayList<>(); - private List foos = new ArrayList<>(); - - @Test - public void testWrite() throws Exception { - Map> map = new HashMap<>(); - ItemWriter fooWriter = new ItemWriter() { - @Override - public void write(List items) throws Exception { - foos.addAll(items); - } - }; - ItemWriter defaultWriter = new ItemWriter() { - @Override - public void write(List items) throws Exception { - defaults.addAll(items); - } - }; - map.put("foo", fooWriter ); - map.put("*", defaultWriter); - writer.setClassifier(new PatternMatchingClassifier<>(map)); - writer.write(Arrays.asList("foo", "foo", "one", "two", "three")); - assertEquals("[foo, foo]", foos.toString()); - assertEquals("[one, two, three]", defaults.toString()); - } - - @Test - public void testSetNullClassifier() throws Exception { - try { - ClassifierCompositeItemWriter writer = new ClassifierCompositeItemWriter<>(); - writer.setClassifier(null); - fail("A classifier is required."); - } - catch (IllegalArgumentException iae) { - assertEquals("Message returned from exception did not match expected result.", "A classifier is required.", - iae.getMessage()); - } - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item.support; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.Test; + +import org.springframework.batch.item.ItemWriter; +import org.springframework.classify.PatternMatchingClassifier; + +import static junit.framework.TestCase.fail; +import static org.junit.Assert.assertEquals; + +/** + * @author Dave Syer + * @author Glenn Renfro + * + */ +public class ClassifierCompositeItemWriterTests { + + private ClassifierCompositeItemWriter writer = new ClassifierCompositeItemWriter<>(); + + private List defaults = new ArrayList<>(); + + private List foos = new ArrayList<>(); + + @Test + public void testWrite() throws Exception { + Map> map = new HashMap<>(); + ItemWriter fooWriter = new ItemWriter() { + @Override + public void write(List items) throws Exception { + foos.addAll(items); + } + }; + ItemWriter defaultWriter = new ItemWriter() { + @Override + public void write(List items) throws Exception { + defaults.addAll(items); + } + }; + map.put("foo", fooWriter); + map.put("*", defaultWriter); + writer.setClassifier(new PatternMatchingClassifier<>(map)); + writer.write(Arrays.asList("foo", "foo", "one", "two", "three")); + assertEquals("[foo, foo]", foos.toString()); + assertEquals("[one, two, three]", defaults.toString()); + } + + @Test + public void testSetNullClassifier() throws Exception { + try { + ClassifierCompositeItemWriter writer = new ClassifierCompositeItemWriter<>(); + writer.setClassifier(null); + fail("A classifier is required."); + } + catch (IllegalArgumentException iae) { + assertEquals("Message returned from exception did not match expected result.", "A classifier is required.", + iae.getMessage()); + } + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/CompositeItemProcessorTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/CompositeItemProcessorTests.java index a2a9af0f7..66e519fa6 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/CompositeItemProcessorTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/CompositeItemProcessorTests.java @@ -31,7 +31,7 @@ import org.springframework.batch.item.ItemProcessor; /** * Tests for {@link CompositeItemProcessor}. - * + * * @author Robert Kasanicky * @author Will Schipp */ @@ -40,6 +40,7 @@ public class CompositeItemProcessorTests { private CompositeItemProcessor composite = new CompositeItemProcessor<>(); private ItemProcessor processor1; + private ItemProcessor processor2; @SuppressWarnings("unchecked") @@ -54,8 +55,8 @@ public class CompositeItemProcessorTests { } /** - * Regular usage scenario - item is passed through the processing chain, - * return value of the of the last transformation is returned by the composite. + * Regular usage scenario - item is passed through the processing chain, return value + * of the of the last transformation is returned by the composite. */ @Test public void testTransform() throws Exception { @@ -72,7 +73,8 @@ public class CompositeItemProcessorTests { } /** - * Test that the CompositeItemProcessor can work with generic types for the ItemProcessor delegates. + * Test that the CompositeItemProcessor can work with generic types for the + * ItemProcessor delegates. */ @Test @SuppressWarnings("unchecked") @@ -93,8 +95,8 @@ public class CompositeItemProcessorTests { } /** - * The list of transformers must not be null or empty and - * can contain only instances of {@link ItemProcessor}. + * The list of transformers must not be null or empty and can contain only instances + * of {@link ItemProcessor}. */ @Test public void testAfterPropertiesSet() throws Exception { @@ -110,7 +112,7 @@ public class CompositeItemProcessorTests { } // empty list - composite.setDelegates(new ArrayList>()); + composite.setDelegates(new ArrayList>()); try { composite.afterPropertiesSet(); fail(); @@ -122,10 +124,11 @@ public class CompositeItemProcessorTests { } @Test - public void testFilteredItemInFirstProcessor() throws Exception{ + public void testFilteredItemInFirstProcessor() throws Exception { Object item = new Object(); when(processor1.process(item)).thenReturn(null); - Assert.assertEquals(null,composite.process(item)); + Assert.assertEquals(null, composite.process(item)); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/CompositeItemStreamTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/CompositeItemStreamTests.java index 523db2b31..582cac2d9 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/CompositeItemStreamTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/CompositeItemStreamTests.java @@ -27,7 +27,7 @@ import org.springframework.batch.item.support.CompositeItemStream; /** * @author Dave Syer - * + * */ public class CompositeItemStreamTests extends TestCase { @@ -37,9 +37,9 @@ public class CompositeItemStreamTests extends TestCase { public void testRegisterAndOpen() { ItemStreamSupport stream = new ItemStreamSupport() { - @Override + @Override public void open(ExecutionContext executionContext) { - super.open(executionContext); + super.open(executionContext); list.add("bar"); } }; @@ -50,9 +50,9 @@ public class CompositeItemStreamTests extends TestCase { public void testRegisterTwice() { ItemStreamSupport stream = new ItemStreamSupport() { - @Override + @Override public void open(ExecutionContext executionContext) { - super.open(executionContext); + super.open(executionContext); list.add("bar"); } }; @@ -64,9 +64,9 @@ public class CompositeItemStreamTests extends TestCase { public void testMark() { manager.register(new ItemStreamSupport() { - @Override + @Override public void update(ExecutionContext executionContext) { - super.update(executionContext); + super.update(executionContext); list.add("bar"); } }); @@ -76,9 +76,9 @@ public class CompositeItemStreamTests extends TestCase { public void testClose() { manager.register(new ItemStreamSupport() { - @Override + @Override public void close() { - super.close(); + super.close(); list.add("bar"); } }); @@ -88,9 +88,9 @@ public class CompositeItemStreamTests extends TestCase { public void testCloseDoesNotUnregister() { manager.setStreams(new ItemStream[] { new ItemStreamSupport() { - @Override + @Override public void open(ExecutionContext executionContext) { - super.open(executionContext); + super.open(executionContext); list.add("bar"); } } }); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/CompositeItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/CompositeItemWriterTests.java index e9e8926c2..e7df95b27 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/CompositeItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/CompositeItemWriterTests.java @@ -27,7 +27,7 @@ import org.springframework.batch.item.ItemWriter; /** * Tests for {@link CompositeItemWriter} - * + * * @author Robert Kasanicky * @author Will Schipp */ @@ -59,7 +59,6 @@ public class CompositeItemWriterTests { itemWriter.setDelegates(writers); itemWriter.write(data); - } @Test diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/ItemCountingItemStreamItemReaderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/ItemCountingItemStreamItemReaderTests.java index 82cfd9d17..032431646 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/ItemCountingItemStreamItemReaderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/ItemCountingItemStreamItemReaderTests.java @@ -1,159 +1,159 @@ -/* - * Copyright 2006-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.support; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import java.util.Arrays; -import java.util.Iterator; - -import org.junit.Before; -import org.junit.Test; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.lang.Nullable; - -/** - * @author Dave Syer - * - */ -public class ItemCountingItemStreamItemReaderTests { - - private ItemCountingItemStreamItemReader reader = new ItemCountingItemStreamItemReader(); - - @Before - public void setUp() { - reader.setName("foo"); - } - - @Test - public void testJumpToItem() throws Exception { - reader.jumpToItem(2); - assertEquals(2, reader.getCurrentItemCount()); - reader.read(); - assertEquals(3, reader.getCurrentItemCount()); - } - - @Test - public void testGetCurrentItemCount() throws Exception { - assertEquals(0, reader.getCurrentItemCount()); - reader.read(); - assertEquals(1, reader.getCurrentItemCount()); - } - - @Test - public void testClose() { - reader.close(); - assertTrue(reader.closeCalled); - } - - @Test(expected=IllegalArgumentException.class) - public void testOpenWithoutName() { - reader = new ItemCountingItemStreamItemReader(); - reader.open(new ExecutionContext()); - assertFalse(reader.openCalled); - } - - @Test - public void testOpen() { - reader.open(new ExecutionContext()); - assertTrue(reader.openCalled); - } - - @Test - public void testReadToEnd() throws Exception { - reader.read(); - reader.read(); - reader.read(); - assertNull(reader.read()); - } - - @Test - public void testUpdate() throws Exception { - reader.read(); - ExecutionContext context = new ExecutionContext(); - reader.update(context); - assertEquals(1, context.size()); - assertEquals(1, context.getInt("foo.read.count")); - } - - @Test - public void testSetName() throws Exception { - reader.setName("bar"); - reader.read(); - ExecutionContext context = new ExecutionContext(); - reader.update(context); - assertEquals(1, context.getInt("bar.read.count")); - } - - @Test - public void testSetSaveState() throws Exception { - reader.read(); - ExecutionContext context = new ExecutionContext(); - reader.update(context); - assertEquals(1, context.size()); - } - - @Test - public void testReadToEndWithMax() throws Exception { - ExecutionContext context = new ExecutionContext(); - context.putInt("foo.read.count.max", 1); - reader.open(context); - reader.read(); - assertNull(reader.read()); - } - - @Test - public void testUpdateWithMax() throws Exception { - ExecutionContext context = new ExecutionContext(); - context.putInt("foo.read.count.max", 1); - reader.open(context); - reader.update(context); - assertEquals(2, context.size()); - } - - private static class ItemCountingItemStreamItemReader extends AbstractItemCountingItemStreamItemReader { - - private boolean closeCalled = false; - - private boolean openCalled = false; - - private Iterator items = Arrays.asList("a", "b", "c").iterator(); - - @Override - protected void doClose() throws Exception { - closeCalled = true; - } - - @Override - protected void doOpen() throws Exception { - openCalled = true; - } - - @Nullable - @Override - protected String doRead() throws Exception { - if (!items.hasNext()) { - return null; - } - return items.next(); - } - - } - -} +/* + * Copyright 2006-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item.support; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.Iterator; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.lang.Nullable; + +/** + * @author Dave Syer + * + */ +public class ItemCountingItemStreamItemReaderTests { + + private ItemCountingItemStreamItemReader reader = new ItemCountingItemStreamItemReader(); + + @Before + public void setUp() { + reader.setName("foo"); + } + + @Test + public void testJumpToItem() throws Exception { + reader.jumpToItem(2); + assertEquals(2, reader.getCurrentItemCount()); + reader.read(); + assertEquals(3, reader.getCurrentItemCount()); + } + + @Test + public void testGetCurrentItemCount() throws Exception { + assertEquals(0, reader.getCurrentItemCount()); + reader.read(); + assertEquals(1, reader.getCurrentItemCount()); + } + + @Test + public void testClose() { + reader.close(); + assertTrue(reader.closeCalled); + } + + @Test(expected = IllegalArgumentException.class) + public void testOpenWithoutName() { + reader = new ItemCountingItemStreamItemReader(); + reader.open(new ExecutionContext()); + assertFalse(reader.openCalled); + } + + @Test + public void testOpen() { + reader.open(new ExecutionContext()); + assertTrue(reader.openCalled); + } + + @Test + public void testReadToEnd() throws Exception { + reader.read(); + reader.read(); + reader.read(); + assertNull(reader.read()); + } + + @Test + public void testUpdate() throws Exception { + reader.read(); + ExecutionContext context = new ExecutionContext(); + reader.update(context); + assertEquals(1, context.size()); + assertEquals(1, context.getInt("foo.read.count")); + } + + @Test + public void testSetName() throws Exception { + reader.setName("bar"); + reader.read(); + ExecutionContext context = new ExecutionContext(); + reader.update(context); + assertEquals(1, context.getInt("bar.read.count")); + } + + @Test + public void testSetSaveState() throws Exception { + reader.read(); + ExecutionContext context = new ExecutionContext(); + reader.update(context); + assertEquals(1, context.size()); + } + + @Test + public void testReadToEndWithMax() throws Exception { + ExecutionContext context = new ExecutionContext(); + context.putInt("foo.read.count.max", 1); + reader.open(context); + reader.read(); + assertNull(reader.read()); + } + + @Test + public void testUpdateWithMax() throws Exception { + ExecutionContext context = new ExecutionContext(); + context.putInt("foo.read.count.max", 1); + reader.open(context); + reader.update(context); + assertEquals(2, context.size()); + } + + private static class ItemCountingItemStreamItemReader extends AbstractItemCountingItemStreamItemReader { + + private boolean closeCalled = false; + + private boolean openCalled = false; + + private Iterator items = Arrays.asList("a", "b", "c").iterator(); + + @Override + protected void doClose() throws Exception { + closeCalled = true; + } + + @Override + protected void doOpen() throws Exception { + openCalled = true; + } + + @Nullable + @Override + protected String doRead() throws Exception { + if (!items.hasNext()) { + return null; + } + return items.next(); + } + + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/IteratorItemReaderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/IteratorItemReaderTests.java index 5991f464d..908e74d9c 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/IteratorItemReaderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/IteratorItemReaderTests.java @@ -1,41 +1,42 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.item.support; - -import java.util.Arrays; - -import junit.framework.TestCase; - -public class IteratorItemReaderTests extends TestCase{ - - public void testIterable() throws Exception { - IteratorItemReader reader = new IteratorItemReader<>(Arrays.asList(new String[]{"a", "b", "c"})); - assertEquals("a", reader.read()); - assertEquals("b", reader.read()); - assertEquals("c", reader.read()); - assertEquals(null, reader.read()); - } - - public void testIterator() throws Exception { - IteratorItemReader reader = new IteratorItemReader<>(Arrays.asList(new String[] { "a", "b", "c" }).iterator()); - assertEquals("a", reader.read()); - assertEquals("b", reader.read()); - assertEquals("c", reader.read()); - assertEquals(null, reader.read()); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.item.support; + +import java.util.Arrays; + +import junit.framework.TestCase; + +public class IteratorItemReaderTests extends TestCase { + + public void testIterable() throws Exception { + IteratorItemReader reader = new IteratorItemReader<>(Arrays.asList(new String[] { "a", "b", "c" })); + assertEquals("a", reader.read()); + assertEquals("b", reader.read()); + assertEquals("c", reader.read()); + assertEquals(null, reader.read()); + } + + public void testIterator() throws Exception { + IteratorItemReader reader = new IteratorItemReader<>( + Arrays.asList(new String[] { "a", "b", "c" }).iterator()); + assertEquals("a", reader.read()); + assertEquals("b", reader.read()); + assertEquals("c", reader.read()); + assertEquals(null, reader.read()); + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/ListItemReaderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/ListItemReaderTests.java index 6b9cb98a1..ee5e63357 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/ListItemReaderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/ListItemReaderTests.java @@ -26,7 +26,7 @@ import junit.framework.TestCase; public class ListItemReaderTests extends TestCase { - ListItemReader reader = new ListItemReader<>(Arrays.asList(new String[]{"a", "b", "c"})); + ListItemReader reader = new ListItemReader<>(Arrays.asList(new String[] { "a", "b", "c" })); public void testNext() throws Exception { assertEquals("a", reader.read()); @@ -36,11 +36,12 @@ public class ListItemReaderTests extends TestCase { } public void testChangeList() throws Exception { - List list = new ArrayList<>(Arrays.asList(new String[]{"a", "b", "c"})); + List list = new ArrayList<>(Arrays.asList(new String[] { "a", "b", "c" })); reader = new ListItemReader<>(list); assertEquals("a", reader.read()); list.clear(); assertEquals(0, list.size()); assertEquals("b", reader.read()); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/ScriptItemProcessorTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/ScriptItemProcessorTests.java index f8d26eb7c..2beaaadae 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/ScriptItemProcessorTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/ScriptItemProcessorTests.java @@ -40,6 +40,7 @@ import static org.junit.Assume.assumeTrue; * @since 3.1 */ public class ScriptItemProcessorTests { + private static List availableLanguages = new ArrayList<>(); @BeforeClass @@ -67,7 +68,8 @@ public class ScriptItemProcessorTests { assumeTrue(languageExists("javascript")); ScriptItemProcessor scriptItemProcessor = new ScriptItemProcessor<>(); - scriptItemProcessor.setScriptSource("function process(item) { return item.toUpperCase(); } process(item);", "javascript"); + scriptItemProcessor.setScriptSource("function process(item) { return item.toUpperCase(); } process(item);", + "javascript"); scriptItemProcessor.afterPropertiesSet(); assertEquals("Incorrect transformed value", "SS", scriptItemProcessor.process("ss")); @@ -111,7 +113,8 @@ public class ScriptItemProcessorTests { assumeTrue(languageExists("bsh")); ScriptItemProcessor scriptItemProcessor = new ScriptItemProcessor<>(); - scriptItemProcessor.setScriptSource("String process(String item) { return item.toUpperCase(); } process(item);", "bsh"); + scriptItemProcessor.setScriptSource("String process(String item) { return item.toUpperCase(); } process(item);", + "bsh"); scriptItemProcessor.afterPropertiesSet(); assertEquals("Incorrect transformed value", "SS", scriptItemProcessor.process("ss")); @@ -133,7 +136,8 @@ public class ScriptItemProcessorTests { assumeTrue(languageExists("groovy")); ScriptItemProcessor scriptItemProcessor = new ScriptItemProcessor<>(); - scriptItemProcessor.setScriptSource("def process(item) { return item.toUpperCase() } \n process(item)", "groovy"); + scriptItemProcessor.setScriptSource("def process(item) { return item.toUpperCase() } \n process(item)", + "groovy"); scriptItemProcessor.afterPropertiesSet(); assertEquals("Incorrect transformed value", "SS", scriptItemProcessor.process("ss")); @@ -188,7 +192,8 @@ public class ScriptItemProcessorTests { @Test(expected = IllegalArgumentException.class) public void testScriptSourceWithNoLanguage() throws Exception { ScriptItemProcessor scriptItemProcessor = new ScriptItemProcessor<>(); - scriptItemProcessor.setScriptSource("function process(item) { return item.toUpperCase(); } process(item);", null); + scriptItemProcessor.setScriptSource("function process(item) { return item.toUpperCase(); } process(item);", + null); scriptItemProcessor.afterPropertiesSet(); } @@ -198,7 +203,8 @@ public class ScriptItemProcessorTests { ScriptItemProcessor scriptItemProcessor = new ScriptItemProcessor<>(); scriptItemProcessor.setItemBindingVariableName("someOtherVarName"); - scriptItemProcessor.setScriptSource("function process(param) { return param.toUpperCase(); } process(someOtherVarName);", "javascript"); + scriptItemProcessor.setScriptSource( + "function process(param) { return param.toUpperCase(); } process(someOtherVarName);", "javascript"); scriptItemProcessor.afterPropertiesSet(); assertEquals("Incorrect transformed value", "SS", scriptItemProcessor.process("ss")); @@ -210,7 +216,8 @@ public class ScriptItemProcessorTests { ScriptItemProcessor scriptItemProcessor = new ScriptItemProcessor(); scriptItemProcessor.setScriptEvaluator(new BshScriptEvaluator()); - scriptItemProcessor.setScriptSource("String process(String item) { return item.toUpperCase(); } process(item);", "bsh"); + scriptItemProcessor.setScriptSource("String process(String item) { return item.toUpperCase(); } process(item);", + "bsh"); scriptItemProcessor.afterPropertiesSet(); assertEquals("Incorrect transformed value", "SS", scriptItemProcessor.process("ss")); @@ -222,7 +229,8 @@ public class ScriptItemProcessorTests { ScriptItemProcessor scriptItemProcessor = new ScriptItemProcessor(); scriptItemProcessor.setScriptEvaluator(new GroovyScriptEvaluator()); - scriptItemProcessor.setScriptSource("def process(item) { return item.toUpperCase() } \n process(item)", "groovy"); + scriptItemProcessor.setScriptSource("def process(item) { return item.toUpperCase() } \n process(item)", + "groovy"); scriptItemProcessor.afterPropertiesSet(); assertEquals("Incorrect transformed value", "SS", scriptItemProcessor.process("ss")); @@ -231,4 +239,5 @@ public class ScriptItemProcessorTests { private boolean languageExists(String engineName) { return availableLanguages.contains(engineName); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/SingleItemPeekableItemReaderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/SingleItemPeekableItemReaderTests.java index 8301d0fb8..138a00445 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/SingleItemPeekableItemReaderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/SingleItemPeekableItemReaderTests.java @@ -29,11 +29,12 @@ import org.springframework.lang.Nullable; * */ public class SingleItemPeekableItemReaderTests { - + private SingleItemPeekableItemReader reader = new SingleItemPeekableItemReader<>(); - + /** - * Test method for {@link org.springframework.batch.item.support.SingleItemPeekableItemReader#read()}. + * Test method for + * {@link org.springframework.batch.item.support.SingleItemPeekableItemReader#read()}. */ @Test public void testRead() throws Exception { @@ -44,7 +45,8 @@ public class SingleItemPeekableItemReaderTests { } /** - * Test method for {@link org.springframework.batch.item.support.SingleItemPeekableItemReader#peek()}. + * Test method for + * {@link org.springframework.batch.item.support.SingleItemPeekableItemReader#peek()}. */ @Test public void testPeek() throws Exception { @@ -57,7 +59,8 @@ public class SingleItemPeekableItemReaderTests { } /** - * Test method for {@link org.springframework.batch.item.support.SingleItemPeekableItemReader#close()}. + * Test method for + * {@link org.springframework.batch.item.support.SingleItemPeekableItemReader#close()}. */ @Test public void testCloseAndOpenNoPeek() throws Exception { @@ -67,11 +70,12 @@ public class SingleItemPeekableItemReaderTests { reader.update(executionContext); reader.close(); reader.open(executionContext); - assertEquals("b", reader.read()); + assertEquals("b", reader.read()); } /** - * Test method for {@link org.springframework.batch.item.support.SingleItemPeekableItemReader#close()}. + * Test method for + * {@link org.springframework.batch.item.support.SingleItemPeekableItemReader#close()}. */ @Test public void testCloseAndOpenWithPeek() throws Exception { @@ -82,7 +86,7 @@ public class SingleItemPeekableItemReaderTests { reader.update(executionContext); reader.close(); reader.open(executionContext); - assertEquals("b", reader.read()); + assertEquals("b", reader.read()); } @Test @@ -94,20 +98,20 @@ public class SingleItemPeekableItemReaderTests { reader.update(executionContext); reader.close(); reader.open(executionContext); - assertEquals("b", reader.read()); + assertEquals("b", reader.read()); assertEquals("c", reader.peek()); reader.update(executionContext); reader.close(); reader.open(executionContext); - assertEquals("c", reader.read()); + assertEquals("c", reader.read()); } public static class CountingListItemReader extends AbstractItemCountingItemStreamItemReader { - + private final List list; - + private int counter = 0; - + public CountingListItemReader(List list) { this.list = list; setName("foo"); @@ -126,12 +130,12 @@ public class SingleItemPeekableItemReaderTests { @Nullable @Override protected T doRead() throws Exception { - if (counter>=list.size()) { + if (counter >= list.size()) { return null; } return list.get(counter++); } - + } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/SynchronizedItemStreamReaderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/SynchronizedItemStreamReaderTests.java index 73107e472..788d24258 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/SynchronizedItemStreamReaderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/SynchronizedItemStreamReaderTests.java @@ -31,26 +31,27 @@ import org.springframework.batch.item.ParseException; import org.springframework.lang.Nullable; /** - * * @author Matthew Ouyang * */ public class SynchronizedItemStreamReaderTests { /** - * A simple class used to test the SynchronizedItemStreamReader. It simply returns - * the number of times the read method has been called, manages some state variables - * and updates an ExecutionContext. - * + * A simple class used to test the SynchronizedItemStreamReader. It simply returns the + * number of times the read method has been called, manages some state variables and + * updates an ExecutionContext. + * * @author Matthew Ouyang * */ private class TestItemReader extends AbstractItemStreamItemReader implements ItemStreamReader { private int cursor = 0; + private boolean isClosed = false; public static final String HAS_BEEN_OPENED = "hasBeenOpened"; + public static final String UPDATE_COUNT_KEY = "updateCount"; @Nullable @@ -75,14 +76,13 @@ public class SynchronizedItemStreamReaderTests { executionContext.putInt(UPDATE_COUNT_KEY, 0); } - executionContext.putInt(UPDATE_COUNT_KEY - , executionContext.getInt(UPDATE_COUNT_KEY) + 1 - ); + executionContext.putInt(UPDATE_COUNT_KEY, executionContext.getInt(UPDATE_COUNT_KEY) + 1); } public boolean isClosed() { return this.isClosed; } + } @Test @@ -100,7 +100,8 @@ public class SynchronizedItemStreamReaderTests { assertEquals(true, executionContext.get(TestItemReader.HAS_BEEN_OPENED)); assertFalse(testItemReader.isClosed()); - /* Set up SIZE threads that read from the reader and updates the execution + /* + * Set up SIZE threads that read from the reader and updates the execution * context. */ final Set ecSet = new HashSet<>(); @@ -112,7 +113,8 @@ public class SynchronizedItemStreamReaderTests { try { ecSet.add(synchronizedItemStreamReader.read()); synchronizedItemStreamReader.update(executionContext); - } catch (Exception ignore) { + } + catch (Exception ignore) { ignore.printStackTrace(); } } @@ -128,9 +130,10 @@ public class SynchronizedItemStreamReaderTests { } testItemReader.close(); - /* Ensure cleanup happens as expected: status variable is set correctly and - * ExecutionContext variable is set properly. Lastly, the Set should - * have 1 to 20 which may not always be the case if the read is not synchronized. + /* + * Ensure cleanup happens as expected: status variable is set correctly and + * ExecutionContext variable is set properly. Lastly, the Set should have + * 1 to 20 which may not always be the case if the read is not synchronized. */ for (int i = 1; i <= SIZE; i++) { assertTrue(ecSet.contains(i)); @@ -138,4 +141,5 @@ public class SynchronizedItemStreamReaderTests { assertTrue(testItemReader.isClosed()); assertEquals(SIZE, executionContext.getInt(TestItemReader.UPDATE_COUNT_KEY)); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/SynchronizedItemStreamWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/SynchronizedItemStreamWriterTests.java index 4c4e28990..2f355ae76 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/SynchronizedItemStreamWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/SynchronizedItemStreamWriterTests.java @@ -22,13 +22,11 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; /** - * * @author Dimitrios Liapis * */ public class SynchronizedItemStreamWriterTests extends AbstractSynchronizedItemStreamWriterTests { - @Override protected SynchronizedItemStreamWriter createNewSynchronizedItemStreamWriter() { SynchronizedItemStreamWriter synchronizedItemStreamWriter = new SynchronizedItemStreamWriter<>(); @@ -42,4 +40,5 @@ public class SynchronizedItemStreamWriterTests extends AbstractSynchronizedItemS () -> ((InitializingBean) new SynchronizedItemStreamWriter<>()).afterPropertiesSet()); assertEquals("A delegate item writer is required", expectedException.getMessage()); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/TransactionAwareListItemReaderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/TransactionAwareListItemReaderTests.java index 5674bf256..4a11f7da3 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/TransactionAwareListItemReaderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/TransactionAwareListItemReaderTests.java @@ -34,10 +34,11 @@ public class TransactionAwareListItemReaderTests extends TestCase { private ListItemReader reader; - @Override + @Override protected void setUp() throws Exception { super.setUp(); - reader = new ListItemReader<>(TransactionAwareProxyFactory.createTransactionalList(Arrays.asList("a", "b", "c"))); + reader = new ListItemReader<>( + TransactionAwareProxyFactory.createTransactionalList(Arrays.asList("a", "b", "c"))); } public void testNext() throws Exception { @@ -52,7 +53,7 @@ public class TransactionAwareListItemReaderTests extends TestCase { final List taken = new ArrayList<>(); try { new TransactionTemplate(transactionManager).execute(new TransactionCallback() { - @Override + @Override public Void doInTransaction(TransactionStatus status) { taken.add(reader.read()); return null; @@ -79,7 +80,7 @@ public class TransactionAwareListItemReaderTests extends TestCase { PlatformTransactionManager transactionManager = new ResourcelessTransactionManager(); final List taken = new ArrayList<>(); new TransactionTemplate(transactionManager).execute(new TransactionCallback() { - @Override + @Override public Void doInTransaction(TransactionStatus status) { Object next = reader.read(); while (next != null) { @@ -98,7 +99,7 @@ public class TransactionAwareListItemReaderTests extends TestCase { final List taken = new ArrayList<>(); try { new TransactionTemplate(transactionManager).execute(new TransactionCallback() { - @Override + @Override public Void doInTransaction(TransactionStatus status) { taken.add(reader.read()); throw new RuntimeException("Rollback!"); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/builder/ClassifierCompositeItemProcessorBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/builder/ClassifierCompositeItemProcessorBuilderTests.java index ac4914eac..3e766836a 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/builder/ClassifierCompositeItemProcessorBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/builder/ClassifierCompositeItemProcessorBuilderTests.java @@ -43,8 +43,7 @@ public class ClassifierCompositeItemProcessorBuilderTests { routingConfiguration.put("foo", fooProcessor); routingConfiguration.put("*", defaultProcessor); ClassifierCompositeItemProcessor processor = new ClassifierCompositeItemProcessorBuilder() - .classifier(new PatternMatchingClassifier<>(routingConfiguration)) - .build(); + .classifier(new PatternMatchingClassifier<>(routingConfiguration)).build(); assertEquals("bar", processor.process("bar")); assertEquals("foo: foo", processor.process("foo")); @@ -62,4 +61,5 @@ public class ClassifierCompositeItemProcessorBuilderTests { "A classifier is required.", iae.getMessage()); } } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/builder/ClassifierCompositeItemWriterBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/builder/ClassifierCompositeItemWriterBuilderTests.java index 616f16dd2..c585bbc34 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/builder/ClassifierCompositeItemWriterBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/builder/ClassifierCompositeItemWriterBuilderTests.java @@ -66,4 +66,5 @@ public class ClassifierCompositeItemWriterBuilderTests { iae.getMessage()); } } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/builder/CompositeItemProcessorBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/builder/CompositeItemProcessorBuilderTests.java index c786619fe..0bd654f12 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/builder/CompositeItemProcessorBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/builder/CompositeItemProcessorBuilderTests.java @@ -91,8 +91,7 @@ public class CompositeItemProcessorBuilderTests { "The delegates list must have one or more delegates."); validateExceptionMessage(new CompositeItemProcessorBuilder<>().delegates(), "The delegates list must have one or more delegates."); - validateExceptionMessage(new CompositeItemProcessorBuilder<>(), - "A list of delegates is required."); + validateExceptionMessage(new CompositeItemProcessorBuilder<>(), "A list of delegates is required."); } private void validateExceptionMessage(CompositeItemProcessorBuilder builder, String message) { @@ -105,4 +104,5 @@ public class CompositeItemProcessorBuilderTests { iae.getMessage()); } } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/builder/CompositeItemWriterBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/builder/CompositeItemWriterBuilderTests.java index 9e1f168d8..19f9e7403 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/builder/CompositeItemWriterBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/builder/CompositeItemWriterBuilderTests.java @@ -103,7 +103,8 @@ public class CompositeItemWriterBuilderTests { if (!ignoreItemStream) { openCount = 1; } - // If user has set ignoreItemStream to true, then it is expected that they opened the delegate writer. + // If user has set ignoreItemStream to true, then it is expected that they opened + // the delegate writer. verify(writer, times(openCount)).open(executionContext); itemWriter.write(data); } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/builder/ScriptItemProcessorBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/builder/ScriptItemProcessorBuilderTests.java index 69a6d5ff6..be8fac219 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/builder/ScriptItemProcessorBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/builder/ScriptItemProcessorBuilderTests.java @@ -38,6 +38,7 @@ import static org.junit.Assume.assumeTrue; * @author Glenn Renfro */ public class ScriptItemProcessorBuilderTests { + private static List availableLanguages = new ArrayList<>(); @BeforeClass @@ -57,9 +58,7 @@ public class ScriptItemProcessorBuilderTests { @Test public void testScriptSource() throws Exception { ScriptItemProcessor scriptItemProcessor = new ScriptItemProcessorBuilder() - .scriptSource("item.toUpperCase();") - .language("javascript") - .build(); + .scriptSource("item.toUpperCase();").language("javascript").build(); scriptItemProcessor.afterPropertiesSet(); assertEquals("Incorrect transformed value", "AA", scriptItemProcessor.process("aa")); @@ -68,10 +67,7 @@ public class ScriptItemProcessorBuilderTests { @Test public void testItemBinding() throws Exception { ScriptItemProcessor scriptItemProcessor = new ScriptItemProcessorBuilder() - .scriptSource("foo.contains('World');") - .language("javascript") - .itemBindingVariableName("foo") - .build(); + .scriptSource("foo.contains('World');").language("javascript").itemBindingVariableName("foo").build(); scriptItemProcessor.afterPropertiesSet(); assertEquals("Incorrect transformed value", true, scriptItemProcessor.process("Hello World")); @@ -81,8 +77,7 @@ public class ScriptItemProcessorBuilderTests { public void testScriptResource() throws Exception { Resource resource = new ClassPathResource("org/springframework/batch/item/support/processor-test-simple.js"); ScriptItemProcessor scriptItemProcessor = new ScriptItemProcessorBuilder() - .scriptResource(resource) - .build(); + .scriptResource(resource).build(); scriptItemProcessor.afterPropertiesSet(); assertEquals("Incorrect transformed value", "BB", scriptItemProcessor.process("bb")); @@ -90,13 +85,13 @@ public class ScriptItemProcessorBuilderTests { @Test public void testNoScriptSourceNorResource() throws Exception { - validateExceptionMessage(new ScriptItemProcessorBuilder<>(), - "scriptResource or scriptSource is required."); + validateExceptionMessage(new ScriptItemProcessorBuilder<>(), "scriptResource or scriptSource is required."); } @Test public void testNoScriptSourceLanguage() throws Exception { - validateExceptionMessage(new ScriptItemProcessorBuilder().scriptSource("foo.contains('World');"), + validateExceptionMessage( + new ScriptItemProcessorBuilder().scriptSource("foo.contains('World');"), "language is required when using scriptSource."); } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/builder/SingleItemPeekableItemReaderBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/builder/SingleItemPeekableItemReaderBuilderTests.java index 183fd02bf..30e753ed3 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/builder/SingleItemPeekableItemReaderBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/builder/SingleItemPeekableItemReaderBuilderTests.java @@ -40,9 +40,7 @@ public class SingleItemPeekableItemReaderBuilderTests { @Test public void testPeek() throws Exception { SingleItemPeekableItemReader reader = new SingleItemPeekableItemReaderBuilder() - .delegate( - new ListItemReader<>(Arrays.asList("a", "b"))) - .build(); + .delegate(new ListItemReader<>(Arrays.asList("a", "b"))).build(); assertEquals("a", reader.peek()); assertEquals("a", reader.read()); assertEquals("b", reader.read()); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/builder/SynchronizedItemStreamReaderBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/builder/SynchronizedItemStreamReaderBuilderTests.java index 5facf3993..8a9ad8a06 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/builder/SynchronizedItemStreamReaderBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/builder/SynchronizedItemStreamReaderBuilderTests.java @@ -1,10 +1,10 @@ /* * Copyright 2017-2019 the original author or authors. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software @@ -143,6 +143,7 @@ public class SynchronizedItemStreamReaderBuilderTests { public boolean isClosed() { return this.isClosed; } + } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/builder/SynchronizedItemStreamWriterBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/builder/SynchronizedItemStreamWriterBuilderTests.java index 4888b4bc9..ee0a3925f 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/builder/SynchronizedItemStreamWriterBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/builder/SynchronizedItemStreamWriterBuilderTests.java @@ -23,18 +23,14 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; /** - * * @author Dimitrios Liapis * */ public class SynchronizedItemStreamWriterBuilderTests extends AbstractSynchronizedItemStreamWriterTests { - @Override protected SynchronizedItemStreamWriter createNewSynchronizedItemStreamWriter() { - return new SynchronizedItemStreamWriterBuilder<>() - .delegate(delegate) - .build(); + return new SynchronizedItemStreamWriterBuilder<>().delegate(delegate).build(); } @Test @@ -48,4 +44,5 @@ public class SynchronizedItemStreamWriterBuilderTests extends AbstractSynchroniz // then assertEquals("A delegate item writer is required", expectedException.getMessage()); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/util/ExecutionContextUserSupportTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/util/ExecutionContextUserSupportTests.java index 284904ef6..f3daeed67 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/util/ExecutionContextUserSupportTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/util/ExecutionContextUserSupportTests.java @@ -27,8 +27,7 @@ public class ExecutionContextUserSupportTests extends TestCase { ExecutionContextUserSupport tested = new ExecutionContextUserSupport(); /** - * Regular usage scenario - prepends the name (supposed to be unique) to - * argument. + * Regular usage scenario - prepends the name (supposed to be unique) to argument. */ public void testGetKey() { tested.setName("uniqueName"); @@ -48,4 +47,5 @@ public class ExecutionContextUserSupportTests extends TestCase { // expected } } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/util/FileUtilsTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/util/FileUtilsTests.java index ce385c4bd..73f510131 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/util/FileUtilsTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/util/FileUtilsTests.java @@ -41,8 +41,8 @@ public class FileUtilsTests { private File file = new File("target/FileUtilsTests.tmp"); /** - * No restart + file should not be overwritten => file is created if it does - * not exist, exception is thrown if it already exists + * No restart + file should not be overwritten => file is created if it does not + * exist, exception is thrown if it already exists */ @Test public void testNoRestart() throws Exception { @@ -77,8 +77,8 @@ public class FileUtilsTests { } /** - * In case of restart, the file is supposed to exist and exception is thrown - * if it does not. + * In case of restart, the file is supposed to exist and exception is thrown if it + * does not. */ @Test public void testRestart() throws Exception { @@ -127,10 +127,10 @@ public class FileUtilsTests { dir1.delete(); } } - + /** - * If the directories on the file path do not exist, they should be created - * This must be true also in append mode + * If the directories on the file path do not exist, they should be created This must + * be true also in append mode */ @Test public void testCreateDirectoryStructureAppendMode() { @@ -152,44 +152,48 @@ public class FileUtilsTests { } @Test - public void testBadFile(){ + public void testBadFile() { @SuppressWarnings("serial") - File file = new File("new file"){ - @Override + File file = new File("new file") { + @Override public boolean createNewFile() throws IOException { throw new IOException(); } }; - try{ + try { FileUtils.setUpOutputFile(file, false, false, false); fail(); - }catch(ItemStreamException ex){ + } + catch (ItemStreamException ex) { assertTrue(ex.getCause() instanceof IOException); - }finally{ + } + finally { file.delete(); } } - + @Test - public void testCouldntCreateFile(){ + public void testCouldntCreateFile() { @SuppressWarnings("serial") - File file = new File("new file"){ - + File file = new File("new file") { + @Override public boolean exists() { return false; } - + }; - try{ + try { FileUtils.setUpOutputFile(file, false, false, false); fail("Expected IOException because file doesn't exist"); - }catch(ItemStreamException ex){ + } + catch (ItemStreamException ex) { String message = ex.getMessage(); - assertTrue("Wrong message: "+message, message.startsWith("Output file was not created")); - }finally{ + assertTrue("Wrong message: " + message, message.startsWith("Output file was not created")); + } + finally { file.delete(); } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/validator/SpringValidatorTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/validator/SpringValidatorTests.java index 2233a481f..f2dcbcb0a 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/validator/SpringValidatorTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/validator/SpringValidatorTests.java @@ -87,8 +87,7 @@ public class SpringValidatorTests { } /** - * Typical failed validation - message contains the item and names of - * invalid fields. + * Typical failed validation - message contains the item and names of invalid fields. */ @Test public void testValidateFailureWithFields() { @@ -97,26 +96,27 @@ public class SpringValidatorTests { fail("exception should have been thrown on invalid value"); } catch (ValidationException expected) { - assertTrue("message should contain the item#toString() value", expected.getMessage().contains( - "TestBeanToString")); + assertTrue("message should contain the item#toString() value", + expected.getMessage().contains("TestBeanToString")); assertTrue("message should contain names of the invalid fields", expected.getMessage().contains("foo")); assertTrue("message should contain names of the invalid fields", expected.getMessage().contains("bar")); } } private static class MockSpringValidator implements Validator { + public static final TestBean ACCEPT_VALUE = new TestBean(); public static final TestBean REJECT_VALUE = new TestBean(); public static final TestBean REJECT_MULTI_VALUE = new TestBean("foo", "bar"); - @Override + @Override public boolean supports(Class clazz) { return clazz.isAssignableFrom(TestBean.class); } - @Override + @Override public void validate(Object value, Errors errors) { if (value.equals(ACCEPT_VALUE)) { return; // return without adding errors @@ -132,10 +132,12 @@ public class SpringValidatorTests { return; } } + } @SuppressWarnings("unused") private static class TestBean { + private String foo; private String bar; @@ -158,9 +160,11 @@ public class SpringValidatorTests { this.bar = bar; } - @Override + @Override public String toString() { return "TestBeanToString"; } + } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/validator/ValidatingItemProcessorTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/validator/ValidatingItemProcessorTests.java index 72f19b1e8..c7b17c788 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/validator/ValidatingItemProcessorTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/validator/ValidatingItemProcessorTests.java @@ -1,68 +1,69 @@ -/* - * Copyright 2008-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.validator; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; - -import org.junit.Test; - -/** - * Tests for {@link ValidatingItemProcessor}. - */ -public class ValidatingItemProcessorTests { - - @SuppressWarnings("unchecked") - private Validator validator = mock(Validator.class); - - private static final String ITEM = "item"; - - @Test - public void testSuccessfulValidation() throws Exception { - - ValidatingItemProcessor tested = new ValidatingItemProcessor<>(validator); - - validator.validate(ITEM); - - assertSame(ITEM, tested.process(ITEM)); - } - - @Test(expected = ValidationException.class) - public void testFailedValidation() throws Exception { - - ValidatingItemProcessor tested = new ValidatingItemProcessor<>(validator); - - processFailedValidation(tested); - } - - @Test - public void testFailedValidation_Filter() throws Exception { - - ValidatingItemProcessor tested = new ValidatingItemProcessor<>(validator); - tested.setFilter(true); - - assertNull(processFailedValidation(tested)); - } - - private String processFailedValidation(ValidatingItemProcessor tested) { - validator.validate(ITEM); - when(validator).thenThrow(new ValidationException("invalid item")); - - return tested.process(ITEM); - } -} +/* + * Copyright 2008-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item.validator; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; + +import org.junit.Test; + +/** + * Tests for {@link ValidatingItemProcessor}. + */ +public class ValidatingItemProcessorTests { + + @SuppressWarnings("unchecked") + private Validator validator = mock(Validator.class); + + private static final String ITEM = "item"; + + @Test + public void testSuccessfulValidation() throws Exception { + + ValidatingItemProcessor tested = new ValidatingItemProcessor<>(validator); + + validator.validate(ITEM); + + assertSame(ITEM, tested.process(ITEM)); + } + + @Test(expected = ValidationException.class) + public void testFailedValidation() throws Exception { + + ValidatingItemProcessor tested = new ValidatingItemProcessor<>(validator); + + processFailedValidation(tested); + } + + @Test + public void testFailedValidation_Filter() throws Exception { + + ValidatingItemProcessor tested = new ValidatingItemProcessor<>(validator); + tested.setFilter(true); + + assertNull(processFailedValidation(tested)); + } + + private String processFailedValidation(ValidatingItemProcessor tested) { + validator.validate(ITEM); + when(validator).thenThrow(new ValidationException("invalid item")); + + return tested.process(ITEM); + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/validator/ValidationExceptionTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/validator/ValidationExceptionTests.java index 1f274449a..b5cb29790 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/validator/ValidationExceptionTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/validator/ValidationExceptionTests.java @@ -20,12 +20,12 @@ import org.springframework.batch.repeat.AbstractExceptionTests; public class ValidationExceptionTests extends AbstractExceptionTests { - @Override + @Override public Exception getException(String msg) throws Exception { return new ValidationException(msg); } - @Override + @Override public Exception getException(String msg, Throwable t) throws Exception { return new ValidationException(msg, t); } @@ -33,4 +33,5 @@ public class ValidationExceptionTests extends AbstractExceptionTests { public void testNothing() throws Exception { // fool coverage tools... } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/AbstractStaxEventReaderItemReaderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/AbstractStaxEventReaderItemReaderTests.java index 37300d161..c82b9a602 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/AbstractStaxEventReaderItemReaderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/AbstractStaxEventReaderItemReaderTests.java @@ -56,8 +56,8 @@ public abstract class AbstractStaxEventReaderItemReaderTests { @Test public void testReadNested() throws Exception { - reader.setResource(new ClassPathResource(ClassUtils - .addResourcePathToPackagePath(getClass(), "input-nested.xml"))); + reader.setResource( + new ClassPathResource(ClassUtils.addResourcePathToPackagePath(getClass(), "input-nested.xml"))); reader.open(new ExecutionContext()); Trade result; List results = new ArrayList<>(); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/AbstractStaxEventWriterItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/AbstractStaxEventWriterItemWriterTests.java index 8d56a73ad..e769b4464 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/AbstractStaxEventWriterItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/AbstractStaxEventWriterItemWriterTests.java @@ -47,7 +47,7 @@ import org.springframework.util.StopWatch; import static org.hamcrest.MatcherAssert.assertThat; public abstract class AbstractStaxEventWriterItemWriterTests { - + private Log logger = LogFactory.getLog(getClass()); private static final int MAX_WRITE = 100; @@ -98,10 +98,8 @@ public abstract class AbstractStaxEventWriterItemWriterTests { stopWatch.stop(); logger.info("Timing for XML writer: " + stopWatch); - assertThat( - Input.from(expected.getFile()), - CompareMatcher.isSimilarTo(Input.from(resource.getFile())) - .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))); + assertThat(Input.from(expected.getFile()), CompareMatcher.isSimilarTo(Input.from(resource.getFile())) + .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))); } @Before diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/EventHelper.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/EventHelper.java index 414860a07..0d195f9f8 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/EventHelper.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/EventHelper.java @@ -21,25 +21,27 @@ import javax.xml.stream.events.XMLEvent; /** * Helper methods for working with XML Events. - * + * * @author Robert Kasanicky */ public class EventHelper { - //utility class - private EventHelper() {} - + // utility class + private EventHelper() { + } + /** * @return element name assuming the event is instance of StartElement */ public static String startElementName(XMLEvent event) { return ((StartElement) event).getName().getLocalPart(); } - + /** * @return element name assuming the event is instance of EndElement */ public static String endElementName(XMLEvent event) { return ((EndElement) event).getName().getLocalPart(); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/Jaxb2MarshallingTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/Jaxb2MarshallingTests.java index c9cf2b2d1..f7ec7d81c 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/Jaxb2MarshallingTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/Jaxb2MarshallingTests.java @@ -35,15 +35,15 @@ public class Jaxb2MarshallingTests extends AbstractStaxEventWriterItemWriterTest @Override protected Marshaller getMarshaller() throws Exception { - + Jaxb2Marshaller marshaller = new Jaxb2Marshaller(); marshaller.setClassesToBeBound(new Class[] { Trade.class }); marshaller.afterPropertiesSet(); - + StringWriter string = new StringWriter(); marshaller.marshal(new Trade("FOO", 100, BigDecimal.valueOf(10.), "bar"), new StreamResult(string)); String content = string.toString(); - assertTrue("Wrong content: "+content, content.contains("bar")); + assertTrue("Wrong content: " + content, content.contains("bar")); return marshaller; } @@ -62,4 +62,5 @@ public class Jaxb2MarshallingTests extends AbstractStaxEventWriterItemWriterTest throw new IllegalStateException(e); } } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/Jaxb2NamespaceMarshallingTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/Jaxb2NamespaceMarshallingTests.java index 3d14a0724..7c3fd1da7 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/Jaxb2NamespaceMarshallingTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/Jaxb2NamespaceMarshallingTests.java @@ -49,7 +49,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertTrue; public class Jaxb2NamespaceMarshallingTests { - + private Log logger = LogFactory.getLog(getClass()); private static final int MAX_WRITE = 100; @@ -100,8 +100,7 @@ public class Jaxb2NamespaceMarshallingTests { stopWatch.stop(); logger.info("Timing for XML writer: " + stopWatch); - assertThat( - Input.from(expected.getFile()), + assertThat(Input.from(expected.getFile()), CompareMatcher.isSimilarTo(Input.from(resource.getFile())).normalizeWhitespace()); } @@ -112,7 +111,7 @@ public class Jaxb2NamespaceMarshallingTests { directory.mkdirs(); outputFile = File.createTempFile(ClassUtils.getShortName(this.getClass()), ".xml", directory); resource = new FileSystemResource(outputFile); - + writer.setResource(resource); writer.setMarshaller(getMarshaller()); @@ -130,15 +129,15 @@ public class Jaxb2NamespaceMarshallingTests { } protected Marshaller getMarshaller() throws Exception { - + Jaxb2Marshaller marshaller = new Jaxb2Marshaller(); marshaller.setClassesToBeBound(new Class[] { QualifiedTrade.class }); marshaller.afterPropertiesSet(); - + StringWriter string = new StringWriter(); marshaller.marshal(new QualifiedTrade("FOO", 100, BigDecimal.valueOf(10.), "bar"), new StreamResult(string)); String content = string.toString(); - assertTrue("Wrong content: "+content, content.contains("bar")); + assertTrue("Wrong content: " + content, content.contains("bar")); return marshaller; } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/Jaxb2NamespaceUnmarshallingTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/Jaxb2NamespaceUnmarshallingTests.java index a80c7dfb8..e73b65a74 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/Jaxb2NamespaceUnmarshallingTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/Jaxb2NamespaceUnmarshallingTests.java @@ -42,8 +42,8 @@ public class Jaxb2NamespaceUnmarshallingTests { private StaxEventItemReader reader = new StaxEventItemReader<>(); - private Resource resource = new ClassPathResource(ClassUtils.addResourcePathToPackagePath(getClass(), - "domain/trades.xml")); + private Resource resource = new ClassPathResource( + ClassUtils.addResourcePathToPackagePath(getClass(), "domain/trades.xml")); @Before public void setUp() throws Exception { @@ -56,8 +56,8 @@ public class Jaxb2NamespaceUnmarshallingTests { @Test public void testUnmarshal() throws Exception { - QualifiedTrade trade = (QualifiedTrade) getUnmarshaller().unmarshal( - new StreamSource(new StringReader(TRADE_XML))); + QualifiedTrade trade = (QualifiedTrade) getUnmarshaller() + .unmarshal(new StreamSource(new StringReader(TRADE_XML))); Assert.assertEquals("XYZ0001", trade.getIsin()); Assert.assertEquals(5, trade.getQuantity()); Assert.assertEquals(new BigDecimal("11.39"), trade.getPrice()); @@ -118,4 +118,5 @@ public class Jaxb2NamespaceUnmarshallingTests { private static String TRADE_XML = "" + "Customer1XYZ000111.395" + ""; + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/Jaxb2UnmarshallingTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/Jaxb2UnmarshallingTests.java index 7de16603f..e3a6364b6 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/Jaxb2UnmarshallingTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/Jaxb2UnmarshallingTests.java @@ -29,7 +29,7 @@ public class Jaxb2UnmarshallingTests extends AbstractStaxEventReaderItemReaderTe marshaller.setClassesToBeBound(new Class[] { Trade.class }); // marshaller.setSchema(new ClassPathResource("trade.xsd", Trade.class)); marshaller.afterPropertiesSet(); - + return marshaller; } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/StaxEventItemReaderCommonTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/StaxEventItemReaderCommonTests.java index d3250fc18..06f4d54ee 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/StaxEventItemReaderCommonTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/StaxEventItemReaderCommonTests.java @@ -1,84 +1,84 @@ -/* - * Copyright 2008-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.xml; - -import java.io.IOException; -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.events.Attribute; -import javax.xml.stream.events.StartElement; -import javax.xml.transform.Source; - -import org.springframework.batch.item.AbstractItemStreamItemReaderTests; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.sample.Foo; -import org.springframework.core.io.ByteArrayResource; -import org.springframework.oxm.Unmarshaller; -import org.springframework.oxm.XmlMappingException; - -import static org.junit.Assert.assertTrue; - -public class StaxEventItemReaderCommonTests extends AbstractItemStreamItemReaderTests { - - private final static String FOOS = " "; - - @Override - protected ItemReader getItemReader() throws Exception { - StaxEventItemReader reader = new StaxEventItemReader<>(); - reader.setResource(new ByteArrayResource(FOOS.getBytes())); - reader.setFragmentRootElementName("foo"); - reader.setUnmarshaller(new Unmarshaller() { - @Override - public Object unmarshal(Source source) throws XmlMappingException, IOException { - Attribute attr = null ; - try { - XMLEventReader eventReader = StaxTestUtils.getXmlEventReader( source); - assertTrue(eventReader.nextEvent().isStartDocument()); - StartElement event = eventReader.nextEvent().asStartElement(); - attr = (Attribute) event.getAttributes().next(); - } - catch (Exception e) { - throw new RuntimeException(e); - } - Foo foo = new Foo(); - foo.setValue(Integer.parseInt(attr.getValue())); - return foo; - } - - @Override - public boolean supports(Class clazz) { - return true; - } - - }); - - reader.setSaveState(true); - reader.afterPropertiesSet(); - return reader; - } - - @Override - protected void pointToEmptyInput(ItemReader tested) throws Exception { - StaxEventItemReader reader = (StaxEventItemReader) tested; - reader.close(); - - reader.setResource(new ByteArrayResource("".getBytes())); - reader.afterPropertiesSet(); - - reader.open(new ExecutionContext()); - } - -} +/* + * Copyright 2008-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item.xml; + +import java.io.IOException; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.events.Attribute; +import javax.xml.stream.events.StartElement; +import javax.xml.transform.Source; + +import org.springframework.batch.item.AbstractItemStreamItemReaderTests; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.sample.Foo; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.oxm.Unmarshaller; +import org.springframework.oxm.XmlMappingException; + +import static org.junit.Assert.assertTrue; + +public class StaxEventItemReaderCommonTests extends AbstractItemStreamItemReaderTests { + + private final static String FOOS = " "; + + @Override + protected ItemReader getItemReader() throws Exception { + StaxEventItemReader reader = new StaxEventItemReader<>(); + reader.setResource(new ByteArrayResource(FOOS.getBytes())); + reader.setFragmentRootElementName("foo"); + reader.setUnmarshaller(new Unmarshaller() { + @Override + public Object unmarshal(Source source) throws XmlMappingException, IOException { + Attribute attr = null; + try { + XMLEventReader eventReader = StaxTestUtils.getXmlEventReader(source); + assertTrue(eventReader.nextEvent().isStartDocument()); + StartElement event = eventReader.nextEvent().asStartElement(); + attr = (Attribute) event.getAttributes().next(); + } + catch (Exception e) { + throw new RuntimeException(e); + } + Foo foo = new Foo(); + foo.setValue(Integer.parseInt(attr.getValue())); + return foo; + } + + @Override + public boolean supports(Class clazz) { + return true; + } + + }); + + reader.setSaveState(true); + reader.afterPropertiesSet(); + return reader; + } + + @Override + protected void pointToEmptyInput(ItemReader tested) throws Exception { + StaxEventItemReader reader = (StaxEventItemReader) tested; + reader.close(); + + reader.setResource(new ByteArrayResource("".getBytes())); + reader.afterPropertiesSet(); + + reader.open(new ExecutionContext()); + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/StaxEventItemReaderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/StaxEventItemReaderTests.java index da7f5cdf2..435955fac 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/StaxEventItemReaderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/StaxEventItemReaderTests.java @@ -60,7 +60,7 @@ import static org.junit.Assert.fail; /** * Tests for {@link StaxEventItemReader}. - * + * * @author Robert Kasanicky * @author Michael Minella * @author Mahmoud Ben Hassine @@ -94,8 +94,8 @@ public class StaxEventItemReaderTests { private Unmarshaller unmarshaller = new MockFragmentUnmarshaller(); private static final String FRAGMENT_ROOT_ELEMENT = "fragment"; - - private static final String[] MULTI_FRAGMENT_ROOT_ELEMENTS = {"fragmentA", "fragmentB"}; + + private static final String[] MULTI_FRAGMENT_ROOT_ELEMENTS = { "fragmentA", "fragmentB" }; private ExecutionContext executionContext; @@ -135,8 +135,8 @@ public class StaxEventItemReaderTests { } /** - * Regular usage scenario. ItemReader should pass XML fragments to unmarshaller wrapped with StartDocument and - * EndDocument events. + * Regular usage scenario. ItemReader should pass XML fragments to unmarshaller + * wrapped with StartDocument and EndDocument events. */ @Test public void testFragmentWrapping() throws Exception { @@ -247,7 +247,7 @@ public class StaxEventItemReaderTests { source.close(); } - + @Test public void testMultiFragment() throws Exception { @@ -262,22 +262,23 @@ public class StaxEventItemReaderTests { assertNull(source.read()); // there are only three fragments source.close(); - } + } @Test public void testMultiFragmentNameSpace() throws Exception { source.setResource(new ByteArrayResource(xmlMultiFragment.getBytes())); - source.setFragmentRootElementNames(new String[] {"{urn:org.test.bar}fragmentA", "fragmentB"}); + source.setFragmentRootElementNames(new String[] { "{urn:org.test.bar}fragmentA", "fragmentB" }); source.afterPropertiesSet(); source.open(executionContext); // see asserts in the mock unmarshaller assertNotNull(source.read()); assertNotNull(source.read()); - assertNull(source.read()); // there are only two fragments (one has wrong namespace) + assertNull(source.read()); // there are only two fragments (one has wrong + // namespace) source.close(); - } + } @Test public void testMultiFragmentRestart() throws Exception { @@ -289,23 +290,23 @@ public class StaxEventItemReaderTests { // see asserts in the mock unmarshaller assertNotNull(source.read()); assertNotNull(source.read()); - - source.update(executionContext); + + source.update(executionContext); assertEquals(2, executionContext.getInt(ClassUtils.getShortName(StaxEventItemReader.class) + ".read.count")); - + source.close(); - + source = createNewInputSource(); source.setResource(new ByteArrayResource(xmlMultiFragment.getBytes())); source.setFragmentRootElementNames(MULTI_FRAGMENT_ROOT_ELEMENTS); source.afterPropertiesSet(); source.open(executionContext); - + assertNotNull(source.read()); assertNull(source.read()); // there are only three fragments source.close(); - } + } @Test public void testMultiFragmentNested() throws Exception { @@ -322,7 +323,7 @@ public class StaxEventItemReaderTests { source.close(); } - + @Test public void testMultiFragmentNestedRestart() throws Exception { @@ -333,24 +334,24 @@ public class StaxEventItemReaderTests { // see asserts in the mock unmarshaller assertNotNull(source.read()); assertNotNull(source.read()); - - source.update(executionContext); + + source.update(executionContext); assertEquals(2, executionContext.getInt(ClassUtils.getShortName(StaxEventItemReader.class) + ".read.count")); - + source.close(); - + source = createNewInputSource(); source.setResource(new ByteArrayResource(xmlMultiFragment.getBytes())); source.setFragmentRootElementNames(MULTI_FRAGMENT_ROOT_ELEMENTS); source.afterPropertiesSet(); source.open(executionContext); - + assertNotNull(source.read()); assertNull(source.read()); // there are only three fragments source.close(); - } - + } + /** * Cursor is moved before beginning of next fragment. */ @@ -372,7 +373,8 @@ public class StaxEventItemReaderTests { * Empty document works OK. */ @Test - public void testMoveCursorToNextFragmentOnEmpty() throws XMLStreamException, FactoryConfigurationError, IOException { + public void testMoveCursorToNextFragmentOnEmpty() + throws XMLStreamException, FactoryConfigurationError, IOException { Resource resource = new ByteArrayResource(emptyXml.getBytes()); XMLEventReader reader = StaxUtils.createDefensiveInputFactory().createXMLEventReader(resource.getInputStream()); @@ -383,7 +385,8 @@ public class StaxEventItemReaderTests { * Document with no fragments works OK. */ @Test - public void testMoveCursorToNextFragmentOnMissing() throws XMLStreamException, FactoryConfigurationError, IOException { + public void testMoveCursorToNextFragmentOnMissing() + throws XMLStreamException, FactoryConfigurationError, IOException { Resource resource = new ByteArrayResource(missingXml.getBytes()); XMLEventReader reader = StaxUtils.createDefensiveInputFactory().createXMLEventReader(resource.getInputStream()); assertFalse(source.moveCursorToNextFragment(reader)); @@ -436,7 +439,8 @@ public class StaxEventItemReaderTests { } /** - * Statistics return the current record count. Calling read after end of input does not increase the counter. + * Statistics return the current record count. Calling read after end of input does + * not increase the counter. */ @Test public void testExecutionContext() throws Exception { @@ -577,9 +581,9 @@ public class StaxEventItemReaderTests { } /** - * Make sure the reader doesn't end up in inconsistent state if there's an error during unmarshalling (BATCH-1738). - * After an error during read the next read call should continue with reading the next - * fragment. + * Make sure the reader doesn't end up in inconsistent state if there's an error + * during unmarshalling (BATCH-1738). After an error during read the next + * read call should continue with reading the next fragment. */ @Test public void exceptionDuringUnmarshalling() throws Exception { @@ -607,9 +611,9 @@ public class StaxEventItemReaderTests { @Test public void testDtdXml() { - String xmlWithDtd = "\n\n]>\n&entityex;"; + String xmlWithDtd = "\n\n]>\n&entityex;"; StaxEventItemReader reader = new StaxEventItemReader<>(); reader.setName("foo"); reader.setResource(new ByteArrayResource(xmlWithDtd.getBytes())); @@ -621,7 +625,8 @@ public class StaxEventItemReaderTests { xmlEventReader.nextEvent(); xmlEventReader.nextEvent(); return xmlEventReader.getElementText(); - } catch (Exception e) { + } + catch (Exception e) { throw new RuntimeException(e); } } @@ -633,7 +638,8 @@ public class StaxEventItemReaderTests { try { reader.read(); fail("Should fail when XML contains DTD"); - } catch (Exception e) { + } + catch (Exception e) { MatcherAssert.assertThat(e.getMessage(), Matchers.containsString("Undeclared general entity \"entityex\"")); } } @@ -684,15 +690,16 @@ public class StaxEventItemReaderTests { } /** - * A simple XMLEvent unmarshaller mock - check for the start and end document events for the fragment root & end - * tags + skips the fragment contents. + * A simple XMLEvent unmarshaller mock - check for the start and end document events + * for the fragment root & end tags + skips the fragment contents. */ private static class MockFragmentUnmarshaller implements Unmarshaller { /** * Skips the XML fragment contents. */ - private List readRecordsInsideFragment(XMLEventReader eventReader, QName fragmentName) throws XMLStreamException { + private List readRecordsInsideFragment(XMLEventReader eventReader, QName fragmentName) + throws XMLStreamException { XMLEvent eventInsideFragment; List events = new ArrayList<>(); do { @@ -702,7 +709,8 @@ public class StaxEventItemReaderTests { break; } events.add(eventReader.nextEvent()); - } while (eventInsideFragment != null); + } + while (eventInsideFragment != null); return events; } @@ -713,8 +721,8 @@ public class StaxEventItemReaderTests { } /** - * A simple mapFragment implementation checking the StaxEventReaderItemReader basic read functionality. - * + * A simple mapFragment implementation checking the StaxEventReaderItemReader + * basic read functionality. * @param source * @return list of the events from fragment body */ @@ -753,7 +761,7 @@ public class StaxEventItemReaderTests { } return fragmentContent; } - + private boolean isFragmentRootElement(String name) { return FRAGMENT_ROOT_ELEMENT.equals(name) || Arrays.asList(MULTI_FRAGMENT_ROOT_ELEMENTS).contains(name); } @@ -762,16 +770,18 @@ public class StaxEventItemReaderTests { @SuppressWarnings("unchecked") private static class ItemCountAwareMockFragmentUnmarshaller extends MockFragmentUnmarshaller { + @Override - public Object unmarshal(Source source) throws XmlMappingException, - IOException { + public Object unmarshal(Source source) throws XmlMappingException, IOException { List fragment = (List) super.unmarshal(source); - if(fragment != null) { + if (fragment != null) { return new ItemCountAwareFragment(fragment); - } else { + } + else { return null; } } + } private static class ItemCountAwareFragment implements ItemCountAware { @@ -809,6 +819,7 @@ public class StaxEventItemReaderTests { public void setOpenCalled(boolean openCalled) { this.openCalled = openCalled; } + } private static class NonExistentResource extends AbstractResource { @@ -830,5 +841,7 @@ public class StaxEventItemReaderTests { public InputStream getInputStream() throws IOException { return null; } + } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/StaxEventItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/StaxEventItemWriterTests.java index 8d97fbbdb..09dd1b09c 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/StaxEventItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/StaxEventItemWriterTests.java @@ -119,7 +119,7 @@ public class StaxEventItemWriterTests { jaxbMarshaller = new Jaxb2Marshaller(); jaxbMarshaller.setClassesToBeBound(JAXBItem.class); } - + /** * Test setting writer name. */ @@ -130,8 +130,9 @@ public class StaxEventItemWriterTests { writer.write(items); writer.update(executionContext); writer.close(); - assertTrue("execution context keys should be prefixed with writer name", executionContext.containsKey("test.position")); - } + assertTrue("execution context keys should be prefixed with writer name", + executionContext.containsKey("test.position")); + } @Test(expected = WriterNotOpenException.class) public void testAssertWriterIsInitialized() throws Exception { @@ -421,8 +422,8 @@ public class StaxEventItemWriterTests { for (int i = 1; i <= NUMBER_OF_RECORDS; i++) { writer.write(items); writer.update(executionContext); - long writeStatistics = executionContext.getLong(ClassUtils.getShortName(StaxEventItemWriter.class) - + ".record.count"); + long writeStatistics = executionContext + .getLong(ClassUtils.getShortName(StaxEventItemWriter.class) + ".record.count"); assertEquals(i, writeStatistics); } @@ -466,7 +467,7 @@ public class StaxEventItemWriterTests { }); writer.setRootTagName("testroot"); - writer.setRootElementAttributes(Collections. singletonMap("attribute", "value")); + writer.setRootElementAttributes(Collections.singletonMap("attribute", "value")); writer.open(executionContext); writer.close(); String content = getOutputFileContent(); @@ -495,7 +496,8 @@ public class StaxEventItemWriterTests { } /** - * Resource is not deleted when items have been written and shouldDeleteIfEmpty flag is set. + * Resource is not deleted when items have been written and shouldDeleteIfEmpty flag + * is set. */ @Test public void testDeleteIfEmptyRecordsWritten() throws Exception { @@ -508,7 +510,8 @@ public class StaxEventItemWriterTests { } /** - * Resource is deleted when no items have been written and shouldDeleteIfEmpty flag is set. + * Resource is deleted when no items have been written and shouldDeleteIfEmpty flag is + * set. */ @Test public void testDeleteIfEmptyNoRecordsWritten() throws Exception { @@ -519,7 +522,8 @@ public class StaxEventItemWriterTests { } /** - * Resource is deleted when items have not been written and shouldDeleteIfEmpty flag is set. + * Resource is deleted when items have not been written and shouldDeleteIfEmpty flag + * is set. */ @Test public void testDeleteIfEmptyNoRecordsWrittenHeaderAndFooter() throws Exception { @@ -562,7 +566,8 @@ public class StaxEventItemWriterTests { } /** - * Resource is not deleted when items have been written and shouldDeleteIfEmpty flag is set. + * Resource is not deleted when items have been written and shouldDeleteIfEmpty flag + * is set. */ @Test public void testDeleteIfEmptyRecordsWrittenRestart() throws Exception { @@ -601,7 +606,8 @@ public class StaxEventItemWriterTests { } /** - * Resource is not deleted when items have been written and shouldDeleteIfEmpty flag is set (restart after delete). + * Resource is not deleted when items have been written and shouldDeleteIfEmpty flag + * is set (restart after delete). */ @Test public void testDeleteIfEmptyNoRecordsWrittenHeaderAndFooterRestartAfterDelete() throws Exception { @@ -650,7 +656,6 @@ public class StaxEventItemWriterTests { assertTrue("Wrong content: " + content, content.contains(TEST_STRING)); } - /** * Item is written to the output file with namespace. */ @@ -662,8 +667,8 @@ public class StaxEventItemWriterTests { writer.write(items); writer.close(); String content = getOutputFileContent(); - assertTrue("Wrong content: " + content, content - .contains((""))); + assertTrue("Wrong content: " + content, + content.contains((""))); assertTrue("Wrong content: " + content, content.contains(TEST_STRING)); assertTrue("Wrong content: " + content, content.contains((""))); } @@ -681,8 +686,8 @@ public class StaxEventItemWriterTests { writer.write(items); writer.close(); String content = getOutputFileContent(); - assertTrue("Wrong content: " + content, content - .contains((""))); + assertTrue("Wrong content: " + content, + content.contains((""))); assertTrue("Wrong content: " + content, content.contains(NS_TEST_STRING)); assertTrue("Wrong content: " + content, content.contains((""))); assertTrue("Wrong content: " + content, content.contains((""))); + assertTrue("Wrong content: " + content, content.contains( + (""))); assertTrue("Wrong content: " + content, content.contains(FOO_TEST_STRING)); assertTrue("Wrong content: " + content, content.contains((""))); assertTrue("Wrong content: " + content, content.contains(("", content); + "", + content); } - + /** - * Test with OXM Marshaller that closes the XMLEventWriter. + * Test with OXM Marshaller that closes the XMLEventWriter. */ // BATCH-2054 @Test @@ -805,7 +810,8 @@ public class StaxEventItemWriterTests { super.marshal(graph, result); try { StaxTestUtils.getXmlEventWriter(result).close(); - } catch (Exception e) { + } + catch (Exception e) { throw new RuntimeException("Exception while writing to output file", e); } } @@ -817,7 +823,7 @@ public class StaxEventItemWriterTests { writer.write(items); writer.write(items); - } + } /** * Test opening and closing corresponding tags in header- and footer callback. @@ -831,11 +837,13 @@ public class StaxEventItemWriterTests { String content = getOutputFileContent(); assertEquals("Wrong content: " + content, - "", content); + "", + content); } - + /** - * Test opening and closing corresponding tags in header- and footer callback (restart). + * Test opening and closing corresponding tags in header- and footer callback + * (restart). */ @Test public void testOpenAndCloseTagsInCallbacksRestart() throws Exception { @@ -843,21 +851,22 @@ public class StaxEventItemWriterTests { writer.open(executionContext); writer.write(items); writer.update(executionContext); - + initWriterForSimpleCallbackTests(); - + writer.open(executionContext); writer.write(items); writer.close(); String content = getOutputFileContent(); - assertEquals("Wrong content: " + content, - "" + - "", content); + assertEquals("Wrong content: " + content, "" + + "", + content); } /** - * Test opening and closing corresponding tags in complex header- and footer callback (restart). + * Test opening and closing corresponding tags in complex header- and footer callback + * (restart). */ @Test public void testOpenAndCloseTagsInComplexCallbacksRestart() throws Exception { @@ -865,22 +874,23 @@ public class StaxEventItemWriterTests { writer.open(executionContext); writer.write(items); writer.update(executionContext); - + initWriterForComplexCallbackTests(); - + writer.open(executionContext); writer.write(items); writer.close(); String content = getOutputFileContent(); assertEquals("Wrong content: " + content, - "" + - "PRE-HEADERPOST-HEADER" + - "" + - "PRE-FOOTERPOST-FOOTER" + - "", content); + "" + + "PRE-HEADERPOST-HEADER" + + "" + + "PRE-FOOTERPOST-FOOTER" + + "", + content); } - + private void initWriterForSimpleCallbackTests() throws Exception { writer = createItemWriter(); writer.setHeaderCallback(new StaxWriterCallback() { @@ -916,7 +926,8 @@ public class StaxEventItemWriterTests { writer.afterPropertiesSet(); } - // more complex callbacks, writing element before and after the multiple corresponding header- and footer elements + // more complex callbacks, writing element before and after the multiple corresponding + // header- and footer elements private void initWriterForComplexCallbackTests() throws Exception { writer = createItemWriter(); writer.setHeaderCallback(new StaxWriterCallback() { @@ -985,12 +996,14 @@ public class StaxEventItemWriterTests { @Override public void marshal(Object graph, Result result) throws XmlMappingException, IOException { - Assert.isInstanceOf( Result.class, result); + Assert.isInstanceOf(Result.class, result); try { - StaxTestUtils.getXmlEventWriter( result ).add( XMLEventFactory.newInstance().createStartElement(namespacePrefix, namespace, graph.toString())); - StaxTestUtils.getXmlEventWriter( result ).add( XMLEventFactory.newInstance().createEndElement(namespacePrefix, namespace, graph.toString())); + StaxTestUtils.getXmlEventWriter(result).add( + XMLEventFactory.newInstance().createStartElement(namespacePrefix, namespace, graph.toString())); + StaxTestUtils.getXmlEventWriter(result).add( + XMLEventFactory.newInstance().createEndElement(namespacePrefix, namespace, graph.toString())); } - catch ( Exception e) { + catch (Exception e) { throw new RuntimeException("Exception while writing to output file", e); } } @@ -999,6 +1012,7 @@ public class StaxEventItemWriterTests { public boolean supports(Class clazz) { return true; } + } /** @@ -1008,7 +1022,6 @@ public class StaxEventItemWriterTests { return getOutputFileContent("UTF-8"); } - /** * @param encoding the encoding * @return output file content as String @@ -1051,8 +1064,9 @@ public class StaxEventItemWriterTests { return source; } - @XmlRootElement(name="item", namespace="https://www.springframework.org/test") + @XmlRootElement(name = "item", namespace = "https://www.springframework.org/test") private static class JAXBItem { + } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/StaxTestUtils.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/StaxTestUtils.java index bb3ab59aa..e4b62a965 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/StaxTestUtils.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/StaxTestUtils.java @@ -28,21 +28,21 @@ import javax.xml.transform.Source; public final class StaxTestUtils { public static XMLEventWriter getXmlEventWriter(Result r) throws Exception { - Method m = r.getClass().getDeclaredMethod("getXMLEventWriter"); - boolean accessible = m.isAccessible(); - m.setAccessible(true); - Object result = m.invoke(r); - m.setAccessible(accessible); - return (XMLEventWriter) result; + Method m = r.getClass().getDeclaredMethod("getXMLEventWriter"); + boolean accessible = m.isAccessible(); + m.setAccessible(true); + Object result = m.invoke(r); + m.setAccessible(accessible); + return (XMLEventWriter) result; } public static XMLEventReader getXmlEventReader(Source s) throws Exception { - Method m = s.getClass().getDeclaredMethod("getXMLEventReader"); - boolean accessible = m.isAccessible(); - m.setAccessible(true); - Object result = m.invoke(s); - m.setAccessible(accessible); - return (XMLEventReader) result; + Method m = s.getClass().getDeclaredMethod("getXMLEventReader"); + boolean accessible = m.isAccessible(); + m.setAccessible(true); + Object result = m.invoke(s); + m.setAccessible(accessible); + return (XMLEventReader) result; } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/TransactionalStaxEventItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/TransactionalStaxEventItemWriterTests.java index 15781af41..65160582f 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/TransactionalStaxEventItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/TransactionalStaxEventItemWriterTests.java @@ -62,7 +62,7 @@ public class TransactionalStaxEventItemWriterTests { // test item for writing to output private Object item = new Object() { - @Override + @Override public String toString() { return ClassUtils.getShortName(StaxEventItemWriter.class) + "-testString"; } @@ -87,12 +87,12 @@ public class TransactionalStaxEventItemWriterTests { public void testWriteAndFlush() throws Exception { writer.open(executionContext); new TransactionTemplate(transactionManager).execute(new TransactionCallback() { - @Override + @Override public Void doInTransaction(TransactionStatus status) { try { writer.write(items); } - catch ( Exception e) { + catch (Exception e) { throw new RuntimeException(e); } return null; @@ -108,9 +108,9 @@ public class TransactionalStaxEventItemWriterTests { */ @Test public void testWriteWithHeaderAfterRollback() throws Exception { - writer.setHeaderCallback(new StaxWriterCallback(){ + writer.setHeaderCallback(new StaxWriterCallback() { - @Override + @Override public void write(XMLEventWriter writer) throws IOException { XMLEventFactory factory = XMLEventFactory.newInstance(); try { @@ -120,14 +120,14 @@ public class TransactionalStaxEventItemWriterTests { catch (XMLStreamException e) { throw new RuntimeException(e); } - + } - + }); writer.open(executionContext); try { new TransactionTemplate(transactionManager).execute(new TransactionCallback() { - @Override + @Override public Void doInTransaction(TransactionStatus status) { try { writer.write(items); @@ -146,7 +146,7 @@ public class TransactionalStaxEventItemWriterTests { writer.close(); writer.open(executionContext); new TransactionTemplate(transactionManager).execute(new TransactionCallback() { - @Override + @Override public Void doInTransaction(TransactionStatus status) { try { writer.write(items); @@ -168,9 +168,9 @@ public class TransactionalStaxEventItemWriterTests { */ @Test public void testWriteWithHeaderAfterFlushAndRollback() throws Exception { - writer.setHeaderCallback(new StaxWriterCallback(){ + writer.setHeaderCallback(new StaxWriterCallback() { - @Override + @Override public void write(XMLEventWriter writer) throws IOException { XMLEventFactory factory = XMLEventFactory.newInstance(); try { @@ -180,13 +180,13 @@ public class TransactionalStaxEventItemWriterTests { catch (XMLStreamException e) { throw new RuntimeException(e); } - + } - + }); writer.open(executionContext); new TransactionTemplate(transactionManager).execute(new TransactionCallback() { - @Override + @Override public Void doInTransaction(TransactionStatus status) { try { writer.write(items); @@ -202,7 +202,7 @@ public class TransactionalStaxEventItemWriterTests { writer.open(executionContext); try { new TransactionTemplate(transactionManager).execute(new TransactionCallback() { - @Override + @Override public Void doInTransaction(TransactionStatus status) { try { writer.write(items); @@ -228,27 +228,30 @@ public class TransactionalStaxEventItemWriterTests { * @return output file content as String */ private String outputFileContent() throws IOException { - return FileUtils.readFileToString(resource.getFile(), (String)null); + return FileUtils.readFileToString(resource.getFile(), (String) null); } /** * Writes object's toString representation as XML comment. */ private static class SimpleMarshaller implements Marshaller { - @Override + + @Override public void marshal(Object graph, Result result) throws XmlMappingException, IOException { try { - StaxTestUtils.getXmlEventWriter(result).add(XMLEventFactory.newInstance().createComment(graph.toString())); + StaxTestUtils.getXmlEventWriter(result) + .add(XMLEventFactory.newInstance().createComment(graph.toString())); } - catch ( Exception e) { + catch (Exception e) { throw new RuntimeException("Exception while writing to output file", e); } } - @Override + @Override public boolean supports(Class clazz) { return true; } + } /** @@ -271,4 +274,5 @@ public class TransactionalStaxEventItemWriterTests { return source; } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/XStreamMarshallingTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/XStreamMarshallingTests.java index 8d4ddd2c4..88d21554a 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/XStreamMarshallingTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/XStreamMarshallingTests.java @@ -21,16 +21,17 @@ import org.springframework.oxm.xstream.XStreamMarshaller; import java.util.Collections; -public class XStreamMarshallingTests extends - AbstractStaxEventWriterItemWriterTests { +public class XStreamMarshallingTests extends AbstractStaxEventWriterItemWriterTests { @Override protected Marshaller getMarshaller() throws Exception { XStreamMarshaller marshaller = new XStreamMarshaller(); -// marshaller.addAlias("trade", Trade.class); + // marshaller.addAlias("trade", Trade.class); marshaller.setAliases(Collections.singletonMap("trade", Trade.class)); - //in XStreamMarshaller.marshalSaxHandlers() method is used SaxWriter, which is configured - //to include enclosing document (SaxWriter.includeEnclosingDocument is always set to TRUE) + // in XStreamMarshaller.marshalSaxHandlers() method is used SaxWriter, which is + // configured + // to include enclosing document (SaxWriter.includeEnclosingDocument is always set + // to TRUE) return marshaller; } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/XStreamUnmarshallingTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/XStreamUnmarshallingTests.java index d74118721..ee889d6bb 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/XStreamUnmarshallingTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/XStreamUnmarshallingTests.java @@ -30,13 +30,13 @@ public class XStreamUnmarshallingTests extends AbstractStaxEventReaderItemReader @Override protected Unmarshaller getUnmarshaller() { XStreamMarshaller unmarshaller = new XStreamMarshaller(); - Map> aliasesMap = new HashMap<>(); + Map> aliasesMap = new HashMap<>(); aliasesMap.put("trade", Trade.class); aliasesMap.put("isin", String.class); aliasesMap.put("customer", String.class); aliasesMap.put("price", BigDecimal.class); unmarshaller.setAliases(aliasesMap); - ExplicitTypePermission typePermission = new ExplicitTypePermission(new Class[]{Trade.class}); + ExplicitTypePermission typePermission = new ExplicitTypePermission(new Class[] { Trade.class }); unmarshaller.setTypePermissions(typePermission); return unmarshaller; } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/builder/StaxEventItemReaderBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/builder/StaxEventItemReaderBuilderTests.java index 6d701f606..56190d722 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/builder/StaxEventItemReaderBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/builder/StaxEventItemReaderBuilderTests.java @@ -46,10 +46,10 @@ import static org.springframework.test.util.ReflectionTestUtils.getField; */ public class StaxEventItemReaderBuilderTests { - private static final String SIMPLE_XML = "1" + - "twothree4" + - "fivesix7" + - "eightnine"; + private static final String SIMPLE_XML = "1" + + "twothree4" + + "fivesix7" + + "eightnine"; @Rule public MockitoRule rule = MockitoJUnit.rule().silent(); @@ -60,21 +60,15 @@ public class StaxEventItemReaderBuilderTests { @Test public void testValidation() { try { - new StaxEventItemReaderBuilder() - .resource(this.resource) - .build(); + new StaxEventItemReaderBuilder().resource(this.resource).build(); fail("saveState == true should require a name"); } catch (IllegalStateException iae) { - assertEquals("A name is required when saveState is set to true.", - iae.getMessage()); + assertEquals("A name is required when saveState is set to true.", iae.getMessage()); } try { - new StaxEventItemReaderBuilder() - .resource(this.resource) - .saveState(false) - .build(); + new StaxEventItemReaderBuilder().resource(this.resource).saveState(false).build(); fail("No root tags have been configured"); } catch (IllegalArgumentException iae) { @@ -84,10 +78,8 @@ public class StaxEventItemReaderBuilderTests { @Test public void testBuildWithoutProvidingResource() { - StaxEventItemReader reader = new StaxEventItemReaderBuilder() - .name("fooReader") - .addFragmentRootElements("foo") - .build(); + StaxEventItemReader reader = new StaxEventItemReaderBuilder().name("fooReader") + .addFragmentRootElements("foo").build(); assertNotNull(reader); } @@ -97,15 +89,9 @@ public class StaxEventItemReaderBuilderTests { Jaxb2Marshaller unmarshaller = new Jaxb2Marshaller(); unmarshaller.setClassesToBeBound(Foo.class); - StaxEventItemReader reader = new StaxEventItemReaderBuilder() - .name("fooReader") - .resource(getResource(SIMPLE_XML)) - .addFragmentRootElements("foo") - .currentItemCount(1) - .maxItemCount(2) - .unmarshaller(unmarshaller) - .xmlInputFactory(XMLInputFactory.newInstance()) - .build(); + StaxEventItemReader reader = new StaxEventItemReaderBuilder().name("fooReader") + .resource(getResource(SIMPLE_XML)).addFragmentRootElements("foo").currentItemCount(1).maxItemCount(2) + .unmarshaller(unmarshaller).xmlInputFactory(XMLInputFactory.newInstance()).build(); reader.afterPropertiesSet(); @@ -134,16 +120,10 @@ public class StaxEventItemReaderBuilderTests { Charset charset = StandardCharsets.ISO_8859_1; ByteBuffer xml = charset.encode(SIMPLE_XML); - StaxEventItemReader reader = new StaxEventItemReaderBuilder() - .name("fooReader") - .resource(new ByteArrayResource(xml.array())) - .encoding(charset.name()) - .addFragmentRootElements("foo") - .currentItemCount(1) - .maxItemCount(2) - .unmarshaller(unmarshaller) - .xmlInputFactory(XMLInputFactory.newInstance()) - .build(); + StaxEventItemReader reader = new StaxEventItemReaderBuilder().name("fooReader") + .resource(new ByteArrayResource(xml.array())).encoding(charset.name()).addFragmentRootElements("foo") + .currentItemCount(1).maxItemCount(2).unmarshaller(unmarshaller) + .xmlInputFactory(XMLInputFactory.newInstance()).build(); reader.afterPropertiesSet(); @@ -166,12 +146,8 @@ public class StaxEventItemReaderBuilderTests { Jaxb2Marshaller unmarshaller = new Jaxb2Marshaller(); unmarshaller.setClassesToBeBound(Foo.class); - StaxEventItemReader reader = new StaxEventItemReaderBuilder() - .name("fooReader") - .resource(this.resource) - .addFragmentRootElements("foo") - .unmarshaller(unmarshaller) - .build(); + StaxEventItemReader reader = new StaxEventItemReaderBuilder().name("fooReader") + .resource(this.resource).addFragmentRootElements("foo").unmarshaller(unmarshaller).build(); reader.afterPropertiesSet(); @@ -184,13 +160,9 @@ public class StaxEventItemReaderBuilderTests { Jaxb2Marshaller unmarshaller = new Jaxb2Marshaller(); unmarshaller.setClassesToBeBound(Foo.class); - StaxEventItemReader reader = new StaxEventItemReaderBuilder() - .name("fooReader") - .resource(getResource(SIMPLE_XML)) - .addFragmentRootElements("foo") - .unmarshaller(unmarshaller) - .saveState(false) - .build(); + StaxEventItemReader reader = new StaxEventItemReaderBuilder().name("fooReader") + .resource(getResource(SIMPLE_XML)).addFragmentRootElements("foo").unmarshaller(unmarshaller) + .saveState(false).build(); reader.afterPropertiesSet(); @@ -214,13 +186,17 @@ public class StaxEventItemReaderBuilderTests { return new ByteArrayResource(contents.getBytes()); } - @XmlRootElement(name="foo") + @XmlRootElement(name = "foo") public static class Foo { + private int first; + private String second; + private String third; - public Foo() {} + public Foo() { + } public Foo(int first, String second, String third) { this.first = first; @@ -256,5 +232,7 @@ public class StaxEventItemReaderBuilderTests { public String toString() { return String.format("{%s, %s, %s}", this.first, this.second, this.third); } + } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/builder/StaxEventItemWriterBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/builder/StaxEventItemWriterBuilderTests.java index 3a280bd02..b517b0916 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/builder/StaxEventItemWriterBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/builder/StaxEventItemWriterBuilderTests.java @@ -57,14 +57,13 @@ public class StaxEventItemWriterBuilderTests { private Marshaller marshaller; - private static final String FULL_OUTPUT = "" + - "\uFEFF" + - "1twothree\uFEFF" + - "4" + - "fivesix\uFEFF" + - "7" + - "eightnine\uFEFF\uFEFF" + - ""; + private static final String FULL_OUTPUT = "" + + "\uFEFF" + + "1twothree\uFEFF" + + "4" + + "fivesix\uFEFF" + + "7" + + "eightnine\uFEFF\uFEFF" + ""; @Before public void setUp() throws IOException { @@ -84,12 +83,8 @@ public class StaxEventItemWriterBuilderTests { @Test(expected = ItemStreamException.class) public void testOverwriteOutput() throws Exception { - StaxEventItemWriter staxEventItemWriter = new StaxEventItemWriterBuilder() - .name("fooWriter") - .marshaller(marshaller) - .resource(this.resource) - .overwriteOutput(false) - .build(); + StaxEventItemWriter staxEventItemWriter = new StaxEventItemWriterBuilder().name("fooWriter") + .marshaller(marshaller).resource(this.resource).overwriteOutput(false).build(); staxEventItemWriter.afterPropertiesSet(); @@ -113,12 +108,8 @@ public class StaxEventItemWriterBuilderTests { public void testDeleteIfEmpty() throws Exception { ExecutionContext executionContext = new ExecutionContext(); - StaxEventItemWriter staxEventItemWriter = new StaxEventItemWriterBuilder() - .name("fooWriter") - .resource(this.resource) - .marshaller(this.marshaller) - .shouldDeleteIfEmpty(true) - .build(); + StaxEventItemWriter staxEventItemWriter = new StaxEventItemWriterBuilder().name("fooWriter") + .resource(this.resource).marshaller(this.marshaller).shouldDeleteIfEmpty(true).build(); staxEventItemWriter.afterPropertiesSet(); staxEventItemWriter.open(executionContext); @@ -134,13 +125,8 @@ public class StaxEventItemWriterBuilderTests { @Test public void testTransactional() { - StaxEventItemWriter staxEventItemWriter = new StaxEventItemWriterBuilder() - .name("fooWriter") - .resource(this.resource) - .marshaller(this.marshaller) - .transactional(true) - .forceSync(true) - .build(); + StaxEventItemWriter staxEventItemWriter = new StaxEventItemWriterBuilder().name("fooWriter") + .resource(this.resource).marshaller(this.marshaller).transactional(true).forceSync(true).build(); ExecutionContext executionContext = new ExecutionContext(); @@ -158,38 +144,25 @@ public class StaxEventItemWriterBuilderTests { Map rootElementAttributes = new HashMap<>(); rootElementAttributes.put("baz", "quix"); - StaxEventItemWriter staxEventItemWriter = new StaxEventItemWriterBuilder() - .name("fooWriter") - .marshaller(marshaller) - .encoding("UTF-16") - .footerCallback(writer -> { + StaxEventItemWriter staxEventItemWriter = new StaxEventItemWriterBuilder().name("fooWriter") + .marshaller(marshaller).encoding("UTF-16").footerCallback(writer -> { XMLEventFactory factory = XMLEventFactory.newInstance(); try { - writer.add(factory.createEndElement("ns", - "https://www.springframework.org/test", - "group")); + writer.add(factory.createEndElement("ns", "https://www.springframework.org/test", "group")); } catch (XMLStreamException e) { throw new RuntimeException(e); } - }) - .headerCallback(writer -> { + }).headerCallback(writer -> { XMLEventFactory factory = XMLEventFactory.newInstance(); try { - writer.add(factory.createStartElement("ns", - "https://www.springframework.org/test", - "group")); + writer.add(factory.createStartElement("ns", "https://www.springframework.org/test", "group")); } catch (XMLStreamException e) { throw new RuntimeException(e); } - }) - .resource(this.resource) - .rootTagName("foobarred") - .rootElementAttributes(rootElementAttributes) - .saveState(false) - .version("1.1") - .build(); + }).resource(this.resource).rootTagName("foobarred").rootElementAttributes(rootElementAttributes) + .saveState(false).version("1.1").build(); staxEventItemWriter.afterPropertiesSet(); @@ -207,25 +180,18 @@ public class StaxEventItemWriterBuilderTests { @Test(expected = IllegalArgumentException.class) public void testMissingMarshallerValidation() { - new StaxEventItemWriterBuilder() - .name("fooWriter") - .build(); + new StaxEventItemWriterBuilder().name("fooWriter").build(); } @Test(expected = IllegalArgumentException.class) public void testMissingNameValidation() { - new StaxEventItemWriterBuilder() - .marshaller(new Jaxb2Marshaller()) - .build(); + new StaxEventItemWriterBuilder().marshaller(new Jaxb2Marshaller()).build(); } @Test public void testStandaloneDeclarationInHeaderWhenNotSet() throws Exception { - StaxEventItemWriter staxEventItemWriter = new StaxEventItemWriterBuilder() - .name("fooWriter") - .marshaller(marshaller) - .resource(this.resource) - .build(); + StaxEventItemWriter staxEventItemWriter = new StaxEventItemWriterBuilder().name("fooWriter") + .marshaller(marshaller).resource(this.resource).build(); staxEventItemWriter.afterPropertiesSet(); @@ -240,12 +206,8 @@ public class StaxEventItemWriterBuilderTests { @Test public void testStandaloneDeclarationInHeaderWhenSetToTrue() throws Exception { - StaxEventItemWriter staxEventItemWriter = new StaxEventItemWriterBuilder() - .name("fooWriter") - .marshaller(marshaller) - .resource(this.resource) - .standalone(true) - .build(); + StaxEventItemWriter staxEventItemWriter = new StaxEventItemWriterBuilder().name("fooWriter") + .marshaller(marshaller).resource(this.resource).standalone(true).build(); staxEventItemWriter.afterPropertiesSet(); @@ -260,12 +222,8 @@ public class StaxEventItemWriterBuilderTests { @Test public void testStandaloneDeclarationInHeaderWhenSetToFalse() throws Exception { - StaxEventItemWriter staxEventItemWriter = new StaxEventItemWriterBuilder() - .name("fooWriter") - .marshaller(marshaller) - .resource(this.resource) - .standalone(false) - .build(); + StaxEventItemWriter staxEventItemWriter = new StaxEventItemWriterBuilder().name("fooWriter") + .marshaller(marshaller).resource(this.resource).standalone(false).build(); staxEventItemWriter.afterPropertiesSet(); @@ -286,13 +244,17 @@ public class StaxEventItemWriterBuilderTests { return FileUtils.readFileToString(resource.getFile(), encoding); } - @XmlRootElement(name="item", namespace="https://www.springframework.org/test") + @XmlRootElement(name = "item", namespace = "https://www.springframework.org/test") public static class Foo { + private int first; + private String second; + private String third; - public Foo() {} + public Foo() { + } public Foo(int first, String second, String third) { this.first = first; @@ -323,5 +285,7 @@ public class StaxEventItemWriterBuilderTests { public void setThird(String third) { this.third = third; } + } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/domain/QualifiedTrade.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/domain/QualifiedTrade.java index db452fe87..2d82ab30e 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/domain/QualifiedTrade.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/domain/QualifiedTrade.java @@ -27,21 +27,21 @@ import jakarta.xml.bind.annotation.XmlType; * @author Rob Harrop * @author Mahmoud Ben Hassine */ -@XmlRootElement(name="trade", namespace="urn:org.springframework.batch.io.oxm.domain") +@XmlRootElement(name = "trade", namespace = "urn:org.springframework.batch.io.oxm.domain") @XmlType @XmlAccessorType(XmlAccessType.FIELD) public class QualifiedTrade { - - @XmlElement(namespace="urn:org.springframework.batch.io.oxm.domain") + + @XmlElement(namespace = "urn:org.springframework.batch.io.oxm.domain") private String isin = ""; - @XmlElement(namespace="urn:org.springframework.batch.io.oxm.domain") + @XmlElement(namespace = "urn:org.springframework.batch.io.oxm.domain") private long quantity = 0; - @XmlElement(namespace="urn:org.springframework.batch.io.oxm.domain") + @XmlElement(namespace = "urn:org.springframework.batch.io.oxm.domain") private BigDecimal price = new BigDecimal(0); - @XmlElement(namespace="urn:org.springframework.batch.io.oxm.domain") + @XmlElement(namespace = "urn:org.springframework.batch.io.oxm.domain") private String customer = ""; public QualifiedTrade() { diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/domain/Trade.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/domain/Trade.java index b0f04e1de..36a60428f 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/domain/Trade.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/domain/Trade.java @@ -24,9 +24,10 @@ import jakarta.xml.bind.annotation.XmlType; * @author Rob Harrop * @author Mahmoud Ben Hassine */ -@XmlRootElement(name="trade") +@XmlRootElement(name = "trade") @XmlType public class Trade { + private String isin = ""; private long quantity = 0; diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/stax/AbstractEventReaderWrapperTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/stax/AbstractEventReaderWrapperTests.java index e1506e755..af84ee710 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/stax/AbstractEventReaderWrapperTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/stax/AbstractEventReaderWrapperTests.java @@ -31,9 +31,10 @@ import junit.framework.TestCase; public class AbstractEventReaderWrapperTests extends TestCase { AbstractEventReaderWrapper eventReaderWrapper; + XMLEventReader xmlEventReader; - @Override + @Override protected void setUp() throws Exception { super.setUp(); @@ -101,8 +102,11 @@ public class AbstractEventReaderWrapperTests extends TestCase { } private static class StubEventReader extends AbstractEventReaderWrapper { + public StubEventReader(XMLEventReader wrappedEventReader) { super(wrappedEventReader); } + } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/stax/AbstractEventWriterWrapperTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/stax/AbstractEventWriterWrapperTests.java index 3cdc84b02..21c1b06c9 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/stax/AbstractEventWriterWrapperTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/stax/AbstractEventWriterWrapperTests.java @@ -29,7 +29,7 @@ import junit.framework.TestCase; /** * @author Lucas Ward * @author Will Schipp - * + * */ public class AbstractEventWriterWrapperTests extends TestCase { @@ -37,7 +37,7 @@ public class AbstractEventWriterWrapperTests extends TestCase { XMLEventWriter xmlEventWriter; - @Override + @Override protected void setUp() throws Exception { super.setUp(); @@ -47,7 +47,7 @@ public class AbstractEventWriterWrapperTests extends TestCase { public void testAdd() throws XMLStreamException { - XMLEvent event = mock(XMLEvent.class); + XMLEvent event = mock(XMLEvent.class); xmlEventWriter.add(event); eventWriterWrapper.add(event); @@ -104,8 +104,11 @@ public class AbstractEventWriterWrapperTests extends TestCase { } private static class StubEventWriter extends AbstractEventWriterWrapper { + public StubEventWriter(XMLEventWriter wrappedEventWriter) { super(wrappedEventWriter); } + } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/stax/DefaultFragmentEventReaderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/stax/DefaultFragmentEventReaderTests.java index 5ef9092c5..c49b0f0af 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/stax/DefaultFragmentEventReaderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/stax/DefaultFragmentEventReaderTests.java @@ -30,7 +30,7 @@ import org.springframework.util.xml.StaxUtils; /** * Tests for {@link DefaultFragmentEventReader}. - * + * * @author Robert Kasanicky * @author Mahmoud Ben Hassine */ @@ -48,33 +48,31 @@ public class DefaultFragmentEventReaderTests extends TestCase { /** * Setup the fragmentReader to read the test input. */ - @Override + @Override protected void setUp() throws Exception { Resource input = new ByteArrayResource(xml.getBytes()); - eventReader = StaxUtils.createDefensiveInputFactory().createXMLEventReader( - input.getInputStream()); + eventReader = StaxUtils.createDefensiveInputFactory().createXMLEventReader(input.getInputStream()); fragmentReader = new DefaultFragmentEventReader(eventReader); } /** - * Marked element should be wrapped with StartDocument and EndDocument - * events. - * Test uses redundant peek() calls before nextEvent() in important moments to assure + * Marked element should be wrapped with StartDocument and EndDocument events. Test + * uses redundant peek() calls before nextEvent() in important moments to assure * peek() has no side effects on the inner state of reader. */ public void testFragmentWrapping() throws XMLStreamException { - + assertTrue(fragmentReader.hasNext()); moveCursorBeforeFragmentStart(); fragmentReader.markStartFragment(); // mark the fragment assertTrue(EventHelper.startElementName(eventReader.peek()).equals("fragment")); - + // StartDocument inserted before StartElement assertTrue(fragmentReader.peek().isStartDocument()); assertTrue(fragmentReader.nextEvent().isStartDocument()); // StartElement follows in the next step - assertTrue(EventHelper.startElementName(fragmentReader.nextEvent()).equals("fragment")); + assertTrue(EventHelper.startElementName(fragmentReader.nextEvent()).equals("fragment")); moveCursorToNextElementEvent(); // misc1 start fragmentReader.nextEvent(); // skip it @@ -83,62 +81,60 @@ public class DefaultFragmentEventReaderTests extends TestCase { moveCursorToNextElementEvent(); // move to end of fragment // expected EndElement, peek first which should have no side effect - assertTrue(EventHelper.endElementName(fragmentReader.nextEvent()).equals("fragment")); + assertTrue(EventHelper.endElementName(fragmentReader.nextEvent()).equals("fragment")); // inserted EndDocument assertTrue(fragmentReader.peek().isEndDocument()); - assertTrue(fragmentReader.nextEvent().isEndDocument()); - + assertTrue(fragmentReader.nextEvent().isEndDocument()); + // now the reader should behave like the document has finished assertTrue(fragmentReader.peek() == null); assertFalse(fragmentReader.hasNext()); - - try{ + + try { fragmentReader.nextEvent(); fail("nextEvent should simulate behavior as if document ended"); } catch (NoSuchElementException expected) { - //expected + // expected } } /** - * When fragment is marked as processed the cursor is moved after the end of - * the fragment. + * When fragment is marked as processed the cursor is moved after the end of the + * fragment. */ public void testMarkFragmentProcessed() throws XMLStreamException { moveCursorBeforeFragmentStart(); fragmentReader.markStartFragment(); // mark the fragment start - + // read only one event to move inside the fragment - XMLEvent startFragment = fragmentReader.nextEvent(); + XMLEvent startFragment = fragmentReader.nextEvent(); assertTrue(startFragment.isStartDocument()); fragmentReader.markFragmentProcessed(); // mark fragment as processed fragmentReader.nextEvent(); // skip whitespace // the next element after fragment end is - XMLEvent misc2 = fragmentReader.nextEvent(); + XMLEvent misc2 = fragmentReader.nextEvent(); assertTrue(EventHelper.startElementName(misc2).equals("misc2")); } - + /** - * Cursor is moved to the end of the fragment as usually even - * if nothing was read from the event reader after beginning - * of fragment was marked. + * Cursor is moved to the end of the fragment as usually even if nothing was read from + * the event reader after beginning of fragment was marked. */ public void testMarkFragmentProcessedImmediatelyAfterMarkFragmentStart() throws Exception { moveCursorBeforeFragmentStart(); fragmentReader.markStartFragment(); fragmentReader.markFragmentProcessed(); - + fragmentReader.nextEvent(); // skip whitespace // the next element after fragment end is - XMLEvent misc2 = fragmentReader.nextEvent(); + XMLEvent misc2 = fragmentReader.nextEvent(); assertTrue(EventHelper.startElementName(misc2).equals("misc2")); } - private void moveCursorToNextElementEvent() throws XMLStreamException { XMLEvent event = eventReader.peek(); @@ -147,7 +143,7 @@ public class DefaultFragmentEventReaderTests extends TestCase { event = eventReader.peek(); } } - + private void moveCursorBeforeFragmentStart() throws XMLStreamException { XMLEvent event = eventReader.peek(); while (!event.isStartElement() || !EventHelper.startElementName(event).equals("fragment")) { diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/stax/NoStartEndDocumentWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/stax/NoStartEndDocumentWriterTests.java index 14e648911..8824855f8 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/stax/NoStartEndDocumentWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/stax/NoStartEndDocumentWriterTests.java @@ -28,7 +28,7 @@ import static org.mockito.Mockito.times; /** * Tests for {@link NoStartEndDocumentStreamWriter} - * + * * @author Robert Kasanicky * @author Will Schipp */ @@ -41,15 +41,14 @@ public class NoStartEndDocumentWriterTests extends TestCase { private XMLEventFactory eventFactory = XMLEventFactory.newInstance(); - @Override + @Override protected void setUp() throws Exception { wrappedWriter = mock(XMLEventWriter.class); writer = new NoStartEndDocumentStreamWriter(wrappedWriter); } /** - * StartDocument and EndDocument events are not passed to the wrapped - * writer. + * StartDocument and EndDocument events are not passed to the wrapped writer. */ public void testNoStartEnd() throws Exception { XMLEvent event = eventFactory.createComment("testEvent"); @@ -62,14 +61,16 @@ public class NoStartEndDocumentWriterTests extends TestCase { writer.add(eventFactory.createEndDocument()); } - + /** - * Close is not delegated to the wrapped writer. Instead, the wrapped writer is flushed. + * Close is not delegated to the wrapped writer. Instead, the wrapped writer is + * flushed. */ public void testClose() throws Exception { writer.close(); - + verify(wrappedWriter, times(1)).flush(); verify(wrappedWriter, never()).close(); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/stax/UnclosedElementCollectingEventWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/stax/UnclosedElementCollectingEventWriterTests.java index 7576f8813..2d683961f 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/stax/UnclosedElementCollectingEventWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/stax/UnclosedElementCollectingEventWriterTests.java @@ -30,7 +30,7 @@ import org.mockito.Mockito; /** * Tests for {@link UnclosedElementCollectingEventWriter} - * + * * @author Jimmy Praet */ public class UnclosedElementCollectingEventWriterTests { @@ -38,63 +38,63 @@ public class UnclosedElementCollectingEventWriterTests { private UnclosedElementCollectingEventWriter writer; private XMLEventWriter wrappedWriter; - + private XMLEventFactory eventFactory = XMLEventFactory.newInstance(); - + private QName elementA = new QName("elementA"); - + private QName elementB = new QName("elementB"); - + private QName elementC = new QName("elementC"); - - @Before + + @Before public void setUp() throws Exception { wrappedWriter = mock(XMLEventWriter.class); writer = new UnclosedElementCollectingEventWriter(wrappedWriter); } - - @Test - public void testNoUnclosedElements() throws Exception { - writer.add(eventFactory.createStartElement(elementA, null, null)); - writer.add(eventFactory.createEndElement(elementA, null)); - assertEquals(0, writer.getUnclosedElements().size()); + @Test + public void testNoUnclosedElements() throws Exception { + writer.add(eventFactory.createStartElement(elementA, null, null)); + writer.add(eventFactory.createEndElement(elementA, null)); + + assertEquals(0, writer.getUnclosedElements().size()); verify(wrappedWriter, Mockito.times(2)).add(Mockito.any(XMLEvent.class)); - } + } - @Test - public void testSingleUnclosedElement() throws Exception { - writer.add(eventFactory.createStartElement(elementA, null, null)); - writer.add(eventFactory.createEndElement(elementA, null)); - writer.add(eventFactory.createStartElement(elementB, null, null)); + @Test + public void testSingleUnclosedElement() throws Exception { + writer.add(eventFactory.createStartElement(elementA, null, null)); + writer.add(eventFactory.createEndElement(elementA, null)); + writer.add(eventFactory.createStartElement(elementB, null, null)); - assertEquals(1, writer.getUnclosedElements().size()); - assertEquals(elementB, writer.getUnclosedElements().get(0)); + assertEquals(1, writer.getUnclosedElements().size()); + assertEquals(elementB, writer.getUnclosedElements().get(0)); verify(wrappedWriter, Mockito.times(3)).add(Mockito.any(XMLEvent.class)); - } + } - @Test - public void testMultipleUnclosedElements() throws Exception { - writer.add(eventFactory.createStartElement(elementA, null, null)); - writer.add(eventFactory.createStartElement(elementB, null, null)); - writer.add(eventFactory.createStartElement(elementC, null, null)); - writer.add(eventFactory.createEndElement(elementC, null)); + @Test + public void testMultipleUnclosedElements() throws Exception { + writer.add(eventFactory.createStartElement(elementA, null, null)); + writer.add(eventFactory.createStartElement(elementB, null, null)); + writer.add(eventFactory.createStartElement(elementC, null, null)); + writer.add(eventFactory.createEndElement(elementC, null)); - assertEquals(2, writer.getUnclosedElements().size()); - assertEquals(elementA, writer.getUnclosedElements().get(0)); - assertEquals(elementB, writer.getUnclosedElements().get(1)); + assertEquals(2, writer.getUnclosedElements().size()); + assertEquals(elementA, writer.getUnclosedElements().get(0)); + assertEquals(elementB, writer.getUnclosedElements().get(1)); verify(wrappedWriter, Mockito.times(4)).add(Mockito.any(XMLEvent.class)); - } - - @Test - public void testMultipleIdenticalUnclosedElement() throws Exception { - writer.add(eventFactory.createStartElement(elementA, null, null)); - writer.add(eventFactory.createStartElement(elementA, null, null)); + } - assertEquals(2, writer.getUnclosedElements().size()); - assertEquals(elementA, writer.getUnclosedElements().get(0)); - assertEquals(elementA, writer.getUnclosedElements().get(1)); + @Test + public void testMultipleIdenticalUnclosedElement() throws Exception { + writer.add(eventFactory.createStartElement(elementA, null, null)); + writer.add(eventFactory.createStartElement(elementA, null, null)); + + assertEquals(2, writer.getUnclosedElements().size()); + assertEquals(elementA, writer.getUnclosedElements().get(0)); + assertEquals(elementA, writer.getUnclosedElements().get(1)); verify(wrappedWriter, Mockito.times(2)).add(Mockito.any(XMLEvent.class)); - } + } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/stax/UnopenedElementClosingEventWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/stax/UnopenedElementClosingEventWriterTests.java index 6fe2acdce..39e5bfd1f 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/stax/UnopenedElementClosingEventWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/xml/stax/UnopenedElementClosingEventWriterTests.java @@ -38,7 +38,7 @@ import org.springframework.dao.DataAccessResourceFailureException; /** * Tests for {@link UnopenedElementClosingEventWriter} - * + * * @author Jimmy Praet */ public class UnopenedElementClosingEventWriterTests { @@ -46,20 +46,20 @@ public class UnopenedElementClosingEventWriterTests { private UnopenedElementClosingEventWriter writer; private XMLEventWriter wrappedWriter; - + private Writer ioWriter; private XMLEventFactory eventFactory = XMLEventFactory.newInstance(); - + private List unopenedElements = new LinkedList<>(); - + private QName unopenedA = new QName("http://test", "unopened-a", "t"); - + private QName unopenedB = new QName("", "unopened-b", ""); - + private QName other = new QName("http://test", "other", "t"); - @Before + @Before public void setUp() throws Exception { wrappedWriter = mock(XMLEventWriter.class); ioWriter = mock(Writer.class); @@ -67,66 +67,66 @@ public class UnopenedElementClosingEventWriterTests { unopenedElements.add(unopenedB); writer = new UnopenedElementClosingEventWriter(wrappedWriter, ioWriter, unopenedElements); } - - @Test - public void testEndUnopenedElements() throws Exception { - EndElement endElementB = eventFactory.createEndElement(unopenedB, null); - writer.add(endElementB); - EndElement endElementA = eventFactory.createEndElement(unopenedA, null); - writer.add(endElementA); + @Test + public void testEndUnopenedElements() throws Exception { + EndElement endElementB = eventFactory.createEndElement(unopenedB, null); + writer.add(endElementB); - verify(wrappedWriter, Mockito.never()).add(endElementB); - verify(wrappedWriter, Mockito.never()).add(endElementA); - verify(wrappedWriter, Mockito.times(2)).flush(); - verify(ioWriter).write(""); - verify(ioWriter).write(""); - verify(ioWriter, Mockito.times(2)).flush(); - } - - @Test - public void testEndUnopenedElementRemovesFromList() throws Exception { - EndElement endElement = eventFactory.createEndElement(unopenedB, null); - writer.add(endElement); - - verify(wrappedWriter, Mockito.never()).add(endElement); - verify(wrappedWriter).flush(); - verify(ioWriter).write(""); - verify(ioWriter).flush(); - - StartElement startElement = eventFactory.createStartElement(unopenedB, null, null); - writer.add(startElement); - endElement = eventFactory.createEndElement(unopenedB, null); - writer.add(endElement); + EndElement endElementA = eventFactory.createEndElement(unopenedA, null); + writer.add(endElementA); - verify(wrappedWriter).add(startElement); - verify(wrappedWriter).add(endElement); - - // only internal list should be modified - assertEquals(2, unopenedElements.size()); - } - - @Test - public void testOtherEndElement() throws Exception { - EndElement endElement = eventFactory.createEndElement(other, null); - writer.add(endElement); - - verify(wrappedWriter).add(endElement); - } + verify(wrappedWriter, Mockito.never()).add(endElementB); + verify(wrappedWriter, Mockito.never()).add(endElementA); + verify(wrappedWriter, Mockito.times(2)).flush(); + verify(ioWriter).write(""); + verify(ioWriter).write(""); + verify(ioWriter, Mockito.times(2)).flush(); + } - @Test - public void testOtherEvent() throws Exception { - XMLEvent event = eventFactory.createCharacters("foo"); - writer.add(event); - - verify(wrappedWriter).add(event); - } - - @Test (expected = DataAccessResourceFailureException.class) - public void testIOException() throws Exception { - EndElement endElementB = eventFactory.createEndElement(unopenedB, null); - Mockito.doThrow(new IOException("Simulated IOException")).when(ioWriter).write(""); - writer.add(endElementB); - } + @Test + public void testEndUnopenedElementRemovesFromList() throws Exception { + EndElement endElement = eventFactory.createEndElement(unopenedB, null); + writer.add(endElement); + + verify(wrappedWriter, Mockito.never()).add(endElement); + verify(wrappedWriter).flush(); + verify(ioWriter).write(""); + verify(ioWriter).flush(); + + StartElement startElement = eventFactory.createStartElement(unopenedB, null, null); + writer.add(startElement); + endElement = eventFactory.createEndElement(unopenedB, null); + writer.add(endElement); + + verify(wrappedWriter).add(startElement); + verify(wrappedWriter).add(endElement); + + // only internal list should be modified + assertEquals(2, unopenedElements.size()); + } + + @Test + public void testOtherEndElement() throws Exception { + EndElement endElement = eventFactory.createEndElement(other, null); + writer.add(endElement); + + verify(wrappedWriter).add(endElement); + } + + @Test + public void testOtherEvent() throws Exception { + XMLEvent event = eventFactory.createCharacters("foo"); + writer.add(event); + + verify(wrappedWriter).add(event); + } + + @Test(expected = DataAccessResourceFailureException.class) + public void testIOException() throws Exception { + EndElement endElementB = eventFactory.createEndElement(unopenedB, null); + Mockito.doThrow(new IOException("Simulated IOException")).when(ioWriter).write(""); + writer.add(endElementB); + } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/jms/ExternalRetryInBatchTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/jms/ExternalRetryInBatchTests.java index 095e65501..049ef90cf 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/jms/ExternalRetryInBatchTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/jms/ExternalRetryInBatchTests.java @@ -74,7 +74,7 @@ public class ExternalRetryInBatchTests { @Before public void onSetUp() throws Exception { getMessages(); // drain queue - JdbcTestUtils.deleteFromTables(jdbcTemplate, "T_BARS"); + JdbcTestUtils.deleteFromTables(jdbcTemplate, "T_BARS"); jmsTemplate.convertAndSend("queue", "foo"); jmsTemplate.convertAndSend("queue", "bar"); provider = new ItemReader() { @@ -92,7 +92,7 @@ public class ExternalRetryInBatchTests { @After public void onTearDown() throws Exception { getMessages(); // drain queue - JdbcTestUtils.deleteFromTables(jdbcTemplate, "T_BARS"); + JdbcTestUtils.deleteFromTables(jdbcTemplate, "T_BARS"); } private void assertInitialState() { @@ -108,8 +108,8 @@ public class ExternalRetryInBatchTests { public void testExternalRetryRecoveryInBatch() throws Exception { assertInitialState(); - retryTemplate.setRetryPolicy(new SimpleRetryPolicy(1, Collections - ., Boolean> singletonMap(Exception.class, true))); + retryTemplate.setRetryPolicy(new SimpleRetryPolicy(1, + Collections., Boolean>singletonMap(Exception.class, true))); repeatTemplate.setCompletionPolicy(new SimpleCompletionPolicy(2)); @@ -128,24 +128,26 @@ public class ExternalRetryInBatchTests { public RepeatStatus doInIteration(RepeatContext context) throws Exception { final String item = provider.read(); - - if (item==null) { + + if (item == null) { return RepeatStatus.FINISHED; } - + RetryCallback callback = new RetryCallback() { @Override public String doWithRetry(RetryContext context) throws Exception { - // No need for transaction here: the whole batch will roll - // back. When it comes back for recovery this code is not + // No need for transaction here: the whole + // batch will roll + // back. When it comes back for recovery this + // code is not // executed... jdbcTemplate.update( - "INSERT into T_BARS (id,name,foo_date) values (?,?,null)", + "INSERT into T_BARS (id,name,foo_date) values (?,?,null)", list.size(), item); throw new RuntimeException("Rollback!"); } }; - + RecoveryCallback recoveryCallback = new RecoveryCallback() { @Override public String recover(RetryContext context) { @@ -157,7 +159,7 @@ public class ExternalRetryInBatchTests { }; retryTemplate.execute(callback, recoveryCallback, new DefaultRetryState(item)); - + return RepeatStatus.CONTINUABLE; } @@ -165,20 +167,24 @@ public class ExternalRetryInBatchTests { }); return null; - } catch (Exception e) { + } + catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } } }); - } catch (Exception e) { + } + catch (Exception e) { if (i == 0 || i == 2) { assertEquals("Rollback!", e.getMessage()); - } else { + } + else { throw e; } - } finally { + } + finally { System.err.println(i + ": " + recovered); } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/poller/DirectPollerTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/poller/DirectPollerTests.java index 547045753..ce9e69630 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/poller/DirectPollerTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/poller/DirectPollerTests.java @@ -29,7 +29,7 @@ import org.junit.Test; /** * @author Dave Syer - * + * */ public class DirectPollerTests { @@ -40,7 +40,7 @@ public class DirectPollerTests { Callable callback = new Callable() { - @Override + @Override public String call() throws Exception { Set executions = new HashSet<>(repository); if (executions.isEmpty()) { @@ -65,7 +65,7 @@ public class DirectPollerTests { Callable callback = new Callable() { - @Override + @Override public String call() throws Exception { Set executions = new HashSet<>(repository); if (executions.isEmpty()) { @@ -90,7 +90,7 @@ public class DirectPollerTests { Callable callback = new Callable() { - @Override + @Override public String call() throws Exception { Set executions = new HashSet<>(repository); if (executions.isEmpty()) { @@ -118,7 +118,7 @@ public class DirectPollerTests { private void sleepAndCreateStringInBackground(final long duration) { new Thread(new Runnable() { - @Override + @Override public void run() { try { Thread.sleep(duration); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/AbstractExceptionTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/AbstractExceptionTests.java index b913d9a3d..a9629568b 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/AbstractExceptionTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/AbstractExceptionTests.java @@ -33,4 +33,5 @@ public abstract class AbstractExceptionTests extends TestCase { public abstract Exception getException(String msg) throws Exception; public abstract Exception getException(String msg, Throwable t) throws Exception; + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/RepeatExceptionTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/RepeatExceptionTests.java index c2ba952fe..422e6c69f 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/RepeatExceptionTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/RepeatExceptionTests.java @@ -20,12 +20,12 @@ import org.springframework.batch.repeat.RepeatException; public class RepeatExceptionTests extends AbstractExceptionTests { - @Override + @Override public Exception getException(String msg) throws Exception { return new RepeatException(msg); } - @Override + @Override public Exception getException(String msg, Throwable t) throws Exception { return new RepeatException(msg, t); } @@ -33,4 +33,5 @@ public class RepeatExceptionTests extends AbstractExceptionTests { public void testNothing() throws Exception { // fool coverage tools... } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/callback/NestedRepeatCallbackTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/callback/NestedRepeatCallbackTests.java index b7856f266..2b9a3ced6 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/callback/NestedRepeatCallbackTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/callback/NestedRepeatCallbackTests.java @@ -29,7 +29,7 @@ public class NestedRepeatCallbackTests extends TestCase { public void testExecute() throws Exception { NestedRepeatCallback callback = new NestedRepeatCallback(new RepeatTemplate(), new RepeatCallback() { - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { count++; return RepeatStatus.continueIf(count <= 1); @@ -39,4 +39,5 @@ public class NestedRepeatCallbackTests extends TestCase { assertEquals(2, count); assertFalse(result.isContinuable()); // False because processing has finished } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/context/RepeatContextCounterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/context/RepeatContextCounterTests.java index ac2792d95..016d31b34 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/context/RepeatContextCounterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/context/RepeatContextCounterTests.java @@ -21,20 +21,21 @@ import junit.framework.TestCase; import org.springframework.batch.repeat.RepeatContext; public class RepeatContextCounterTests extends TestCase { - + RepeatContext parent = new RepeatContextSupport(null); + RepeatContext context = new RepeatContextSupport(parent); - + public void testAttributeCreated() { new RepeatContextCounter(context, "FOO"); assertTrue(context.hasAttribute("FOO")); } - + public void testAttributeCreatedWithNullParent() { new RepeatContextCounter(parent, "FOO", true); assertTrue(parent.hasAttribute("FOO")); } - + public void testVanillaIncrement() throws Exception { RepeatContextCounter counter = new RepeatContextCounter(context, "FOO"); assertEquals(0, counter.getCount()); @@ -43,11 +44,11 @@ public class RepeatContextCounterTests extends TestCase { counter.increment(2); assertEquals(3, counter.getCount()); } - + public void testAttributeCreatedInParent() throws Exception { new RepeatContextCounter(context, "FOO", true); - assertFalse(context.hasAttribute("FOO")); - assertTrue(parent.hasAttribute("FOO")); + assertFalse(context.hasAttribute("FOO")); + assertTrue(parent.hasAttribute("FOO")); } public void testParentIncrement() throws Exception { diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/context/RepeatContextSupportTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/context/RepeatContextSupportTests.java index 152bd2092..fac3853a5 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/context/RepeatContextSupportTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/context/RepeatContextSupportTests.java @@ -29,13 +29,14 @@ public class RepeatContextSupportTests extends TestCase { private List list = new ArrayList<>(); /** - * Test method for {@link org.springframework.batch.repeat.context.RepeatContextSupport#registerDestructionCallback(java.lang.String, java.lang.Runnable)}. + * Test method for + * {@link org.springframework.batch.repeat.context.RepeatContextSupport#registerDestructionCallback(java.lang.String, java.lang.Runnable)}. */ public void testDestructionCallbackSunnyDay() throws Exception { RepeatContextSupport context = new RepeatContextSupport(null); context.setAttribute("foo", "FOO"); context.registerDestructionCallback("foo", new Runnable() { - @Override + @Override public void run() { list.add("bar"); } @@ -46,37 +47,39 @@ public class RepeatContextSupportTests extends TestCase { } /** - * Test method for {@link org.springframework.batch.repeat.context.RepeatContextSupport#registerDestructionCallback(java.lang.String, java.lang.Runnable)}. + * Test method for + * {@link org.springframework.batch.repeat.context.RepeatContextSupport#registerDestructionCallback(java.lang.String, java.lang.Runnable)}. */ public void testDestructionCallbackMissingAttribute() throws Exception { RepeatContextSupport context = new RepeatContextSupport(null); context.registerDestructionCallback("foo", new Runnable() { - @Override + @Override public void run() { list.add("bar"); } }); context.close(); - // No check for the attribute before executing callback + // No check for the attribute before executing callback assertEquals(1, list.size()); } /** - * Test method for {@link org.springframework.batch.repeat.context.RepeatContextSupport#registerDestructionCallback(java.lang.String, java.lang.Runnable)}. + * Test method for + * {@link org.springframework.batch.repeat.context.RepeatContextSupport#registerDestructionCallback(java.lang.String, java.lang.Runnable)}. */ public void testDestructionCallbackWithException() throws Exception { RepeatContextSupport context = new RepeatContextSupport(null); context.setAttribute("foo", "FOO"); context.setAttribute("bar", "BAR"); context.registerDestructionCallback("bar", new Runnable() { - @Override + @Override public void run() { list.add("spam"); throw new RuntimeException("fail!"); } }); context.registerDestructionCallback("foo", new Runnable() { - @Override + @Override public void run() { list.add("bar"); throw new RuntimeException("fail!"); @@ -85,7 +88,8 @@ public class RepeatContextSupportTests extends TestCase { try { context.close(); fail("Expected RuntimeException"); - } catch (RuntimeException e) { + } + catch (RuntimeException e) { // We don't care which one was thrown... assertEquals("fail!", e.getMessage()); } @@ -94,4 +98,5 @@ public class RepeatContextSupportTests extends TestCase { assertTrue(list.contains("bar")); assertTrue(list.contains("spam")); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/exception/CompositeExceptionHandlerTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/exception/CompositeExceptionHandlerTests.java index f1b297c41..31c45d706 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/exception/CompositeExceptionHandlerTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/exception/CompositeExceptionHandlerTests.java @@ -40,23 +40,21 @@ public class CompositeExceptionHandlerTests extends TestCase { public void testDelegation() throws Throwable { final List list = new ArrayList<>(); - handler.setHandlers(new ExceptionHandler[] { - new ExceptionHandler() { - @Override - public void handleException(RepeatContext context, Throwable throwable) throws RuntimeException { - list.add("1"); - } - }, - new ExceptionHandler() { - @Override - public void handleException(RepeatContext context, Throwable throwable) throws RuntimeException { - list.add("2"); - } + handler.setHandlers(new ExceptionHandler[] { new ExceptionHandler() { + @Override + public void handleException(RepeatContext context, Throwable throwable) throws RuntimeException { + list.add("1"); } - }); + }, new ExceptionHandler() { + @Override + public void handleException(RepeatContext context, Throwable throwable) throws RuntimeException { + list.add("2"); + } + } }); handler.handleException(null, new RuntimeException()); assertEquals(2, list.size()); assertEquals("1", list.get(0)); assertEquals("2", list.get(1)); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/exception/DefaultExceptionHandlerTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/exception/DefaultExceptionHandlerTests.java index 1a003d5f8..fa2e58fb7 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/exception/DefaultExceptionHandlerTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/exception/DefaultExceptionHandlerTests.java @@ -23,13 +23,15 @@ import org.springframework.batch.repeat.RepeatContext; public class DefaultExceptionHandlerTests extends TestCase { private DefaultExceptionHandler handler = new DefaultExceptionHandler(); + private RepeatContext context = null; - + public void testRuntimeException() throws Throwable { try { handler.handleException(context, new RuntimeException("Foo")); fail("Expected RuntimeException"); - } catch (RuntimeException e) { + } + catch (RuntimeException e) { assertEquals("Foo", e.getMessage()); } } @@ -38,8 +40,10 @@ public class DefaultExceptionHandlerTests extends TestCase { try { handler.handleException(context, new Error("Foo")); fail("Expected Error"); - } catch (Error e) { + } + catch (Error e) { assertEquals("Foo", e.getMessage()); } } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/exception/LogOrRethrowExceptionHandlerTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/exception/LogOrRethrowExceptionHandlerTests.java index d61ecbb12..fee8cd6e8 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/exception/LogOrRethrowExceptionHandlerTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/exception/LogOrRethrowExceptionHandlerTests.java @@ -42,7 +42,7 @@ public class LogOrRethrowExceptionHandlerTests extends TestCase { private RepeatContext context = null; - @Override + @Override protected void setUp() throws Exception { super.setUp(); Logger logger = LoggerFactory.getLogger(LogOrRethrowExceptionHandler.class); @@ -54,7 +54,8 @@ public class LogOrRethrowExceptionHandlerTests extends TestCase { rootLoggerConfig.getAppenders().forEach((name, appender) -> { rootLoggerConfig.removeAppender(name); }); - Appender appender = WriterAppender.createAppender(PatternLayout.createDefaultLayout(), null, writer,"TESTWriter", false, false); + Appender appender = WriterAppender.createAppender(PatternLayout.createDefaultLayout(), null, writer, + "TESTWriter", false, false); rootLoggerConfig.addAppender(appender, org.apache.logging.log4j.Level.DEBUG, null); } @@ -80,8 +81,8 @@ public class LogOrRethrowExceptionHandlerTests extends TestCase { @SuppressWarnings("serial") public void testNotRethrownErrorLevel() throws Throwable { - handler.setExceptionClassifier(new ClassifierSupport(Level.RETHROW) { - @Override + handler.setExceptionClassifier(new ClassifierSupport(Level.RETHROW) { + @Override public Level classify(Throwable throwable) { return Level.ERROR; } @@ -93,8 +94,8 @@ public class LogOrRethrowExceptionHandlerTests extends TestCase { @SuppressWarnings("serial") public void testNotRethrownWarnLevel() throws Throwable { - handler.setExceptionClassifier(new ClassifierSupport(Level.RETHROW) { - @Override + handler.setExceptionClassifier(new ClassifierSupport(Level.RETHROW) { + @Override public Level classify(Throwable throwable) { return Level.WARN; } @@ -106,8 +107,8 @@ public class LogOrRethrowExceptionHandlerTests extends TestCase { @SuppressWarnings("serial") public void testNotRethrownDebugLevel() throws Throwable { - handler.setExceptionClassifier(new ClassifierSupport(Level.RETHROW) { - @Override + handler.setExceptionClassifier(new ClassifierSupport(Level.RETHROW) { + @Override public Level classify(Throwable throwable) { return Level.DEBUG; } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/exception/RethrowOnThresholdExceptionHandlerTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/exception/RethrowOnThresholdExceptionHandlerTests.java index 5fade13e8..1b318f2f0 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/exception/RethrowOnThresholdExceptionHandlerTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/exception/RethrowOnThresholdExceptionHandlerTests.java @@ -59,7 +59,7 @@ public class RethrowOnThresholdExceptionHandlerTests { @Test public void testNotRethrownWithThreshold() throws Throwable { - handler.setThresholds(Collections., Integer> singletonMap(Exception.class, 1)); + handler.setThresholds(Collections., Integer>singletonMap(Exception.class, 1)); // No exception... handler.handleException(context, new RuntimeException("Foo")); AtomicInteger counter = (AtomicInteger) context.getAttribute(context.attributeNames()[0]); @@ -69,7 +69,7 @@ public class RethrowOnThresholdExceptionHandlerTests { @Test public void testRethrowOnThreshold() throws Throwable { - handler.setThresholds(Collections., Integer> singletonMap(Exception.class, 2)); + handler.setThresholds(Collections., Integer>singletonMap(Exception.class, 2)); // No exception... handler.handleException(context, new RuntimeException("Foo")); handler.handleException(context, new RuntimeException("Foo")); @@ -84,7 +84,7 @@ public class RethrowOnThresholdExceptionHandlerTests { @Test public void testNotUseParent() throws Throwable { - handler.setThresholds(Collections., Integer> singletonMap(Exception.class, 1)); + handler.setThresholds(Collections., Integer>singletonMap(Exception.class, 1)); // No exception... handler.handleException(context, new RuntimeException("Foo")); context = new RepeatContextSupport(parent); @@ -99,7 +99,7 @@ public class RethrowOnThresholdExceptionHandlerTests { @Test public void testUseParent() throws Throwable { - handler.setThresholds(Collections., Integer> singletonMap(Exception.class, 1)); + handler.setThresholds(Collections., Integer>singletonMap(Exception.class, 1)); handler.setUseParent(true); // No exception... handler.handleException(context, new RuntimeException("Foo")); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/exception/SimpleLimitExceptionHandlerTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/exception/SimpleLimitExceptionHandlerTests.java index fec0a2627..f5cc984e4 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/exception/SimpleLimitExceptionHandlerTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/exception/SimpleLimitExceptionHandlerTests.java @@ -31,7 +31,7 @@ import org.springframework.batch.repeat.context.RepeatContextSupport; /** * Unit tests for {@link SimpleLimitExceptionHandler} - * + * * @author Robert Kasanicky * @author Dave Syer */ @@ -80,9 +80,8 @@ public class SimpleLimitExceptionHandlerTests { } /** - * Other than nominated exception type should be rethrown, ignoring the - * exception limit. - * + * Other than nominated exception type should be rethrown, ignoring the exception + * limit. * @throws Exception */ @Test @@ -91,7 +90,7 @@ public class SimpleLimitExceptionHandlerTests { final int MORE_THAN_ZERO = 1; handler.setLimit(MORE_THAN_ZERO); - handler.setExceptionClasses(Collections.> singleton(IllegalArgumentException.class)); + handler.setExceptionClasses(Collections.>singleton(IllegalArgumentException.class)); handler.afterPropertiesSet(); try { @@ -105,16 +104,14 @@ public class SimpleLimitExceptionHandlerTests { } /** - * TransactionInvalidException should only be rethrown below the exception - * limit. - * + * TransactionInvalidException should only be rethrown below the exception limit. * @throws Exception */ @Test public void testLimitedExceptionTypeNotThrown() throws Throwable { final int MORE_THAN_ZERO = 1; handler.setLimit(MORE_THAN_ZERO); - handler.setExceptionClasses(Collections.> singleton(RuntimeException.class)); + handler.setExceptionClasses(Collections.>singleton(RuntimeException.class)); handler.afterPropertiesSet(); try { @@ -126,9 +123,7 @@ public class SimpleLimitExceptionHandlerTests { } /** - * TransactionInvalidException should only be rethrown below the exception - * limit. - * + * TransactionInvalidException should only be rethrown below the exception limit. * @throws Exception */ @Test @@ -137,7 +132,7 @@ public class SimpleLimitExceptionHandlerTests { final int MORE_THAN_ZERO = 1; handler.setLimit(MORE_THAN_ZERO); - handler.setExceptionClasses(Collections.> singleton(RuntimeException.class)); + handler.setExceptionClasses(Collections.>singleton(RuntimeException.class)); handler.afterPropertiesSet(); RepeatContextSupport parent = new RepeatContextSupport(null); @@ -154,9 +149,7 @@ public class SimpleLimitExceptionHandlerTests { } /** - * TransactionInvalidException should only be rethrown below the exception - * limit. - * + * TransactionInvalidException should only be rethrown below the exception limit. * @throws Exception */ @Test @@ -165,7 +158,7 @@ public class SimpleLimitExceptionHandlerTests { final int MORE_THAN_ZERO = 1; handler.setLimit(MORE_THAN_ZERO); - handler.setExceptionClasses(Collections.> singleton(RuntimeException.class)); + handler.setExceptionClasses(Collections.>singleton(RuntimeException.class)); handler.setUseParent(true); handler.afterPropertiesSet(); @@ -184,8 +177,8 @@ public class SimpleLimitExceptionHandlerTests { } /** - * Exceptions are swallowed until the exception limit is exceeded. After the - * limit is exceeded exceptions are rethrown + * Exceptions are swallowed until the exception limit is exceeded. After the limit is + * exceeded exceptions are rethrown */ @Test public void testExceptionNotThrownBelowLimit() throws Throwable { @@ -220,9 +213,8 @@ public class SimpleLimitExceptionHandlerTests { } /** - * TransactionInvalidExceptions are swallowed until the exception limit is - * exceeded. After the limit is exceeded exceptions are rethrown as - * BatchCriticalExceptions + * TransactionInvalidExceptions are swallowed until the exception limit is exceeded. + * After the limit is exceeded exceptions are rethrown as BatchCriticalExceptions */ @Test public void testExceptionThrownAboveLimit() throws Throwable { @@ -266,4 +258,5 @@ public class SimpleLimitExceptionHandlerTests { assertEquals("foo", expected.getMessage()); } } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/interceptor/RepeatOperationsInterceptorTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/interceptor/RepeatOperationsInterceptorTests.java index aa85662f2..7472ddb40 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/interceptor/RepeatOperationsInterceptorTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/interceptor/RepeatOperationsInterceptorTests.java @@ -42,7 +42,7 @@ public class RepeatOperationsInterceptorTests extends TestCase { private ServiceImpl target; - @Override + @Override protected void setUp() throws Exception { super.setUp(); interceptor = new RepeatOperationsInterceptor(); @@ -69,7 +69,7 @@ public class RepeatOperationsInterceptorTests extends TestCase { public void testSetTemplate() throws Exception { final List calls = new ArrayList<>(); interceptor.setRepeatOperations(new RepeatOperations() { - @Override + @Override public RepeatStatus iterate(RepeatCallback callback) { try { Object result = callback.doInIteration(null); @@ -89,7 +89,7 @@ public class RepeatOperationsInterceptorTests extends TestCase { public void testCallbackNotExecuted() throws Exception { final List calls = new ArrayList<>(); interceptor.setRepeatOperations(new RepeatOperations() { - @Override + @Override public RepeatStatus iterate(RepeatCallback callback) { calls.add(null); return RepeatStatus.FINISHED; @@ -99,9 +99,10 @@ public class RepeatOperationsInterceptorTests extends TestCase { try { service.service(); fail("Expected IllegalStateException"); - } catch (IllegalStateException e) { + } + catch (IllegalStateException e) { String message = e.getMessage(); - assertTrue("Wrong exception message: "+message, message.toLowerCase().contains("no result available")); + assertTrue("Wrong exception message: " + message, message.toLowerCase().contains("no result available")); } assertEquals(1, calls.size()); } @@ -162,7 +163,7 @@ public class RepeatOperationsInterceptorTests extends TestCase { ((Advised) service).addAdvice(interceptor); final List list = new ArrayList<>(); ((Advised) service).addAdvice(new MethodInterceptor() { - @Override + @Override public Object invoke(MethodInvocation invocation) throws Throwable { list.add("chain"); return invocation.proceed(); @@ -179,7 +180,7 @@ public class RepeatOperationsInterceptorTests extends TestCase { public void testIllegalMethodInvocationType() throws Throwable { try { interceptor.invoke(new MethodInvocation() { - @Override + @Override public Method getMethod() { try { return Object.class.getMethod("toString"); @@ -189,22 +190,22 @@ public class RepeatOperationsInterceptorTests extends TestCase { } } - @Override + @Override public Object[] getArguments() { return null; } - @Override + @Override public AccessibleObject getStaticPart() { return null; } - @Override + @Override public Object getThis() { return null; } - @Override + @Override public Object proceed() throws Throwable { return null; } @@ -212,12 +213,13 @@ public class RepeatOperationsInterceptorTests extends TestCase { fail("IllegalStateException expected"); } catch (IllegalStateException e) { - assertTrue("Exception message should contain MethodInvocation: " + e.getMessage(), e.getMessage().indexOf( - "MethodInvocation") >= 0); + assertTrue("Exception message should contain MethodInvocation: " + e.getMessage(), + e.getMessage().indexOf("MethodInvocation") >= 0); } } private interface Service { + Object service() throws Exception; void alternate() throws Exception; @@ -227,15 +229,17 @@ public class RepeatOperationsInterceptorTests extends TestCase { Object error() throws Exception; boolean isContinuable() throws Exception; + } private static class ServiceImpl implements Service { + private int count = 0; private boolean complete; private int maxService = 2; - + /** * Public setter for the maximum number of times to call service(). * @param maxService the maxService to set @@ -244,7 +248,7 @@ public class RepeatOperationsInterceptorTests extends TestCase { this.maxService = maxService; } - @Override + @Override public Object service() throws Exception { count++; if (count <= maxService) { @@ -259,26 +263,27 @@ public class RepeatOperationsInterceptorTests extends TestCase { this.complete = complete; } - @Override + @Override public void alternate() throws Exception { count++; } - @Override + @Override public Object exception() throws Exception { throw new RuntimeException("Duh! Stupid."); } - @Override + @Override public Object error() throws Exception { throw new Error("Duh! Stupid error."); } - @Override + @Override public boolean isContinuable() throws Exception { count++; return !complete; } + } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/jms/AsynchronousTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/jms/AsynchronousTests.java index 6b0c494d9..034de3f0b 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/jms/AsynchronousTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/jms/AsynchronousTests.java @@ -64,7 +64,7 @@ public class AsynchronousTests { foo = (String) jmsTemplate.receiveAndConvert("queue"); count++; } - JdbcTestUtils.deleteFromTables(jdbcTemplate, "T_BARS"); + JdbcTestUtils.deleteFromTables(jdbcTemplate, "T_BARS"); // Queue is now drained... assertNull(foo); @@ -72,7 +72,7 @@ public class AsynchronousTests { // Add a couple of messages... jmsTemplate.convertAndSend("queue", "foo"); jmsTemplate.convertAndSend("queue", "bar"); - + } @After @@ -114,7 +114,7 @@ public class AsynchronousTests { container.start(); // Need to sleep for at least a second here... - waitFor(list,2,2000); + waitFor(list, 2, 2000); System.err.println(jdbcTemplate.queryForList("select * from T_BARS")); @@ -156,7 +156,7 @@ public class AsynchronousTests { // Need to sleep here, but not too long or the // container goes into its own recovery cycle and spits out the bad // message... - waitFor(list,2,500); + waitFor(list, 2, 500); container.stop(); @@ -185,7 +185,7 @@ public class AsynchronousTests { private void waitFor(List list, int size, int timeout) throws InterruptedException { int count = 0; int max = timeout / 50; - while (count list = new ArrayList<>(); @@ -41,12 +42,12 @@ public class CompositeRepeatListenerTests extends TestCase { */ public void testSetListeners() { listener.setListeners(new RepeatListener[] { new RepeatListener() { - @Override + @Override public void open(RepeatContext context) { list.add("fail"); } }, new RepeatListener() { - @Override + @Override public void open(RepeatContext context) { list.add("continue"); } @@ -56,12 +57,11 @@ public class CompositeRepeatListenerTests extends TestCase { } /** - * Test method for - * {@link CompositeRepeatListener#register(RepeatListener)}. + * Test method for {@link CompositeRepeatListener#register(RepeatListener)}. */ public void testSetListener() { listener.register(new RepeatListener() { - @Override + @Override public void before(RepeatContext context) { list.add("fail"); } @@ -72,7 +72,7 @@ public class CompositeRepeatListenerTests extends TestCase { public void testClose() { listener.register(new RepeatListener() { - @Override + @Override public void close(RepeatContext context) { list.add("foo"); } @@ -83,7 +83,7 @@ public class CompositeRepeatListenerTests extends TestCase { public void testOnError() { listener.register(new RepeatListener() { - @Override + @Override public void onError(RepeatContext context, Throwable e) { list.add(e); } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/listener/RepeatListenerTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/listener/RepeatListenerTests.java index e61a3c6b4..ee239d2e2 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/listener/RepeatListenerTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/listener/RepeatListenerTests.java @@ -37,18 +37,18 @@ public class RepeatListenerTests extends TestCase { RepeatTemplate template = new RepeatTemplate(); final List calls = new ArrayList<>(); template.setListeners(new RepeatListener[] { new RepeatListener() { - @Override + @Override public void before(RepeatContext context) { calls.add("1"); } }, new RepeatListener() { - @Override + @Override public void before(RepeatContext context) { calls.add("2"); } } }); template.iterate(new RepeatCallback() { - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { count++; return RepeatStatus.continueIf(count <= 1); @@ -66,14 +66,14 @@ public class RepeatListenerTests extends TestCase { RepeatTemplate template = new RepeatTemplate(); final List calls = new ArrayList<>(); template.registerListener(new RepeatListener() { - @Override + @Override public void before(RepeatContext context) { calls.add("1"); context.setCompleteOnly(); } }); template.iterate(new RepeatCallback() { - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { count++; return RepeatStatus.FINISHED; @@ -88,18 +88,18 @@ public class RepeatListenerTests extends TestCase { RepeatTemplate template = new RepeatTemplate(); final List calls = new ArrayList<>(); template.setListeners(new RepeatListener[] { new RepeatListener() { - @Override + @Override public void after(RepeatContext context, RepeatStatus result) { calls.add("1"); } }, new RepeatListener() { - @Override + @Override public void after(RepeatContext context, RepeatStatus result) { calls.add("2"); } } }); template.iterate(new RepeatCallback() { - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { count++; return RepeatStatus.continueIf(count <= 1); @@ -115,19 +115,19 @@ public class RepeatListenerTests extends TestCase { RepeatTemplate template = new RepeatTemplate(); final List calls = new ArrayList<>(); template.setListeners(new RepeatListener[] { new RepeatListener() { - @Override + @Override public void open(RepeatContext context) { calls.add("1"); } }, new RepeatListener() { - @Override + @Override public void open(RepeatContext context) { calls.add("2"); context.setCompleteOnly(); } } }); template.iterate(new RepeatCallback() { - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { count++; return RepeatStatus.CONTINUABLE; @@ -141,13 +141,13 @@ public class RepeatListenerTests extends TestCase { RepeatTemplate template = new RepeatTemplate(); final List calls = new ArrayList<>(); template.registerListener(new RepeatListener() { - @Override + @Override public void open(RepeatContext context) { calls.add("1"); } }); template.iterate(new RepeatCallback() { - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { count++; context.setCompleteOnly(); @@ -162,18 +162,18 @@ public class RepeatListenerTests extends TestCase { RepeatTemplate template = new RepeatTemplate(); final List calls = new ArrayList<>(); template.setListeners(new RepeatListener[] { new RepeatListener() { - @Override + @Override public void close(RepeatContext context) { calls.add("1"); } }, new RepeatListener() { - @Override + @Override public void close(RepeatContext context) { calls.add("2"); } } }); template.iterate(new RepeatCallback() { - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { count++; return RepeatStatus.continueIf(count < 2); @@ -185,24 +185,23 @@ public class RepeatListenerTests extends TestCase { assertEquals("[2, 1]", calls.toString()); } - public void testOnErrorInterceptors() throws Exception { RepeatTemplate template = new RepeatTemplate(); final List calls = new ArrayList<>(); template.setListeners(new RepeatListener[] { new RepeatListener() { - @Override + @Override public void onError(RepeatContext context, Throwable t) { calls.add("1"); } }, new RepeatListener() { - @Override + @Override public void onError(RepeatContext context, Throwable t) { calls.add("2"); } } }); try { template.iterate(new RepeatCallback() { - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { throw new IllegalStateException("Bogus"); } @@ -220,19 +219,19 @@ public class RepeatListenerTests extends TestCase { RepeatTemplate template = new RepeatTemplate(); final List calls = new ArrayList<>(); template.setListeners(new RepeatListener[] { new RepeatListener() { - @Override + @Override public void after(RepeatContext context, RepeatStatus result) { calls.add("1"); } }, new RepeatListener() { - @Override + @Override public void onError(RepeatContext context, Throwable t) { calls.add("2"); } } }); try { template.iterate(new RepeatCallback() { - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { throw new IllegalStateException("Bogus"); } @@ -253,12 +252,12 @@ public class RepeatListenerTests extends TestCase { final List calls = new ArrayList<>(); final List fails = new ArrayList<>(); template.setListeners(new RepeatListener[] { new RepeatListener() { - @Override + @Override public void after(RepeatContext context, RepeatStatus result) { calls.add("1"); } }, new RepeatListener() { - @Override + @Override public void onError(RepeatContext context, Throwable t) { calls.add("2"); fails.add("2"); @@ -266,7 +265,7 @@ public class RepeatListenerTests extends TestCase { } }); try { template.iterate(new RepeatCallback() { - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { throw new IllegalStateException("Bogus"); } @@ -281,8 +280,9 @@ public class RepeatListenerTests extends TestCase { System.err.println(calls); // The after is not executed on error... assertEquals("2", calls.get(0)); - assertEquals("2", calls.get(calls.size()-1)); + assertEquals("2", calls.get(calls.size() - 1)); assertFalse(calls.contains("1")); assertEquals(fails.size(), calls.size()); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/policy/CompositeCompletionPolicyTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/policy/CompositeCompletionPolicyTests.java index a28b60a29..23c37edc3 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/policy/CompositeCompletionPolicyTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/policy/CompositeCompletionPolicyTests.java @@ -33,8 +33,8 @@ public class CompositeCompletionPolicyTests extends TestCase { public void testTrivialPolicies() throws Exception { CompositeCompletionPolicy policy = new CompositeCompletionPolicy(); - policy.setPolicies(new CompletionPolicy[] { new MockCompletionPolicySupport(), - new MockCompletionPolicySupport() }); + policy.setPolicies( + new CompletionPolicy[] { new MockCompletionPolicySupport(), new MockCompletionPolicySupport() }); RepeatContext context = policy.start(null); assertEquals(0, context.getStartedCount()); assertFalse(policy.isComplete(context)); @@ -45,9 +45,9 @@ public class CompositeCompletionPolicyTests extends TestCase { public void testNonTrivialPolicies() throws Exception { CompositeCompletionPolicy policy = new CompositeCompletionPolicy(); - policy.setPolicies(new CompletionPolicy[] { new MockCompletionPolicySupport(), - new MockCompletionPolicySupport() { - @Override + policy.setPolicies( + new CompletionPolicy[] { new MockCompletionPolicySupport(), new MockCompletionPolicySupport() { + @Override public boolean isComplete(RepeatContext context) { return true; } @@ -58,9 +58,9 @@ public class CompositeCompletionPolicyTests extends TestCase { public void testNonTrivialPoliciesWithResult() throws Exception { CompositeCompletionPolicy policy = new CompositeCompletionPolicy(); - policy.setPolicies(new CompletionPolicy[] { new MockCompletionPolicySupport(), - new MockCompletionPolicySupport() { - @Override + policy.setPolicies( + new CompletionPolicy[] { new MockCompletionPolicySupport(), new MockCompletionPolicySupport() { + @Override public boolean isComplete(RepeatContext context, RepeatStatus result) { return true; } @@ -68,4 +68,5 @@ public class CompositeCompletionPolicyTests extends TestCase { RepeatContext context = policy.start(null); assertTrue(policy.isComplete(context, null)); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/policy/CountingCompletionPolicyTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/policy/CountingCompletionPolicyTests.java index f639e0b7d..59bee4b24 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/policy/CountingCompletionPolicyTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/policy/CountingCompletionPolicyTests.java @@ -26,7 +26,7 @@ public class CountingCompletionPolicyTests extends TestCase { public void testDefaultBehaviour() throws Exception { CountingCompletionPolicy policy = new CountingCompletionPolicy() { - @Override + @Override protected int getCount(RepeatContext context) { return 1; } @@ -37,7 +37,7 @@ public class CountingCompletionPolicyTests extends TestCase { public void testNullResult() throws Exception { CountingCompletionPolicy policy = new CountingCompletionPolicy() { - @Override + @Override protected int getCount(RepeatContext context) { return 1; } @@ -49,7 +49,7 @@ public class CountingCompletionPolicyTests extends TestCase { public void testFinishedResult() throws Exception { CountingCompletionPolicy policy = new CountingCompletionPolicy() { - @Override + @Override protected int getCount(RepeatContext context) { return 1; } @@ -63,12 +63,12 @@ public class CountingCompletionPolicyTests extends TestCase { CountingCompletionPolicy policy = new CountingCompletionPolicy() { int count = 0; - @Override + @Override protected int getCount(RepeatContext context) { return count; } - @Override + @Override protected int doUpdate(RepeatContext context) { count++; return 1; @@ -86,19 +86,19 @@ public class CountingCompletionPolicyTests extends TestCase { CountingCompletionPolicy policy = new CountingCompletionPolicy() { int count = 0; - @Override + @Override protected int getCount(RepeatContext context) { return count; } - @Override + @Override protected int doUpdate(RepeatContext context) { super.doUpdate(context); count++; return 1; } - @Override + @Override public RepeatContext start(RepeatContext context) { count = 0; return super.start(context); @@ -118,19 +118,19 @@ public class CountingCompletionPolicyTests extends TestCase { CountingCompletionPolicy policy = new CountingCompletionPolicy() { int count = 0; - @Override + @Override protected int getCount(RepeatContext context) { return count; } - @Override + @Override protected int doUpdate(RepeatContext context) { super.doUpdate(context); count++; return 1; } - @Override + @Override public RepeatContext start(RepeatContext context) { count = 0; return super.start(context); @@ -146,4 +146,5 @@ public class CountingCompletionPolicyTests extends TestCase { policy.update(context); assertTrue(policy.isComplete(context)); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/policy/MockCompletionPolicySupport.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/policy/MockCompletionPolicySupport.java index 8c47b0a53..329314292 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/policy/MockCompletionPolicySupport.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/policy/MockCompletionPolicySupport.java @@ -20,7 +20,7 @@ import org.springframework.batch.repeat.RepeatContext; public class MockCompletionPolicySupport extends CompletionPolicySupport { - @Override + @Override public boolean isComplete(RepeatContext context) { return false; } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/policy/SimpleCompletionPolicyTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/policy/SimpleCompletionPolicyTests.java index 28501a998..c79cbbc5d 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/policy/SimpleCompletionPolicyTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/policy/SimpleCompletionPolicyTests.java @@ -29,7 +29,7 @@ public class SimpleCompletionPolicyTests extends TestCase { RepeatStatus dummy = RepeatStatus.CONTINUABLE; - @Override + @Override protected void setUp() throws Exception { super.setUp(); context = policy.start(null); @@ -72,4 +72,5 @@ public class SimpleCompletionPolicyTests extends TestCase { policy.update(context); assertFalse(policy.isComplete(context, dummy)); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/policy/TimeoutCompletionPolicyTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/policy/TimeoutCompletionPolicyTests.java index d6388a8c2..6b77479c7 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/policy/TimeoutCompletionPolicyTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/policy/TimeoutCompletionPolicyTests.java @@ -40,7 +40,7 @@ public class TimeoutCompletionPolicyTests { RepeatContext context = policy.start(null); assertFalse(policy.isComplete(context, null)); } - + @Test public void testNonContinuableResult() throws Exception { TimeoutTerminationPolicy policy = new TimeoutTerminationPolicy(); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/AbstractTradeBatchTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/AbstractTradeBatchTests.java index 8ffd7b025..fabd0dbea 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/AbstractTradeBatchTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/AbstractTradeBatchTests.java @@ -66,22 +66,26 @@ public abstract class AbstractTradeBatchTests { } protected static class TradeMapper implements FieldSetMapper { - @Override + + @Override public Trade mapFieldSet(FieldSet fs) { return new Trade(fs); } + } protected static class TradeWriter implements ItemWriter { + int count = 0; // This has to be synchronized because we are going to test the state // (count) at the end of a concurrent batch run. - @Override + @Override public synchronized void write(List data) { count++; System.out.println("Executing trade '" + data + "'"); } + } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/ChunkedRepeatTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/ChunkedRepeatTests.java index 234d4d0b6..7c73662f9 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/ChunkedRepeatTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/ChunkedRepeatTests.java @@ -32,19 +32,19 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; /** - * Test various approaches to chunking of a batch. Not really a unit test, but - * it should be fast. - * + * Test various approaches to chunking of a batch. Not really a unit test, but it should + * be fast. + * * @author Dave Syer - * + * */ public class ChunkedRepeatTests extends AbstractTradeBatchTests { int count = 0; /** - * Chunking using a dedicated TerminationPolicy. Transactions would be laid - * on at the level of chunkTemplate.execute() or the surrounding callback. + * Chunking using a dedicated TerminationPolicy. Transactions would be laid on at the + * level of chunkTemplate.execute() or the surrounding callback. */ @Test public void testChunkedBatchWithTerminationPolicy() throws Exception { @@ -59,7 +59,7 @@ public class ChunkedRepeatTests extends AbstractTradeBatchTests { RepeatStatus result = repeatTemplate.iterate(new NestedRepeatCallback(chunkTemplate, callback) { - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { count++; // for test assertion return super.doInIteration(context); @@ -77,8 +77,8 @@ public class ChunkedRepeatTests extends AbstractTradeBatchTests { } /** - * Chunking with an asynchronous taskExecutor in the chunks. Transactions - * have to be at the level of the business callback. + * Chunking with an asynchronous taskExecutor in the chunks. Transactions have to be + * at the level of the business callback. */ @Test public void testAsynchronousChunkedBatchWithCompletionPolicy() throws Exception { @@ -94,7 +94,7 @@ public class ChunkedRepeatTests extends AbstractTradeBatchTests { RepeatStatus result = repeatTemplate.iterate(new NestedRepeatCallback(chunkTemplate, callback) { - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { count++; // for test assertion return super.doInIteration(context); @@ -104,13 +104,13 @@ public class ChunkedRepeatTests extends AbstractTradeBatchTests { assertEquals(NUMBER_OF_ITEMS, processor.count); assertFalse(result.isContinuable()); - assertTrue("Expected at least 3 chunks but found: "+count, count>=3); + assertTrue("Expected at least 3 chunks but found: " + count, count >= 3); } /** - * Explicit chunking of input data. Transactions would be laid on at the - * level of template.execute(). + * Explicit chunking of input data. Transactions would be laid on at the level of + * template.execute(). */ @Test public void testChunksWithTruncatedItemProvider() throws Exception { @@ -121,6 +121,7 @@ public class ChunkedRepeatTests extends AbstractTradeBatchTests { // (but non-transactional in that case). class Chunker { + boolean ready = false; int count = 0; @@ -145,6 +146,7 @@ public class ChunkedRepeatTests extends AbstractTradeBatchTests { void increment() { count++; } + } final Chunker chunker = new Chunker(); @@ -154,7 +156,7 @@ public class ChunkedRepeatTests extends AbstractTradeBatchTests { ItemReader truncated = new ItemReader() { int count = 0; - @Nullable + @Nullable @Override public Trade read() throws Exception { if (count++ < 2) @@ -165,7 +167,7 @@ public class ChunkedRepeatTests extends AbstractTradeBatchTests { chunker.reset(); template.iterate(new ItemReaderRepeatCallback(truncated, processor) { - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { RepeatStatus result = super.doInIteration(context); if (!result.isContinuable() && chunker.first()) { diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/ItemReaderRepeatCallback.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/ItemReaderRepeatCallback.java index aaafcb8a6..99c709fac 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/ItemReaderRepeatCallback.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/ItemReaderRepeatCallback.java @@ -30,6 +30,7 @@ import org.springframework.batch.repeat.RepeatContext; public class ItemReaderRepeatCallback implements RepeatCallback { private final ItemReader reader; + private final ItemWriter writer; /** @@ -41,13 +42,17 @@ public class ItemReaderRepeatCallback implements RepeatCallback { this.reader = reader; } - /* (non-Javadoc) - * @see org.springframework.batch.repeat.RepeatCallback#doInIteration(org.springframework.batch.repeat.RepeatContext) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.repeat.RepeatCallback#doInIteration(org.springframework. + * batch.repeat.RepeatContext) */ - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { T item = reader.read(); - if (item==null) { + if (item == null) { return RepeatStatus.FINISHED; } writer.write(Collections.singletonList(item)); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/RepeatSynchronizationManagerTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/RepeatSynchronizationManagerTests.java index 1d17e355b..cb342725b 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/RepeatSynchronizationManagerTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/RepeatSynchronizationManagerTests.java @@ -25,12 +25,12 @@ public class RepeatSynchronizationManagerTests extends TestCase { private RepeatContext context = new RepeatContextSupport(null); - @Override + @Override protected void setUp() throws Exception { RepeatSynchronizationManager.clear(); } - - @Override + + @Override protected void tearDown() throws Exception { RepeatSynchronizationManager.clear(); } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/ResultHolderResultQueueTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/ResultHolderResultQueueTests.java index 67bcd3853..2dbb87445 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/ResultHolderResultQueueTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/ResultHolderResultQueueTests.java @@ -15,7 +15,6 @@ */ package org.springframework.batch.repeat.support; - import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -60,20 +59,21 @@ public class ResultHolderResultQueueTests { this.result = result; } - @Override + @Override public RepeatContext getContext() { return null; } - @Override + @Override public Throwable getError() { return error; } - @Override + @Override public RepeatStatus getResult() { return result; } + } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/SimpleRepeatTemplateTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/SimpleRepeatTemplateTests.java index ff322d0b0..0e60677bc 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/SimpleRepeatTemplateTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/SimpleRepeatTemplateTests.java @@ -64,7 +64,6 @@ public class SimpleRepeatTemplateTests extends AbstractTradeBatchTests { /** * Check that a dedicated TerminationPolicy can terminate the batch. - * * @throws Exception */ @Test @@ -80,7 +79,6 @@ public class SimpleRepeatTemplateTests extends AbstractTradeBatchTests { /** * Check that a dedicated TerminationPolicy can terminate the batch. - * * @throws Exception */ @Test @@ -88,7 +86,7 @@ public class SimpleRepeatTemplateTests extends AbstractTradeBatchTests { try { template.iterate(new RepeatCallback() { - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { count++; throw new IllegalStateException("foo!"); @@ -101,13 +99,12 @@ public class SimpleRepeatTemplateTests extends AbstractTradeBatchTests { } assertEquals(1, count); - assertTrue("Too many attempts: "+count, count<=10); + assertTrue("Too many attempts: " + count, count <= 10); } /** * Check that the context is closed. - * * @throws Exception */ @Test @@ -116,20 +113,20 @@ public class SimpleRepeatTemplateTests extends AbstractTradeBatchTests { final List list = new ArrayList<>(); final RepeatContext context = new RepeatContextSupport(null) { - @Override + @Override public void close() { super.close(); list.add("close"); } }; template.setCompletionPolicy(new CompletionPolicySupport() { - @Override + @Override public RepeatContext start(RepeatContext c) { return context; } }); template.iterate(new RepeatCallback() { - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { count++; return RepeatStatus.continueIf(count < 1); @@ -143,7 +140,6 @@ public class SimpleRepeatTemplateTests extends AbstractTradeBatchTests { /** * Check that the context is closed. - * * @throws Exception */ @Test @@ -152,14 +148,14 @@ public class SimpleRepeatTemplateTests extends AbstractTradeBatchTests { final List list = new ArrayList<>(); final RepeatContext context = new RepeatContextSupport(null) { - @Override + @Override public void close() { super.close(); list.add("close"); } }; template.setCompletionPolicy(new CompletionPolicySupport() { - @Override + @Override public RepeatContext start(RepeatContext c) { return context; } @@ -167,7 +163,7 @@ public class SimpleRepeatTemplateTests extends AbstractTradeBatchTests { try { template.iterate(new RepeatCallback() { - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { count++; throw new RuntimeException("foo"); @@ -185,7 +181,6 @@ public class SimpleRepeatTemplateTests extends AbstractTradeBatchTests { /** * Check that the exception handler is called. - * * @throws Exception */ @Test @@ -194,7 +189,7 @@ public class SimpleRepeatTemplateTests extends AbstractTradeBatchTests { final List list = new ArrayList<>(); template.setExceptionHandler(new ExceptionHandler() { - @Override + @Override public void handleException(RepeatContext context, Throwable throwable) throws RuntimeException { list.add(throwable); throw (RuntimeException) throwable; @@ -203,7 +198,7 @@ public class SimpleRepeatTemplateTests extends AbstractTradeBatchTests { try { template.iterate(new RepeatCallback() { - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { count++; throw new RuntimeException("foo"); @@ -221,7 +216,6 @@ public class SimpleRepeatTemplateTests extends AbstractTradeBatchTests { /** * Check that a the context can be used to signal early completion. - * * @throws Exception */ @Test @@ -229,7 +223,7 @@ public class SimpleRepeatTemplateTests extends AbstractTradeBatchTests { RepeatStatus result = template.iterate(new ItemReaderRepeatCallback(provider, processor) { - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { RepeatStatus result = super.doInIteration(context); if (processor.count >= 2) { @@ -251,7 +245,6 @@ public class SimpleRepeatTemplateTests extends AbstractTradeBatchTests { /** * Check that a the context can be used to signal early completion. - * * @throws Exception */ @Test @@ -259,7 +252,7 @@ public class SimpleRepeatTemplateTests extends AbstractTradeBatchTests { RepeatStatus result = template.iterate(new ItemReaderRepeatCallback(provider, processor) { - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { RepeatStatus result = super.doInIteration(context); if (processor.count >= 2) { @@ -284,7 +277,7 @@ public class SimpleRepeatTemplateTests extends AbstractTradeBatchTests { RepeatTemplate outer = getRepeatTemplate(); RepeatTemplate inner = getRepeatTemplate(); outer.iterate(new NestedRepeatCallback(inner, new RepeatCallback() { - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { count++; assertNotNull(context); @@ -293,7 +286,7 @@ public class SimpleRepeatTemplateTests extends AbstractTradeBatchTests { return RepeatStatus.FINISHED; } }) { - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { count++; assertSame(context, RepeatSynchronizationManager.getContext()); @@ -308,7 +301,7 @@ public class SimpleRepeatTemplateTests extends AbstractTradeBatchTests { RepeatTemplate outer = getRepeatTemplate(); RepeatTemplate inner = getRepeatTemplate(); outer.iterate(new NestedRepeatCallback(inner, new RepeatCallback() { - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { count++; assertEquals(2, count); @@ -316,7 +309,7 @@ public class SimpleRepeatTemplateTests extends AbstractTradeBatchTests { return RepeatStatus.FINISHED; } }) { - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { count++; context.setCompleteOnly(); @@ -332,7 +325,7 @@ public class SimpleRepeatTemplateTests extends AbstractTradeBatchTests { outer.setCompletionPolicy(new SimpleCompletionPolicy(2)); RepeatTemplate inner = getRepeatTemplate(); outer.iterate(new NestedRepeatCallback(inner, new RepeatCallback() { - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { count++; assertNotNull(context); @@ -341,7 +334,7 @@ public class SimpleRepeatTemplateTests extends AbstractTradeBatchTests { return RepeatStatus.FINISHED; } }) { - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { count++; assertSame(context, RepeatSynchronizationManager.getContext()); @@ -369,7 +362,7 @@ public class SimpleRepeatTemplateTests extends AbstractTradeBatchTests { template.setCompletionPolicy(new SimpleCompletionPolicy(2)); try { template.iterate(new RepeatCallback() { - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { count++; if (count < 2) { @@ -387,9 +380,8 @@ public class SimpleRepeatTemplateTests extends AbstractTradeBatchTests { } /** - * Check that a the session can be used to signal early completion, but an - * exception takes precedence. - * + * Check that a the session can be used to signal early completion, but an exception + * takes precedence. * @throws Exception */ @Test @@ -402,7 +394,7 @@ public class SimpleRepeatTemplateTests extends AbstractTradeBatchTests { try { result = template.iterate(new ItemReaderRepeatCallback(provider, processor) { - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { RepeatStatus result = super.doInIteration(context); if (processor.count >= 2) { @@ -430,42 +422,47 @@ public class SimpleRepeatTemplateTests extends AbstractTradeBatchTests { } /** - * Checked exceptions are wrapped into runtime RepeatException. - * RepeatException should be unwrapped before before it is passed to - * listeners and exception handler. + * Checked exceptions are wrapped into runtime RepeatException. RepeatException should + * be unwrapped before before it is passed to listeners and exception handler. */ @Test public void testExceptionUnwrapping() { @SuppressWarnings("serial") class TestException extends Exception { + TestException(String msg) { super(msg); } + } final TestException exception = new TestException("CRASH!"); class ExceptionHandlerStub implements ExceptionHandler { + boolean called = false; - @Override + @Override public void handleException(RepeatContext context, Throwable throwable) throws Throwable { called = true; assertSame(exception, throwable); throw throwable; // re-throw so that repeat template // terminates iteration } + } ExceptionHandlerStub exHandler = new ExceptionHandlerStub(); class RepeatListenerStub implements RepeatListener { + boolean called = false; - @Override + @Override public void onError(RepeatContext context, Throwable throwable) { called = true; assertSame(exception, throwable); } + } RepeatListenerStub listener = new RepeatListenerStub(); @@ -474,7 +471,7 @@ public class SimpleRepeatTemplateTests extends AbstractTradeBatchTests { try { template.iterate(new RepeatCallback() { - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { throw new RepeatException("typically thrown by nested repeat template", exception); } @@ -489,4 +486,5 @@ public class SimpleRepeatTemplateTests extends AbstractTradeBatchTests { assertTrue(exHandler.called); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/TaskExecutorRepeatTemplateAsynchronousTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/TaskExecutorRepeatTemplateAsynchronousTests.java index 9e3fd5728..12ad7b2f5 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/TaskExecutorRepeatTemplateAsynchronousTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/TaskExecutorRepeatTemplateAsynchronousTests.java @@ -64,7 +64,7 @@ public class TaskExecutorRepeatTemplateAsynchronousTests extends AbstractTradeBa template.setTaskExecutor(taskExecutor); try { template.iterate(new RepeatCallback() { - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { count++; throw new IllegalStateException("foo!"); @@ -91,13 +91,13 @@ public class TaskExecutorRepeatTemplateAsynchronousTests extends AbstractTradeBa template.setTaskExecutor(taskExecutor); template.setExceptionHandler(new ExceptionHandler() { - @Override + @Override public void handleException(RepeatContext context, Throwable throwable) throws Throwable { count++; } }); template.iterate(new RepeatCallback() { - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { throw new IllegalStateException("foo!"); } @@ -115,7 +115,7 @@ public class TaskExecutorRepeatTemplateAsynchronousTests extends AbstractTradeBa RepeatTemplate inner = new RepeatTemplate(); outer.iterate(new NestedRepeatCallback(inner, new RepeatCallback() { - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { count++; assertNotNull(context); @@ -124,7 +124,7 @@ public class TaskExecutorRepeatTemplateAsynchronousTests extends AbstractTradeBa return RepeatStatus.FINISHED; } }) { - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { count++; assertNotNull(context); @@ -139,10 +139,9 @@ public class TaskExecutorRepeatTemplateAsynchronousTests extends AbstractTradeBa } /** - * Run a batch with a single template that itself has an async task - * executor. The result is a batch that runs in multiple threads (up to the - * throttle limit of the template). - * + * Run a batch with a single template that itself has an async task executor. The + * result is a batch that runs in multiple threads (up to the throttle limit of the + * template). * @throws Exception */ @Test @@ -152,7 +151,7 @@ public class TaskExecutorRepeatTemplateAsynchronousTests extends AbstractTradeBa final Set threadNames = new HashSet<>(); final RepeatCallback callback = new RepeatCallback() { - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { assertNotSame(threadName, Thread.currentThread().getName()); threadNames.add(Thread.currentThread().getName()); @@ -188,7 +187,7 @@ public class TaskExecutorRepeatTemplateAsynchronousTests extends AbstractTradeBa final List items = new ArrayList<>(); final RepeatCallback callback = new RepeatCallback() { - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { assertNotSame(threadName, Thread.currentThread().getName()); Trade item = provider.read(); @@ -220,9 +219,7 @@ public class TaskExecutorRepeatTemplateAsynchronousTests extends AbstractTradeBa } /** - * Wrap an otherwise synchronous batch in a callback to an asynchronous - * template. - * + * Wrap an otherwise synchronous batch in a callback to an asynchronous template. * @throws Exception */ @Test @@ -237,7 +234,7 @@ public class TaskExecutorRepeatTemplateAsynchronousTests extends AbstractTradeBa final Set threadNames = new HashSet<>(); final RepeatCallback stepCallback = new ItemReaderRepeatCallback(provider, processor) { - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { assertNotSame(threadName, Thread.currentThread().getName()); threadNames.add(Thread.currentThread().getName()); @@ -250,7 +247,7 @@ public class TaskExecutorRepeatTemplateAsynchronousTests extends AbstractTradeBa } }; RepeatCallback jobCallback = new RepeatCallback() { - @Override + @Override public RepeatStatus doInIteration(RepeatContext context) throws Exception { stepTemplate.iterate(stepCallback); return RepeatStatus.FINISHED; diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/TaskExecutorRepeatTemplateBulkAsynchronousTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/TaskExecutorRepeatTemplateBulkAsynchronousTests.java index dabbb30c2..e4184ce3d 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/TaskExecutorRepeatTemplateBulkAsynchronousTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/TaskExecutorRepeatTemplateBulkAsynchronousTests.java @@ -40,18 +40,17 @@ import org.springframework.core.task.TaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; /** - * Simple tests for concurrent behaviour in repeat template, in particular the - * barrier at the end of the iteration. N.B. these tests may fail if - * insufficient threads are available (e.g. on a single-core machine, or under - * load). They shouldn't deadlock though. - * + * Simple tests for concurrent behaviour in repeat template, in particular the barrier at + * the end of the iteration. N.B. these tests may fail if insufficient threads are + * available (e.g. on a single-core machine, or under load). They shouldn't deadlock + * though. + * * @author Dave Syer - * + * */ public class TaskExecutorRepeatTemplateBulkAsynchronousTests { - static Log logger = LogFactory - .getLog(TaskExecutorRepeatTemplateBulkAsynchronousTests.class); + static Log logger = LogFactory.getLog(TaskExecutorRepeatTemplateBulkAsynchronousTests.class); private int total = 1000; @@ -89,8 +88,7 @@ public class TaskExecutorRepeatTemplateBulkAsynchronousTests { private volatile AtomicInteger count = new AtomicInteger(0); @Override - public RepeatStatus doInIteration(RepeatContext context) - throws Exception { + public RepeatStatus doInIteration(RepeatContext context) throws Exception { int position = count.incrementAndGet(); String item = position <= total ? "" + position : null; items.add("" + item); @@ -98,20 +96,17 @@ public class TaskExecutorRepeatTemplateBulkAsynchronousTests { beBusy(); } /* - * In a multi-threaded task, one of the callbacks can call - * FINISHED early, while other threads are still working, and - * would do more work if the callback was called again. (This - * happens for instance if there is a failure and you want to - * retry the work.) + * In a multi-threaded task, one of the callbacks can call FINISHED early, + * while other threads are still working, and would do more work if the + * callback was called again. (This happens for instance if there is a + * failure and you want to retry the work.) */ - RepeatStatus result = RepeatStatus.continueIf(position != early - && item != null); + RepeatStatus result = RepeatStatus.continueIf(position != early && item != null); if (position == error) { throw new RuntimeException("Planned"); } if (!result.isContinuable()) { - logger.debug("Returning " + result + " for count=" - + position); + logger.debug("Returning " + result + " for count=" + position); } return result; } @@ -164,8 +159,7 @@ public class TaskExecutorRepeatTemplateBulkAsynchronousTests { taskExecutor.setQueueCapacity(0); // This is the most sensible setting, otherwise the bookkeeping in // ResultHolderResultQueue gets out of whack when tasks are aborted. - taskExecutor - .setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); + taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); taskExecutor.afterPropertiesSet(); template.setTaskExecutor(taskExecutor); @@ -226,14 +220,15 @@ public class TaskExecutorRepeatTemplateBulkAsynchronousTests { try { template.iterate(callback); fail("Expected planned exception"); - } catch (Exception e) { + } + catch (Exception e) { assertEquals("Planned", e.getMessage()); } int frequency = Collections.frequency(items, "null"); assertEquals(0, frequency); } - + @Test public void testErrorThrownByCallback() throws Exception { @@ -242,11 +237,10 @@ public class TaskExecutorRepeatTemplateBulkAsynchronousTests { private volatile AtomicInteger count = new AtomicInteger(0); @Override - public RepeatStatus doInIteration(RepeatContext context) - throws Exception { + public RepeatStatus doInIteration(RepeatContext context) throws Exception { int position = count.incrementAndGet(); - - if(position == 4) { + + if (position == 4) { throw new OutOfMemoryError("Planned"); } else { @@ -254,26 +248,27 @@ public class TaskExecutorRepeatTemplateBulkAsynchronousTests { } } }; - + template.setCompletionPolicy(new SimpleCompletionPolicy(10)); try { template.iterate(callback); fail("Expected planned exception"); - } catch (OutOfMemoryError oome) { + } + catch (OutOfMemoryError oome) { assertEquals("Planned", oome.getMessage()); - } catch (Exception e) { + } + catch (Exception e) { e.printStackTrace(); fail("Wrong exception was thrown: " + e); } } /** - * Slightly flakey convenience method. If this doesn't do something that - * lasts sufficiently long for another worker to be launched while it is - * busy, the early completion tests will fail. "Sufficiently long" is the - * problem so we try and block until we know someone else is busy? - * + * Slightly flakey convenience method. If this doesn't do something that lasts + * sufficiently long for another worker to be launched while it is busy, the early + * completion tests will fail. "Sufficiently long" is the problem so we try and block + * until we know someone else is busy? * @throws Exception */ private void beBusy() throws Exception { diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/TaskExecutorRepeatTemplateTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/TaskExecutorRepeatTemplateTests.java index 355b174a2..12b6a0533 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/TaskExecutorRepeatTemplateTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/TaskExecutorRepeatTemplateTests.java @@ -20,22 +20,22 @@ import static org.junit.Assert.fail; import org.junit.Test; - /** * @author Dave Syer */ public class TaskExecutorRepeatTemplateTests extends SimpleRepeatTemplateTests { - @Override + @Override public RepeatTemplate getRepeatTemplate() { return new TaskExecutorRepeatTemplate(); } - + @Test public void testSetThrottleLimit() throws Exception { try { new TaskExecutorRepeatTemplate().setThrottleLimit(-1); - } catch (Exception e) { + } + catch (Exception e) { // unexpected - no check for illegal values fail("Unexpected Exception setting throttle limit"); } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/ThrottleLimitResultQueueTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/ThrottleLimitResultQueueTests.java index ef45e3ed5..b1004b153 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/ThrottleLimitResultQueueTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/ThrottleLimitResultQueueTests.java @@ -24,15 +24,14 @@ import java.util.NoSuchElementException; import org.junit.Test; - /** * @author Dave Syer * */ public class ThrottleLimitResultQueueTests { - + private ThrottleLimitResultQueue queue = new ThrottleLimitResultQueue<>(1); - + @Test public void testPutTake() throws Exception { queue.expect(); @@ -50,7 +49,8 @@ public class ThrottleLimitResultQueueTests { try { queue.put("foo"); fail("Expected IllegalArgumentException"); - } catch (IllegalArgumentException e) { + } + catch (IllegalArgumentException e) { // expected } } @@ -61,7 +61,8 @@ public class ThrottleLimitResultQueueTests { try { queue.take(); fail("Expected NoSuchElementException"); - } catch (NoSuchElementException e) { + } + catch (NoSuchElementException e) { // expected } } @@ -70,7 +71,7 @@ public class ThrottleLimitResultQueueTests { public void testThrottleLimit() throws Exception { queue.expect(); new Thread(new Runnable() { - @Override + @Override public void run() { try { Thread.sleep(100L); @@ -87,7 +88,8 @@ public class ThrottleLimitResultQueueTests { long t1 = System.currentTimeMillis(); assertEquals("foo", queue.take()); assertTrue(queue.isExpecting()); - assertTrue("Did not block on expect (throttle limit should have been hit): time taken="+(t1-t0), t1-t0>50); + assertTrue("Did not block on expect (throttle limit should have been hit): time taken=" + (t1 - t0), + t1 - t0 > 50); } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/Trade.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/Trade.java index 1f8e8f0ba..c03919a52 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/Trade.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/support/Trade.java @@ -49,8 +49,9 @@ public class Trade { return quantity; } - @Override + @Override public String toString() { return "Trade: [isin=" + isin + ",quantity=" + quantity + ",price=" + price + "]"; } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/jms/ExternalRetryTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/jms/ExternalRetryTests.java index 74b441768..aa428679f 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/jms/ExternalRetryTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/jms/ExternalRetryTests.java @@ -65,7 +65,7 @@ public class ExternalRetryTests { @Before public void onSetUp() throws Exception { getMessages(); // drain queue - JdbcTestUtils.deleteFromTables(jdbcTemplate, "T_BARS"); + JdbcTestUtils.deleteFromTables(jdbcTemplate, "T_BARS"); jmsTemplate.convertAndSend("queue", "foo"); provider = new ItemReader() { @Nullable @@ -89,8 +89,8 @@ public class ExternalRetryTests { private List recovered = new ArrayList<>(); /* - * Message processing is successful on the second attempt but must receive - * the message again. + * Message processing is successful on the second attempt but must receive the message + * again. */ @Test public void testExternalRetrySuccessOnSecondAttempt() throws Exception { @@ -103,8 +103,7 @@ public class ExternalRetryTests { for (Object text : texts) { - jdbcTemplate.update("INSERT into T_BARS (id,name,foo_date) values (?,?,null)", list.size(), - text); + jdbcTemplate.update("INSERT into T_BARS (id,name,foo_date) values (?,?,null)", list.size(), text); if (list.size() == 1) { throw new RuntimeException("Rollback!"); } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/jms/SynchronousTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/jms/SynchronousTests.java index 67af4bab1..2d40b1f5f 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/jms/SynchronousTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/jms/SynchronousTests.java @@ -62,7 +62,7 @@ public class SynchronousTests { @BeforeTransaction public void onSetUpBeforeTransaction() throws Exception { - JdbcTestUtils.deleteFromTables(jdbcTemplate, "T_BARS"); + JdbcTestUtils.deleteFromTables(jdbcTemplate, "T_BARS"); jmsTemplate.convertAndSend("queue", "foo"); jmsTemplate.convertAndSend("queue", "foo"); final String text = (String) jmsTemplate.receiveAndConvert("queue"); @@ -82,7 +82,7 @@ public class SynchronousTests { foo = (String) jmsTemplate.receiveAndConvert("queue"); count++; } - JdbcTestUtils.deleteFromTables(jdbcTemplate, "T_BARS"); + JdbcTestUtils.deleteFromTables(jdbcTemplate, "T_BARS"); } private void assertInitialState() { @@ -93,21 +93,21 @@ public class SynchronousTests { List list = new ArrayList<>(); /* - * Message processing is successful on the second attempt without having to - * receive the message again. + * Message processing is successful on the second attempt without having to receive + * the message again. */ - @Transactional @Test + @Transactional + @Test public void testInternalRetrySuccessOnSecondAttempt() throws Exception { assertInitialState(); /* - * We either want the JMS receive to be outside a transaction, or we - * need the database transaction in the retry to be PROPAGATION_NESTED. - * Otherwise JMS will roll back when the retry callback is eventually - * successful because of the previous exception. - * PROPAGATION_REQUIRES_NEW is wrong because it doesn't allow the outer - * transaction to fail and rollback the inner one. + * We either want the JMS receive to be outside a transaction, or we need the + * database transaction in the retry to be PROPAGATION_NESTED. Otherwise JMS will + * roll back when the retry callback is eventually successful because of the + * previous exception. PROPAGATION_REQUIRES_NEW is wrong because it doesn't allow + * the outer transaction to fail and rollback the inner one. */ final String text = (String) jmsTemplate.receiveAndConvert("queue"); assertNotNull(text); @@ -124,7 +124,8 @@ public class SynchronousTests { list.add(text); System.err.println("Inserting: [" + list.size() + "," + text + "]"); - jdbcTemplate.update("INSERT into T_BARS (id,name,foo_date) values (?,?,null)", list.size(), text); + jdbcTemplate.update("INSERT into T_BARS (id,name,foo_date) values (?,?,null)", list.size(), + text); if (list.size() == 1) { throw new RuntimeException("Rollback!"); } @@ -149,10 +150,11 @@ public class SynchronousTests { } /* - * Message processing is successful on the second attempt without having to - * receive the message again - uses JmsItemProvider internally. + * Message processing is successful on the second attempt without having to receive + * the message again - uses JmsItemProvider internally. */ - @Transactional @Test + @Transactional + @Test public void testInternalRetrySuccessOnSecondAttemptWithItemProvider() throws Exception { assertInitialState(); @@ -176,7 +178,8 @@ public class SynchronousTests { list.add(item); System.err.println("Inserting: [" + list.size() + "," + item + "]"); - jdbcTemplate.update("INSERT into T_BARS (id,name,foo_date) values (?,?,null)", list.size(), item); + jdbcTemplate.update("INSERT into T_BARS (id,name,foo_date) values (?,?,null)", list.size(), + item); if (list.size() == 1) { throw new RuntimeException("Rollback!"); } @@ -202,21 +205,21 @@ public class SynchronousTests { } /* - * Message processing is successful on the second attempt without having to - * receive the message again. + * Message processing is successful on the second attempt without having to receive + * the message again. */ - @Transactional @Test + @Transactional + @Test public void testInternalRetrySuccessOnFirstAttemptRollbackOuter() throws Exception { assertInitialState(); /* - * We either want the JMS receive to be outside a transaction, or we - * need the database transaction in the retry to be PROPAGATION_NESTED. - * Otherwise JMS will roll back when the retry callback is eventually - * successful because of the previous exception. - * PROPAGATION_REQUIRES_NEW is wrong because it doesn't allow the outer - * transaction to fail and rollback the inner one. + * We either want the JMS receive to be outside a transaction, or we need the + * database transaction in the retry to be PROPAGATION_NESTED. Otherwise JMS will + * roll back when the retry callback is eventually successful because of the + * previous exception. PROPAGATION_REQUIRES_NEW is wrong because it doesn't allow + * the outer transaction to fail and rollback the inner one. */ TransactionTemplate outerTxTemplate = new TransactionTemplate(transactionManager); @@ -240,7 +243,8 @@ public class SynchronousTests { list.add(text); System.err.println("Inserting: [" + list.size() + "," + text + "]"); - jdbcTemplate.update("INSERT into T_BARS (id,name,foo_date) values (?,?,null)", list.size(), text); + jdbcTemplate.update("INSERT into T_BARS (id,name,foo_date) values (?,?,null)", + list.size(), text); return text; } @@ -248,7 +252,8 @@ public class SynchronousTests { } }); - } catch (Exception e) { + } + catch (Exception e) { throw new RuntimeException(e); } @@ -277,8 +282,8 @@ public class SynchronousTests { } /* - * Message processing is successful on the second attempt but must receive - * the message again. + * Message processing is successful on the second attempt but must receive the message + * again. */ @Test public void testExternalRetrySuccessOnSecondAttempt() throws Exception { @@ -289,7 +294,7 @@ public class SynchronousTests { @Override public String doWithRetry(RetryContext status) throws Exception { - // use REQUIRES_NEW so that the retry executes in its own transaction + // use REQUIRES_NEW so that the retry executes in its own transaction TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager); transactionTemplate.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRES_NEW); return transactionTemplate.execute(new TransactionCallback() { @@ -300,7 +305,8 @@ public class SynchronousTests { // transaction... final String text = (String) jmsTemplate.receiveAndConvert("queue"); list.add(text); - jdbcTemplate.update("INSERT into T_BARS (id,name,foo_date) values (?,?,null)", list.size(), text); + jdbcTemplate.update("INSERT into T_BARS (id,name,foo_date) values (?,?,null)", list.size(), + text); if (list.size() == 1) { throw new RuntimeException("Rollback!"); } @@ -328,7 +334,8 @@ public class SynchronousTests { /* * Message processing fails. */ - @Transactional @Test + @Transactional + @Test public void testExternalRetryFailOnSecondAttempt() throws Exception { assertInitialState(); @@ -339,7 +346,7 @@ public class SynchronousTests { @Override public String doWithRetry(RetryContext status) throws Exception { - // use REQUIRES_NEW so that the retry executes in its own transaction + // use REQUIRES_NEW so that the retry executes in its own transaction TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager); transactionTemplate.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRES_NEW); return transactionTemplate.execute(new TransactionCallback() { @@ -350,7 +357,8 @@ public class SynchronousTests { // transaction... final String text = (String) jmsTemplate.receiveAndConvert("queue"); list.add(text); - jdbcTemplate.update("INSERT into T_BARS (id,name,foo_date) values (?,?,null)", list.size(), text); + jdbcTemplate.update("INSERT into T_BARS (id,name,foo_date) values (?,?,null)", list.size(), + text); throw new RuntimeException("Rollback!"); } @@ -360,8 +368,8 @@ public class SynchronousTests { }); /* - * N.B. the message can be re-directed to an error queue by setting - * an error destination in a JmsItemProvider. + * N.B. the message can be re-directed to an error queue by setting an error + * destination in a JmsItemProvider. */ fail("Expected RuntimeException"); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/AnnotationMethodResolverTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/AnnotationMethodResolverTests.java index b9efef403..0aec1951b 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/AnnotationMethodResolverTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/AnnotationMethodResolverTests.java @@ -1,103 +1,103 @@ -/* - * Copyright 2002-2008 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.support; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.lang.reflect.Method; - -import org.junit.Test; -import org.springframework.batch.support.AnnotationMethodResolver; - -/** - * @author Mark Fisher - */ -public class AnnotationMethodResolverTests { - - @Test - public void singleAnnotation() { - AnnotationMethodResolver resolver = new AnnotationMethodResolver(TestAnnotation.class); - Method method = resolver.findMethod(SingleAnnotationTestBean.class); - assertNotNull(method); - } - - @Test(expected = IllegalArgumentException.class) - public void multipleAnnotations() { - AnnotationMethodResolver resolver = new AnnotationMethodResolver(TestAnnotation.class); - resolver.findMethod(MultipleAnnotationTestBean.class); - } - - @Test - public void noAnnotations() { - AnnotationMethodResolver resolver = new AnnotationMethodResolver(TestAnnotation.class); - Method method = resolver.findMethod(NoAnnotationTestBean.class); - assertNull(method); - } - - - @Target(ElementType.METHOD) - @Retention(RetentionPolicy.RUNTIME) - private static @interface TestAnnotation { - } - - - @SuppressWarnings("unused") - private static class SingleAnnotationTestBean { - - @TestAnnotation - public String upperCase(String s) { - return s.toUpperCase(); - } - - public String lowerCase(String s) { - return s.toLowerCase(); - } - } - - - private static class MultipleAnnotationTestBean { - - @TestAnnotation - public String upperCase(String s) { - return s.toUpperCase(); - } - - @TestAnnotation - public String lowerCase(String s) { - return s.toLowerCase(); - } - } - - - @SuppressWarnings("unused") - private static class NoAnnotationTestBean { - - public String upperCase(String s) { - return s.toUpperCase(); - } - - String lowerCase(String s) { - return s.toLowerCase(); - } - } - -} +/* + * Copyright 2002-2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.support; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.reflect.Method; + +import org.junit.Test; +import org.springframework.batch.support.AnnotationMethodResolver; + +/** + * @author Mark Fisher + */ +public class AnnotationMethodResolverTests { + + @Test + public void singleAnnotation() { + AnnotationMethodResolver resolver = new AnnotationMethodResolver(TestAnnotation.class); + Method method = resolver.findMethod(SingleAnnotationTestBean.class); + assertNotNull(method); + } + + @Test(expected = IllegalArgumentException.class) + public void multipleAnnotations() { + AnnotationMethodResolver resolver = new AnnotationMethodResolver(TestAnnotation.class); + resolver.findMethod(MultipleAnnotationTestBean.class); + } + + @Test + public void noAnnotations() { + AnnotationMethodResolver resolver = new AnnotationMethodResolver(TestAnnotation.class); + Method method = resolver.findMethod(NoAnnotationTestBean.class); + assertNull(method); + } + + @Target(ElementType.METHOD) + @Retention(RetentionPolicy.RUNTIME) + private static @interface TestAnnotation { + + } + + @SuppressWarnings("unused") + private static class SingleAnnotationTestBean { + + @TestAnnotation + public String upperCase(String s) { + return s.toUpperCase(); + } + + public String lowerCase(String s) { + return s.toLowerCase(); + } + + } + + private static class MultipleAnnotationTestBean { + + @TestAnnotation + public String upperCase(String s) { + return s.toUpperCase(); + } + + @TestAnnotation + public String lowerCase(String s) { + return s.toLowerCase(); + } + + } + + @SuppressWarnings("unused") + private static class NoAnnotationTestBean { + + public String upperCase(String s) { + return s.toUpperCase(); + } + + String lowerCase(String s) { + return s.toLowerCase(); + } + + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/DatabaseTypeIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/DatabaseTypeIntegrationTests.java index d21106b99..72c6c9806 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/DatabaseTypeIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/DatabaseTypeIntegrationTests.java @@ -1,47 +1,47 @@ -/* - * Copyright 2006-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.support; - -import org.junit.Test; - -import javax.sql.DataSource; - -import static org.junit.Assert.assertEquals; - -/** - * @author Dave Syer - * - */ -public class DatabaseTypeIntegrationTests { - - @Test - public void testH2() throws Exception { - DataSource dataSource = DatabaseTypeTestUtils.getDataSource(org.h2.Driver.class, - "jdbc:h2:file:./target/data/sample"); - assertEquals(DatabaseType.H2, DatabaseType.fromMetaData(dataSource)); - dataSource.getConnection(); - } - - @Test - public void testDerby() throws Exception { - DataSource dataSource = DatabaseTypeTestUtils.getDataSource(org.apache.derby.jdbc.EmbeddedDriver.class, - "jdbc:derby:./target/derby-home/test;create=true", "sa", ""); - assertEquals(DatabaseType.DERBY, DatabaseType.fromMetaData(dataSource)); - dataSource.getConnection(); - } - -} +/* + * Copyright 2006-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.support; + +import org.junit.Test; + +import javax.sql.DataSource; + +import static org.junit.Assert.assertEquals; + +/** + * @author Dave Syer + * + */ +public class DatabaseTypeIntegrationTests { + + @Test + public void testH2() throws Exception { + DataSource dataSource = DatabaseTypeTestUtils.getDataSource(org.h2.Driver.class, + "jdbc:h2:file:./target/data/sample"); + assertEquals(DatabaseType.H2, DatabaseType.fromMetaData(dataSource)); + dataSource.getConnection(); + } + + @Test + public void testDerby() throws Exception { + DataSource dataSource = DatabaseTypeTestUtils.getDataSource(org.apache.derby.jdbc.EmbeddedDriver.class, + "jdbc:derby:./target/derby-home/test;create=true", "sa", ""); + assertEquals(DatabaseType.DERBY, DatabaseType.fromMetaData(dataSource)); + dataSource.getConnection(); + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/DatabaseTypeTestUtils.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/DatabaseTypeTestUtils.java index c78e7915d..f58592b41 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/DatabaseTypeTestUtils.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/DatabaseTypeTestUtils.java @@ -1,74 +1,75 @@ -/* - * Copyright 2006-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.support; - -import java.sql.Connection; -import java.sql.DatabaseMetaData; -import javax.sql.DataSource; - -import org.apache.commons.dbcp2.BasicDataSource; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -/** - * @author Dave Syer - * @author Will Schipp - * - */ -public class DatabaseTypeTestUtils { - - public static DataSource getDataSource(Class driver, String url, String username, String password) throws Exception { - BasicDataSource dataSource = new BasicDataSource(); - dataSource.setDriverClassName(driver.getName()); - dataSource.setUrl(url); - dataSource.setUsername(username); - dataSource.setPassword(password); - return dataSource; - } - - public static DataSource getDataSource(Class driver, String url) throws Exception { - return getDataSource(driver, url, null, null); - } - - public static DataSource getMockDataSource() throws Exception { - return getMockDataSource(DatabaseType.HSQL.getProductName()); - } - - public static DataSource getMockDataSource(String databaseProductName) throws Exception { - return getMockDataSource(databaseProductName, null); - } - - public static DataSource getMockDataSource(String databaseProductName, String databaseVersion) throws Exception { - DatabaseMetaData dmd = mock(DatabaseMetaData.class); - DataSource ds = mock(DataSource.class); - Connection con = mock(Connection.class); - when(ds.getConnection()).thenReturn(con); - when(con.getMetaData()).thenReturn(dmd); - when(dmd.getDatabaseProductName()).thenReturn(databaseProductName); - if (databaseVersion!=null) { - when(dmd.getDatabaseProductVersion()).thenReturn(databaseVersion); - } - return ds; - } - - public static DataSource getMockDataSource(Exception e) throws Exception { - DataSource ds = mock(DataSource.class); - when(ds.getConnection()).thenReturn(null); - return ds; - } - -} +/* + * Copyright 2006-2017 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.support; + +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import javax.sql.DataSource; + +import org.apache.commons.dbcp2.BasicDataSource; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * @author Dave Syer + * @author Will Schipp + * + */ +public class DatabaseTypeTestUtils { + + public static DataSource getDataSource(Class driver, String url, String username, String password) + throws Exception { + BasicDataSource dataSource = new BasicDataSource(); + dataSource.setDriverClassName(driver.getName()); + dataSource.setUrl(url); + dataSource.setUsername(username); + dataSource.setPassword(password); + return dataSource; + } + + public static DataSource getDataSource(Class driver, String url) throws Exception { + return getDataSource(driver, url, null, null); + } + + public static DataSource getMockDataSource() throws Exception { + return getMockDataSource(DatabaseType.HSQL.getProductName()); + } + + public static DataSource getMockDataSource(String databaseProductName) throws Exception { + return getMockDataSource(databaseProductName, null); + } + + public static DataSource getMockDataSource(String databaseProductName, String databaseVersion) throws Exception { + DatabaseMetaData dmd = mock(DatabaseMetaData.class); + DataSource ds = mock(DataSource.class); + Connection con = mock(Connection.class); + when(ds.getConnection()).thenReturn(con); + when(con.getMetaData()).thenReturn(dmd); + when(dmd.getDatabaseProductName()).thenReturn(databaseProductName); + if (databaseVersion != null) { + when(dmd.getDatabaseProductVersion()).thenReturn(databaseVersion); + } + return ds; + } + + public static DataSource getMockDataSource(Exception e) throws Exception { + DataSource ds = mock(DataSource.class); + when(ds.getConnection()).thenReturn(null); + return ds; + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/DatabaseTypeTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/DatabaseTypeTests.java index ad563a434..3509aab30 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/DatabaseTypeTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/DatabaseTypeTests.java @@ -37,10 +37,9 @@ import static org.springframework.batch.support.DatabaseType.HANA; import static org.springframework.batch.support.DatabaseType.fromProductName; /** - * * @author Lucas Ward * @author Will Schipp - * + * */ public class DatabaseTypeTests { @@ -144,14 +143,14 @@ public class DatabaseTypeTests { DataSource ds = DatabaseTypeTestUtils.getMockDataSource("Adaptive Server Enterprise"); assertEquals(SYBASE, DatabaseType.fromMetaData(ds)); } - + @Test public void testFromMetaDataForHana() throws Exception { DataSource ds = DatabaseTypeTestUtils.getMockDataSource("HDB"); assertEquals(HANA, DatabaseType.fromMetaData(ds)); } - @Test(expected=MetaDataAccessException.class) + @Test(expected = MetaDataAccessException.class) public void testBadMetaData() throws Exception { DataSource ds = DatabaseTypeTestUtils.getMockDataSource(new MetaDataAccessException("Bad!")); assertEquals(SYBASE, DatabaseType.fromMetaData(ds)); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/DefaultPropertyEditorRegistrarTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/DefaultPropertyEditorRegistrarTests.java index 29420a88c..83c1d89b4 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/DefaultPropertyEditorRegistrarTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/DefaultPropertyEditorRegistrarTests.java @@ -72,11 +72,11 @@ public class DefaultPropertyEditorRegistrarTests { @SuppressWarnings("unused") private static class BeanWithIntArray { + private int[] numbers; private long number; - public void setNumbers(int[] numbers) { this.numbers = numbers; } @@ -84,6 +84,7 @@ public class DefaultPropertyEditorRegistrarTests { public void setNumber(long number) { this.number = number; } + } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/LastModifiedResourceComparatorTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/LastModifiedResourceComparatorTests.java index e08c1c1b1..91d15e7f3 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/LastModifiedResourceComparatorTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/LastModifiedResourceComparatorTests.java @@ -1,61 +1,61 @@ -/* - * Copyright 2006-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.support; - -import org.junit.Test; -import org.springframework.core.io.FileSystemResource; - -import java.io.File; -import java.io.IOException; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -/** - * @author Dave Syer - * @author Mahmoud Ben Hassine - * - */ -public class LastModifiedResourceComparatorTests { - - public static final String FILE_PATH = "src/test/resources/org/springframework/batch/support/existing.txt"; - - private LastModifiedResourceComparator comparator = new LastModifiedResourceComparator(); - - @Test(expected = IllegalArgumentException.class) - public void testCompareTwoNonExistent() { - comparator.compare(new FileSystemResource("garbage"), new FileSystemResource("crap")); - } - - @Test(expected = IllegalArgumentException.class) - public void testCompareOneNonExistent() { - comparator.compare(new FileSystemResource(FILE_PATH), new FileSystemResource("crap")); - } - - @Test - public void testCompareSame() { - assertEquals(0, comparator.compare(new FileSystemResource(FILE_PATH), new FileSystemResource(FILE_PATH))); - } - - @Test - public void testCompareNewWithOld() throws IOException { - File temp = File.createTempFile(getClass().getSimpleName(), ".txt"); - temp.deleteOnExit(); - assertTrue(temp.exists()); - assertEquals(1, comparator.compare(new FileSystemResource(temp), new FileSystemResource(FILE_PATH))); - } - -} +/* + * Copyright 2006-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.support; + +import org.junit.Test; +import org.springframework.core.io.FileSystemResource; + +import java.io.File; +import java.io.IOException; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * @author Dave Syer + * @author Mahmoud Ben Hassine + * + */ +public class LastModifiedResourceComparatorTests { + + public static final String FILE_PATH = "src/test/resources/org/springframework/batch/support/existing.txt"; + + private LastModifiedResourceComparator comparator = new LastModifiedResourceComparator(); + + @Test(expected = IllegalArgumentException.class) + public void testCompareTwoNonExistent() { + comparator.compare(new FileSystemResource("garbage"), new FileSystemResource("crap")); + } + + @Test(expected = IllegalArgumentException.class) + public void testCompareOneNonExistent() { + comparator.compare(new FileSystemResource(FILE_PATH), new FileSystemResource("crap")); + } + + @Test + public void testCompareSame() { + assertEquals(0, comparator.compare(new FileSystemResource(FILE_PATH), new FileSystemResource(FILE_PATH))); + } + + @Test + public void testCompareNewWithOld() throws IOException { + File temp = File.createTempFile(getClass().getSimpleName(), ".txt"); + temp.deleteOnExit(); + assertTrue(temp.exists()); + assertEquals(1, comparator.compare(new FileSystemResource(temp), new FileSystemResource(FILE_PATH))); + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/PatternMatcherTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/PatternMatcherTests.java index f6fc338d1..b7e31c927 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/PatternMatcherTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/PatternMatcherTests.java @@ -135,4 +135,5 @@ public class PatternMatcherTests { public void testMatchPrefixDefaultValueNoMatch() { assertEquals(1, new PatternMatcher<>(defaultMap).match("bat").intValue()); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/PropertiesConverterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/PropertiesConverterTests.java index ecd638cbb..60967946d 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/PropertiesConverterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/PropertiesConverterTests.java @@ -27,42 +27,43 @@ import org.springframework.util.StringUtils; /** * Unit tests for {@link PropertiesConverter} - * + * * @author Robert Kasanicky */ public class PropertiesConverterTests { - - //convenience attributes for storing results of conversions + + // convenience attributes for storing results of conversions private Properties props = null; + private String string = null; - + /** * Check that Properties can be converted to String and back correctly. */ @Test public void testTwoWayRegularConversion() { - + Properties storedProps = new Properties(); storedProps.setProperty("key1", "value1"); storedProps.setProperty("key2", "value2"); - + props = PropertiesConverter.stringToProperties(PropertiesConverter.propertiesToString(storedProps)); - + assertEquals(storedProps, props); } - + /** * Check that Properties can be comma delimited. */ @Test public void testRegularConversionWithComma() { - + Properties storedProps = new Properties(); storedProps.setProperty("key1", "value1"); storedProps.setProperty("key2", "value2"); - + props = PropertiesConverter.stringToProperties("key1=value1,key2=value2"); - + assertEquals(storedProps, props); } @@ -71,13 +72,13 @@ public class PropertiesConverterTests { */ @Test public void testRegularConversionWithCommaAndWhitespace() { - + Properties storedProps = new Properties(); storedProps.setProperty("key1", "value1"); storedProps.setProperty("key2", "value2"); - + props = PropertiesConverter.stringToProperties("key1=value1, key2=value2"); - + assertEquals(storedProps, props); } @@ -86,15 +87,15 @@ public class PropertiesConverterTests { */ @Test public void testShortConversionWithCommas() { - + Properties storedProps = new Properties(); storedProps.setProperty("key1", "value1"); storedProps.setProperty("key2", "value2"); - + String value = PropertiesConverter.propertiesToString(storedProps); - - assertTrue("Wrong value: "+value, value.contains("key1=value1")); - assertTrue("Wrong value: "+value, value.contains("key2=value2")); + + assertTrue("Wrong value: " + value, value.contains("key1=value1")); + assertTrue("Wrong value: " + value, value.contains("key2=value2")); assertEquals(1, StringUtils.countOccurrencesOf(value, ",")); } @@ -103,13 +104,13 @@ public class PropertiesConverterTests { */ @Test public void testRegularConversionWithCommaAndNewline() { - + Properties storedProps = new Properties(); storedProps.setProperty("key1", "value1"); storedProps.setProperty("key2", "value2"); - + props = PropertiesConverter.stringToProperties("key1=value1\n key2=value2"); - + assertEquals(storedProps, props); } @@ -122,7 +123,7 @@ public class PropertiesConverterTests { assertNotNull(props); assertEquals("properties are empty", 0, props.size()); } - + /** * Null or empty properties should be converted to empty String */ @@ -130,11 +131,11 @@ public class PropertiesConverterTests { public void testPropertiesToStringNull() { string = PropertiesConverter.propertiesToString(null); assertEquals("", string); - + string = PropertiesConverter.propertiesToString(new Properties()); assertEquals("", string); } - + @Test public void testEscapedColon() throws Exception { Properties props = new Properties(); @@ -143,5 +144,5 @@ public class PropertiesConverterTests { props = PropertiesConverter.stringToProperties(str); assertEquals("C:/test", props.getProperty("test")); } - + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/ReflectionUtilsTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/ReflectionUtilsTests.java index 89e84db62..23ac7e605 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/ReflectionUtilsTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/ReflectionUtilsTests.java @@ -57,17 +57,19 @@ public class ReflectionUtilsTests { String name = iterator.next().getName(); - if(name.equals("toString")) { + if (name.equals("toString")) { toStringFound = true; - } else if(name.equals("methodOne")) { + } + else if (name.equals("methodOne")) { methodOneFound = true; } name = iterator.next().getName(); - if(name.equals("toString")) { + if (name.equals("toString")) { toStringFound = true; - } else if(name.equals("methodOne")) { + } + else if (name.equals("methodOne")) { methodOneFound = true; } @@ -84,6 +86,7 @@ public class ReflectionUtilsTests { public String toString() { return "AnnotatedClass"; } + } public static class AnnotatedSubClass extends AnnotatedClass { @@ -92,5 +95,7 @@ public class ReflectionUtilsTests { public void methodOne() { System.err.println("This is method 1 in the sub class"); } + } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/SimpleMethodInvokerTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/SimpleMethodInvokerTests.java index f29878474..411c90214 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/SimpleMethodInvokerTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/SimpleMethodInvokerTests.java @@ -49,97 +49,102 @@ import static org.junit.Assert.assertTrue; public class SimpleMethodInvokerTests { TestClass testClass; + String value = "foo"; + @Before - public void setUp(){ + public void setUp() { testClass = new TestClass(); } - + @Test - public void testMethod() throws Exception{ - + public void testMethod() throws Exception { + Method method = TestClass.class.getMethod("before"); MethodInvoker methodInvoker = new SimpleMethodInvoker(testClass, method); methodInvoker.invokeMethod(value); assertTrue(testClass.beforeCalled); } - + @Test - public void testMethodByName() throws Exception{ - + public void testMethodByName() throws Exception { + MethodInvoker methodInvoker = new SimpleMethodInvoker(testClass, "before", String.class); methodInvoker.invokeMethod(value); assertTrue(testClass.beforeCalled); } - + @Test - public void testMethodWithExecution() throws Exception{ + public void testMethodWithExecution() throws Exception { Method method = TestClass.class.getMethod("beforeWithArgument", String.class); MethodInvoker methodInvoker = new SimpleMethodInvoker(testClass, method); methodInvoker.invokeMethod(value); assertTrue(testClass.beforeCalled); } - + @Test - public void testMethodByNameWithExecution() throws Exception{ + public void testMethodByNameWithExecution() throws Exception { MethodInvoker methodInvoker = new SimpleMethodInvoker(testClass, "beforeWithArgument", String.class); methodInvoker.invokeMethod(value); assertTrue(testClass.beforeCalled); } - - @Test(expected=IllegalArgumentException.class) - public void testMethodWithTooManyArguments() throws Exception{ + + @Test(expected = IllegalArgumentException.class) + public void testMethodWithTooManyArguments() throws Exception { Method method = TestClass.class.getMethod("beforeWithTooManyArguments", String.class, int.class); MethodInvoker methodInvoker = new SimpleMethodInvoker(testClass, method); methodInvoker.invokeMethod(value); assertFalse(testClass.beforeCalled); } - - @Test(expected=IllegalArgumentException.class) - public void testMethodByNameWithTooManyArguments() throws Exception{ + + @Test(expected = IllegalArgumentException.class) + public void testMethodByNameWithTooManyArguments() throws Exception { MethodInvoker methodInvoker = new SimpleMethodInvoker(testClass, "beforeWithTooManyArguments", String.class); methodInvoker.invokeMethod(value); assertFalse(testClass.beforeCalled); } - + @Test - public void testMethodWithArgument() throws Exception{ + public void testMethodWithArgument() throws Exception { MethodInvoker methodInvoker = new SimpleMethodInvoker(testClass, "argumentTest", Object.class); methodInvoker.invokeMethod(new Object()); assertTrue(testClass.argumentTestCalled); } - + @Test - public void testEquals() throws Exception{ + public void testEquals() throws Exception { Method method = TestClass.class.getMethod("beforeWithArgument", String.class); MethodInvoker methodInvoker = new SimpleMethodInvoker(testClass, method); - + method = TestClass.class.getMethod("beforeWithArgument", String.class); MethodInvoker methodInvoker2 = new SimpleMethodInvoker(testClass, method); assertEquals(methodInvoker, methodInvoker2); } - + @SuppressWarnings("unused") - private class TestClass{ - + private class TestClass { + boolean beforeCalled = false; + boolean argumentTestCalled = false; - - public void before(){ + + public void before() { beforeCalled = true; } - - public void beforeWithArgument(String value){ + + public void beforeWithArgument(String value) { beforeCalled = true; } - - public void beforeWithTooManyArguments(String value, int someInt){ + + public void beforeWithTooManyArguments(String value, int someInt) { beforeCalled = true; } - - public void argumentTest(Object object){ + + public void argumentTest(Object object) { Assert.notNull(object, "Object must not be null"); argumentTestCalled = true; } + } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/SystemPropertyInitializerTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/SystemPropertyInitializerTests.java index 2a0c2cd23..29f5c57da 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/SystemPropertyInitializerTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/SystemPropertyInitializerTests.java @@ -1,60 +1,61 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.support; - -import static org.junit.Assert.assertEquals; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -/** - * @author Dave Syer - * - */ -public class SystemPropertyInitializerTests { - - private static final String SIMPLE_NAME = SystemPropertyInitializerTests.class.getSimpleName(); - private SystemPropertyInitializer initializer = new SystemPropertyInitializer(); - - @Before - @After - public void initializeProperty() { - System.clearProperty(SystemPropertyInitializer.ENVIRONMENT); - System.clearProperty(SIMPLE_NAME); - } - - @Test - public void testSetKeyName() throws Exception { - initializer.setKeyName(SIMPLE_NAME); - System.setProperty(SIMPLE_NAME, "foo"); - initializer.afterPropertiesSet(); - assertEquals("foo", System.getProperty(SIMPLE_NAME)); - } - - @Test - public void testSetDefaultValue() throws Exception { - initializer.setDefaultValue("foo"); - initializer.afterPropertiesSet(); - assertEquals("foo", System.getProperty(SystemPropertyInitializer.ENVIRONMENT)); - } - - @Test(expected=IllegalStateException.class) - public void testNoDefaultValue() throws Exception { - initializer.afterPropertiesSet(); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.support; + +import static org.junit.Assert.assertEquals; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +/** + * @author Dave Syer + * + */ +public class SystemPropertyInitializerTests { + + private static final String SIMPLE_NAME = SystemPropertyInitializerTests.class.getSimpleName(); + + private SystemPropertyInitializer initializer = new SystemPropertyInitializer(); + + @Before + @After + public void initializeProperty() { + System.clearProperty(SystemPropertyInitializer.ENVIRONMENT); + System.clearProperty(SIMPLE_NAME); + } + + @Test + public void testSetKeyName() throws Exception { + initializer.setKeyName(SIMPLE_NAME); + System.setProperty(SIMPLE_NAME, "foo"); + initializer.afterPropertiesSet(); + assertEquals("foo", System.getProperty(SIMPLE_NAME)); + } + + @Test + public void testSetDefaultValue() throws Exception { + initializer.setDefaultValue("foo"); + initializer.afterPropertiesSet(); + assertEquals("foo", System.getProperty(SystemPropertyInitializer.ENVIRONMENT)); + } + + @Test(expected = IllegalStateException.class) + public void testNoDefaultValue() throws Exception { + initializer.afterPropertiesSet(); + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/transaction/ConcurrentTransactionAwareProxyTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/transaction/ConcurrentTransactionAwareProxyTests.java index f18a65907..552425cbe 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/transaction/ConcurrentTransactionAwareProxyTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/transaction/ConcurrentTransactionAwareProxyTests.java @@ -1,268 +1,268 @@ -/* - * Copyright 2006-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.support.transaction; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.Callable; -import java.util.concurrent.CompletionService; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorCompletionService; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.junit.After; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.springframework.transaction.PlatformTransactionManager; -import org.springframework.transaction.TransactionStatus; -import org.springframework.transaction.support.TransactionCallback; -import org.springframework.transaction.support.TransactionTemplate; -import org.springframework.util.Assert; - -/** - * @author Dave Syer - * @author Mahmoud Ben Hassine - * - */ -@Ignore // FIXME https://github.com/spring-projects/spring-batch/issues/3847 -public class ConcurrentTransactionAwareProxyTests { - - private static Log logger = LogFactory.getLog(ConcurrentTransactionAwareProxyTests.class); - - private PlatformTransactionManager transactionManager = new ResourcelessTransactionManager(); - - int outerMax = 20; - - int innerMax = 30; - - private ExecutorService executor; - - private CompletionService> completionService; - - @Before - public void init() { - executor = Executors.newFixedThreadPool(outerMax); - completionService = new ExecutorCompletionService<>(executor); - } - - @After - public void close() { - executor.shutdown(); - } - - @Test(expected = Throwable.class) - public void testConcurrentTransactionalSet() throws Exception { - Set set = TransactionAwareProxyFactory.createTransactionalSet(); - testSet(set); - } - - @Test - public void testConcurrentTransactionalAppendOnlySet() throws Exception { - Set set = TransactionAwareProxyFactory.createAppendOnlyTransactionalSet(); - testSet(set); - } - - @Test - public void testConcurrentTransactionalAppendOnlyList() throws Exception { - List list = TransactionAwareProxyFactory.createAppendOnlyTransactionalList(); - testList(list, false); - } - - @Test - public void testConcurrentTransactionalAppendOnlyMap() throws Exception { - Map> map = TransactionAwareProxyFactory.createAppendOnlyTransactionalMap(); - testMap(map); - } - - @Test(expected = ExecutionException.class) - public void testConcurrentTransactionalMap() throws Exception { - Map> map = TransactionAwareProxyFactory.createTransactionalMap(); - testMap(map); - } - - @Test - public void testTransactionalContains() throws Exception { - final Map> map = TransactionAwareProxyFactory.createAppendOnlyTransactionalMap(); - boolean result = new TransactionTemplate(transactionManager).execute(new TransactionCallback() { - @Override - public Boolean doInTransaction(TransactionStatus status) { - return map.containsKey("foo"); - } - }); - assertFalse(result); - } - - private void testSet(final Set set) throws Exception { - - for (int i = 0; i < outerMax; i++) { - - final int count = i; - completionService.submit(new Callable>() { - @Override - public List call() throws Exception { - List list = new ArrayList<>(); - for (int i = 0; i < innerMax; i++) { - String value = count + "bar" + i; - saveInSetAndAssert(set, value); - list.add(value); - } - return list; - } - }); - - } - - for (int i = 0; i < outerMax; i++) { - List result = completionService.take().get(); - assertEquals(innerMax, result.size()); - } - - assertEquals(innerMax * outerMax, set.size()); - - } - - private void testList(final List list, final boolean mutate) throws Exception { - - for (int i = 0; i < outerMax; i++) { - - completionService.submit(new Callable>() { - @Override - public List call() throws Exception { - List result = new ArrayList<>(); - for (int i = 0; i < innerMax; i++) { - String value = "bar" + i; - saveInListAndAssert(list, value); - result.add(value); - // Need to slow it down to allow threads to interleave - Thread.sleep(10L); - if (mutate) { - list.remove(value); - list.add(value); - } - } - logger.info("Added: " + innerMax + " values"); - return result; - } - }); - - } - - for (int i = 0; i < outerMax; i++) { - List result = completionService.take().get(); - assertEquals("Wrong number of results in inner task", innerMax, result.size()); - } - - assertEquals("Wrong number of results in aggregate", innerMax * outerMax, list.size()); - - } - - private void testMap(final Map> map) throws Exception { - - int numberOfKeys = outerMax; - - for (int i = 0; i < outerMax; i++) { - - for (int j = 0; j < numberOfKeys; j++) { - final long id = j * 1000 + 123L + i; - - completionService.submit(new Callable>() { - @Override - public List call() throws Exception { - List list = new ArrayList<>(); - for (int i = 0; i < innerMax; i++) { - String value = "bar" + i; - list.add(saveInMapAndAssert(map, id, value).get("foo")); - } - return list; - } - }); - } - - for (int j = 0; j < numberOfKeys; j++) { - completionService.take().get(); - } - - } - - } - - private String saveInSetAndAssert(final Set set, final String value) { - - new TransactionTemplate(transactionManager).execute(new TransactionCallback() { - @Override - public Void doInTransaction(TransactionStatus status) { - set.add(value); - return null; - } - }); - - Assert.state(set.contains(value), "Lost update: value=" + value); - - return value; - - } - - private String saveInListAndAssert(final List list, final String value) { - - new TransactionTemplate(transactionManager).execute(new TransactionCallback() { - @Override - public Void doInTransaction(TransactionStatus status) { - list.add(value); - return null; - } - }); - - Assert.state(list.contains(value), "Lost update: value=" + value); - - return value; - - } - - private Map saveInMapAndAssert(final Map> map, final Long id, - final String value) { - - new TransactionTemplate(transactionManager).execute(new TransactionCallback() { - @Override - public Void doInTransaction(TransactionStatus status) { - if (!map.containsKey(id)) { - map.put(id, new HashMap<>()); - } - map.get(id).put("foo", value); - return null; - } - }); - - Map result = map.get(id); - Assert.state(result != null, "Lost insert: null String at value=" + value); - String foo = result.get("foo"); - Assert.state(value.equals(foo), "Lost update: wrong value=" + value + " (found " + foo + ") for id=" + id); - - return result; - - } - -} +/* + * Copyright 2006-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.support.transaction; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.CompletionService; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorCompletionService; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.After; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.TransactionStatus; +import org.springframework.transaction.support.TransactionCallback; +import org.springframework.transaction.support.TransactionTemplate; +import org.springframework.util.Assert; + +/** + * @author Dave Syer + * @author Mahmoud Ben Hassine + * + */ +@Ignore // FIXME https://github.com/spring-projects/spring-batch/issues/3847 +public class ConcurrentTransactionAwareProxyTests { + + private static Log logger = LogFactory.getLog(ConcurrentTransactionAwareProxyTests.class); + + private PlatformTransactionManager transactionManager = new ResourcelessTransactionManager(); + + int outerMax = 20; + + int innerMax = 30; + + private ExecutorService executor; + + private CompletionService> completionService; + + @Before + public void init() { + executor = Executors.newFixedThreadPool(outerMax); + completionService = new ExecutorCompletionService<>(executor); + } + + @After + public void close() { + executor.shutdown(); + } + + @Test(expected = Throwable.class) + public void testConcurrentTransactionalSet() throws Exception { + Set set = TransactionAwareProxyFactory.createTransactionalSet(); + testSet(set); + } + + @Test + public void testConcurrentTransactionalAppendOnlySet() throws Exception { + Set set = TransactionAwareProxyFactory.createAppendOnlyTransactionalSet(); + testSet(set); + } + + @Test + public void testConcurrentTransactionalAppendOnlyList() throws Exception { + List list = TransactionAwareProxyFactory.createAppendOnlyTransactionalList(); + testList(list, false); + } + + @Test + public void testConcurrentTransactionalAppendOnlyMap() throws Exception { + Map> map = TransactionAwareProxyFactory.createAppendOnlyTransactionalMap(); + testMap(map); + } + + @Test(expected = ExecutionException.class) + public void testConcurrentTransactionalMap() throws Exception { + Map> map = TransactionAwareProxyFactory.createTransactionalMap(); + testMap(map); + } + + @Test + public void testTransactionalContains() throws Exception { + final Map> map = TransactionAwareProxyFactory.createAppendOnlyTransactionalMap(); + boolean result = new TransactionTemplate(transactionManager).execute(new TransactionCallback() { + @Override + public Boolean doInTransaction(TransactionStatus status) { + return map.containsKey("foo"); + } + }); + assertFalse(result); + } + + private void testSet(final Set set) throws Exception { + + for (int i = 0; i < outerMax; i++) { + + final int count = i; + completionService.submit(new Callable>() { + @Override + public List call() throws Exception { + List list = new ArrayList<>(); + for (int i = 0; i < innerMax; i++) { + String value = count + "bar" + i; + saveInSetAndAssert(set, value); + list.add(value); + } + return list; + } + }); + + } + + for (int i = 0; i < outerMax; i++) { + List result = completionService.take().get(); + assertEquals(innerMax, result.size()); + } + + assertEquals(innerMax * outerMax, set.size()); + + } + + private void testList(final List list, final boolean mutate) throws Exception { + + for (int i = 0; i < outerMax; i++) { + + completionService.submit(new Callable>() { + @Override + public List call() throws Exception { + List result = new ArrayList<>(); + for (int i = 0; i < innerMax; i++) { + String value = "bar" + i; + saveInListAndAssert(list, value); + result.add(value); + // Need to slow it down to allow threads to interleave + Thread.sleep(10L); + if (mutate) { + list.remove(value); + list.add(value); + } + } + logger.info("Added: " + innerMax + " values"); + return result; + } + }); + + } + + for (int i = 0; i < outerMax; i++) { + List result = completionService.take().get(); + assertEquals("Wrong number of results in inner task", innerMax, result.size()); + } + + assertEquals("Wrong number of results in aggregate", innerMax * outerMax, list.size()); + + } + + private void testMap(final Map> map) throws Exception { + + int numberOfKeys = outerMax; + + for (int i = 0; i < outerMax; i++) { + + for (int j = 0; j < numberOfKeys; j++) { + final long id = j * 1000 + 123L + i; + + completionService.submit(new Callable>() { + @Override + public List call() throws Exception { + List list = new ArrayList<>(); + for (int i = 0; i < innerMax; i++) { + String value = "bar" + i; + list.add(saveInMapAndAssert(map, id, value).get("foo")); + } + return list; + } + }); + } + + for (int j = 0; j < numberOfKeys; j++) { + completionService.take().get(); + } + + } + + } + + private String saveInSetAndAssert(final Set set, final String value) { + + new TransactionTemplate(transactionManager).execute(new TransactionCallback() { + @Override + public Void doInTransaction(TransactionStatus status) { + set.add(value); + return null; + } + }); + + Assert.state(set.contains(value), "Lost update: value=" + value); + + return value; + + } + + private String saveInListAndAssert(final List list, final String value) { + + new TransactionTemplate(transactionManager).execute(new TransactionCallback() { + @Override + public Void doInTransaction(TransactionStatus status) { + list.add(value); + return null; + } + }); + + Assert.state(list.contains(value), "Lost update: value=" + value); + + return value; + + } + + private Map saveInMapAndAssert(final Map> map, final Long id, + final String value) { + + new TransactionTemplate(transactionManager).execute(new TransactionCallback() { + @Override + public Void doInTransaction(TransactionStatus status) { + if (!map.containsKey(id)) { + map.put(id, new HashMap<>()); + } + map.get(id).put("foo", value); + return null; + } + }); + + Map result = map.get(id); + Assert.state(result != null, "Lost insert: null String at value=" + value); + String foo = result.get("foo"); + Assert.state(value.equals(foo), "Lost update: wrong value=" + value + " (found " + foo + ") for id=" + id); + + return result; + + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/transaction/ResourcelessTransactionManagerTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/transaction/ResourcelessTransactionManagerTests.java index 0f58a83fa..3d41b7c44 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/transaction/ResourcelessTransactionManagerTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/transaction/ResourcelessTransactionManagerTests.java @@ -29,7 +29,7 @@ public class ResourcelessTransactionManagerTests { private ResourcelessTransactionManager transactionManager = new ResourcelessTransactionManager(); private int txStatus = Integer.MIN_VALUE; - + private int count = 0; @Test @@ -115,13 +115,13 @@ public class ResourcelessTransactionManagerTests { public void testRollback() { try { new TransactionTemplate(transactionManager).execute(status -> { - TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { - @Override - public void afterCompletion(int status) { - txStatus = status; - } - }); - throw new RuntimeException("Rollback!"); + TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { + @Override + public void afterCompletion(int status) { + txStatus = status; + } + }); + throw new RuntimeException("Rollback!"); }); fail("Expected RuntimeException"); } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/transaction/TransactionAwareBufferedWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/transaction/TransactionAwareBufferedWriterTests.java index 638d6d68c..94786b6db 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/transaction/TransactionAwareBufferedWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/transaction/TransactionAwareBufferedWriterTests.java @@ -41,7 +41,7 @@ import static org.mockito.Mockito.when; * @author Michael Minella * @author Will Schipp * @author Niels Ferguson - * + * */ public class TransactionAwareBufferedWriterTests { @@ -120,7 +120,8 @@ public class TransactionAwareBufferedWriterTests { public void testCloseOutsideTransaction() throws Exception { ArgumentCaptor byteBufferCaptor = ArgumentCaptor.forClass(ByteBuffer.class); - when(fileChannel.write(byteBufferCaptor.capture())).thenAnswer(invocation -> ((ByteBuffer) invocation.getArguments()[0]).remaining()); + when(fileChannel.write(byteBufferCaptor.capture())) + .thenAnswer(invocation -> ((ByteBuffer) invocation.getArguments()[0]).remaining()); writer.write("foo"); writer.close(); @@ -293,37 +294,39 @@ public class TransactionAwareBufferedWriterTests { }); fail("Exception was not thrown"); - } catch (FlushFailedException ffe) { + } + catch (FlushFailedException ffe) { assertEquals("Could not write to output buffer", ffe.getMessage()); } } - + // BATCH-2018 @Test public void testResourceKeyCollision() throws Exception { final int limit = 5000; final TransactionAwareBufferedWriter[] writers = new TransactionAwareBufferedWriter[limit]; final String[] results = new String[limit]; - for(int i = 0; i< limit; i++) { + for (int i = 0; i < limit; i++) { final int index = i; @SuppressWarnings("resource") FileChannel fileChannel = mock(FileChannel.class); when(fileChannel.write(any(ByteBuffer.class))).thenAnswer(invocation -> { ByteBuffer buffer = (ByteBuffer) invocation.getArguments()[0]; String val = new String(buffer.array(), "UTF-8"); - if(results[index] == null) { + if (results[index] == null) { results[index] = val; - } else { + } + else { results[index] += val; } return buffer.limit(); }); writers[i] = new TransactionAwareBufferedWriter(fileChannel, null); } - + new TransactionTemplate(transactionManager).execute((TransactionCallback) status -> { try { - for(int i=0; i< limit; i++) { + for (int i = 0; i < limit; i++) { writers[i].write(String.valueOf(i)); } } @@ -332,15 +335,15 @@ public class TransactionAwareBufferedWriterTests { } return null; }); - - for(int i=0; i< limit; i++) { + + for (int i = 0; i < limit; i++) { assertEquals(String.valueOf(i), results[i]); - } + } } - //BATCH-3745 + // BATCH-3745 @Test - public void testWriteInTransactionWithOffset() throws IOException{ + public void testWriteInTransactionWithOffset() throws IOException { ArgumentCaptor bb = ArgumentCaptor.forClass(ByteBuffer.class); when(fileChannel.write(bb.capture())).thenReturn(3); @@ -348,7 +351,8 @@ public class TransactionAwareBufferedWriterTests { try { writer.write("hamburger", 4, 3); - } catch (IOException e) { + } + catch (IOException e) { throw new IllegalStateException("Unexpected IOException", e); } return null; @@ -364,4 +368,5 @@ public class TransactionAwareBufferedWriterTests { bb.get(bytearr); return new String(bytearr); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/transaction/TransactionAwareListFactoryTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/transaction/TransactionAwareListFactoryTests.java index 0d34edee0..a6e685337 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/transaction/TransactionAwareListFactoryTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/transaction/TransactionAwareListFactoryTests.java @@ -66,7 +66,7 @@ public class TransactionAwareListFactoryTests { @Test public void testTransactionalAdd() throws Exception { transactionTemplate.execute(new TransactionCallback() { - @Override + @Override public Void doInTransaction(TransactionStatus status) { testAdd(); return null; @@ -78,7 +78,7 @@ public class TransactionAwareListFactoryTests { @Test public void testTransactionalRemove() throws Exception { transactionTemplate.execute(new TransactionCallback() { - @Override + @Override public Void doInTransaction(TransactionStatus status) { testRemove(); return null; @@ -90,7 +90,7 @@ public class TransactionAwareListFactoryTests { @Test public void testTransactionalClear() throws Exception { transactionTemplate.execute(new TransactionCallback() { - @Override + @Override public Void doInTransaction(TransactionStatus status) { testClear(); return null; @@ -103,7 +103,7 @@ public class TransactionAwareListFactoryTests { public void testTransactionalAddWithRollback() throws Exception { try { transactionTemplate.execute(new TransactionCallback() { - @Override + @Override public Void doInTransaction(TransactionStatus status) { testAdd(); throw new RuntimeException("Rollback!"); @@ -121,7 +121,7 @@ public class TransactionAwareListFactoryTests { public void testTransactionalRemoveWithRollback() throws Exception { try { transactionTemplate.execute(new TransactionCallback() { - @Override + @Override public Void doInTransaction(TransactionStatus status) { testRemove(); throw new RuntimeException("Rollback!"); @@ -139,7 +139,7 @@ public class TransactionAwareListFactoryTests { public void testTransactionalClearWithRollback() throws Exception { try { transactionTemplate.execute(new TransactionCallback() { - @Override + @Override public Void doInTransaction(TransactionStatus status) { testClear(); throw new RuntimeException("Rollback!"); @@ -152,4 +152,5 @@ public class TransactionAwareListFactoryTests { } assertEquals(3, list.size()); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/transaction/TransactionAwareMapFactoryTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/transaction/TransactionAwareMapFactoryTests.java index fa0e10932..501eb90ae 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/transaction/TransactionAwareMapFactoryTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/transaction/TransactionAwareMapFactoryTests.java @@ -31,7 +31,7 @@ public class TransactionAwareMapFactoryTests extends TestCase { Map map; - @Override + @Override protected void setUp() throws Exception { Map seed = new HashMap<>(); seed.put("foo", "oof"); @@ -73,7 +73,7 @@ public class TransactionAwareMapFactoryTests extends TestCase { public void testTransactionalAdd() throws Exception { transactionTemplate.execute(new TransactionCallback() { - @Override + @Override public Void doInTransaction(TransactionStatus status) { testAdd(); return null; @@ -84,7 +84,7 @@ public class TransactionAwareMapFactoryTests extends TestCase { public void testTransactionalEmpty() throws Exception { transactionTemplate.execute(new TransactionCallback() { - @Override + @Override public Void doInTransaction(TransactionStatus status) { testEmpty(); return null; @@ -95,7 +95,7 @@ public class TransactionAwareMapFactoryTests extends TestCase { public void testTransactionalValues() throws Exception { transactionTemplate.execute(new TransactionCallback() { - @Override + @Override public Void doInTransaction(TransactionStatus status) { testValues(); return null; @@ -106,7 +106,7 @@ public class TransactionAwareMapFactoryTests extends TestCase { public void testTransactionalRemove() throws Exception { transactionTemplate.execute(new TransactionCallback() { - @Override + @Override public Void doInTransaction(TransactionStatus status) { testRemove(); return null; @@ -117,7 +117,7 @@ public class TransactionAwareMapFactoryTests extends TestCase { public void testTransactionalClear() throws Exception { transactionTemplate.execute(new TransactionCallback() { - @Override + @Override public Void doInTransaction(TransactionStatus status) { testClear(); return null; @@ -129,7 +129,7 @@ public class TransactionAwareMapFactoryTests extends TestCase { public void testTransactionalAddWithRollback() throws Exception { try { transactionTemplate.execute(new TransactionCallback() { - @Override + @Override public Void doInTransaction(TransactionStatus status) { testAdd(); throw new RuntimeException("Rollback!"); @@ -146,7 +146,7 @@ public class TransactionAwareMapFactoryTests extends TestCase { public void testTransactionalRemoveWithRollback() throws Exception { try { transactionTemplate.execute(new TransactionCallback() { - @Override + @Override public Void doInTransaction(TransactionStatus status) { testRemove(); throw new RuntimeException("Rollback!"); @@ -163,7 +163,7 @@ public class TransactionAwareMapFactoryTests extends TestCase { public void testTransactionalClearWithRollback() throws Exception { try { transactionTemplate.execute(new TransactionCallback() { - @Override + @Override public Void doInTransaction(TransactionStatus status) { testClear(); throw new RuntimeException("Rollback!"); @@ -176,4 +176,5 @@ public class TransactionAwareMapFactoryTests extends TestCase { } assertEquals(3, map.size()); } + } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/transaction/TransactionAwareProxyFactoryTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/transaction/TransactionAwareProxyFactoryTests.java index 97b230a99..a87f3a047 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/transaction/TransactionAwareProxyFactoryTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/transaction/TransactionAwareProxyFactoryTests.java @@ -54,8 +54,8 @@ public class TransactionAwareProxyFactoryTests extends TestCase { } public void testCreateMapWithValues() throws Exception { - Map map = TransactionAwareProxyFactory.createTransactionalMap(Collections.singletonMap("foo", - "bar")); + Map map = TransactionAwareProxyFactory + .createTransactionalMap(Collections.singletonMap("foo", "bar")); assertEquals(1, map.size()); } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/transaction/TransactionAwareSetFactoryTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/transaction/TransactionAwareSetFactoryTests.java index d19adb279..1b70b66c6 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/transaction/TransactionAwareSetFactoryTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/transaction/TransactionAwareSetFactoryTests.java @@ -67,7 +67,7 @@ public class TransactionAwareSetFactoryTests { @Test public void testTransactionalAdd() throws Exception { transactionTemplate.execute(new TransactionCallback() { - @Override + @Override public Void doInTransaction(TransactionStatus status) { testAdd(); return null; @@ -79,7 +79,7 @@ public class TransactionAwareSetFactoryTests { @Test public void testTransactionalRemove() throws Exception { transactionTemplate.execute(new TransactionCallback() { - @Override + @Override public Void doInTransaction(TransactionStatus status) { testRemove(); return null; @@ -91,7 +91,7 @@ public class TransactionAwareSetFactoryTests { @Test public void testTransactionalClear() throws Exception { transactionTemplate.execute(new TransactionCallback() { - @Override + @Override public Void doInTransaction(TransactionStatus status) { testClear(); return null; @@ -104,7 +104,7 @@ public class TransactionAwareSetFactoryTests { public void testTransactionalAddWithRollback() throws Exception { try { transactionTemplate.execute(new TransactionCallback() { - @Override + @Override public Void doInTransaction(TransactionStatus status) { testAdd(); throw new RuntimeException("Rollback!"); @@ -122,7 +122,7 @@ public class TransactionAwareSetFactoryTests { public void testTransactionalRemoveWithRollback() throws Exception { try { transactionTemplate.execute(new TransactionCallback() { - @Override + @Override public Void doInTransaction(TransactionStatus status) { testRemove(); throw new RuntimeException("Rollback!"); @@ -140,7 +140,7 @@ public class TransactionAwareSetFactoryTests { public void testTransactionalClearWithRollback() throws Exception { try { transactionTemplate.execute(new TransactionCallback() { - @Override + @Override public Void doInTransaction(TransactionStatus status) { testClear(); throw new RuntimeException("Rollback!"); @@ -153,4 +153,5 @@ public class TransactionAwareSetFactoryTests { } assertEquals(3, set.size()); } + } diff --git a/spring-batch-infrastructure/src/test/java/test/jdbc/datasource/DataSourceInitializer.java b/spring-batch-infrastructure/src/test/java/test/jdbc/datasource/DataSourceInitializer.java index 53658f9bc..2dd3bc487 100644 --- a/spring-batch-infrastructure/src/test/java/test/jdbc/datasource/DataSourceInitializer.java +++ b/spring-batch-infrastructure/src/test/java/test/jdbc/datasource/DataSourceInitializer.java @@ -40,17 +40,17 @@ import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; /** - * Wrapper for a {@link DataSource} that can run scripts on start up and shut - * down. Us as a bean definition

      - * - * Run this class to initialize a database in a running server process. - * Make sure the server is running first by launching the "hsql-server" from the - * hsql.server project. Then you can right click in Eclipse and - * Run As -> Java Application. Do the same any time you want to wipe the - * database and start again. - * + * Wrapper for a {@link DataSource} that can run scripts on start up and shut down. Us as + * a bean definition
      + *
      + * + * Run this class to initialize a database in a running server process. Make sure the + * server is running first by launching the "hsql-server" from the + * hsql.server project. Then you can right click in Eclipse and Run As -> + * Java Application. Do the same any time you want to wipe the database and start again. + * * @author Dave Syer - * + * */ public class DataSourceInitializer implements InitializingBean, DisposableBean { @@ -68,7 +68,6 @@ public class DataSourceInitializer implements InitializingBean, DisposableBean { /** * Main method as convenient entry point. - * * @param args */ @SuppressWarnings("resource") @@ -81,21 +80,22 @@ public class DataSourceInitializer implements InitializingBean, DisposableBean { * @throws Throwable * @see java.lang.Object#finalize() */ - @Override + @Override protected void finalize() throws Throwable { logger.debug("finalize called for " + dataSource); super.finalize(); initialized = false; } - @Override + @Override public void destroy() { logger.info("destroy called for " + dataSource); doDestroy(); } public void doDestroy() { - if (destroyScripts==null) return; + if (destroyScripts == null) + return; for (int i = 0; i < destroyScripts.length; i++) { Resource destroyScript = destroyScripts[i]; try { @@ -112,7 +112,7 @@ public class DataSourceInitializer implements InitializingBean, DisposableBean { } } - @Override + @Override public void afterPropertiesSet() throws Exception { Assert.notNull(dataSource, "A DataSource is required"); initialize(); @@ -139,13 +139,13 @@ public class DataSourceInitializer implements InitializingBean, DisposableBean { TransactionTemplate transactionTemplate = new TransactionTemplate(new DataSourceTransactionManager(dataSource)); transactionTemplate.execute(new TransactionCallback() { - @Override + @Override @SuppressWarnings("unchecked") public Void doInTransaction(TransactionStatus status) { String[] scripts; try { - scripts = StringUtils.delimitedListToStringArray(stripComments(IOUtils.readLines(scriptResource - .getInputStream(), "UTF-8")), ";"); + scripts = StringUtils.delimitedListToStringArray( + stripComments(IOUtils.readLines(scriptResource.getInputStream(), "UTF-8")), ";"); } catch (IOException e) { throw new BeanInitializationException("Cannot load script from [" + scriptResource + "]", e); diff --git a/spring-batch-infrastructure/src/test/java/test/jdbc/datasource/DerbyDataSourceFactoryBean.java b/spring-batch-infrastructure/src/test/java/test/jdbc/datasource/DerbyDataSourceFactoryBean.java index 82bd7aaa4..f8274543e 100644 --- a/spring-batch-infrastructure/src/test/java/test/jdbc/datasource/DerbyDataSourceFactoryBean.java +++ b/spring-batch-infrastructure/src/test/java/test/jdbc/datasource/DerbyDataSourceFactoryBean.java @@ -34,7 +34,7 @@ public class DerbyDataSourceFactoryBean extends AbstractFactoryBean this.dataDirectory = dataDirectory; } - @Override + @Override protected DataSource createInstance() throws Exception { File directory = new File(dataDirectory); System.setProperty("derby.system.home", directory.getCanonicalPath()); @@ -46,11 +46,11 @@ public class DerbyDataSourceFactoryBean extends AbstractFactoryBean ds.setCreateDatabase("create"); logger.info("Created instance of " + ds.toString()); - + return ds; } - @Override + @Override public Class getObjectType() { return DataSource.class; } diff --git a/spring-batch-infrastructure/src/test/java/test/jdbc/datasource/DerbyShutdownBean.java b/spring-batch-infrastructure/src/test/java/test/jdbc/datasource/DerbyShutdownBean.java index 2e40826d1..11393c99d 100644 --- a/spring-batch-infrastructure/src/test/java/test/jdbc/datasource/DerbyShutdownBean.java +++ b/spring-batch-infrastructure/src/test/java/test/jdbc/datasource/DerbyShutdownBean.java @@ -29,31 +29,30 @@ public class DerbyShutdownBean implements DisposableBean { private static Log logger = LogFactory.getLog(DerbyShutdownBean.class); private DataSource dataSource; - - private boolean isShutdown = false; + private boolean isShutdown = false; public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } - @Override + @Override public void destroy() throws Exception { logger.info("Attempting Derby database shut down on: " + dataSource); - if (!isShutdown && dataSource != null - && dataSource instanceof EmbeddedDataSource) { + if (!isShutdown && dataSource != null && dataSource instanceof EmbeddedDataSource) { EmbeddedDataSource ds = (EmbeddedDataSource) dataSource; try { ds.setShutdownDatabase("shutdown"); ds.getConnection(); - } catch (SQLException except) { + } + catch (SQLException except) { if (except.getSQLState().equals("08006")) { // SQLState derby throws when shutting down the database logger.info("Derby database is now shut down."); isShutdown = true; - } else { - logger.error("Problem shutting down Derby " - + except.getMessage()); + } + else { + logger.error("Problem shutting down Derby " + except.getMessage()); } } } diff --git a/spring-batch-infrastructure/src/test/java/test/jdbc/proc/derby/TestProcedures.java b/spring-batch-infrastructure/src/test/java/test/jdbc/proc/derby/TestProcedures.java index 2c3b2e6ae..f4f61f3bc 100644 --- a/spring-batch-infrastructure/src/test/java/test/jdbc/proc/derby/TestProcedures.java +++ b/spring-batch-infrastructure/src/test/java/test/jdbc/proc/derby/TestProcedures.java @@ -20,8 +20,8 @@ import java.sql.*; /** * @author trisberg * - * CALL SQLJ.install_jar('testproc.jar', 'APP.TESTPROC', 0); - * CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY('derby.database.classpath', 'APP.TESTPROC'); + * CALL SQLJ.install_jar('testproc.jar', 'APP.TESTPROC', 0); CALL + * SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY('derby.database.classpath', 'APP.TESTPROC'); * * CALL SQLJ.replace_jar('testproc.jar', 'APP.TESTPROC'); * @@ -31,19 +31,20 @@ import java.sql.*; public class TestProcedures { - public static void readFoos(ResultSet[] rs) throws SQLException { - String SQL = "SELECT id, name, value FROM T_FOOS"; - Connection conn = DriverManager.getConnection("jdbc:default:connection"); - PreparedStatement ps1 = conn.prepareStatement(SQL); - rs[0] = ps1.executeQuery(); - } + public static void readFoos(ResultSet[] rs) throws SQLException { + String SQL = "SELECT id, name, value FROM T_FOOS"; + Connection conn = DriverManager.getConnection("jdbc:default:connection"); + PreparedStatement ps1 = conn.prepareStatement(SQL); + rs[0] = ps1.executeQuery(); + } + + public static void readSomeFoos(int fromId, int toId, ResultSet[] rs) throws SQLException { + String SQL = "SELECT id, name, value FROM T_FOOS WHERE id between ? and ?"; + Connection conn = DriverManager.getConnection("jdbc:default:connection"); + PreparedStatement ps2 = conn.prepareStatement(SQL); + ps2.setInt(1, fromId); + ps2.setInt(2, toId); + rs[0] = ps2.executeQuery(); + } - public static void readSomeFoos(int fromId, int toId, ResultSet[] rs) throws SQLException { - String SQL = "SELECT id, name, value FROM T_FOOS WHERE id between ? and ?"; - Connection conn = DriverManager.getConnection("jdbc:default:connection"); - PreparedStatement ps2 = conn.prepareStatement(SQL); - ps2.setInt(1, fromId); - ps2.setInt(2, toId); - rs[0] = ps2.executeQuery(); - } } diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/async/AsyncItemProcessor.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/async/AsyncItemProcessor.java index cd742a6cb..db1ddbcf0 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/async/AsyncItemProcessor.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/async/AsyncItemProcessor.java @@ -1,129 +1,123 @@ -/* - * Copyright 2006-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.integration.async; - -import java.util.concurrent.Callable; -import java.util.concurrent.Future; -import java.util.concurrent.FutureTask; - -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.scope.context.StepContext; -import org.springframework.batch.core.scope.context.StepSynchronizationManager; -import org.springframework.batch.item.ItemProcessor; -import org.springframework.batch.item.ItemWriter; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.core.task.SyncTaskExecutor; -import org.springframework.core.task.TaskExecutor; -import org.springframework.lang.Nullable; -import org.springframework.util.Assert; - -/** - * An {@link ItemProcessor} that delegates to a nested processor and in the - * background. To allow for background processing the return value from the - * processor is a {@link Future} which needs to be unpacked before the item can - * be used by a client. - * - * Because the {@link Future} is typically unwrapped in the {@link ItemWriter}, - * there are lifecycle and stats limitations (since the framework doesn't know - * what the result of the processor is). While not an exhaustive list, things like - * {@link StepExecution#filterCount} will not reflect the number of filtered items - * and {@link org.springframework.batch.core.ItemProcessListener#onProcessError(Object, Exception)} - * will not be called. - * - * @author Dave Syer - * - * @param the input object type - * @param the output object type (will be wrapped in a Future) - * @see AsyncItemWriter - */ -public class AsyncItemProcessor implements ItemProcessor>, InitializingBean { - - private ItemProcessor delegate; - - private TaskExecutor taskExecutor = new SyncTaskExecutor(); - - /** - * Check mandatory properties (the {@link #setDelegate(ItemProcessor)}). - * - * @see InitializingBean#afterPropertiesSet() - */ - public void afterPropertiesSet() throws Exception { - Assert.notNull(delegate, "The delegate must be set."); - } - - /** - * The {@link ItemProcessor} to use to delegate processing to in a - * background thread. - * - * @param delegate the {@link ItemProcessor} to use as a delegate - */ - public void setDelegate(ItemProcessor delegate) { - this.delegate = delegate; - } - - /** - * The {@link TaskExecutor} to use to allow the item processing to proceed - * in the background. Defaults to a {@link SyncTaskExecutor} so no threads - * are created unless this is overridden. - * - * @param taskExecutor a {@link TaskExecutor} - */ - public void setTaskExecutor(TaskExecutor taskExecutor) { - this.taskExecutor = taskExecutor; - } - - /** - * Transform the input by delegating to the provided item processor. The - * return value is wrapped in a {@link Future} so that clients can unpack it - * later. - * - * @see ItemProcessor#process(Object) - */ - @Nullable - public Future process(final I item) throws Exception { - final StepExecution stepExecution = getStepExecution(); - FutureTask task = new FutureTask<>(new Callable() { - public O call() throws Exception { - if (stepExecution != null) { - StepSynchronizationManager.register(stepExecution); - } - try { - return delegate.process(item); - } - finally { - if (stepExecution != null) { - StepSynchronizationManager.close(); - } - } - } - }); - taskExecutor.execute(task); - return task; - } - - /** - * @return the current step execution if there is one - */ - private StepExecution getStepExecution() { - StepContext context = StepSynchronizationManager.getContext(); - if (context==null) { - return null; - } - StepExecution stepExecution = context.getStepExecution(); - return stepExecution; - } - -} +/* + * Copyright 2006-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.integration.async; + +import java.util.concurrent.Callable; +import java.util.concurrent.Future; +import java.util.concurrent.FutureTask; + +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.scope.context.StepContext; +import org.springframework.batch.core.scope.context.StepSynchronizationManager; +import org.springframework.batch.item.ItemProcessor; +import org.springframework.batch.item.ItemWriter; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.core.task.SyncTaskExecutor; +import org.springframework.core.task.TaskExecutor; +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; + +/** + * An {@link ItemProcessor} that delegates to a nested processor and in the background. To + * allow for background processing the return value from the processor is a {@link Future} + * which needs to be unpacked before the item can be used by a client. + * + * Because the {@link Future} is typically unwrapped in the {@link ItemWriter}, there are + * lifecycle and stats limitations (since the framework doesn't know what the result of + * the processor is). While not an exhaustive list, things like + * {@link StepExecution#filterCount} will not reflect the number of filtered items and + * {@link org.springframework.batch.core.ItemProcessListener#onProcessError(Object, Exception)} + * will not be called. + * + * @author Dave Syer + * @param the input object type + * @param the output object type (will be wrapped in a Future) + * @see AsyncItemWriter + */ +public class AsyncItemProcessor implements ItemProcessor>, InitializingBean { + + private ItemProcessor delegate; + + private TaskExecutor taskExecutor = new SyncTaskExecutor(); + + /** + * Check mandatory properties (the {@link #setDelegate(ItemProcessor)}). + * + * @see InitializingBean#afterPropertiesSet() + */ + public void afterPropertiesSet() throws Exception { + Assert.notNull(delegate, "The delegate must be set."); + } + + /** + * The {@link ItemProcessor} to use to delegate processing to in a background thread. + * @param delegate the {@link ItemProcessor} to use as a delegate + */ + public void setDelegate(ItemProcessor delegate) { + this.delegate = delegate; + } + + /** + * The {@link TaskExecutor} to use to allow the item processing to proceed in the + * background. Defaults to a {@link SyncTaskExecutor} so no threads are created unless + * this is overridden. + * @param taskExecutor a {@link TaskExecutor} + */ + public void setTaskExecutor(TaskExecutor taskExecutor) { + this.taskExecutor = taskExecutor; + } + + /** + * Transform the input by delegating to the provided item processor. The return value + * is wrapped in a {@link Future} so that clients can unpack it later. + * + * @see ItemProcessor#process(Object) + */ + @Nullable + public Future process(final I item) throws Exception { + final StepExecution stepExecution = getStepExecution(); + FutureTask task = new FutureTask<>(new Callable() { + public O call() throws Exception { + if (stepExecution != null) { + StepSynchronizationManager.register(stepExecution); + } + try { + return delegate.process(item); + } + finally { + if (stepExecution != null) { + StepSynchronizationManager.close(); + } + } + } + }); + taskExecutor.execute(task); + return task; + } + + /** + * @return the current step execution if there is one + */ + private StepExecution getStepExecution() { + StepContext context = StepSynchronizationManager.getContext(); + if (context == null) { + return null; + } + StepExecution stepExecution = context.getStepExecution(); + return stepExecution; + } + +} diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/async/AsyncItemWriter.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/async/AsyncItemWriter.java index 1df06bff1..f5d4bcd60 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/async/AsyncItemWriter.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/async/AsyncItemWriter.java @@ -1,108 +1,110 @@ -/* - * Copyright 2006-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.integration.async; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemStream; -import org.springframework.batch.item.ItemStreamException; -import org.springframework.batch.item.ItemStreamWriter; -import org.springframework.batch.item.ItemWriter; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.util.Assert; - -public class AsyncItemWriter implements ItemStreamWriter>, InitializingBean { - - private static final Log logger = LogFactory.getLog(AsyncItemWriter.class); - - private ItemWriter delegate; - - public void afterPropertiesSet() throws Exception { - Assert.notNull(delegate, "A delegate ItemWriter must be provided."); - } - - /** - * @param delegate ItemWriter that does the actual writing of the Future results - */ - public void setDelegate(ItemWriter delegate) { - this.delegate = delegate; - } - - /** - * In the processing of the {@link java.util.concurrent.Future}s passed, nulls are not passed to the - * delegate since they are considered filtered out by the {@link org.springframework.batch.integration.async.AsyncItemProcessor}'s - * delegated {@link org.springframework.batch.item.ItemProcessor}. If the unwrapping - * of the {@link Future} results in an {@link ExecutionException}, that will be - * unwrapped and the cause will be thrown. - * - * @param items {@link java.util.concurrent.Future}s to be unwrapped and passed to the delegate - * @throws Exception The exception returned by the Future if one was thrown - */ - public void write(List> items) throws Exception { - List list = new ArrayList<>(); - for (Future future : items) { - try { - T item = future.get(); - - if(item != null) { - list.add(future.get()); - } - } - catch (ExecutionException e) { - Throwable cause = e.getCause(); - - if(cause != null && cause instanceof Exception) { - logger.debug("An exception was thrown while processing an item", e); - - throw (Exception) cause; - } - else { - throw e; - } - } - } - - delegate.write(list); - } - - @Override - public void open(ExecutionContext executionContext) throws ItemStreamException { - if (delegate instanceof ItemStream) { - ((ItemStream) delegate).open(executionContext); - } - } - - @Override - public void update(ExecutionContext executionContext) throws ItemStreamException { - if (delegate instanceof ItemStream) { - ((ItemStream) delegate).update(executionContext); - } - } - - @Override - public void close() throws ItemStreamException { - if (delegate instanceof ItemStream) { - ((ItemStream) delegate).close(); - } - } -} +/* + * Copyright 2006-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.integration.async; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ItemStream; +import org.springframework.batch.item.ItemStreamException; +import org.springframework.batch.item.ItemStreamWriter; +import org.springframework.batch.item.ItemWriter; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.util.Assert; + +public class AsyncItemWriter implements ItemStreamWriter>, InitializingBean { + + private static final Log logger = LogFactory.getLog(AsyncItemWriter.class); + + private ItemWriter delegate; + + public void afterPropertiesSet() throws Exception { + Assert.notNull(delegate, "A delegate ItemWriter must be provided."); + } + + /** + * @param delegate ItemWriter that does the actual writing of the Future results + */ + public void setDelegate(ItemWriter delegate) { + this.delegate = delegate; + } + + /** + * In the processing of the {@link java.util.concurrent.Future}s passed, nulls are + * not passed to the delegate since they are considered filtered out by the + * {@link org.springframework.batch.integration.async.AsyncItemProcessor}'s delegated + * {@link org.springframework.batch.item.ItemProcessor}. If the unwrapping of the + * {@link Future} results in an {@link ExecutionException}, that will be unwrapped and + * the cause will be thrown. + * @param items {@link java.util.concurrent.Future}s to be unwrapped and passed to the + * delegate + * @throws Exception The exception returned by the Future if one was thrown + */ + public void write(List> items) throws Exception { + List list = new ArrayList<>(); + for (Future future : items) { + try { + T item = future.get(); + + if (item != null) { + list.add(future.get()); + } + } + catch (ExecutionException e) { + Throwable cause = e.getCause(); + + if (cause != null && cause instanceof Exception) { + logger.debug("An exception was thrown while processing an item", e); + + throw (Exception) cause; + } + else { + throw e; + } + } + } + + delegate.write(list); + } + + @Override + public void open(ExecutionContext executionContext) throws ItemStreamException { + if (delegate instanceof ItemStream) { + ((ItemStream) delegate).open(executionContext); + } + } + + @Override + public void update(ExecutionContext executionContext) throws ItemStreamException { + if (delegate instanceof ItemStream) { + ((ItemStream) delegate).update(executionContext); + } + } + + @Override + public void close() throws ItemStreamException { + if (delegate instanceof ItemStream) { + ((ItemStream) delegate).close(); + } + } + +} diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/async/StepExecutionInterceptor.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/async/StepExecutionInterceptor.java index 560cae129..c81f3bd1a 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/async/StepExecutionInterceptor.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/async/StepExecutionInterceptor.java @@ -24,11 +24,10 @@ import org.springframework.messaging.MessageChannel; import org.springframework.messaging.support.ChannelInterceptor; /** - * A {@link ChannelInterceptor} that adds the current {@link StepExecution} (if - * there is one) as a header to the message. Downstream asynchronous handlers - * can then take advantage of the step context without needing to be step - * scoped, which is a problem for handlers executing in another thread because - * the scope context is not available. + * A {@link ChannelInterceptor} that adds the current {@link StepExecution} (if there is + * one) as a header to the message. Downstream asynchronous handlers can then take + * advantage of the step context without needing to be step scoped, which is a problem for + * handlers executing in another thread because the scope context is not available. * * @author Dave Syer * diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/async/package-info.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/async/package-info.java index 807d25ae4..7285a61be 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/async/package-info.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/async/package-info.java @@ -1,5 +1,6 @@ /** - * Components for executing item processing asynchronously and writing the results when processing is complete. + * Components for executing item processing asynchronously and writing the results when + * processing is complete. * * @author Michael Minella * @author Mahmoud Ben Hassine diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/AsynchronousFailureException.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/AsynchronousFailureException.java index 02a94cc57..5573b1798 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/AsynchronousFailureException.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/AsynchronousFailureException.java @@ -19,24 +19,21 @@ package org.springframework.batch.integration.chunk; import org.springframework.batch.item.ItemWriterException; /** - * Exception indicating that a failure or early completion condition was - * detected in a remote worker. - * + * Exception indicating that a failure or early completion condition was detected in a + * remote worker. + * * @author Dave Syer - * + * */ public class AsynchronousFailureException extends ItemWriterException { private static final long serialVersionUID = 1L; /** - * Create a new {@link AsynchronousFailureException} based on a message and - * another exception. - * - * @param message - * the message for this exception - * @param cause - * the other exception + * Create a new {@link AsynchronousFailureException} based on a message and another + * exception. + * @param message the message for this exception + * @param cause the other exception */ public AsynchronousFailureException(String message, Throwable cause) { super(message, cause); @@ -44,9 +41,7 @@ public class AsynchronousFailureException extends ItemWriterException { /** * Create a new {@link AsynchronousFailureException} based on a message. - * - * @param message - * the message for this exception + * @param message the message for this exception */ public AsynchronousFailureException(String message) { super(message); diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/ChunkHandler.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/ChunkHandler.java index c6bbdcabe..cb8c8b88e 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/ChunkHandler.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/ChunkHandler.java @@ -16,28 +16,27 @@ package org.springframework.batch.integration.chunk; - /** - * Interface for a remote worker in the Remote Chunking pattern. A request comes from a manager process containing some - * items to be processed. Once the items are done with a response needs to be generated containing a summary of the - * result. - * + * Interface for a remote worker in the Remote Chunking pattern. A request comes from a + * manager process containing some items to be processed. Once the items are done with a + * response needs to be generated containing a summary of the result. + * * @author Dave Syer - * - * @param the type of the items to be processed (it is recommended to use a Memento like a primary key) + * @param the type of the items to be processed (it is recommended to use a Memento + * like a primary key) */ public interface ChunkHandler { /** - * Handle the chunk, processing all the items and returning a response summarising the result. If the result is a - * failure then the response should say so. The handler only throws an exception if it needs to roll back a - * transaction and knows that the request will be re-delivered (if not to the same handler then to one processing - * the same Step). - * + * Handle the chunk, processing all the items and returning a response summarising the + * result. If the result is a failure then the response should say so. The handler + * only throws an exception if it needs to roll back a transaction and knows that the + * request will be re-delivered (if not to the same handler then to one processing the + * same Step). * @param chunk a request containing the chunk to process * @return a response summarising the result - * - * @throws Exception if the handler needs to roll back a transaction and have the chunk re-delivered + * @throws Exception if the handler needs to roll back a transaction and have the + * chunk re-delivered */ ChunkResponse handleChunk(ChunkRequest chunk) throws Exception; diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/ChunkMessageChannelItemWriter.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/ChunkMessageChannelItemWriter.java index cb5e8c685..0141cbff8 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/ChunkMessageChannelItemWriter.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/ChunkMessageChannelItemWriter.java @@ -1,344 +1,344 @@ -/* - * Copyright 2006-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.integration.chunk; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Queue; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.atomic.AtomicInteger; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.StepContribution; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.StepExecutionListener; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemStream; -import org.springframework.batch.item.ItemStreamException; -import org.springframework.batch.item.ItemWriter; -import org.springframework.integration.core.MessagingTemplate; -import org.springframework.lang.Nullable; -import org.springframework.messaging.Message; -import org.springframework.messaging.PollableChannel; -import org.springframework.messaging.support.GenericMessage; -import org.springframework.util.Assert; - -public class ChunkMessageChannelItemWriter implements StepExecutionListener, ItemWriter, - ItemStream, StepContributionSource { - - private static final Log logger = LogFactory.getLog(ChunkMessageChannelItemWriter.class); - - static final String ACTUAL = ChunkMessageChannelItemWriter.class.getName() + ".ACTUAL"; - - static final String EXPECTED = ChunkMessageChannelItemWriter.class.getName() + ".EXPECTED"; - - private static final long DEFAULT_THROTTLE_LIMIT = 6; - - private MessagingTemplate messagingGateway; - - private final LocalState localState = new LocalState(); - - private long throttleLimit = DEFAULT_THROTTLE_LIMIT; - - private final int DEFAULT_MAX_WAIT_TIMEOUTS = 40; - - private int maxWaitTimeouts = DEFAULT_MAX_WAIT_TIMEOUTS; - - private PollableChannel replyChannel; - - /** - * The maximum number of times to wait at the end of a step for a non-null result from the remote workers. This is a - * multiplier on the receive timeout set separately on the gateway. The ideal value is a compromise between allowing - * slow workers time to finish, and responsiveness if there is a dead worker. Defaults to 40. - * - * @param maxWaitTimeouts the maximum number of wait timeouts - */ - public void setMaxWaitTimeouts(int maxWaitTimeouts) { - this.maxWaitTimeouts = maxWaitTimeouts; - } - - /** - * Public setter for the throttle limit. This limits the number of pending requests for chunk processing to avoid - * overwhelming the receivers. - * @param throttleLimit the throttle limit to set - */ - public void setThrottleLimit(long throttleLimit) { - this.throttleLimit = throttleLimit; - } - - public void setMessagingOperations(MessagingTemplate messagingGateway) { - this.messagingGateway = messagingGateway; - } - - public void setReplyChannel(PollableChannel replyChannel) { - this.replyChannel = replyChannel; - } - - public void write(List items) throws Exception { - - // Block until expecting <= throttle limit - while (localState.getExpecting() > throttleLimit) { - getNextResult(); - } - - if (!items.isEmpty()) { - - ChunkRequest request = localState.getRequest(items); - if (logger.isDebugEnabled()) { - logger.debug("Dispatching chunk: " + request); - } - messagingGateway.send(new GenericMessage<>(request)); - localState.incrementExpected(); - - } - - } - - @Override - public void beforeStep(StepExecution stepExecution) { - localState.setStepExecution(stepExecution); - } - - @Nullable - @Override - public ExitStatus afterStep(StepExecution stepExecution) { - if (!(stepExecution.getStatus() == BatchStatus.COMPLETED)) { - return ExitStatus.EXECUTING; - } - long expecting = localState.getExpecting(); - boolean timedOut; - try { - logger.debug("Waiting for results in step listener..."); - timedOut = !waitForResults(); - logger.debug("Finished waiting for results in step listener."); - } - catch (RuntimeException e) { - logger.debug("Detected failure waiting for results in step listener.", e); - stepExecution.setStatus(BatchStatus.FAILED); - return ExitStatus.FAILED.addExitDescription(e.getClass().getName() + ": " + e.getMessage()); - } - finally { - - if (logger.isDebugEnabled()) { - logger.debug("Finished waiting for results in step listener. Still expecting: " - + localState.getExpecting()); - } - - for (StepContribution contribution : getStepContributions()) { - stepExecution.apply(contribution); - } - } - if (timedOut) { - stepExecution.setStatus(BatchStatus.FAILED); - return ExitStatus.FAILED.addExitDescription("Timed out waiting for " + localState.getExpecting() - + " backlog at end of step"); - } - return ExitStatus.COMPLETED.addExitDescription("Waited for " + expecting + " results."); - } - - public void close() throws ItemStreamException { - localState.reset(); - } - - public void open(ExecutionContext executionContext) throws ItemStreamException { - if (executionContext.containsKey(EXPECTED)) { - localState.open(executionContext.getInt(EXPECTED), executionContext.getInt(ACTUAL)); - if (!waitForResults()) { - throw new ItemStreamException("Timed out waiting for back log on open"); - } - } - } - - public void update(ExecutionContext executionContext) throws ItemStreamException { - executionContext.putInt(EXPECTED, localState.expected.intValue()); - executionContext.putInt(ACTUAL, localState.actual.intValue()); - } - - public Collection getStepContributions() { - List contributions = new ArrayList<>(); - for (ChunkResponse response : localState.pollChunkResponses()) { - StepContribution contribution = response.getStepContribution(); - if (logger.isDebugEnabled()) { - logger.debug("Applying: " + response); - } - contributions.add(contribution); - } - return contributions; - } - - /** - * Wait until all the results that are in the pipeline come back to the reply channel. - * - * @return true if successfully received a result, false if timed out - */ - private boolean waitForResults() throws AsynchronousFailureException { - int count = 0; - int maxCount = maxWaitTimeouts; - Throwable failure = null; - if (logger.isInfoEnabled()) { - logger.info("Waiting for " + localState.getExpecting() + " results"); - } - while (localState.getExpecting() > 0 && count++ < maxCount) { - try { - getNextResult(); - } - catch (Throwable t) { - logger.error("Detected error in remote result. Trying to recover " + localState.getExpecting() - + " outstanding results before completing.", t); - failure = t; - } - } - if (failure != null) { - throw wrapIfNecessary(failure); - } - return count < maxCount; - } - - /** - * Get the next result if it is available (within the timeout specified in the gateway), otherwise do nothing. - * - * @throws AsynchronousFailureException If there is a response and it contains a failed chunk response. - * - * @throws IllegalStateException if the result contains the wrong job instance id (maybe we are sharing a channel - * and we shouldn't be) - */ - @SuppressWarnings("unchecked") - private void getNextResult() throws AsynchronousFailureException { - Message message = (Message) messagingGateway.receive(replyChannel); - if (message != null) { - ChunkResponse payload = message.getPayload(); - if (logger.isDebugEnabled()) { - logger.debug("Found result: " + payload); - } - Long jobInstanceId = payload.getJobId(); - Assert.state(jobInstanceId != null, "Message did not contain job instance id."); - Assert.state(jobInstanceId.equals(localState.getJobId()), "Message contained wrong job instance id [" - + jobInstanceId + "] should have been [" + localState.getJobId() + "]."); - if (payload.isRedelivered()) { - logger - .warn("Redelivered result detected, which may indicate stale state. In the best case, we just picked up a timed out message " - + "from a previous failed execution. In the worst case (and if this is not a restart), " - + "the step may now timeout. In that case if you believe that all messages " - + "from workers have been sent, the business state " - + "is probably inconsistent, and the step will fail."); - localState.incrementRedelivered(); - } - localState.pushResponse(payload); - localState.incrementActual(); - if (!payload.isSuccessful()) { - throw new AsynchronousFailureException("Failure or interrupt detected in handler: " - + payload.getMessage()); - } - } - } - - /** - * Re-throws the original throwable if it is unchecked, wraps checked exceptions into - * {@link AsynchronousFailureException}. - */ - private static AsynchronousFailureException wrapIfNecessary(Throwable throwable) { - if (throwable instanceof Error) { - throw (Error) throwable; - } - else if (throwable instanceof AsynchronousFailureException) { - return (AsynchronousFailureException) throwable; - } - else { - return new AsynchronousFailureException("Exception in remote process", throwable); - } - } - - private static class LocalState { - - private final AtomicInteger current = new AtomicInteger(-1); - - private final AtomicInteger actual = new AtomicInteger(); - - private final AtomicInteger expected = new AtomicInteger(); - - private final AtomicInteger redelivered = new AtomicInteger(); - - private StepExecution stepExecution; - - private final Queue contributions = new LinkedBlockingQueue<>(); - - public int getExpecting() { - return expected.get() - actual.get(); - } - - public ChunkRequest getRequest(List items) { - return new ChunkRequest<>(current.incrementAndGet(), items, getJobId(), createStepContribution()); - } - - public void open(int expectedValue, int actualValue) { - actual.set(actualValue); - expected.set(expectedValue); - } - - public Collection pollChunkResponses() { - Collection set = new ArrayList<>(); - synchronized (contributions) { - ChunkResponse item = contributions.poll(); - while (item != null) { - set.add(item); - item = contributions.poll(); - } - } - return set; - } - - public void pushResponse(ChunkResponse stepContribution) { - synchronized (contributions) { - contributions.add(stepContribution); - } - } - - public void incrementRedelivered() { - redelivered.incrementAndGet(); - } - - public void incrementActual() { - actual.incrementAndGet(); - } - - public void incrementExpected() { - expected.incrementAndGet(); - } - - public StepContribution createStepContribution() { - return stepExecution.createStepContribution(); - } - - public Long getJobId() { - return stepExecution.getJobExecution().getJobId(); - } - - public void setStepExecution(StepExecution stepExecution) { - this.stepExecution = stepExecution; - } - - public void reset() { - expected.set(0); - actual.set(0); - } - } - -} +/* + * Copyright 2006-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.integration.chunk; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Queue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.atomic.AtomicInteger; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.StepContribution; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.StepExecutionListener; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ItemStream; +import org.springframework.batch.item.ItemStreamException; +import org.springframework.batch.item.ItemWriter; +import org.springframework.integration.core.MessagingTemplate; +import org.springframework.lang.Nullable; +import org.springframework.messaging.Message; +import org.springframework.messaging.PollableChannel; +import org.springframework.messaging.support.GenericMessage; +import org.springframework.util.Assert; + +public class ChunkMessageChannelItemWriter + implements StepExecutionListener, ItemWriter, ItemStream, StepContributionSource { + + private static final Log logger = LogFactory.getLog(ChunkMessageChannelItemWriter.class); + + static final String ACTUAL = ChunkMessageChannelItemWriter.class.getName() + ".ACTUAL"; + + static final String EXPECTED = ChunkMessageChannelItemWriter.class.getName() + ".EXPECTED"; + + private static final long DEFAULT_THROTTLE_LIMIT = 6; + + private MessagingTemplate messagingGateway; + + private final LocalState localState = new LocalState(); + + private long throttleLimit = DEFAULT_THROTTLE_LIMIT; + + private final int DEFAULT_MAX_WAIT_TIMEOUTS = 40; + + private int maxWaitTimeouts = DEFAULT_MAX_WAIT_TIMEOUTS; + + private PollableChannel replyChannel; + + /** + * The maximum number of times to wait at the end of a step for a non-null result from + * the remote workers. This is a multiplier on the receive timeout set separately on + * the gateway. The ideal value is a compromise between allowing slow workers time to + * finish, and responsiveness if there is a dead worker. Defaults to 40. + * @param maxWaitTimeouts the maximum number of wait timeouts + */ + public void setMaxWaitTimeouts(int maxWaitTimeouts) { + this.maxWaitTimeouts = maxWaitTimeouts; + } + + /** + * Public setter for the throttle limit. This limits the number of pending requests + * for chunk processing to avoid overwhelming the receivers. + * @param throttleLimit the throttle limit to set + */ + public void setThrottleLimit(long throttleLimit) { + this.throttleLimit = throttleLimit; + } + + public void setMessagingOperations(MessagingTemplate messagingGateway) { + this.messagingGateway = messagingGateway; + } + + public void setReplyChannel(PollableChannel replyChannel) { + this.replyChannel = replyChannel; + } + + public void write(List items) throws Exception { + + // Block until expecting <= throttle limit + while (localState.getExpecting() > throttleLimit) { + getNextResult(); + } + + if (!items.isEmpty()) { + + ChunkRequest request = localState.getRequest(items); + if (logger.isDebugEnabled()) { + logger.debug("Dispatching chunk: " + request); + } + messagingGateway.send(new GenericMessage<>(request)); + localState.incrementExpected(); + + } + + } + + @Override + public void beforeStep(StepExecution stepExecution) { + localState.setStepExecution(stepExecution); + } + + @Nullable + @Override + public ExitStatus afterStep(StepExecution stepExecution) { + if (!(stepExecution.getStatus() == BatchStatus.COMPLETED)) { + return ExitStatus.EXECUTING; + } + long expecting = localState.getExpecting(); + boolean timedOut; + try { + logger.debug("Waiting for results in step listener..."); + timedOut = !waitForResults(); + logger.debug("Finished waiting for results in step listener."); + } + catch (RuntimeException e) { + logger.debug("Detected failure waiting for results in step listener.", e); + stepExecution.setStatus(BatchStatus.FAILED); + return ExitStatus.FAILED.addExitDescription(e.getClass().getName() + ": " + e.getMessage()); + } + finally { + + if (logger.isDebugEnabled()) { + logger.debug("Finished waiting for results in step listener. Still expecting: " + + localState.getExpecting()); + } + + for (StepContribution contribution : getStepContributions()) { + stepExecution.apply(contribution); + } + } + if (timedOut) { + stepExecution.setStatus(BatchStatus.FAILED); + return ExitStatus.FAILED.addExitDescription( + "Timed out waiting for " + localState.getExpecting() + " backlog at end of step"); + } + return ExitStatus.COMPLETED.addExitDescription("Waited for " + expecting + " results."); + } + + public void close() throws ItemStreamException { + localState.reset(); + } + + public void open(ExecutionContext executionContext) throws ItemStreamException { + if (executionContext.containsKey(EXPECTED)) { + localState.open(executionContext.getInt(EXPECTED), executionContext.getInt(ACTUAL)); + if (!waitForResults()) { + throw new ItemStreamException("Timed out waiting for back log on open"); + } + } + } + + public void update(ExecutionContext executionContext) throws ItemStreamException { + executionContext.putInt(EXPECTED, localState.expected.intValue()); + executionContext.putInt(ACTUAL, localState.actual.intValue()); + } + + public Collection getStepContributions() { + List contributions = new ArrayList<>(); + for (ChunkResponse response : localState.pollChunkResponses()) { + StepContribution contribution = response.getStepContribution(); + if (logger.isDebugEnabled()) { + logger.debug("Applying: " + response); + } + contributions.add(contribution); + } + return contributions; + } + + /** + * Wait until all the results that are in the pipeline come back to the reply channel. + * @return true if successfully received a result, false if timed out + */ + private boolean waitForResults() throws AsynchronousFailureException { + int count = 0; + int maxCount = maxWaitTimeouts; + Throwable failure = null; + if (logger.isInfoEnabled()) { + logger.info("Waiting for " + localState.getExpecting() + " results"); + } + while (localState.getExpecting() > 0 && count++ < maxCount) { + try { + getNextResult(); + } + catch (Throwable t) { + logger.error("Detected error in remote result. Trying to recover " + localState.getExpecting() + + " outstanding results before completing.", t); + failure = t; + } + } + if (failure != null) { + throw wrapIfNecessary(failure); + } + return count < maxCount; + } + + /** + * Get the next result if it is available (within the timeout specified in the + * gateway), otherwise do nothing. + * @throws AsynchronousFailureException If there is a response and it contains a + * failed chunk response. + * @throws IllegalStateException if the result contains the wrong job instance id + * (maybe we are sharing a channel and we shouldn't be) + */ + @SuppressWarnings("unchecked") + private void getNextResult() throws AsynchronousFailureException { + Message message = (Message) messagingGateway.receive(replyChannel); + if (message != null) { + ChunkResponse payload = message.getPayload(); + if (logger.isDebugEnabled()) { + logger.debug("Found result: " + payload); + } + Long jobInstanceId = payload.getJobId(); + Assert.state(jobInstanceId != null, "Message did not contain job instance id."); + Assert.state(jobInstanceId.equals(localState.getJobId()), "Message contained wrong job instance id [" + + jobInstanceId + "] should have been [" + localState.getJobId() + "]."); + if (payload.isRedelivered()) { + logger.warn( + "Redelivered result detected, which may indicate stale state. In the best case, we just picked up a timed out message " + + "from a previous failed execution. In the worst case (and if this is not a restart), " + + "the step may now timeout. In that case if you believe that all messages " + + "from workers have been sent, the business state " + + "is probably inconsistent, and the step will fail."); + localState.incrementRedelivered(); + } + localState.pushResponse(payload); + localState.incrementActual(); + if (!payload.isSuccessful()) { + throw new AsynchronousFailureException( + "Failure or interrupt detected in handler: " + payload.getMessage()); + } + } + } + + /** + * Re-throws the original throwable if it is unchecked, wraps checked exceptions into + * {@link AsynchronousFailureException}. + */ + private static AsynchronousFailureException wrapIfNecessary(Throwable throwable) { + if (throwable instanceof Error) { + throw (Error) throwable; + } + else if (throwable instanceof AsynchronousFailureException) { + return (AsynchronousFailureException) throwable; + } + else { + return new AsynchronousFailureException("Exception in remote process", throwable); + } + } + + private static class LocalState { + + private final AtomicInteger current = new AtomicInteger(-1); + + private final AtomicInteger actual = new AtomicInteger(); + + private final AtomicInteger expected = new AtomicInteger(); + + private final AtomicInteger redelivered = new AtomicInteger(); + + private StepExecution stepExecution; + + private final Queue contributions = new LinkedBlockingQueue<>(); + + public int getExpecting() { + return expected.get() - actual.get(); + } + + public ChunkRequest getRequest(List items) { + return new ChunkRequest<>(current.incrementAndGet(), items, getJobId(), createStepContribution()); + } + + public void open(int expectedValue, int actualValue) { + actual.set(actualValue); + expected.set(expectedValue); + } + + public Collection pollChunkResponses() { + Collection set = new ArrayList<>(); + synchronized (contributions) { + ChunkResponse item = contributions.poll(); + while (item != null) { + set.add(item); + item = contributions.poll(); + } + } + return set; + } + + public void pushResponse(ChunkResponse stepContribution) { + synchronized (contributions) { + contributions.add(stepContribution); + } + } + + public void incrementRedelivered() { + redelivered.incrementAndGet(); + } + + public void incrementActual() { + actual.incrementAndGet(); + } + + public void incrementExpected() { + expected.incrementAndGet(); + } + + public StepContribution createStepContribution() { + return stepExecution.createStepContribution(); + } + + public Long getJobId() { + return stepExecution.getJobExecution().getJobId(); + } + + public void setStepExecution(StepExecution stepExecution) { + this.stepExecution = stepExecution; + } + + public void reset() { + expected.set(0); + actual.set(0); + } + + } + +} diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/ChunkProcessorChunkHandler.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/ChunkProcessorChunkHandler.java index cc39c8a7c..7ff9115bd 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/ChunkProcessorChunkHandler.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/ChunkProcessorChunkHandler.java @@ -33,13 +33,13 @@ import org.springframework.retry.RetryException; import org.springframework.util.Assert; /** - * A {@link ChunkHandler} based on a {@link ChunkProcessor}. Knows how to distinguish between a processor that is fault - * tolerant, and one that is not. If the processor is fault tolerant then exceptions can be propagated on the assumption - * that there will be a roll back and the request will be re-delivered. + * A {@link ChunkHandler} based on a {@link ChunkProcessor}. Knows how to distinguish + * between a processor that is fault tolerant, and one that is not. If the processor is + * fault tolerant then exceptions can be propagated on the assumption that there will be a + * roll back and the request will be re-delivered. * * @author Dave Syer * @author Michael Minella - * * @param the type of the items in the chunk to be handled */ @MessageEndpoint @@ -60,7 +60,6 @@ public class ChunkProcessorChunkHandler implements ChunkHandler, Initializ /** * Public setter for the {@link ChunkProcessor}. - * * @param chunkProcessor the chunkProcessor to set */ public void setChunkProcessor(ChunkProcessor chunkProcessor) { @@ -83,8 +82,8 @@ public class ChunkProcessorChunkHandler implements ChunkHandler, Initializ Throwable failure = process(chunkRequest, stepContribution); if (failure != null) { logger.debug("Failed chunk", failure); - return new ChunkResponse(false, chunkRequest.getSequence(), chunkRequest.getJobId(), stepContribution, failure.getClass().getName() - + ": " + failure.getMessage()); + return new ChunkResponse(false, chunkRequest.getSequence(), chunkRequest.getJobId(), stepContribution, + failure.getClass().getName() + ": " + failure.getMessage()); } if (logger.isDebugEnabled()) { diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/ChunkRequest.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/ChunkRequest.java index c43c8ff58..3ae79c6e2 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/ChunkRequest.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/ChunkRequest.java @@ -22,11 +22,9 @@ import java.util.Collection; import org.springframework.batch.core.StepContribution; /** - * Encapsulation of a chunk of items to be processed remotely as part of a step - * execution. - * + * Encapsulation of a chunk of items to be processed remotely as part of a step execution. + * * @author Dave Syer - * * @param the type of the items to process */ public class ChunkRequest implements Serializable { diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/ChunkResponse.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/ChunkResponse.java index a8faaf430..30965cb77 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/ChunkResponse.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/ChunkResponse.java @@ -22,11 +22,12 @@ import org.springframework.batch.core.StepContribution; import org.springframework.lang.Nullable; /** - * Encapsulates a response to processing a chunk of items, summarising the result as a {@link StepContribution}. - * + * Encapsulates a response to processing a chunk of items, summarising the result as a + * {@link StepContribution}. + * * @author Dave Syer * @author Mahmoud Ben Hassine - * + * */ public class ChunkResponse implements Serializable { @@ -39,7 +40,7 @@ public class ChunkResponse implements Serializable { private final boolean status; private final String message; - + private final boolean redelivered; private final int sequence; @@ -52,7 +53,8 @@ public class ChunkResponse implements Serializable { this(status, sequence, jobId, stepContribution, null); } - public ChunkResponse(boolean status, int sequence, Long jobId, StepContribution stepContribution, @Nullable String message) { + public ChunkResponse(boolean status, int sequence, Long jobId, StepContribution stepContribution, + @Nullable String message) { this(status, sequence, jobId, stepContribution, message, false); } @@ -60,7 +62,8 @@ public class ChunkResponse implements Serializable { this(input.status, input.sequence, input.jobId, input.stepContribution, input.message, redelivered); } - public ChunkResponse(boolean status, int sequence, Long jobId, StepContribution stepContribution, @Nullable String message, boolean redelivered) { + public ChunkResponse(boolean status, int sequence, Long jobId, StepContribution stepContribution, + @Nullable String message, boolean redelivered) { this.status = status; this.sequence = sequence; this.jobId = jobId; @@ -76,7 +79,7 @@ public class ChunkResponse implements Serializable { public Long getJobId() { return jobId; } - + public int getSequence() { return sequence; } @@ -84,7 +87,7 @@ public class ChunkResponse implements Serializable { public boolean isSuccessful() { return status; } - + public boolean isRedelivered() { return redelivered; } @@ -98,8 +101,8 @@ public class ChunkResponse implements Serializable { */ @Override public String toString() { - return getClass().getSimpleName() + ": jobId=" + jobId + ", sequence=" + sequence + ", stepContribution=" + stepContribution - + ", successful=" + status; + return getClass().getSimpleName() + ": jobId=" + jobId + ", sequence=" + sequence + ", stepContribution=" + + stepContribution + ", successful=" + status; } } diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/JmsRedeliveredExtractor.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/JmsRedeliveredExtractor.java index 952ef1749..bb483cd29 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/JmsRedeliveredExtractor.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/JmsRedeliveredExtractor.java @@ -1,38 +1,38 @@ -/* - * Copyright 2009-2010 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.integration.chunk; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.messaging.handler.annotation.Header; -import org.springframework.jms.support.JmsHeaders; - -/** - * @author Dave Syer - * - */ -public class JmsRedeliveredExtractor { - - private static final Log logger = LogFactory.getLog(JmsRedeliveredExtractor.class); - - public ChunkResponse extract(ChunkResponse input, @Header(JmsHeaders.REDELIVERED) boolean redelivered) { - if (logger.isDebugEnabled()) { - logger.debug("Extracted redelivered flag for response, value="+redelivered); - } - return new ChunkResponse(input, redelivered); - } - -} +/* + * Copyright 2009-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.integration.chunk; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.messaging.handler.annotation.Header; +import org.springframework.jms.support.JmsHeaders; + +/** + * @author Dave Syer + * + */ +public class JmsRedeliveredExtractor { + + private static final Log logger = LogFactory.getLog(JmsRedeliveredExtractor.class); + + public ChunkResponse extract(ChunkResponse input, @Header(JmsHeaders.REDELIVERED) boolean redelivered) { + if (logger.isDebugEnabled()) { + logger.debug("Extracted redelivered flag for response, value=" + redelivered); + } + return new ChunkResponse(input, redelivered); + } + +} diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/MessageSourcePollerInterceptor.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/MessageSourcePollerInterceptor.java index ecebd838a..2a2abd11d 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/MessageSourcePollerInterceptor.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/MessageSourcePollerInterceptor.java @@ -9,12 +9,12 @@ import org.springframework.messaging.MessageChannel; import org.springframework.messaging.support.ChannelInterceptor; import org.springframework.util.Assert; - /** - * A {@link ChannelInterceptor} that turns a pollable channel into a "pass-thru channel": if a client calls - * receive() on the channel it will delegate to a {@link MessageSource} to pull the message directly from - * an external source. This is particularly useful in combination with a message channel in thread scope, in which case - * the receive() can join a transaction which was started by the caller. + * A {@link ChannelInterceptor} that turns a pollable channel into a "pass-thru channel": + * if a client calls receive() on the channel it will delegate to a + * {@link MessageSource} to pull the message directly from an external source. This is + * particularly useful in combination with a message channel in thread scope, in which + * case the receive() can join a transaction which was started by the caller. * * @author Dave Syer * @@ -41,9 +41,8 @@ public class MessageSourcePollerInterceptor implements ChannelInterceptor, Initi } /** - * Optional MessageChannel for injecting the message received from the source (defaults to the channel intercepted - * in {@link #preReceive(MessageChannel)}). - * + * Optional MessageChannel for injecting the message received from the source + * (defaults to the channel intercepted in {@link #preReceive(MessageChannel)}). * @param channel the channel to set */ public void setChannel(MessageChannel channel) { @@ -66,8 +65,8 @@ public class MessageSourcePollerInterceptor implements ChannelInterceptor, Initi } /** - * Receive from the {@link MessageSource} and send immediately to the input channel, so that the call that we are - * intercepting always a message to receive. + * Receive from the {@link MessageSource} and send immediately to the input channel, + * so that the call that we are intercepting always a message to receive. * * @see ChannelInterceptor#preReceive(MessageChannel) */ diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/RemoteChunkHandlerFactoryBean.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/RemoteChunkHandlerFactoryBean.java index 1fe6ec3da..d6ccd4325 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/RemoteChunkHandlerFactoryBean.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/RemoteChunkHandlerFactoryBean.java @@ -36,16 +36,18 @@ import org.springframework.util.Assert; import org.springframework.util.ReflectionUtils; /** - * Convenient factory bean for a chunk handler that also converts an existing chunk-oriented step into a remote chunk - * manager. The idea is to lift the existing chunk processor out of a Step that works locally, and replace it with a one - * that writes chunks into a message channel. The existing step hands its business chunk processing responsibility over - * to the handler produced by the factory, which then needs to be set up as a worker on the other end of the channel the - * chunks are being sent to. Once this chunk handler is installed the application is playing the role of both the manager - * and the worker listeners in the Remote Chunking pattern for the Step in question. - * + * Convenient factory bean for a chunk handler that also converts an existing + * chunk-oriented step into a remote chunk manager. The idea is to lift the existing chunk + * processor out of a Step that works locally, and replace it with a one that writes + * chunks into a message channel. The existing step hands its business chunk processing + * responsibility over to the handler produced by the factory, which then needs to be set + * up as a worker on the other end of the channel the chunks are being sent to. Once this + * chunk handler is installed the application is playing the role of both the manager and + * the worker listeners in the Remote Chunking pattern for the Step in question. + * * @author Dave Syer * @author Mahmoud Ben Hassine - * + * */ public class RemoteChunkHandlerFactoryBean implements FactoryBean> { @@ -59,7 +61,6 @@ public class RemoteChunkHandlerFactoryBean implements FactoryBean implements FactoryBean chunkWriter) { @@ -78,8 +79,8 @@ public class RemoteChunkHandlerFactoryBean implements FactoryBean implements FactoryBean getObjectType() { @@ -96,7 +97,7 @@ public class RemoteChunkHandlerFactoryBean implements FactoryBean implements FactoryBean getObject() throws Exception { @@ -124,8 +125,8 @@ public class RemoteChunkHandlerFactoryBean implements FactoryBean, "Tasklet must be ChunkOrientedTasklet in step=" - + step.getName()); + Assert.state(tasklet instanceof ChunkOrientedTasklet, + "Tasklet must be ChunkOrientedTasklet in step=" + step.getName()); ChunkProcessor chunkProcessor = getChunkProcessor((ChunkOrientedTasklet) tasklet); Assert.state(chunkProcessor != null, "ChunkProcessor must be accessible in Tasklet in step=" + step.getName()); @@ -161,35 +162,37 @@ public class RemoteChunkHandlerFactoryBean implements FactoryBean tasklet, ItemWriter chunkWriter, final StepContributionSource stepContributionSource) { - setField(tasklet, "chunkProcessor", new SimpleChunkProcessor(new PassThroughItemProcessor<>(), - chunkWriter) { - @Override - protected void write(StepContribution contribution, Chunk inputs, Chunk outputs) throws Exception { - doWrite(outputs.getItems()); - // Do not update the step contribution until the chunks are - // actually processed - updateStepContribution(contribution, stepContributionSource); - } - }); + setField(tasklet, "chunkProcessor", + new SimpleChunkProcessor(new PassThroughItemProcessor<>(), chunkWriter) { + @Override + protected void write(StepContribution contribution, Chunk inputs, Chunk outputs) + throws Exception { + doWrite(outputs.getItems()); + // Do not update the step contribution until the chunks are + // actually processed + updateStepContribution(contribution, stepContributionSource); + } + }); } /** - * Update a StepContribution with all the data from a StepContributionSource. The filter and write counts plus the - * exit status will be updated to reflect the data in the source. - * + * Update a StepContribution with all the data from a StepContributionSource. The + * filter and write counts plus the exit status will be updated to reflect the data in + * the source. * @param contribution the current contribution * @param stepContributionSource a source of StepContributions */ - protected void updateStepContribution(StepContribution contribution, StepContributionSource stepContributionSource) { + protected void updateStepContribution(StepContribution contribution, + StepContributionSource stepContributionSource) { for (StepContribution result : stepContributionSource.getStepContributions()) { contribution.incrementFilterCount(result.getFilterCount()); contribution.incrementWriteCount(result.getWriteCount()); diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/RemoteChunkingManagerStepBuilder.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/RemoteChunkingManagerStepBuilder.java index c3c35e9dd..8a684c704 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/RemoteChunkingManagerStepBuilder.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/RemoteChunkingManagerStepBuilder.java @@ -44,38 +44,46 @@ import org.springframework.transaction.interceptor.TransactionAttribute; import org.springframework.util.Assert; /** - * Builder for a manager step in a remote chunking setup. This builder creates and - * sets a {@link ChunkMessageChannelItemWriter} on the manager step. + * Builder for a manager step in a remote chunking setup. This builder creates and sets a + * {@link ChunkMessageChannelItemWriter} on the manager step. * - *

      If no {@code messagingTemplate} is provided through - * {@link RemoteChunkingManagerStepBuilder#messagingTemplate(MessagingTemplate)}, - * this builder will create one and set its default channel to the {@code outputChannel} - * provided through {@link RemoteChunkingManagerStepBuilder#outputChannel(MessageChannel)}.

      + *

      + * If no {@code messagingTemplate} is provided through + * {@link RemoteChunkingManagerStepBuilder#messagingTemplate(MessagingTemplate)}, this + * builder will create one and set its default channel to the {@code outputChannel} + * provided through + * {@link RemoteChunkingManagerStepBuilder#outputChannel(MessageChannel)}. + *

      * - *

      If a {@code messagingTemplate} is provided, it is assumed that it is fully configured + *

      + * If a {@code messagingTemplate} is provided, it is assumed that it is fully configured * and that its default channel is set to an output channel on which requests to workers - * will be sent.

      + * will be sent. + *

      * * @param type of input items * @param type of output items - * * @since 4.2 * @author Mahmoud Ben Hassine */ public class RemoteChunkingManagerStepBuilder extends FaultTolerantStepBuilder { private MessagingTemplate messagingTemplate; + private PollableChannel inputChannel; + private MessageChannel outputChannel; private final int DEFAULT_MAX_WAIT_TIMEOUTS = 40; + private static final long DEFAULT_THROTTLE_LIMIT = 6; + private int maxWaitTimeouts = DEFAULT_MAX_WAIT_TIMEOUTS; + private long throttleLimit = DEFAULT_THROTTLE_LIMIT; /** * Create a new {@link RemoteChunkingManagerStepBuilder}. - * * @param stepName name of the manager step */ public RemoteChunkingManagerStepBuilder(String stepName) { @@ -83,10 +91,9 @@ public class RemoteChunkingManagerStepBuilder extends FaultTolerantStepBui } /** - * Set the input channel on which replies from workers will be received. - * The provided input channel will be set as a reply channel on the + * Set the input channel on which replies from workers will be received. The provided + * input channel will be set as a reply channel on the * {@link ChunkMessageChannelItemWriter} created by this builder. - * * @param inputChannel the input channel * @return this builder instance for fluent chaining * @@ -99,12 +106,14 @@ public class RemoteChunkingManagerStepBuilder extends FaultTolerantStepBui } /** - * Set the output channel on which requests to workers will be sent. By using - * this setter, a default messaging template will be created and the output - * channel will be set as its default channel. - *

      Use either this setter or {@link RemoteChunkingManagerStepBuilder#messagingTemplate(MessagingTemplate)} - * to provide a fully configured messaging template.

      - * + * Set the output channel on which requests to workers will be sent. By using this + * setter, a default messaging template will be created and the output channel will be + * set as its default channel. + *

      + * Use either this setter or + * {@link RemoteChunkingManagerStepBuilder#messagingTemplate(MessagingTemplate)} to + * provide a fully configured messaging template. + *

      * @param outputChannel the output channel. * @return this builder instance for fluent chaining * @@ -117,12 +126,14 @@ public class RemoteChunkingManagerStepBuilder extends FaultTolerantStepBui } /** - * Set the {@link MessagingTemplate} to use to send data to workers. - * The default channel of the messaging template must be set. - *

      Use either this setter to provide a fully configured messaging template or - * provide an output channel through {@link RemoteChunkingManagerStepBuilder#outputChannel(MessageChannel)} - * and a default messaging template will be created.

      - * + * Set the {@link MessagingTemplate} to use to send data to workers. The + * default channel of the messaging template must be set. + *

      + * Use either this setter to provide a fully configured messaging template or provide + * an output channel through + * {@link RemoteChunkingManagerStepBuilder#outputChannel(MessageChannel)} and a + * default messaging template will be created. + *

      * @param messagingTemplate the messaging template to use * @return this builder instance for fluent chaining * @see RemoteChunkingManagerStepBuilder#outputChannel(MessageChannel) @@ -134,10 +145,10 @@ public class RemoteChunkingManagerStepBuilder extends FaultTolerantStepBui } /** - * The maximum number of times to wait at the end of a step for a non-null result from the remote workers. This is a - * multiplier on the receive timeout set separately on the gateway. The ideal value is a compromise between allowing - * slow workers time to finish, and responsiveness if there is a dead worker. Defaults to 40. - * + * The maximum number of times to wait at the end of a step for a non-null result from + * the remote workers. This is a multiplier on the receive timeout set separately on + * the gateway. The ideal value is a compromise between allowing slow workers time to + * finish, and responsiveness if there is a dead worker. Defaults to 40. * @param maxWaitTimeouts the maximum number of wait timeouts * @return this builder instance for fluent chaining * @see ChunkMessageChannelItemWriter#setMaxWaitTimeouts(int) @@ -149,9 +160,8 @@ public class RemoteChunkingManagerStepBuilder extends FaultTolerantStepBui } /** - * Public setter for the throttle limit. This limits the number of pending requests for chunk processing to avoid - * overwhelming the receivers. - * + * Public setter for the throttle limit. This limits the number of pending requests + * for chunk processing to avoid overwhelming the receivers. * @param throttleLimit the throttle limit to set * @return this builder instance for fluent chaining * @see ChunkMessageChannelItemWriter#setThrottleLimit(long) @@ -164,7 +174,6 @@ public class RemoteChunkingManagerStepBuilder extends FaultTolerantStepBui /** * Build a manager {@link TaskletStep}. - * * @return the configured manager step * @see RemoteChunkHandlerFactoryBean */ @@ -194,10 +203,9 @@ public class RemoteChunkingManagerStepBuilder extends FaultTolerantStepBui } /* - * The following methods override those from parent builders and return - * the current builder type. - * FIXME: Change parent builders to be generic and return current builder - * type in each method. + * The following methods override those from parent builders and return the current + * builder type. FIXME: Change parent builders to be generic and return current + * builder type in each method. */ @Override @@ -339,23 +347,22 @@ public class RemoteChunkingManagerStepBuilder extends FaultTolerantStepBui } /** - * This method will throw a {@link UnsupportedOperationException} since - * the item writer of the manager step in a remote chunking setup will be - * automatically set to an instance of {@link ChunkMessageChannelItemWriter}. - * - * When building a manager step for remote chunking, no item writer must be - * provided. + * This method will throw a {@link UnsupportedOperationException} since the item + * writer of the manager step in a remote chunking setup will be automatically set to + * an instance of {@link ChunkMessageChannelItemWriter}. * + * When building a manager step for remote chunking, no item writer must be provided. * @throws UnsupportedOperationException if an item writer is provided * @see ChunkMessageChannelItemWriter * @see RemoteChunkHandlerFactoryBean#setChunkWriter(ItemWriter) */ @Override - public RemoteChunkingManagerStepBuilder writer(ItemWriter writer) throws UnsupportedOperationException { - throw new UnsupportedOperationException("When configuring a manager step " + - "for remote chunking, the item writer will be automatically set " + - "to an instance of ChunkMessageChannelItemWriter. The item writer " + - "must not be provided in this case."); + public RemoteChunkingManagerStepBuilder writer(ItemWriter writer) + throws UnsupportedOperationException { + throw new UnsupportedOperationException( + "When configuring a manager step " + "for remote chunking, the item writer will be automatically set " + + "to an instance of ChunkMessageChannelItemWriter. The item writer " + + "must not be provided in this case."); } @Override @@ -417,4 +424,5 @@ public class RemoteChunkingManagerStepBuilder extends FaultTolerantStepBui super.processor(itemProcessor); return this; } + } diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/RemoteChunkingManagerStepBuilderFactory.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/RemoteChunkingManagerStepBuilderFactory.java index f83149512..5bb12d187 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/RemoteChunkingManagerStepBuilderFactory.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/RemoteChunkingManagerStepBuilderFactory.java @@ -19,8 +19,8 @@ import org.springframework.batch.core.repository.JobRepository; import org.springframework.transaction.PlatformTransactionManager; /** - * Convenient factory for a {@link RemoteChunkingManagerStepBuilder} which sets - * the {@link JobRepository} and {@link PlatformTransactionManager} automatically. + * Convenient factory for a {@link RemoteChunkingManagerStepBuilder} which sets the + * {@link JobRepository} and {@link PlatformTransactionManager} automatically. * * @since 4.2 * @author Mahmoud Ben Hassine @@ -33,12 +33,10 @@ public class RemoteChunkingManagerStepBuilderFactory { /** * Create a new {@link RemoteChunkingManagerStepBuilderFactory}. - * * @param jobRepository the job repository to use * @param transactionManager the transaction manager to use */ - public RemoteChunkingManagerStepBuilderFactory( - JobRepository jobRepository, + public RemoteChunkingManagerStepBuilderFactory(JobRepository jobRepository, PlatformTransactionManager transactionManager) { this.jobRepository = jobRepository; @@ -48,15 +46,13 @@ public class RemoteChunkingManagerStepBuilderFactory { /** * Creates a {@link RemoteChunkingManagerStepBuilder} and initializes its job * repository and transaction manager. - * * @param name the name of the step * @param type of input items * @param type of output items * @return a {@link RemoteChunkingManagerStepBuilder} */ public RemoteChunkingManagerStepBuilder get(String name) { - return new RemoteChunkingManagerStepBuilder(name) - .repository(this.jobRepository) + return new RemoteChunkingManagerStepBuilder(name).repository(this.jobRepository) .transactionManager(this.transactionManager); } diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/RemoteChunkingWorkerBuilder.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/RemoteChunkingWorkerBuilder.java index 3eb0f02cd..5435a353a 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/RemoteChunkingWorkerBuilder.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/RemoteChunkingWorkerBuilder.java @@ -28,18 +28,16 @@ import org.springframework.util.Assert; * Builder for a worker in a remote chunking setup. This builder: * *
        - *
      • creates a {@link ChunkProcessorChunkHandler} with the provided - * item processor and writer. If no item processor is provided, a - * {@link PassThroughItemProcessor} will be used
      • - *
      • creates an {@link IntegrationFlow} with the - * {@link ChunkProcessorChunkHandler} as a service activator which listens - * to incoming requests on inputChannel and sends replies - * on outputChannel
      • + *
      • creates a {@link ChunkProcessorChunkHandler} with the provided item processor and + * writer. If no item processor is provided, a {@link PassThroughItemProcessor} will be + * used
      • + *
      • creates an {@link IntegrationFlow} with the {@link ChunkProcessorChunkHandler} as a + * service activator which listens to incoming requests on inputChannel and + * sends replies on outputChannel
      • *
      * * @param type of input items * @param type of output items - * * @since 4.1 * @author Mahmoud Ben Hassine */ @@ -48,14 +46,15 @@ public class RemoteChunkingWorkerBuilder { private static final String SERVICE_ACTIVATOR_METHOD_NAME = "handleChunk"; private ItemProcessor itemProcessor; + private ItemWriter itemWriter; + private MessageChannel inputChannel; + private MessageChannel outputChannel; /** - * Set the {@link ItemProcessor} to use to process items sent by the manager - * step. - * + * Set the {@link ItemProcessor} to use to process items sent by the manager step. * @param itemProcessor to use * @return this builder instance for fluent chaining */ @@ -67,7 +66,6 @@ public class RemoteChunkingWorkerBuilder { /** * Set the {@link ItemWriter} to use to write items sent by the manager step. - * * @param itemWriter to use * @return this builder instance for fluent chaining */ @@ -79,7 +77,6 @@ public class RemoteChunkingWorkerBuilder { /** * Set the input channel on which items sent by the manager are received. - * * @param inputChannel the input channel * @return this builder instance for fluent chaining */ @@ -91,7 +88,6 @@ public class RemoteChunkingWorkerBuilder { /** * Set the output channel on which replies will be sent to the manager step. - * * @param outputChannel the output channel * @return this builder instance for fluent chaining */ @@ -103,18 +99,17 @@ public class RemoteChunkingWorkerBuilder { /** * Create an {@link IntegrationFlow} with a {@link ChunkProcessorChunkHandler} - * configured as a service activator listening to the input channel and replying - * on the output channel. - * + * configured as a service activator listening to the input channel and replying on + * the output channel. * @return the integration flow */ - @SuppressWarnings({"unchecked", "rawtypes"}) + @SuppressWarnings({ "unchecked", "rawtypes" }) public IntegrationFlow build() { Assert.notNull(this.itemWriter, "An ItemWriter must be provided"); Assert.notNull(this.inputChannel, "An InputChannel must be provided"); Assert.notNull(this.outputChannel, "An OutputChannel must be provided"); - if(this.itemProcessor == null) { + if (this.itemProcessor == null) { this.itemProcessor = new PassThroughItemProcessor(); } SimpleChunkProcessor chunkProcessor = new SimpleChunkProcessor<>(this.itemProcessor, this.itemWriter); @@ -122,11 +117,8 @@ public class RemoteChunkingWorkerBuilder { ChunkProcessorChunkHandler chunkProcessorChunkHandler = new ChunkProcessorChunkHandler<>(); chunkProcessorChunkHandler.setChunkProcessor(chunkProcessor); - return IntegrationFlows - .from(this.inputChannel) - .handle(chunkProcessorChunkHandler, SERVICE_ACTIVATOR_METHOD_NAME) - .channel(this.outputChannel) - .get(); + return IntegrationFlows.from(this.inputChannel) + .handle(chunkProcessorChunkHandler, SERVICE_ACTIVATOR_METHOD_NAME).channel(this.outputChannel).get(); } } diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/StepContributionSource.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/StepContributionSource.java index 9b6997f67..50b599a93 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/StepContributionSource.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/chunk/StepContributionSource.java @@ -22,18 +22,17 @@ import org.springframework.batch.core.StepContribution; import org.springframework.batch.core.StepExecution; /** - * A source of {@link StepContribution} instances that can be aggregated and used to update an ongoing - * {@link StepExecution}. - * + * A source of {@link StepContribution} instances that can be aggregated and used to + * update an ongoing {@link StepExecution}. + * * @author Dave Syer - * + * */ public interface StepContributionSource { /** - * Get the currently available contributions and drain the source. The next call would return an empty collection, - * unless new contributions have arrived. - * + * Get the currently available contributions and drain the source. The next call would + * return an empty collection, unless new contributions have arrived. * @return a collection of {@link StepContribution} instances */ Collection getStepContributions(); diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/config/annotation/BatchIntegrationConfiguration.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/config/annotation/BatchIntegrationConfiguration.java index 3a973f571..192adb107 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/config/annotation/BatchIntegrationConfiguration.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/config/annotation/BatchIntegrationConfiguration.java @@ -51,9 +51,7 @@ public class BatchIntegrationConfiguration implements InitializingBean { private RemotePartitioningWorkerStepBuilderFactory remotePartitioningWorkerStepBuilderFactory; @Autowired - public BatchIntegrationConfiguration( - JobRepository jobRepository, - JobExplorer jobExplorer, + public BatchIntegrationConfiguration(JobRepository jobRepository, JobExplorer jobExplorer, PlatformTransactionManager transactionManager) { this.jobRepository = jobRepository; @@ -67,7 +65,7 @@ public class BatchIntegrationConfiguration implements InitializingBean { } @Bean - public RemoteChunkingWorkerBuilder remoteChunkingWorkerBuilder() { + public RemoteChunkingWorkerBuilder remoteChunkingWorkerBuilder() { return remoteChunkingWorkerBuilder; } @@ -86,9 +84,10 @@ public class BatchIntegrationConfiguration implements InitializingBean { this.remoteChunkingManagerStepBuilderFactory = new RemoteChunkingManagerStepBuilderFactory(this.jobRepository, this.transactionManager); this.remoteChunkingWorkerBuilder = new RemoteChunkingWorkerBuilder<>(); - this.remotePartitioningManagerStepBuilderFactory = new RemotePartitioningManagerStepBuilderFactory(this.jobRepository, - this.jobExplorer, this.transactionManager); - this.remotePartitioningWorkerStepBuilderFactory = new RemotePartitioningWorkerStepBuilderFactory(this.jobRepository, - this.jobExplorer, this.transactionManager); + this.remotePartitioningManagerStepBuilderFactory = new RemotePartitioningManagerStepBuilderFactory( + this.jobRepository, this.jobExplorer, this.transactionManager); + this.remotePartitioningWorkerStepBuilderFactory = new RemotePartitioningWorkerStepBuilderFactory( + this.jobRepository, this.jobExplorer, this.transactionManager); } + } diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/config/annotation/EnableBatchIntegration.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/config/annotation/EnableBatchIntegration.java index 8d5897ec4..68534d86a 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/config/annotation/EnableBatchIntegration.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/config/annotation/EnableBatchIntegration.java @@ -29,24 +29,25 @@ import org.springframework.context.annotation.Import; import org.springframework.integration.config.EnableIntegration; /** - * Enable Spring Batch Integration features and provide a base configuration for - * setting up remote chunking or partitioning infrastructure beans. + * Enable Spring Batch Integration features and provide a base configuration for setting + * up remote chunking or partitioning infrastructure beans. * - * By adding this annotation on a {@link org.springframework.context.annotation.Configuration} - * class, it will be possible to autowire the following beans: + * By adding this annotation on a + * {@link org.springframework.context.annotation.Configuration} class, it will be possible + * to autowire the following beans: * *
        - *
      • {@link RemoteChunkingManagerStepBuilderFactory}: - * used to create a manager step of a remote chunking setup by automatically - * setting the job repository and transaction manager.
      • - *
      • {@link RemoteChunkingWorkerBuilder}: used to create the integration - * flow on the worker side of a remote chunking setup.
      • - *
      • {@link RemotePartitioningManagerStepBuilderFactory}: used to create - * a manager step of a remote partitioning setup by automatically setting - * the job repository, job explorer, bean factory and transaction manager.
      • - *
      • {@link RemotePartitioningWorkerStepBuilderFactory}: used to create - * a worker step of a remote partitioning setup by automatically setting - * the job repository, job explorer, bean factory and transaction manager.
      • + *
      • {@link RemoteChunkingManagerStepBuilderFactory}: used to create a manager step of a + * remote chunking setup by automatically setting the job repository and transaction + * manager.
      • + *
      • {@link RemoteChunkingWorkerBuilder}: used to create the integration flow on the + * worker side of a remote chunking setup.
      • + *
      • {@link RemotePartitioningManagerStepBuilderFactory}: used to create a manager step + * of a remote partitioning setup by automatically setting the job repository, job + * explorer, bean factory and transaction manager.
      • + *
      • {@link RemotePartitioningWorkerStepBuilderFactory}: used to create a worker step of + * a remote partitioning setup by automatically setting the job repository, job explorer, + * bean factory and transaction manager.
      • *
      * * For remote chunking, an example of a configuration class would be: @@ -140,4 +141,5 @@ import org.springframework.integration.config.EnableIntegration; @EnableIntegration @Import(BatchIntegrationConfiguration.class) public @interface EnableBatchIntegration { + } diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/config/xml/BatchIntegrationNamespaceHandler.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/config/xml/BatchIntegrationNamespaceHandler.java index 2d6bba008..d6028037f 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/config/xml/BatchIntegrationNamespaceHandler.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/config/xml/BatchIntegrationNamespaceHandler.java @@ -26,14 +26,18 @@ import org.springframework.integration.config.xml.AbstractIntegrationNamespaceHa * @since 1.3 */ public class BatchIntegrationNamespaceHandler extends AbstractIntegrationNamespaceHandler { - /* (non-Javadoc) + + /* + * (non-Javadoc) + * * @see org.springframework.beans.factory.xml.NamespaceHandler#init() */ public void init() { - this.registerBeanDefinitionParser("job-launching-gateway", new JobLaunchingGatewayParser()); + this.registerBeanDefinitionParser("job-launching-gateway", new JobLaunchingGatewayParser()); RemoteChunkingManagerParser remoteChunkingManagerParser = new RemoteChunkingManagerParser(); this.registerBeanDefinitionParser("remote-chunking-manager", remoteChunkingManagerParser); RemoteChunkingWorkerParser remoteChunkingWorkerParser = new RemoteChunkingWorkerParser(); this.registerBeanDefinitionParser("remote-chunking-worker", remoteChunkingWorkerParser); } + } diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/config/xml/JobLaunchingGatewayParser.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/config/xml/JobLaunchingGatewayParser.java index 7bb3f769d..1435e16df 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/config/xml/JobLaunchingGatewayParser.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/config/xml/JobLaunchingGatewayParser.java @@ -28,9 +28,8 @@ import org.w3c.dom.Element; /** * The parser for the Job-Launching Gateway, which will instantiate a - * {@link JobLaunchingGatewayParser}. If no {@link JobLauncher} reference has - * been provided, this parse will use the use the globally registered bean - * 'jobLauncher'. + * {@link JobLaunchingGatewayParser}. If no {@link JobLauncher} reference has been + * provided, this parse will use the use the globally registered bean 'jobLauncher'. * * @author Gunnar Hillert * @since 1.3 @@ -48,8 +47,8 @@ public class JobLaunchingGatewayParser extends AbstractConsumerEndpointParser { @Override protected BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) { - final BeanDefinitionBuilder jobLaunchingGatewayBuilder = - BeanDefinitionBuilder.genericBeanDefinition(JobLaunchingGateway.class); + final BeanDefinitionBuilder jobLaunchingGatewayBuilder = BeanDefinitionBuilder + .genericBeanDefinition(JobLaunchingGateway.class); final String jobLauncher = element.getAttribute("job-launcher"); @@ -63,7 +62,8 @@ public class JobLaunchingGatewayParser extends AbstractConsumerEndpointParser { jobLaunchingGatewayBuilder.addConstructorArgReference("jobLauncher"); } - IntegrationNamespaceUtils.setValueIfAttributeDefined(jobLaunchingGatewayBuilder, element, "reply-timeout", "sendTimeout"); + IntegrationNamespaceUtils.setValueIfAttributeDefined(jobLaunchingGatewayBuilder, element, "reply-timeout", + "sendTimeout"); final String replyChannel = element.getAttribute("reply-channel"); diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/config/xml/RemoteChunkingManagerParser.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/config/xml/RemoteChunkingManagerParser.java index 0959fa4e0..082fcab92 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/config/xml/RemoteChunkingManagerParser.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/config/xml/RemoteChunkingManagerParser.java @@ -36,13 +36,21 @@ import org.w3c.dom.Element; * @since 3.1 */ public class RemoteChunkingManagerParser extends AbstractBeanDefinitionParser { + private static final String MESSAGE_TEMPLATE_ATTRIBUTE = "message-template"; + private static final String STEP_ATTRIBUTE = "step"; + private static final String REPLY_CHANNEL_ATTRIBUTE = "reply-channel"; + private static final String MESSAGING_OPERATIONS_PROPERTY = "messagingOperations"; + private static final String REPLY_CHANNEL_PROPERTY = "replyChannel"; + private static final String CHUNK_WRITER_PROPERTY = "chunkWriter"; + private static final String STEP_PROPERTY = "step"; + private static final String CHUNK_HANDLER_BEAN_NAME_PREFIX = "remoteChunkHandlerFactoryBean_"; @Override @@ -61,24 +69,22 @@ public class RemoteChunkingManagerParser extends AbstractBeanDefinitionParser { BeanDefinitionRegistry beanDefinitionRegistry = parserContext.getRegistry(); - BeanDefinition chunkMessageChannelItemWriter = - BeanDefinitionBuilder - .genericBeanDefinition(ChunkMessageChannelItemWriter.class) - .addPropertyReference(MESSAGING_OPERATIONS_PROPERTY, messageTemplate) - .addPropertyReference(REPLY_CHANNEL_PROPERTY, replyChannel) - .getBeanDefinition(); + BeanDefinition chunkMessageChannelItemWriter = BeanDefinitionBuilder + .genericBeanDefinition(ChunkMessageChannelItemWriter.class) + .addPropertyReference(MESSAGING_OPERATIONS_PROPERTY, messageTemplate) + .addPropertyReference(REPLY_CHANNEL_PROPERTY, replyChannel).getBeanDefinition(); beanDefinitionRegistry.registerBeanDefinition(id, chunkMessageChannelItemWriter); - BeanDefinition remoteChunkHandlerFactoryBean = - BeanDefinitionBuilder - .genericBeanDefinition(RemoteChunkHandlerFactoryBean.class) - .addPropertyValue(CHUNK_WRITER_PROPERTY, chunkMessageChannelItemWriter) - .addPropertyValue(STEP_PROPERTY, step) - .getBeanDefinition(); + BeanDefinition remoteChunkHandlerFactoryBean = BeanDefinitionBuilder + .genericBeanDefinition(RemoteChunkHandlerFactoryBean.class) + .addPropertyValue(CHUNK_WRITER_PROPERTY, chunkMessageChannelItemWriter) + .addPropertyValue(STEP_PROPERTY, step).getBeanDefinition(); - beanDefinitionRegistry.registerBeanDefinition(CHUNK_HANDLER_BEAN_NAME_PREFIX + step, remoteChunkHandlerFactoryBean); + beanDefinitionRegistry.registerBeanDefinition(CHUNK_HANDLER_BEAN_NAME_PREFIX + step, + remoteChunkHandlerFactoryBean); return null; } + } diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/config/xml/RemoteChunkingWorkerParser.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/config/xml/RemoteChunkingWorkerParser.java index f0052f4ad..2fa90ff7b 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/config/xml/RemoteChunkingWorkerParser.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/config/xml/RemoteChunkingWorkerParser.java @@ -45,13 +45,21 @@ import org.springframework.util.StringUtils; * @since 3.1 */ public class RemoteChunkingWorkerParser extends AbstractBeanDefinitionParser { + private static final String INPUT_CHANNEL_ATTRIBUTE = "input-channel"; + private static final String OUTPUT_CHANNEL_ATTRIBUTE = "output-channel"; + private static final String ITEM_PROCESSOR_ATTRIBUTE = "item-processor"; + private static final String ITEM_WRITER_ATTRIBUTE = "item-writer"; + private static final String ITEM_PROCESSOR_PROPERTY_NAME = "itemProcessor"; + private static final String ITEM_WRITER_PROPERTY_NAME = "itemWriter"; + private static final String CHUNK_PROCESSOR_PROPERTY_NAME = "chunkProcessor"; + private static final String CHUNK_PROCESSOR_CHUNK_HANDLER_BEAN_NAME_PREFIX = "chunkProcessorChunkHandler_"; @Override @@ -72,24 +80,24 @@ public class RemoteChunkingWorkerParser extends AbstractBeanDefinitionParser { BeanDefinitionRegistry beanDefinitionRegistry = parserContext.getRegistry(); - BeanDefinitionBuilder chunkProcessorBuilder = - BeanDefinitionBuilder - .genericBeanDefinition(SimpleChunkProcessor.class) - .addPropertyReference(ITEM_WRITER_PROPERTY_NAME, itemWriter); + BeanDefinitionBuilder chunkProcessorBuilder = BeanDefinitionBuilder + .genericBeanDefinition(SimpleChunkProcessor.class) + .addPropertyReference(ITEM_WRITER_PROPERTY_NAME, itemWriter); - if(StringUtils.hasText(itemProcessor)) { + if (StringUtils.hasText(itemProcessor)) { chunkProcessorBuilder.addPropertyReference(ITEM_PROCESSOR_PROPERTY_NAME, itemProcessor); - } else { + } + else { chunkProcessorBuilder.addPropertyValue(ITEM_PROCESSOR_PROPERTY_NAME, new PassThroughItemProcessor<>()); } - BeanDefinition chunkProcessorChunkHandler = - BeanDefinitionBuilder - .genericBeanDefinition(ChunkProcessorChunkHandler.class) - .addPropertyValue(CHUNK_PROCESSOR_PROPERTY_NAME, chunkProcessorBuilder.getBeanDefinition()) - .getBeanDefinition(); + BeanDefinition chunkProcessorChunkHandler = BeanDefinitionBuilder + .genericBeanDefinition(ChunkProcessorChunkHandler.class) + .addPropertyValue(CHUNK_PROCESSOR_PROPERTY_NAME, chunkProcessorBuilder.getBeanDefinition()) + .getBeanDefinition(); - beanDefinitionRegistry.registerBeanDefinition(CHUNK_PROCESSOR_CHUNK_HANDLER_BEAN_NAME_PREFIX + id, chunkProcessorChunkHandler); + beanDefinitionRegistry.registerBeanDefinition(CHUNK_PROCESSOR_CHUNK_HANDLER_BEAN_NAME_PREFIX + id, + chunkProcessorChunkHandler); new ServiceActivatorParser(id).parse(element, parserContext); @@ -97,9 +105,13 @@ public class RemoteChunkingWorkerParser extends AbstractBeanDefinitionParser { } private static class ServiceActivatorParser extends AbstractConsumerEndpointParser { + private static final String TARGET_METHOD_NAME_PROPERTY_NAME = "targetMethodName"; + private static final String TARGET_OBJECT_PROPERTY_NAME = "targetObject"; + private static final String HANDLE_CHUNK_METHOD_NAME = "handleChunk"; + private static final String CHUNK_PROCESSOR_CHUNK_HANDLER_BEAN_NAME_PREFIX = "chunkProcessorChunkHandler_"; private String id; @@ -110,10 +122,14 @@ public class RemoteChunkingWorkerParser extends AbstractBeanDefinitionParser { @Override protected BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) { - BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(ServiceActivatorFactoryBean.class); + BeanDefinitionBuilder builder = BeanDefinitionBuilder + .genericBeanDefinition(ServiceActivatorFactoryBean.class); builder.addPropertyValue(TARGET_METHOD_NAME_PROPERTY_NAME, HANDLE_CHUNK_METHOD_NAME); - builder.addPropertyValue(TARGET_OBJECT_PROPERTY_NAME, new RuntimeBeanReference(CHUNK_PROCESSOR_CHUNK_HANDLER_BEAN_NAME_PREFIX + id)); + builder.addPropertyValue(TARGET_OBJECT_PROPERTY_NAME, + new RuntimeBeanReference(CHUNK_PROCESSOR_CHUNK_HANDLER_BEAN_NAME_PREFIX + id)); return builder; } + } + } diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/launch/JobLaunchRequest.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/launch/JobLaunchRequest.java index 116b4975c..ceebf3428 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/launch/JobLaunchRequest.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/launch/JobLaunchRequest.java @@ -19,10 +19,11 @@ import org.springframework.batch.core.Job; import org.springframework.batch.core.JobParameters; /** - * Encapsulation of a {@link Job} and its {@link JobParameters} forming a request for a job to be launched. - * + * Encapsulation of a {@link Job} and its {@link JobParameters} forming a request for a + * job to be launched. + * * @author Dave Syer - * + * */ public class JobLaunchRequest { diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/launch/JobLaunchRequestHandler.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/launch/JobLaunchRequestHandler.java index 20f18afad..7de15d337 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/launch/JobLaunchRequestHandler.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/launch/JobLaunchRequestHandler.java @@ -21,6 +21,7 @@ import org.springframework.batch.core.JobExecutionException; /** * Interface for handling a {@link JobLaunchRequest} and returning a {@link JobExecution}. + * * @author Dave Syer * */ diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/launch/JobLaunchingGateway.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/launch/JobLaunchingGateway.java index c1cb65b20..a16365cc0 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/launch/JobLaunchingGateway.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/launch/JobLaunchingGateway.java @@ -25,11 +25,10 @@ import org.springframework.messaging.MessageHandlingException; import org.springframework.util.Assert; /** - * The {@link JobLaunchingGateway} is used to launch Batch Jobs. Internally it - * delegates to a {@link JobLaunchingMessageHandler}. + * The {@link JobLaunchingGateway} is used to launch Batch Jobs. Internally it delegates + * to a {@link JobLaunchingMessageHandler}. * * @author Gunnar Hillert - * * @since 1.3 */ public class JobLaunchingGateway extends AbstractReplyProducingMessageHandler { @@ -38,7 +37,6 @@ public class JobLaunchingGateway extends AbstractReplyProducingMessageHandler { /** * Constructor taking a {@link JobLauncher} as parameter. - * * @param jobLauncher Must not be null. * */ @@ -48,15 +46,12 @@ public class JobLaunchingGateway extends AbstractReplyProducingMessageHandler { } /** - * Launches a Batch Job using the provided request {@link Message}. The payload - * of the {@link Message} must be an instance of {@link JobLaunchRequest}. - * + * Launches a Batch Job using the provided request {@link Message}. The payload of the + * {@link Message} must be an instance of {@link JobLaunchRequest}. * @param requestMessage must not be null. - * @return Generally a {@link JobExecution} will always be returned. An - * exception ({@link MessageHandlingException}) will only be thrown if there - * is a failure to start the job. The cause of the exception will be a - * {@link JobExecutionException}. - * + * @return Generally a {@link JobExecution} will always be returned. An exception + * ({@link MessageHandlingException}) will only be thrown if there is a failure to + * start the job. The cause of the exception will be a {@link JobExecutionException}. * @throws MessageHandlingException when a job cannot be launched */ @Override @@ -74,7 +69,8 @@ public class JobLaunchingGateway extends AbstractReplyProducingMessageHandler { try { jobExecution = this.jobLaunchingMessageHandler.launch(jobLaunchRequest); - } catch (JobExecutionException e) { + } + catch (JobExecutionException e) { throw new MessageHandlingException(requestMessage, e); } diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/launch/JobLaunchingMessageHandler.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/launch/JobLaunchingMessageHandler.java index e905151ba..3058af63a 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/launch/JobLaunchingMessageHandler.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/launch/JobLaunchingMessageHandler.java @@ -24,7 +24,9 @@ import org.springframework.batch.core.launch.JobLauncher; import org.springframework.integration.annotation.ServiceActivator; /** - * Message handler which uses strategies to convert a Message into a job and a set of job parameters + * Message handler which uses strategies to convert a Message into a job and a set of job + * parameters + * * @author Jonas Partner * @author Dave Syer * @author Gunnar Hillert @@ -35,7 +37,8 @@ public class JobLaunchingMessageHandler implements JobLaunchRequestHandler { private final JobLauncher jobLauncher; /** - * @param jobLauncher {@link org.springframework.batch.core.launch.JobLauncher} used to execute Spring Batch jobs + * @param jobLauncher {@link org.springframework.batch.core.launch.JobLauncher} used + * to execute Spring Batch jobs */ public JobLaunchingMessageHandler(JobLauncher jobLauncher) { super(); diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/BeanFactoryStepLocator.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/BeanFactoryStepLocator.java index d034d84d4..e066ca48c 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/BeanFactoryStepLocator.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/BeanFactoryStepLocator.java @@ -1,48 +1,48 @@ -package org.springframework.batch.integration.partition; - -import java.util.Arrays; -import java.util.Collection; - -import org.springframework.batch.core.Step; -import org.springframework.batch.core.step.StepLocator; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.BeanFactoryAware; -import org.springframework.beans.factory.ListableBeanFactory; -import org.springframework.util.Assert; - -/** - * A {@link StepLocator} implementation that just looks in its enclosing bean - * factory for components of type {@link Step}. - * - * @author Dave Syer - * @author Mahmoud Ben Hassine - * - */ -public class BeanFactoryStepLocator implements StepLocator, BeanFactoryAware { - - private BeanFactory beanFactory; - - public void setBeanFactory(BeanFactory beanFactory) throws BeansException { - this.beanFactory = beanFactory; - } - - /** - * Look up a bean with the provided name of type {@link Step}. - * @see StepLocator#getStep(String) - */ - public Step getStep(String stepName) { - return beanFactory.getBean(stepName, Step.class); - } - - /** - * Look in the bean factory for all beans of type {@link Step}. - * @throws IllegalStateException if the {@link BeanFactory} is not listable - * @see StepLocator#getStepNames() - */ - public Collection getStepNames() { - Assert.state(beanFactory instanceof ListableBeanFactory, "BeanFactory is not listable."); - return Arrays.asList(((ListableBeanFactory) beanFactory).getBeanNamesForType(Step.class)); - } - -} +package org.springframework.batch.integration.partition; + +import java.util.Arrays; +import java.util.Collection; + +import org.springframework.batch.core.Step; +import org.springframework.batch.core.step.StepLocator; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.beans.factory.ListableBeanFactory; +import org.springframework.util.Assert; + +/** + * A {@link StepLocator} implementation that just looks in its enclosing bean factory for + * components of type {@link Step}. + * + * @author Dave Syer + * @author Mahmoud Ben Hassine + * + */ +public class BeanFactoryStepLocator implements StepLocator, BeanFactoryAware { + + private BeanFactory beanFactory; + + public void setBeanFactory(BeanFactory beanFactory) throws BeansException { + this.beanFactory = beanFactory; + } + + /** + * Look up a bean with the provided name of type {@link Step}. + * @see StepLocator#getStep(String) + */ + public Step getStep(String stepName) { + return beanFactory.getBean(stepName, Step.class); + } + + /** + * Look in the bean factory for all beans of type {@link Step}. + * @throws IllegalStateException if the {@link BeanFactory} is not listable + * @see StepLocator#getStepNames() + */ + public Collection getStepNames() { + Assert.state(beanFactory instanceof ListableBeanFactory, "BeanFactory is not listable."); + return Arrays.asList(((ListableBeanFactory) beanFactory).getBeanNamesForType(Step.class)); + } + +} diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/MessageChannelPartitionHandler.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/MessageChannelPartitionHandler.java index 9af4324f3..2b9bccfa9 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/MessageChannelPartitionHandler.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/MessageChannelPartitionHandler.java @@ -1,319 +1,335 @@ -/* - * Copyright 2009-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.integration.partition; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.Set; -import java.util.concurrent.Callable; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; - -import javax.sql.DataSource; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.batch.core.Step; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.explore.JobExplorer; -import org.springframework.batch.core.explore.support.JobExplorerFactoryBean; -import org.springframework.batch.core.partition.PartitionHandler; -import org.springframework.batch.core.partition.StepExecutionSplitter; -import org.springframework.batch.core.repository.JobRepository; -import org.springframework.batch.poller.DirectPoller; -import org.springframework.batch.poller.Poller; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.integration.MessageTimeoutException; -import org.springframework.integration.annotation.Aggregator; -import org.springframework.integration.annotation.MessageEndpoint; -import org.springframework.integration.annotation.Payloads; -import org.springframework.integration.channel.QueueChannel; -import org.springframework.integration.core.MessagingTemplate; -import org.springframework.integration.support.MessageBuilder; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageChannel; -import org.springframework.messaging.PollableChannel; -import org.springframework.util.Assert; -import org.springframework.util.CollectionUtils; - -/** - * A {@link PartitionHandler} that uses {@link MessageChannel} instances to send instructions to remote workers and - * receive their responses. The {@link MessageChannel} provides a nice abstraction so that the location of the workers - * and the transport used to communicate with them can be changed at run time. The communication with the remote workers - * does not need to be transactional or have guaranteed delivery, so a local thread pool based implementation works as - * well as a remote web service or JMS implementation. If a remote worker fails, the job will fail and can be restarted - * to pick up missing messages and processing. The remote workers need access to the Spring Batch {@link JobRepository} - * so that the shared state across those restarts can be managed centrally. - * - * While a {@link org.springframework.messaging.MessageChannel} is used for sending the requests to the workers, the - * worker's responses can be obtained in one of two ways: - *
        - *
      • A reply channel - Workers will respond with messages that will be aggregated via this component.
      • - *
      • Polling the job repository - Since the state of each worker is maintained independently within the job - * repository, we can poll the store to determine the state without the need of the workers to formally respond.
      • - *
      - * - * Note: The reply channel for this is instance based. Sharing this component across - * multiple step instances may result in the crossing of messages. It's recommended that - * this component be step or job scoped. - * - * @author Dave Syer - * @author Will Schipp - * @author Michael Minella - * @author Mahmoud Ben Hassine - * - */ -@MessageEndpoint -public class MessageChannelPartitionHandler implements PartitionHandler, InitializingBean { - - private static Log logger = LogFactory.getLog(MessageChannelPartitionHandler.class); - - private int gridSize = 1; - - private MessagingTemplate messagingGateway; - - private String stepName; - - private long pollInterval = 10000; - - private JobExplorer jobExplorer; - - private boolean pollRepositoryForResults = false; - - private long timeout = -1; - - private DataSource dataSource; - - /** - * pollable channel for the replies - */ - private PollableChannel replyChannel; - - @Override - public void afterPropertiesSet() throws Exception { - Assert.notNull(stepName, "A step name must be provided for the remote workers."); - Assert.state(messagingGateway != null, "The MessagingOperations must be set"); - - pollRepositoryForResults = !(dataSource == null && jobExplorer == null); - - if(pollRepositoryForResults) { - logger.debug("MessageChannelPartitionHandler is configured to poll the job repository for worker results"); - } - - if(dataSource != null && jobExplorer == null) { - JobExplorerFactoryBean jobExplorerFactoryBean = new JobExplorerFactoryBean(); - jobExplorerFactoryBean.setDataSource(dataSource); - jobExplorerFactoryBean.afterPropertiesSet(); - jobExplorer = jobExplorerFactoryBean.getObject(); - } - - if (!pollRepositoryForResults && replyChannel == null) { - replyChannel = new QueueChannel(); - }//end if - - } - - /** - * When using job repository polling, the time limit to wait. - * - * @param timeout milliseconds to wait, defaults to -1 (no timeout). - */ - public void setTimeout(long timeout) { - this.timeout = timeout; - } - - /** - * {@link org.springframework.batch.core.explore.JobExplorer} to use to query the job repository. Either this or - * a {@link javax.sql.DataSource} is required when using job repository polling. - * - * @param jobExplorer {@link org.springframework.batch.core.explore.JobExplorer} to use for lookups - */ - public void setJobExplorer(JobExplorer jobExplorer) { - this.jobExplorer = jobExplorer; - } - - /** - * How often to poll the job repository for the status of the workers. - * - * @param pollInterval milliseconds between polls, defaults to 10000 (10 seconds). - */ - public void setPollInterval(long pollInterval) { - this.pollInterval = pollInterval; - } - - /** - * {@link javax.sql.DataSource} pointing to the job repository - * - * @param dataSource {@link javax.sql.DataSource} that points to the job repository's store - */ - public void setDataSource(DataSource dataSource) { - this.dataSource = dataSource; - } - - /** - * A pre-configured gateway for sending and receiving messages to the remote workers. Using this property allows a - * large degree of control over the timeouts and other properties of the send. It should have channels set up - * internally:
      • request channel capable of accepting {@link StepExecutionRequest} payloads
      • reply - * channel that returns a list of {@link StepExecution} results
      The timeout for the reply should be set - * sufficiently long that the remote steps have time to complete. - * - * @param messagingGateway the {@link org.springframework.integration.core.MessagingTemplate} to set - */ - public void setMessagingOperations(MessagingTemplate messagingGateway) { - this.messagingGateway = messagingGateway; - } - - /** - * Passed to the {@link StepExecutionSplitter} in the {@link #handle(StepExecutionSplitter, StepExecution)} method, - * instructing it how many {@link StepExecution} instances are required, ideally. The {@link StepExecutionSplitter} - * is allowed to ignore the grid size in the case of a restart, since the input data partitions must be preserved. - * - * @param gridSize the number of step executions that will be created - */ - public void setGridSize(int gridSize) { - this.gridSize = gridSize; - } - - /** - * The name of the {@link Step} that will be used to execute the partitioned {@link StepExecution}. This is a - * regular Spring Batch step, with all the business logic required to complete an execution based on the input - * parameters in its {@link StepExecution} context. The name will be translated into a {@link Step} instance by the - * remote worker. - * - * @param stepName the name of the {@link Step} instance to execute business logic - */ - public void setStepName(String stepName) { - this.stepName = stepName; - } - - /** - * @param messages the messages to be aggregated - * @return the list as it was passed in - */ - @Aggregator(sendPartialResultsOnExpiry = "true") - public List aggregate(@Payloads List messages) { - return messages; - } - - public void setReplyChannel(PollableChannel replyChannel) { - this.replyChannel = replyChannel; - } - - /** - * Sends {@link StepExecutionRequest} objects to the request channel of the {@link MessagingTemplate}, and then - * receives the result back as a list of {@link StepExecution} on a reply channel. Use the {@link #aggregate(List)} - * method as an aggregator of the individual remote replies. The receive timeout needs to be set realistically in - * the {@link MessagingTemplate} and the aggregator, so that there is a good chance of all work being done. - * - * @see PartitionHandler#handle(StepExecutionSplitter, StepExecution) - */ - public Collection handle(StepExecutionSplitter stepExecutionSplitter, - final StepExecution managerStepExecution) throws Exception { - - final Set split = stepExecutionSplitter.split(managerStepExecution, gridSize); - - if(CollectionUtils.isEmpty(split)) { - return split; - } - - int count = 0; - - for (StepExecution stepExecution : split) { - Message request = createMessage(count++, split.size(), new StepExecutionRequest( - stepName, stepExecution.getJobExecutionId(), stepExecution.getId()), replyChannel); - if (logger.isDebugEnabled()) { - logger.debug("Sending request: " + request); - } - messagingGateway.send(request); - } - - if(!pollRepositoryForResults) { - return receiveReplies(replyChannel); - } - else { - return pollReplies(managerStepExecution, split); - } - } - - private Collection pollReplies(final StepExecution managerStepExecution, final Set split) throws Exception { - final Collection result = new ArrayList<>(split.size()); - - Callable> callback = new Callable>() { - @Override - public Collection call() throws Exception { - - for(Iterator stepExecutionIterator = split.iterator(); stepExecutionIterator.hasNext(); ) { - StepExecution curStepExecution = stepExecutionIterator.next(); - - if(!result.contains(curStepExecution)) { - StepExecution partitionStepExecution = - jobExplorer.getStepExecution(managerStepExecution.getJobExecutionId(), curStepExecution.getId()); - - if(!partitionStepExecution.getStatus().isRunning()) { - result.add(partitionStepExecution); - } - } - } - - if(logger.isDebugEnabled()) { - logger.debug(String.format("Currently waiting on %s partitions to finish", split.size())); - } - - if(result.size() == split.size()) { - return result; - } - else { - return null; - } - } - }; - - Poller> poller = new DirectPoller<>(pollInterval); - Future> resultsFuture = poller.poll(callback); - - if(timeout >= 0) { - return resultsFuture.get(timeout, TimeUnit.MILLISECONDS); - } - else { - return resultsFuture.get(); - } - } - - private Collection receiveReplies(PollableChannel currentReplyChannel) { - @SuppressWarnings("unchecked") - Message> message = (Message>) messagingGateway.receive(currentReplyChannel); - - if(message == null) { - throw new MessageTimeoutException("Timeout occurred before all partitions returned"); - } else if (logger.isDebugEnabled()) { - logger.debug("Received replies: " + message); - } - - return message.getPayload(); - } - - private Message createMessage(int sequenceNumber, int sequenceSize, - StepExecutionRequest stepExecutionRequest, PollableChannel replyChannel) { - return MessageBuilder.withPayload(stepExecutionRequest).setSequenceNumber(sequenceNumber) - .setSequenceSize(sequenceSize) - .setCorrelationId(stepExecutionRequest.getJobExecutionId() + ":" + stepExecutionRequest.getStepName()) - .setReplyChannel(replyChannel) - .build(); - } -} +/* + * Copyright 2009-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.integration.partition; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; + +import javax.sql.DataSource; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.springframework.batch.core.Step; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.explore.JobExplorer; +import org.springframework.batch.core.explore.support.JobExplorerFactoryBean; +import org.springframework.batch.core.partition.PartitionHandler; +import org.springframework.batch.core.partition.StepExecutionSplitter; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.poller.DirectPoller; +import org.springframework.batch.poller.Poller; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.integration.MessageTimeoutException; +import org.springframework.integration.annotation.Aggregator; +import org.springframework.integration.annotation.MessageEndpoint; +import org.springframework.integration.annotation.Payloads; +import org.springframework.integration.channel.QueueChannel; +import org.springframework.integration.core.MessagingTemplate; +import org.springframework.integration.support.MessageBuilder; +import org.springframework.messaging.Message; +import org.springframework.messaging.MessageChannel; +import org.springframework.messaging.PollableChannel; +import org.springframework.util.Assert; +import org.springframework.util.CollectionUtils; + +/** + * A {@link PartitionHandler} that uses {@link MessageChannel} instances to send + * instructions to remote workers and receive their responses. The {@link MessageChannel} + * provides a nice abstraction so that the location of the workers and the transport used + * to communicate with them can be changed at run time. The communication with the remote + * workers does not need to be transactional or have guaranteed delivery, so a local + * thread pool based implementation works as well as a remote web service or JMS + * implementation. If a remote worker fails, the job will fail and can be restarted to + * pick up missing messages and processing. The remote workers need access to the Spring + * Batch {@link JobRepository} so that the shared state across those restarts can be + * managed centrally. + * + * While a {@link org.springframework.messaging.MessageChannel} is used for sending the + * requests to the workers, the worker's responses can be obtained in one of two ways: + *
        + *
      • A reply channel - Workers will respond with messages that will be aggregated via + * this component.
      • + *
      • Polling the job repository - Since the state of each worker is maintained + * independently within the job repository, we can poll the store to determine the state + * without the need of the workers to formally respond.
      • + *
      + * + * Note: The reply channel for this is instance based. Sharing this component across + * multiple step instances may result in the crossing of messages. It's recommended that + * this component be step or job scoped. + * + * @author Dave Syer + * @author Will Schipp + * @author Michael Minella + * @author Mahmoud Ben Hassine + * + */ +@MessageEndpoint +public class MessageChannelPartitionHandler implements PartitionHandler, InitializingBean { + + private static Log logger = LogFactory.getLog(MessageChannelPartitionHandler.class); + + private int gridSize = 1; + + private MessagingTemplate messagingGateway; + + private String stepName; + + private long pollInterval = 10000; + + private JobExplorer jobExplorer; + + private boolean pollRepositoryForResults = false; + + private long timeout = -1; + + private DataSource dataSource; + + /** + * pollable channel for the replies + */ + private PollableChannel replyChannel; + + @Override + public void afterPropertiesSet() throws Exception { + Assert.notNull(stepName, "A step name must be provided for the remote workers."); + Assert.state(messagingGateway != null, "The MessagingOperations must be set"); + + pollRepositoryForResults = !(dataSource == null && jobExplorer == null); + + if (pollRepositoryForResults) { + logger.debug("MessageChannelPartitionHandler is configured to poll the job repository for worker results"); + } + + if (dataSource != null && jobExplorer == null) { + JobExplorerFactoryBean jobExplorerFactoryBean = new JobExplorerFactoryBean(); + jobExplorerFactoryBean.setDataSource(dataSource); + jobExplorerFactoryBean.afterPropertiesSet(); + jobExplorer = jobExplorerFactoryBean.getObject(); + } + + if (!pollRepositoryForResults && replyChannel == null) { + replyChannel = new QueueChannel(); + } // end if + + } + + /** + * When using job repository polling, the time limit to wait. + * @param timeout milliseconds to wait, defaults to -1 (no timeout). + */ + public void setTimeout(long timeout) { + this.timeout = timeout; + } + + /** + * {@link org.springframework.batch.core.explore.JobExplorer} to use to query the job + * repository. Either this or a {@link javax.sql.DataSource} is required when using + * job repository polling. + * @param jobExplorer {@link org.springframework.batch.core.explore.JobExplorer} to + * use for lookups + */ + public void setJobExplorer(JobExplorer jobExplorer) { + this.jobExplorer = jobExplorer; + } + + /** + * How often to poll the job repository for the status of the workers. + * @param pollInterval milliseconds between polls, defaults to 10000 (10 seconds). + */ + public void setPollInterval(long pollInterval) { + this.pollInterval = pollInterval; + } + + /** + * {@link javax.sql.DataSource} pointing to the job repository + * @param dataSource {@link javax.sql.DataSource} that points to the job repository's + * store + */ + public void setDataSource(DataSource dataSource) { + this.dataSource = dataSource; + } + + /** + * A pre-configured gateway for sending and receiving messages to the remote workers. + * Using this property allows a large degree of control over the timeouts and other + * properties of the send. It should have channels set up internally: + *
        + *
      • request channel capable of accepting {@link StepExecutionRequest} payloads
      • + *
      • reply channel that returns a list of {@link StepExecution} results
      • + *
      + * The timeout for the reply should be set sufficiently long that the remote steps + * have time to complete. + * @param messagingGateway the + * {@link org.springframework.integration.core.MessagingTemplate} to set + */ + public void setMessagingOperations(MessagingTemplate messagingGateway) { + this.messagingGateway = messagingGateway; + } + + /** + * Passed to the {@link StepExecutionSplitter} in the + * {@link #handle(StepExecutionSplitter, StepExecution)} method, instructing it how + * many {@link StepExecution} instances are required, ideally. The + * {@link StepExecutionSplitter} is allowed to ignore the grid size in the case of a + * restart, since the input data partitions must be preserved. + * @param gridSize the number of step executions that will be created + */ + public void setGridSize(int gridSize) { + this.gridSize = gridSize; + } + + /** + * The name of the {@link Step} that will be used to execute the partitioned + * {@link StepExecution}. This is a regular Spring Batch step, with all the business + * logic required to complete an execution based on the input parameters in its + * {@link StepExecution} context. The name will be translated into a {@link Step} + * instance by the remote worker. + * @param stepName the name of the {@link Step} instance to execute business logic + */ + public void setStepName(String stepName) { + this.stepName = stepName; + } + + /** + * @param messages the messages to be aggregated + * @return the list as it was passed in + */ + @Aggregator(sendPartialResultsOnExpiry = "true") + public List aggregate(@Payloads List messages) { + return messages; + } + + public void setReplyChannel(PollableChannel replyChannel) { + this.replyChannel = replyChannel; + } + + /** + * Sends {@link StepExecutionRequest} objects to the request channel of the + * {@link MessagingTemplate}, and then receives the result back as a list of + * {@link StepExecution} on a reply channel. Use the {@link #aggregate(List)} method + * as an aggregator of the individual remote replies. The receive timeout needs to be + * set realistically in the {@link MessagingTemplate} and the aggregator, so + * that there is a good chance of all work being done. + * + * @see PartitionHandler#handle(StepExecutionSplitter, StepExecution) + */ + public Collection handle(StepExecutionSplitter stepExecutionSplitter, + final StepExecution managerStepExecution) throws Exception { + + final Set split = stepExecutionSplitter.split(managerStepExecution, gridSize); + + if (CollectionUtils.isEmpty(split)) { + return split; + } + + int count = 0; + + for (StepExecution stepExecution : split) { + Message request = createMessage(count++, split.size(), + new StepExecutionRequest(stepName, stepExecution.getJobExecutionId(), stepExecution.getId()), + replyChannel); + if (logger.isDebugEnabled()) { + logger.debug("Sending request: " + request); + } + messagingGateway.send(request); + } + + if (!pollRepositoryForResults) { + return receiveReplies(replyChannel); + } + else { + return pollReplies(managerStepExecution, split); + } + } + + private Collection pollReplies(final StepExecution managerStepExecution, + final Set split) throws Exception { + final Collection result = new ArrayList<>(split.size()); + + Callable> callback = new Callable>() { + @Override + public Collection call() throws Exception { + + for (Iterator stepExecutionIterator = split.iterator(); stepExecutionIterator + .hasNext();) { + StepExecution curStepExecution = stepExecutionIterator.next(); + + if (!result.contains(curStepExecution)) { + StepExecution partitionStepExecution = jobExplorer + .getStepExecution(managerStepExecution.getJobExecutionId(), curStepExecution.getId()); + + if (!partitionStepExecution.getStatus().isRunning()) { + result.add(partitionStepExecution); + } + } + } + + if (logger.isDebugEnabled()) { + logger.debug(String.format("Currently waiting on %s partitions to finish", split.size())); + } + + if (result.size() == split.size()) { + return result; + } + else { + return null; + } + } + }; + + Poller> poller = new DirectPoller<>(pollInterval); + Future> resultsFuture = poller.poll(callback); + + if (timeout >= 0) { + return resultsFuture.get(timeout, TimeUnit.MILLISECONDS); + } + else { + return resultsFuture.get(); + } + } + + private Collection receiveReplies(PollableChannel currentReplyChannel) { + @SuppressWarnings("unchecked") + Message> message = (Message>) messagingGateway + .receive(currentReplyChannel); + + if (message == null) { + throw new MessageTimeoutException("Timeout occurred before all partitions returned"); + } + else if (logger.isDebugEnabled()) { + logger.debug("Received replies: " + message); + } + + return message.getPayload(); + } + + private Message createMessage(int sequenceNumber, int sequenceSize, + StepExecutionRequest stepExecutionRequest, PollableChannel replyChannel) { + return MessageBuilder.withPayload(stepExecutionRequest).setSequenceNumber(sequenceNumber) + .setSequenceSize(sequenceSize) + .setCorrelationId(stepExecutionRequest.getJobExecutionId() + ":" + stepExecutionRequest.getStepName()) + .setReplyChannel(replyChannel).build(); + } + +} diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningManagerStepBuilder.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningManagerStepBuilder.java index 56af8c13d..bcf5c6bdb 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningManagerStepBuilder.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningManagerStepBuilder.java @@ -42,14 +42,19 @@ import org.springframework.util.Assert; * Builder for a manager step in a remote partitioning setup. This builder creates and * sets a {@link MessageChannelPartitionHandler} on the manager step. * - *

      If no {@code messagingTemplate} is provided through - * {@link RemotePartitioningManagerStepBuilder#messagingTemplate(MessagingTemplate)}, - * this builder will create one and set its default channel to the {@code outputChannel} - * provided through {@link RemotePartitioningManagerStepBuilder#outputChannel(MessageChannel)}.

      + *

      + * If no {@code messagingTemplate} is provided through + * {@link RemotePartitioningManagerStepBuilder#messagingTemplate(MessagingTemplate)}, this + * builder will create one and set its default channel to the {@code outputChannel} + * provided through + * {@link RemotePartitioningManagerStepBuilder#outputChannel(MessageChannel)}. + *

      * - *

      If a {@code messagingTemplate} is provided, it is assumed that it is fully configured + *

      + * If a {@code messagingTemplate} is provided, it is assumed that it is fully configured * and that its default channel is set to an output channel on which requests to workers - * will be sent.

      + * will be sent. + *

      * * @since 4.2 * @author Mahmoud Ben Hassine @@ -57,14 +62,21 @@ import org.springframework.util.Assert; public class RemotePartitioningManagerStepBuilder extends PartitionStepBuilder { private static final long DEFAULT_POLL_INTERVAL = 10000L; + private static final long DEFAULT_TIMEOUT = -1L; private MessagingTemplate messagingTemplate; + private MessageChannel inputChannel; + private MessageChannel outputChannel; + private JobExplorer jobExplorer; + private BeanFactory beanFactory; + private long pollInterval = DEFAULT_POLL_INTERVAL; + private long timeout = DEFAULT_TIMEOUT; /** @@ -87,12 +99,14 @@ public class RemotePartitioningManagerStepBuilder extends PartitionStepBuilder { } /** - * Set the output channel on which requests to workers will be sent. By using - * this setter, a default messaging template will be created and the output - * channel will be set as its default channel. - *

      Use either this setter or {@link RemotePartitioningManagerStepBuilder#messagingTemplate(MessagingTemplate)} - * to provide a fully configured messaging template.

      - * + * Set the output channel on which requests to workers will be sent. By using this + * setter, a default messaging template will be created and the output channel will be + * set as its default channel. + *

      + * Use either this setter or + * {@link RemotePartitioningManagerStepBuilder#messagingTemplate(MessagingTemplate)} + * to provide a fully configured messaging template. + *

      * @param outputChannel the output channel. * @return this builder instance for fluent chaining * @see RemotePartitioningManagerStepBuilder#messagingTemplate(MessagingTemplate) @@ -104,12 +118,14 @@ public class RemotePartitioningManagerStepBuilder extends PartitionStepBuilder { } /** - * Set the {@link MessagingTemplate} to use to send data to workers. - * The default channel of the messaging template must be set. - *

      Use either this setter to provide a fully configured messaging template or - * provide an output channel through {@link RemotePartitioningManagerStepBuilder#outputChannel(MessageChannel)} - * and a default messaging template will be created.

      - * + * Set the {@link MessagingTemplate} to use to send data to workers. The + * default channel of the messaging template must be set. + *

      + * Use either this setter to provide a fully configured messaging template or provide + * an output channel through + * {@link RemotePartitioningManagerStepBuilder#outputChannel(MessageChannel)} and a + * default messaging template will be created. + *

      * @param messagingTemplate the messaging template to use * @return this builder instance for fluent chaining * @see RemotePartitioningManagerStepBuilder#outputChannel(MessageChannel) @@ -132,7 +148,8 @@ public class RemotePartitioningManagerStepBuilder extends PartitionStepBuilder { } /** - * How often to poll the job repository for the status of the workers. Defaults to 10 seconds. + * How often to poll the job repository for the status of the workers. Defaults to 10 + * seconds. * @param pollInterval the poll interval value in milliseconds * @return this builder instance for fluent chaining */ @@ -143,7 +160,8 @@ public class RemotePartitioningManagerStepBuilder extends PartitionStepBuilder { } /** - * When using job repository polling, the time limit to wait. Defaults to -1 (no timeout). + * When using job repository polling, the time limit to wait. Defaults to -1 (no + * timeout). * @param timeout the timeout value in milliseconds * @return this builder instance for fluent chaining */ @@ -189,15 +207,10 @@ public class RemotePartitioningManagerStepBuilder extends PartitionStepBuilder { else { PollableChannel replies = new QueueChannel(); partitionHandler.setReplyChannel(replies); - StandardIntegrationFlow standardIntegrationFlow = IntegrationFlows - .from(this.inputChannel) - .aggregate(aggregatorSpec -> aggregatorSpec.processor(partitionHandler)) - .channel(replies) - .get(); + StandardIntegrationFlow standardIntegrationFlow = IntegrationFlows.from(this.inputChannel) + .aggregate(aggregatorSpec -> aggregatorSpec.processor(partitionHandler)).channel(replies).get(); IntegrationFlowContext integrationFlowContext = this.beanFactory.getBean(IntegrationFlowContext.class); - integrationFlowContext.registration(standardIntegrationFlow) - .autoStartup(false) - .register(); + integrationFlowContext.registration(standardIntegrationFlow).autoStartup(false).register(); } try { @@ -282,24 +295,23 @@ public class RemotePartitioningManagerStepBuilder extends PartitionStepBuilder { } /** - * This method will throw a {@link UnsupportedOperationException} since - * the partition handler of the manager step will be automatically set to an - * instance of {@link MessageChannelPartitionHandler}. - * - * When building a manager step for remote partitioning using this builder, - * no partition handler must be provided. + * This method will throw a {@link UnsupportedOperationException} since the partition + * handler of the manager step will be automatically set to an instance of + * {@link MessageChannelPartitionHandler}. * + * When building a manager step for remote partitioning using this builder, no + * partition handler must be provided. * @param partitionHandler a partition handler * @return this builder instance for fluent chaining * @throws UnsupportedOperationException if a partition handler is provided */ @Override - public RemotePartitioningManagerStepBuilder partitionHandler(PartitionHandler partitionHandler) throws UnsupportedOperationException { - throw new UnsupportedOperationException("When configuring a manager step " + - "for remote partitioning using the RemotePartitioningManagerStepBuilder, " + - "the partition handler will be automatically set to an instance " + - "of MessageChannelPartitionHandler. The partition handler must " + - "not be provided in this case."); + public RemotePartitioningManagerStepBuilder partitionHandler(PartitionHandler partitionHandler) + throws UnsupportedOperationException { + throw new UnsupportedOperationException("When configuring a manager step " + + "for remote partitioning using the RemotePartitioningManagerStepBuilder, " + + "the partition handler will be automatically set to an instance " + + "of MessageChannelPartitionHandler. The partition handler must " + "not be provided in this case."); } } diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningManagerStepBuilderFactory.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningManagerStepBuilderFactory.java index 7697eeca4..1f3b4afc1 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningManagerStepBuilderFactory.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningManagerStepBuilderFactory.java @@ -24,8 +24,8 @@ import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.transaction.PlatformTransactionManager; /** - * Convenient factory for a {@link RemotePartitioningManagerStepBuilder} which sets - * the {@link JobRepository}, {@link JobExplorer}, {@link BeanFactory} and + * Convenient factory for a {@link RemotePartitioningManagerStepBuilder} which sets the + * {@link JobRepository}, {@link JobExplorer}, {@link BeanFactory} and * {@link PlatformTransactionManager} automatically. * * @since 4.2 @@ -34,10 +34,12 @@ import org.springframework.transaction.PlatformTransactionManager; public class RemotePartitioningManagerStepBuilderFactory implements BeanFactoryAware { private BeanFactory beanFactory; - final private JobExplorer jobExplorer; - final private JobRepository jobRepository; - final private PlatformTransactionManager transactionManager; + final private JobExplorer jobExplorer; + + final private JobRepository jobRepository; + + final private PlatformTransactionManager transactionManager; /** * Create a new {@link RemotePartitioningManagerStepBuilderFactory}. @@ -45,8 +47,8 @@ public class RemotePartitioningManagerStepBuilderFactory implements BeanFactoryA * @param jobExplorer the job explorer to use * @param transactionManager the transaction manager to use */ - public RemotePartitioningManagerStepBuilderFactory(JobRepository jobRepository, - JobExplorer jobExplorer, PlatformTransactionManager transactionManager) { + public RemotePartitioningManagerStepBuilderFactory(JobRepository jobRepository, JobExplorer jobExplorer, + PlatformTransactionManager transactionManager) { this.jobRepository = jobRepository; this.jobExplorer = jobExplorer; @@ -65,10 +67,8 @@ public class RemotePartitioningManagerStepBuilderFactory implements BeanFactoryA * @return a {@link RemotePartitioningManagerStepBuilder} */ public RemotePartitioningManagerStepBuilder get(String name) { - return new RemotePartitioningManagerStepBuilder(name) - .repository(this.jobRepository) - .jobExplorer(this.jobExplorer) - .beanFactory(this.beanFactory) + return new RemotePartitioningManagerStepBuilder(name).repository(this.jobRepository) + .jobExplorer(this.jobExplorer).beanFactory(this.beanFactory) .transactionManager(this.transactionManager); } diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningWorkerStepBuilder.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningWorkerStepBuilder.java index d2a45ffd6..0f95ac12b 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningWorkerStepBuilder.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningWorkerStepBuilder.java @@ -46,20 +46,20 @@ import org.springframework.transaction.PlatformTransactionManager; import org.springframework.util.Assert; /** - * Builder for a worker step in a remote partitioning setup. This builder - * creates an {@link IntegrationFlow} that: + * Builder for a worker step in a remote partitioning setup. This builder creates an + * {@link IntegrationFlow} that: * *
        - *
      • listens to {@link StepExecutionRequest}s coming from the manager - * on the input channel
      • - *
      • invokes the {@link StepExecutionRequestHandler} to execute the worker - * step for each incoming request. The worker step is located using the provided - * {@link StepLocator}. If no {@link StepLocator} is provided, a {@link BeanFactoryStepLocator} - * configured with the current {@link BeanFactory} will be used - *
      • replies to the manager on the output channel (when the manager step is - * configured to aggregate replies from workers). If no output channel - * is provided, a {@link NullChannel} will be used (assuming the manager side - * is configured to poll the job repository for workers status)
      • + *
      • listens to {@link StepExecutionRequest}s coming from the manager on the input + * channel
      • + *
      • invokes the {@link StepExecutionRequestHandler} to execute the worker step for each + * incoming request. The worker step is located using the provided {@link StepLocator}. If + * no {@link StepLocator} is provided, a {@link BeanFactoryStepLocator} configured with + * the current {@link BeanFactory} will be used + *
      • replies to the manager on the output channel (when the manager step is configured + * to aggregate replies from workers). If no output channel is provided, a + * {@link NullChannel} will be used (assuming the manager side is configured to poll the + * job repository for workers status)
      • *
      * * @since 4.1 @@ -68,12 +68,17 @@ import org.springframework.util.Assert; public class RemotePartitioningWorkerStepBuilder extends StepBuilder { private static final String SERVICE_ACTIVATOR_METHOD_NAME = "handle"; + private static final Log logger = LogFactory.getLog(RemotePartitioningWorkerStepBuilder.class); private MessageChannel inputChannel; + private MessageChannel outputChannel; + private JobExplorer jobExplorer; + private StepLocator stepLocator; + private BeanFactory beanFactory; /** @@ -85,8 +90,8 @@ public class RemotePartitioningWorkerStepBuilder extends StepBuilder { } /** - * Set the input channel on which step execution requests sent by the manager - * are received. + * Set the input channel on which step execution requests sent by the manager are + * received. * @param inputChannel the input channel * @return this builder instance for fluent chaining */ @@ -220,8 +225,8 @@ public class RemotePartitioningWorkerStepBuilder extends StepBuilder { /** * Create an {@link IntegrationFlow} with a {@link StepExecutionRequestHandler} - * configured as a service activator listening to the input channel and replying - * on the output channel. + * configured as a service activator listening to the input channel and replying on + * the output channel. */ private void configureWorkerIntegrationFlow() { Assert.notNull(this.inputChannel, "An InputChannel must be provided"); @@ -234,8 +239,8 @@ public class RemotePartitioningWorkerStepBuilder extends StepBuilder { } if (this.outputChannel == null) { if (logger.isDebugEnabled()) { - logger.debug("The output channel is set to a NullChannel. " + - "The manager step must poll the job repository for workers status."); + logger.debug("The output channel is set to a NullChannel. " + + "The manager step must poll the job repository for workers status."); } this.outputChannel = new NullChannel(); } @@ -244,15 +249,10 @@ public class RemotePartitioningWorkerStepBuilder extends StepBuilder { stepExecutionRequestHandler.setJobExplorer(this.jobExplorer); stepExecutionRequestHandler.setStepLocator(this.stepLocator); - StandardIntegrationFlow standardIntegrationFlow = IntegrationFlows - .from(this.inputChannel) - .handle(stepExecutionRequestHandler, SERVICE_ACTIVATOR_METHOD_NAME) - .channel(this.outputChannel) - .get(); + StandardIntegrationFlow standardIntegrationFlow = IntegrationFlows.from(this.inputChannel) + .handle(stepExecutionRequestHandler, SERVICE_ACTIVATOR_METHOD_NAME).channel(this.outputChannel).get(); IntegrationFlowContext integrationFlowContext = this.beanFactory.getBean(IntegrationFlowContext.class); - integrationFlowContext.registration(standardIntegrationFlow) - .autoStartup(false) - .register(); + integrationFlowContext.registration(standardIntegrationFlow).autoStartup(false).register(); } } diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningWorkerStepBuilderFactory.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningWorkerStepBuilderFactory.java index 674d6c5df..601d878ef 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningWorkerStepBuilderFactory.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningWorkerStepBuilderFactory.java @@ -24,8 +24,8 @@ import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.transaction.PlatformTransactionManager; /** - * Convenient factory for a {@link RemotePartitioningWorkerStepBuilder} which sets - * the {@link JobRepository}, {@link JobExplorer}, {@link BeanFactory} and + * Convenient factory for a {@link RemotePartitioningWorkerStepBuilder} which sets the + * {@link JobRepository}, {@link JobExplorer}, {@link BeanFactory} and * {@link PlatformTransactionManager} automatically. * * @since 4.1 @@ -34,10 +34,12 @@ import org.springframework.transaction.PlatformTransactionManager; public class RemotePartitioningWorkerStepBuilderFactory implements BeanFactoryAware { private BeanFactory beanFactory; - final private JobExplorer jobExplorer; - final private JobRepository jobRepository; - final private PlatformTransactionManager transactionManager; + final private JobExplorer jobExplorer; + + final private JobRepository jobRepository; + + final private PlatformTransactionManager transactionManager; /** * Create a new {@link RemotePartitioningWorkerStepBuilderFactory}. @@ -45,9 +47,8 @@ public class RemotePartitioningWorkerStepBuilderFactory implements BeanFactoryAw * @param jobExplorer the job explorer to use * @param transactionManager the transaction manager to use */ - public RemotePartitioningWorkerStepBuilderFactory(JobRepository jobRepository, - JobExplorer jobExplorer, - PlatformTransactionManager transactionManager) { + public RemotePartitioningWorkerStepBuilderFactory(JobRepository jobRepository, JobExplorer jobExplorer, + PlatformTransactionManager transactionManager) { this.jobExplorer = jobExplorer; this.jobRepository = jobRepository; @@ -66,10 +67,8 @@ public class RemotePartitioningWorkerStepBuilderFactory implements BeanFactoryAw * @return a {@link RemotePartitioningWorkerStepBuilder} */ public RemotePartitioningWorkerStepBuilder get(String name) { - return new RemotePartitioningWorkerStepBuilder(name) - .repository(this.jobRepository) - .jobExplorer(this.jobExplorer) - .beanFactory(this.beanFactory) + return new RemotePartitioningWorkerStepBuilder(name).repository(this.jobRepository) + .jobExplorer(this.jobExplorer).beanFactory(this.beanFactory) .transactionManager(this.transactionManager); } diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/StepExecutionRequest.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/StepExecutionRequest.java index 89132967b..b987733ee 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/StepExecutionRequest.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/StepExecutionRequest.java @@ -1,71 +1,71 @@ -/* - * Copyright 2009-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.integration.partition; - -import java.io.Serializable; - -/** - * Class encapsulating information required to request a step execution in - * a remote partitioning setup. - * - * @author Dave Syer - * @author Mahmoud Ben Hassine - */ -public class StepExecutionRequest implements Serializable { - - private static final long serialVersionUID = 1L; - - private Long stepExecutionId; - - private String stepName; - - private Long jobExecutionId; - - private StepExecutionRequest() { - //For Jackson deserialization - } - - /** - * Create a new {@link StepExecutionRequest} instance. - * @param stepName the name of the step to execute - * @param jobExecutionId the id of the job execution - * @param stepExecutionId the id of the step execution - */ - public StepExecutionRequest(String stepName, Long jobExecutionId, Long stepExecutionId) { - this.stepName = stepName; - this.jobExecutionId = jobExecutionId; - this.stepExecutionId = stepExecutionId; - } - - public Long getJobExecutionId() { - return jobExecutionId; - } - - public Long getStepExecutionId() { - return stepExecutionId; - } - - public String getStepName() { - return stepName; - } - - @Override - public String toString() { - return String.format("StepExecutionRequest: [jobExecutionId=%d, stepExecutionId=%d, stepName=%s]", - jobExecutionId, stepExecutionId, stepName); - } - -} +/* + * Copyright 2009-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.integration.partition; + +import java.io.Serializable; + +/** + * Class encapsulating information required to request a step execution in a remote + * partitioning setup. + * + * @author Dave Syer + * @author Mahmoud Ben Hassine + */ +public class StepExecutionRequest implements Serializable { + + private static final long serialVersionUID = 1L; + + private Long stepExecutionId; + + private String stepName; + + private Long jobExecutionId; + + private StepExecutionRequest() { + // For Jackson deserialization + } + + /** + * Create a new {@link StepExecutionRequest} instance. + * @param stepName the name of the step to execute + * @param jobExecutionId the id of the job execution + * @param stepExecutionId the id of the step execution + */ + public StepExecutionRequest(String stepName, Long jobExecutionId, Long stepExecutionId) { + this.stepName = stepName; + this.jobExecutionId = jobExecutionId; + this.stepExecutionId = stepExecutionId; + } + + public Long getJobExecutionId() { + return jobExecutionId; + } + + public Long getStepExecutionId() { + return stepExecutionId; + } + + public String getStepName() { + return stepName; + } + + @Override + public String toString() { + return String.format("StepExecutionRequest: [jobExecutionId=%d, stepExecutionId=%d, stepName=%s]", + jobExecutionId, stepExecutionId, stepName); + } + +} diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/StepExecutionRequestHandler.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/StepExecutionRequestHandler.java index 258b2404a..bebf4f9d3 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/StepExecutionRequestHandler.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/StepExecutionRequestHandler.java @@ -1,80 +1,78 @@ -package org.springframework.batch.integration.partition; - -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.JobInterruptedException; -import org.springframework.batch.core.Step; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.explore.JobExplorer; -import org.springframework.batch.core.step.NoSuchStepException; -import org.springframework.batch.core.step.StepLocator; -import org.springframework.integration.annotation.MessageEndpoint; -import org.springframework.integration.annotation.ServiceActivator; - -/** - * A {@link MessageEndpoint} that can handle a {@link StepExecutionRequest} and - * return a {@link StepExecution} as the result. Typically these need to be - * aggregated into a response to a partition handler. - * - * @author Dave Syer - * - */ -@MessageEndpoint -public class StepExecutionRequestHandler { - - private JobExplorer jobExplorer; - - private StepLocator stepLocator; - - /** - * Used to locate a {@link Step} to execute for each request. - * @param stepLocator a {@link StepLocator} - */ - public void setStepLocator(StepLocator stepLocator) { - this.stepLocator = stepLocator; - } - - /** - * An explorer that should be used to check for {@link StepExecution} - * completion. - * - * @param jobExplorer a {@link JobExplorer} that is linked to the shared - * repository used by all remote workers. - */ - public void setJobExplorer(JobExplorer jobExplorer) { - this.jobExplorer = jobExplorer; - } - - @ServiceActivator - public StepExecution handle(StepExecutionRequest request) { - - Long jobExecutionId = request.getJobExecutionId(); - Long stepExecutionId = request.getStepExecutionId(); - StepExecution stepExecution = jobExplorer.getStepExecution(jobExecutionId, stepExecutionId); - if (stepExecution == null) { - throw new NoSuchStepException("No StepExecution could be located for this request: " + request); - } - - String stepName = request.getStepName(); - Step step = stepLocator.getStep(stepName); - if (step == null) { - throw new NoSuchStepException(String.format("No Step with name [%s] could be located.", stepName)); - } - - try { - step.execute(stepExecution); - } - catch (JobInterruptedException e) { - stepExecution.setStatus(BatchStatus.STOPPED); - // The receiver should update the stepExecution in repository - } - catch (Throwable e) { - stepExecution.addFailureException(e); - stepExecution.setStatus(BatchStatus.FAILED); - // The receiver should update the stepExecution in repository - } - - return stepExecution; - - } - -} +package org.springframework.batch.integration.partition; + +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.JobInterruptedException; +import org.springframework.batch.core.Step; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.explore.JobExplorer; +import org.springframework.batch.core.step.NoSuchStepException; +import org.springframework.batch.core.step.StepLocator; +import org.springframework.integration.annotation.MessageEndpoint; +import org.springframework.integration.annotation.ServiceActivator; + +/** + * A {@link MessageEndpoint} that can handle a {@link StepExecutionRequest} and return a + * {@link StepExecution} as the result. Typically these need to be aggregated into a + * response to a partition handler. + * + * @author Dave Syer + * + */ +@MessageEndpoint +public class StepExecutionRequestHandler { + + private JobExplorer jobExplorer; + + private StepLocator stepLocator; + + /** + * Used to locate a {@link Step} to execute for each request. + * @param stepLocator a {@link StepLocator} + */ + public void setStepLocator(StepLocator stepLocator) { + this.stepLocator = stepLocator; + } + + /** + * An explorer that should be used to check for {@link StepExecution} completion. + * @param jobExplorer a {@link JobExplorer} that is linked to the shared repository + * used by all remote workers. + */ + public void setJobExplorer(JobExplorer jobExplorer) { + this.jobExplorer = jobExplorer; + } + + @ServiceActivator + public StepExecution handle(StepExecutionRequest request) { + + Long jobExecutionId = request.getJobExecutionId(); + Long stepExecutionId = request.getStepExecutionId(); + StepExecution stepExecution = jobExplorer.getStepExecution(jobExecutionId, stepExecutionId); + if (stepExecution == null) { + throw new NoSuchStepException("No StepExecution could be located for this request: " + request); + } + + String stepName = request.getStepName(); + Step step = stepLocator.getStep(stepName); + if (step == null) { + throw new NoSuchStepException(String.format("No Step with name [%s] could be located.", stepName)); + } + + try { + step.execute(stepExecution); + } + catch (JobInterruptedException e) { + stepExecution.setStatus(BatchStatus.STOPPED); + // The receiver should update the stepExecution in repository + } + catch (Throwable e) { + stepExecution.addFailureException(e); + stepExecution.setStatus(BatchStatus.FAILED); + // The receiver should update the stepExecution in repository + } + + return stepExecution; + + } + +} diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/step/DelegateStep.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/step/DelegateStep.java index 3a70d90ba..be2b3bd04 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/step/DelegateStep.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/step/DelegateStep.java @@ -22,11 +22,11 @@ import org.springframework.batch.core.step.AbstractStep; import org.springframework.util.Assert; /** - * Provides a wrapper for an existing {@link Step}, delegating execution to it, - * but serving all other operations locally. - * + * Provides a wrapper for an existing {@link Step}, delegating execution to it, but + * serving all other operations locally. + * * @author Dave Syer - * + * */ public class DelegateStep extends AbstractStep { @@ -38,13 +38,13 @@ public class DelegateStep extends AbstractStep { public void setDelegate(Step delegate) { this.delegate = delegate; } - + /** * Check mandatory properties (delegate). */ @Override public void afterPropertiesSet() throws Exception { - Assert.state(delegate!=null, "A delegate Step must be provided"); + Assert.state(delegate != null, "A delegate Step must be provided"); super.afterPropertiesSet(); } diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/JobRepositorySupport.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/JobRepositorySupport.java index 4a54fdae0..30d2be884 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/JobRepositorySupport.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/JobRepositorySupport.java @@ -1,112 +1,136 @@ -/* - * Copyright 2006-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.integration; - -import java.util.Collection; - -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobInstance; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException; -import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException; -import org.springframework.batch.core.repository.JobRepository; -import org.springframework.batch.core.repository.JobRestartException; -import org.springframework.lang.Nullable; - -/** - * @author Dave Syer - * @author Mahmoud Ben Hassine - * - */ -public class JobRepositorySupport implements JobRepository { - - /* (non-Javadoc) - * @see org.springframework.batch.core.repository.JobRepository#createJobExecution(org.springframework.batch.core.Job, org.springframework.batch.core.JobParameters) - */ - public JobExecution createJobExecution(String jobName, JobParameters jobParameters) - throws JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException { - return new JobExecution(new JobInstance(0L, jobName), jobParameters); - } - - /* (non-Javadoc) - * @see org.springframework.batch.core.repository.JobRepository#getLastStepExecution(org.springframework.batch.core.JobInstance, org.springframework.batch.core.Step) - */ - @Nullable - public StepExecution getLastStepExecution(JobInstance jobInstance, String stepName) { - return null; - } - - /* (non-Javadoc) - * @see org.springframework.batch.core.repository.JobRepository#getStepExecutionCount(org.springframework.batch.core.JobInstance, org.springframework.batch.core.Step) - */ - public int getStepExecutionCount(JobInstance jobInstance, String stepName) { - return 0; - } - - /* (non-Javadoc) - * @see org.springframework.batch.core.repository.JobRepository#saveOrUpdate(org.springframework.batch.core.JobExecution) - */ - public void update(JobExecution jobExecution) { - } - - /* (non-Javadoc) - * @see org.springframework.batch.core.repository.JobRepository#saveOrUpdate(org.springframework.batch.core.StepExecution) - */ - public void saveOrUpdate(StepExecution stepExecution) { - } - - /* (non-Javadoc) - * @see org.springframework.batch.core.repository.JobRepository#saveOrUpdateExecutionContext(org.springframework.batch.core.StepExecution) - */ - public void updateExecutionContext(StepExecution stepExecution) { - } - - public void updateExecutionContext(JobExecution jobExecution) { - } - - public void add(StepExecution stepExecution) { - } - - public void update(StepExecution stepExecution) { - } - - public boolean isJobInstanceExists(String jobName, JobParameters jobParameters) { - return false; - } - - /* (non-Javadoc) - * @see org.springframework.batch.core.repository.JobRepository#getLastJobExecution(java.lang.String, org.springframework.batch.core.JobParameters) - */ - @Nullable - public JobExecution getLastJobExecution(String jobName, JobParameters jobParameters) { - return null; - } - - public void addAll(Collection stepExecutions) { - if(stepExecutions != null) { - for (StepExecution stepExecution : stepExecutions) { - add(stepExecution); - } - } - } - - public JobInstance createJobInstance(String jobName, - JobParameters jobParameters) { - return null; - } - -} +/* + * Copyright 2006-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.integration; + +import java.util.Collection; + +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobInstance; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException; +import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.core.repository.JobRestartException; +import org.springframework.lang.Nullable; + +/** + * @author Dave Syer + * @author Mahmoud Ben Hassine + * + */ +public class JobRepositorySupport implements JobRepository { + + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.core.repository.JobRepository#createJobExecution(org. + * springframework.batch.core.Job, org.springframework.batch.core.JobParameters) + */ + public JobExecution createJobExecution(String jobName, JobParameters jobParameters) + throws JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException { + return new JobExecution(new JobInstance(0L, jobName), jobParameters); + } + + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.core.repository.JobRepository#getLastStepExecution(org. + * springframework.batch.core.JobInstance, org.springframework.batch.core.Step) + */ + @Nullable + public StepExecution getLastStepExecution(JobInstance jobInstance, String stepName) { + return null; + } + + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.core.repository.JobRepository#getStepExecutionCount(org. + * springframework.batch.core.JobInstance, org.springframework.batch.core.Step) + */ + public int getStepExecutionCount(JobInstance jobInstance, String stepName) { + return 0; + } + + /* + * (non-Javadoc) + * + * @see org.springframework.batch.core.repository.JobRepository#saveOrUpdate(org. + * springframework.batch.core.JobExecution) + */ + public void update(JobExecution jobExecution) { + } + + /* + * (non-Javadoc) + * + * @see org.springframework.batch.core.repository.JobRepository#saveOrUpdate(org. + * springframework.batch.core.StepExecution) + */ + public void saveOrUpdate(StepExecution stepExecution) { + } + + /* + * (non-Javadoc) + * + * @see org.springframework.batch.core.repository.JobRepository# + * saveOrUpdateExecutionContext(org.springframework.batch.core.StepExecution) + */ + public void updateExecutionContext(StepExecution stepExecution) { + } + + public void updateExecutionContext(JobExecution jobExecution) { + } + + public void add(StepExecution stepExecution) { + } + + public void update(StepExecution stepExecution) { + } + + public boolean isJobInstanceExists(String jobName, JobParameters jobParameters) { + return false; + } + + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.core.repository.JobRepository#getLastJobExecution(java. + * lang.String, org.springframework.batch.core.JobParameters) + */ + @Nullable + public JobExecution getLastJobExecution(String jobName, JobParameters jobParameters) { + return null; + } + + public void addAll(Collection stepExecutions) { + if (stepExecutions != null) { + for (StepExecution stepExecution : stepExecutions) { + add(stepExecution); + } + } + } + + public JobInstance createJobInstance(String jobName, JobParameters jobParameters) { + return null; + } + +} diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/JobSupport.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/JobSupport.java index c480dd562..7f629c47a 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/JobSupport.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/JobSupport.java @@ -8,10 +8,10 @@ import org.springframework.batch.core.job.DefaultJobParametersValidator; import org.springframework.lang.Nullable; public class JobSupport implements Job { - + String name; - - public JobSupport(String name){ + + public JobSupport(String name) { this.name = name; } @@ -25,12 +25,12 @@ public class JobSupport implements Job { public boolean isRestartable() { return false; } - + @Nullable public JobParametersIncrementer getJobParametersIncrementer() { return null; } - + public JobParametersValidator getJobParametersValidator() { return new DefaultJobParametersValidator(); } diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/SmokeTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/SmokeTests.java index 5e2a2c649..cf501d414 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/SmokeTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/SmokeTests.java @@ -1,61 +1,60 @@ -package org.springframework.batch.integration; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.integration.annotation.MessageEndpoint; -import org.springframework.integration.annotation.ServiceActivator; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageChannel; -import org.springframework.messaging.PollableChannel; -import org.springframework.messaging.support.GenericMessage; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -public class SmokeTests { - - @Autowired - private MessageChannel smokein; - - @Autowired - private PollableChannel smokeout; - - - @Test - public void testDummyWithSimpleAssert() throws Exception { - assertTrue(true); - } - - @Test - public void testVanillaSendAndReceive() throws Exception { - smokein.send(new GenericMessage<>("foo")); - @SuppressWarnings("unchecked") - Message message = (Message) smokeout.receive(100); - String result = message == null ? null : message.getPayload(); - assertEquals("foo: 1", result); - assertEquals(1, AnnotatedEndpoint.count); - } - - @MessageEndpoint - static class AnnotatedEndpoint { - - // This has to be static because Spring Integration registers the handler - // more than once (every time a test instance is created), but only one of - // them will get the message. - private volatile static int count = 0; - - @ServiceActivator(inputChannel = "smokein", outputChannel = "smokeout") - public String process(String message) { - count++; - String result = message + ": " + count; - return result; - } - - } - -} +package org.springframework.batch.integration; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.integration.annotation.MessageEndpoint; +import org.springframework.integration.annotation.ServiceActivator; +import org.springframework.messaging.Message; +import org.springframework.messaging.MessageChannel; +import org.springframework.messaging.PollableChannel; +import org.springframework.messaging.support.GenericMessage; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class SmokeTests { + + @Autowired + private MessageChannel smokein; + + @Autowired + private PollableChannel smokeout; + + @Test + public void testDummyWithSimpleAssert() throws Exception { + assertTrue(true); + } + + @Test + public void testVanillaSendAndReceive() throws Exception { + smokein.send(new GenericMessage<>("foo")); + @SuppressWarnings("unchecked") + Message message = (Message) smokeout.receive(100); + String result = message == null ? null : message.getPayload(); + assertEquals("foo: 1", result); + assertEquals(1, AnnotatedEndpoint.count); + } + + @MessageEndpoint + static class AnnotatedEndpoint { + + // This has to be static because Spring Integration registers the handler + // more than once (every time a test instance is created), but only one of + // them will get the message. + private volatile static int count = 0; + + @ServiceActivator(inputChannel = "smokein", outputChannel = "smokeout") + public String process(String message) { + count++; + String result = message + ": " + count; + return result; + } + + } + +} diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/StepSupport.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/StepSupport.java index 355d147c7..b9a64e735 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/StepSupport.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/StepSupport.java @@ -1,74 +1,84 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.integration; - -import org.springframework.batch.core.JobInterruptedException; -import org.springframework.batch.core.Step; -import org.springframework.batch.core.StepExecution; - -/** - * @author Dave Syer - * - */ -public class StepSupport implements Step { - - private String name; - private int startLimit = 1; - - /** - * @param name - */ - public StepSupport(String name) { - super(); - this.name = name; - } - - /* (non-Javadoc) - * @see org.springframework.batch.core.Step#execute(org.springframework.batch.core.StepExecution) - */ - public void execute(StepExecution stepExecution) throws JobInterruptedException { - } - - /* (non-Javadoc) - * @see org.springframework.batch.core.Step#getName() - */ - public String getName() { - return name; - } - - /* (non-Javadoc) - * @see org.springframework.batch.core.Step#getStartLimit() - */ - public int getStartLimit() { - return startLimit; - } - - /* (non-Javadoc) - * @see org.springframework.batch.core.Step#isAllowStartIfComplete() - */ - public boolean isAllowStartIfComplete() { - return false; - } - - /** - * Public setter for the startLimit. - * @param startLimit the startLimit to set - */ - public void setStartLimit(int startLimit) { - this.startLimit = startLimit; - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.integration; + +import org.springframework.batch.core.JobInterruptedException; +import org.springframework.batch.core.Step; +import org.springframework.batch.core.StepExecution; + +/** + * @author Dave Syer + * + */ +public class StepSupport implements Step { + + private String name; + + private int startLimit = 1; + + /** + * @param name + */ + public StepSupport(String name) { + super(); + this.name = name; + } + + /* + * (non-Javadoc) + * + * @see org.springframework.batch.core.Step#execute(org.springframework.batch.core. + * StepExecution) + */ + public void execute(StepExecution stepExecution) throws JobInterruptedException { + } + + /* + * (non-Javadoc) + * + * @see org.springframework.batch.core.Step#getName() + */ + public String getName() { + return name; + } + + /* + * (non-Javadoc) + * + * @see org.springframework.batch.core.Step#getStartLimit() + */ + public int getStartLimit() { + return startLimit; + } + + /* + * (non-Javadoc) + * + * @see org.springframework.batch.core.Step#isAllowStartIfComplete() + */ + public boolean isAllowStartIfComplete() { + return false; + } + + /** + * Public setter for the startLimit. + * @param startLimit the startLimit to set + */ + public void setStartLimit(int startLimit) { + this.startLimit = startLimit; + } + +} diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/async/AsyncItemProcessorMessagingGatewayTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/async/AsyncItemProcessorMessagingGatewayTests.java index 40f75c1c6..56a3db77e 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/async/AsyncItemProcessorMessagingGatewayTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/async/AsyncItemProcessorMessagingGatewayTests.java @@ -1,119 +1,123 @@ -/* - * Copyright 2006-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.integration.async; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.Future; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.MethodRule; -import org.junit.runner.RunWith; -import org.junit.runners.model.FrameworkMethod; -import org.junit.runners.model.Statement; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.item.ItemProcessor; -import org.springframework.batch.test.MetaDataInstanceFactory; -import org.springframework.batch.test.StepScopeTestUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.task.SimpleAsyncTaskExecutor; -import org.springframework.integration.annotation.MessageEndpoint; -import org.springframework.integration.annotation.ServiceActivator; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration -public class AsyncItemProcessorMessagingGatewayTests { - - private final AsyncItemProcessor processor = new AsyncItemProcessor<>(); - - private final StepExecution stepExecution = MetaDataInstanceFactory.createStepExecution(new JobParametersBuilder().addLong("factor", 2L).toJobParameters());; - - @Rule - public MethodRule rule = new MethodRule() { - public Statement apply(final Statement base, FrameworkMethod method, Object target) { - return new Statement() { - @Override - public void evaluate() throws Throwable { - StepScopeTestUtils.doInStepScope(stepExecution, new Callable() { - public Void call() throws Exception { - try { - base.evaluate(); - } - catch (Exception e) { - throw e; - } - catch (Throwable e) { - throw new Error(e); - } - return null; - } - }); - }; - }; - } - }; - - @Autowired - private ItemProcessor delegate; - - @Test - public void testMultiExecution() throws Exception { - processor.setDelegate(delegate); - processor.setTaskExecutor(new SimpleAsyncTaskExecutor()); - List> list = new ArrayList<>(); - for (int count = 0; count < 10; count++) { - list.add(processor.process("foo" + count)); - } - for (Future future : list) { - String value = future.get(); - /** - * This delegate is a Spring Integration MessagingGateway. It can - * easily return null because of a timeout, but that will be treated - * by Batch as a filtered item, whereas it is really more like a - * skip. So we have to throw an exception in the processor if an - * unexpected null value comes back. - */ - assertNotNull(value); - assertTrue(value.matches("foo.*foo.*")); - } - } - - @MessageEndpoint - public static class Doubler { - private int factor = 1; - - public void setFactor(int factor) { - this.factor = factor; - } - - @ServiceActivator - public String cat(String value) { - for (int i=1; i processor = new AsyncItemProcessor<>(); + + private final StepExecution stepExecution = MetaDataInstanceFactory + .createStepExecution(new JobParametersBuilder().addLong("factor", 2L).toJobParameters()); + + ; + + @Rule + public MethodRule rule = new MethodRule() { + public Statement apply(final Statement base, FrameworkMethod method, Object target) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + StepScopeTestUtils.doInStepScope(stepExecution, new Callable() { + public Void call() throws Exception { + try { + base.evaluate(); + } + catch (Exception e) { + throw e; + } + catch (Throwable e) { + throw new Error(e); + } + return null; + } + }); + }; + }; + } + }; + + @Autowired + private ItemProcessor delegate; + + @Test + public void testMultiExecution() throws Exception { + processor.setDelegate(delegate); + processor.setTaskExecutor(new SimpleAsyncTaskExecutor()); + List> list = new ArrayList<>(); + for (int count = 0; count < 10; count++) { + list.add(processor.process("foo" + count)); + } + for (Future future : list) { + String value = future.get(); + /** + * This delegate is a Spring Integration MessagingGateway. It can easily + * return null because of a timeout, but that will be treated by Batch as a + * filtered item, whereas it is really more like a skip. So we have to throw + * an exception in the processor if an unexpected null value comes back. + */ + assertNotNull(value); + assertTrue(value.matches("foo.*foo.*")); + } + } + + @MessageEndpoint + public static class Doubler { + + private int factor = 1; + + public void setFactor(int factor) { + this.factor = factor; + } + + @ServiceActivator + public String cat(String value) { + for (int i = 1; i < factor; i++) { + value += value; + } + return value; + } + + } + +} diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/async/AsyncItemProcessorTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/async/AsyncItemProcessorTests.java index 2e26966a7..a27db8bbf 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/async/AsyncItemProcessorTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/async/AsyncItemProcessorTests.java @@ -1,90 +1,91 @@ -/* - * Copyright 2006-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.integration.async; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.Future; - -import org.junit.Test; -import org.springframework.batch.core.scope.context.StepContext; -import org.springframework.batch.core.scope.context.StepSynchronizationManager; -import org.springframework.batch.item.ItemProcessor; -import org.springframework.batch.test.MetaDataInstanceFactory; -import org.springframework.batch.test.StepScopeTestUtils; -import org.springframework.core.task.SimpleAsyncTaskExecutor; -import org.springframework.lang.Nullable; - -public class AsyncItemProcessorTests { - - private AsyncItemProcessor processor = new AsyncItemProcessor<>(); - - private ItemProcessor delegate = new ItemProcessor() { - @Nullable - public String process(String item) throws Exception { - return item + item; - }; - }; - - @Test(expected = IllegalArgumentException.class) - public void testNoDelegate() throws Exception { - processor.afterPropertiesSet(); - } - - @Test - public void testExecution() throws Exception { - processor.setDelegate(delegate); - Future result = processor.process("foo"); - assertEquals("foofoo", result.get()); - } - - @Test - public void testExecutionInStepScope() throws Exception { - delegate = new ItemProcessor() { - @Nullable - public String process(String item) throws Exception { - StepContext context = StepSynchronizationManager.getContext(); - assertTrue(context != null && context.getStepExecution() != null); - return item + item; - }; - }; - processor.setDelegate(delegate); - Future result = StepScopeTestUtils.doInStepScope(MetaDataInstanceFactory.createStepExecution(), new Callable>() { - public Future call() throws Exception { - return processor.process("foo"); - } - }); - assertEquals("foofoo", result.get()); - } - - @Test - public void testMultiExecution() throws Exception { - processor.setDelegate(delegate); - processor.setTaskExecutor(new SimpleAsyncTaskExecutor()); - List> list = new ArrayList<>(); - for (int count = 0; count < 10; count++) { - list.add(processor.process("foo" + count)); - } - for (Future future : list) { - assertTrue(future.get().matches("foo.*foo.*")); - } - } - -} +/* + * Copyright 2006-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.integration.async; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.Future; + +import org.junit.Test; +import org.springframework.batch.core.scope.context.StepContext; +import org.springframework.batch.core.scope.context.StepSynchronizationManager; +import org.springframework.batch.item.ItemProcessor; +import org.springframework.batch.test.MetaDataInstanceFactory; +import org.springframework.batch.test.StepScopeTestUtils; +import org.springframework.core.task.SimpleAsyncTaskExecutor; +import org.springframework.lang.Nullable; + +public class AsyncItemProcessorTests { + + private AsyncItemProcessor processor = new AsyncItemProcessor<>(); + + private ItemProcessor delegate = new ItemProcessor() { + @Nullable + public String process(String item) throws Exception { + return item + item; + }; + }; + + @Test(expected = IllegalArgumentException.class) + public void testNoDelegate() throws Exception { + processor.afterPropertiesSet(); + } + + @Test + public void testExecution() throws Exception { + processor.setDelegate(delegate); + Future result = processor.process("foo"); + assertEquals("foofoo", result.get()); + } + + @Test + public void testExecutionInStepScope() throws Exception { + delegate = new ItemProcessor() { + @Nullable + public String process(String item) throws Exception { + StepContext context = StepSynchronizationManager.getContext(); + assertTrue(context != null && context.getStepExecution() != null); + return item + item; + }; + }; + processor.setDelegate(delegate); + Future result = StepScopeTestUtils.doInStepScope(MetaDataInstanceFactory.createStepExecution(), + new Callable>() { + public Future call() throws Exception { + return processor.process("foo"); + } + }); + assertEquals("foofoo", result.get()); + } + + @Test + public void testMultiExecution() throws Exception { + processor.setDelegate(delegate); + processor.setTaskExecutor(new SimpleAsyncTaskExecutor()); + List> list = new ArrayList<>(); + for (int count = 0; count < 10; count++) { + list.add(processor.process("foo" + count)); + } + for (Future future : list) { + assertTrue(future.get().matches("foo.*foo.*")); + } + } + +} diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/async/AsyncItemWriterTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/async/AsyncItemWriterTests.java index e1475ac29..3681870bc 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/async/AsyncItemWriterTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/async/AsyncItemWriterTests.java @@ -44,7 +44,9 @@ import static org.junit.Assert.assertTrue; public class AsyncItemWriterTests { private AsyncItemWriter writer; + private List writtenItems; + private TaskExecutor taskExecutor; @Before @@ -174,7 +176,8 @@ public class AsyncItemWriterTests { } @Override - public String get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { + public String get(long timeout, TimeUnit unit) + throws InterruptedException, ExecutionException, TimeoutException { return null; } }); @@ -228,8 +231,11 @@ public class AsyncItemWriterTests { private class ListItemWriter implements ItemWriter { protected List items; + public boolean isOpened = false; + public boolean isUpdated = false; + public boolean isClosed = false; public ListItemWriter(List items) { @@ -240,12 +246,17 @@ public class AsyncItemWriterTests { public void write(List items) throws Exception { this.items.addAll(items); } + } private class ListItemStreamWriter implements ItemStreamWriter { + public boolean isOpened = false; + public boolean isUpdated = false; + public boolean isClosed = false; + protected List items; public ListItemStreamWriter(List items) { @@ -271,5 +282,7 @@ public class AsyncItemWriterTests { public void close() throws ItemStreamException { isClosed = true; } + } + } diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/async/PollingAsyncItemProcessorMessagingGatewayTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/async/PollingAsyncItemProcessorMessagingGatewayTests.java index 520c7f373..ac7aaac22 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/async/PollingAsyncItemProcessorMessagingGatewayTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/async/PollingAsyncItemProcessorMessagingGatewayTests.java @@ -1,118 +1,121 @@ -/* - * Copyright 2006-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.integration.async; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.Future; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.MethodRule; -import org.junit.runner.RunWith; -import org.junit.runners.model.FrameworkMethod; -import org.junit.runners.model.Statement; - -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.item.ItemProcessor; -import org.springframework.batch.test.MetaDataInstanceFactory; -import org.springframework.batch.test.StepScopeTestUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.task.SimpleAsyncTaskExecutor; -import org.springframework.integration.annotation.MessageEndpoint; -import org.springframework.integration.annotation.ServiceActivator; -import org.springframework.messaging.handler.annotation.Header; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration -public class PollingAsyncItemProcessorMessagingGatewayTests { - - private AsyncItemProcessor processor = new AsyncItemProcessor<>(); - - private StepExecution stepExecution = MetaDataInstanceFactory.createStepExecution(new JobParametersBuilder().addLong("factor", 2L).toJobParameters());; - - @Rule - public MethodRule rule = new MethodRule() { - public Statement apply(final Statement base, FrameworkMethod method, Object target) { - return new Statement() { - @Override - public void evaluate() throws Throwable { - StepScopeTestUtils.doInStepScope(stepExecution, new Callable() { - public Void call() throws Exception { - try { - base.evaluate(); - } - catch (Exception e) { - throw e; - } - catch (Throwable e) { - throw new Error(e); - } - return null; - } - }); - }; - }; - } - }; - - @Autowired - private ItemProcessor delegate; - - @Test - public void testMultiExecution() throws Exception { - processor.setDelegate(delegate); - processor.setTaskExecutor(new SimpleAsyncTaskExecutor()); - List> list = new ArrayList<>(); - for (int count = 0; count < 10; count++) { - list.add(processor.process("foo" + count)); - } - for (Future future : list) { - String value = future.get(); - /** - * This delegate is a Spring Integration MessagingGateway. It can - * easily return null because of a timeout, but that will be treated - * by Batch as a filtered item, whereas it is really more like a - * skip. So we have to throw an exception in the processor if an - * unexpected null value comes back. - */ - assertNotNull(value); - assertTrue(value.matches("foo.*foo.*")); - } - } - - @MessageEndpoint - public static class Doubler { - - @ServiceActivator - public String cat(String value, @Header(value="stepExecution.jobExecution.jobParameters.getLong('factor')", required=false) Integer input) { - long factor = input==null ? 1 : input; - for (int i=1; i processor = new AsyncItemProcessor<>(); + + private StepExecution stepExecution = MetaDataInstanceFactory + .createStepExecution(new JobParametersBuilder().addLong("factor", 2L).toJobParameters()); + + ; + + @Rule + public MethodRule rule = new MethodRule() { + public Statement apply(final Statement base, FrameworkMethod method, Object target) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + StepScopeTestUtils.doInStepScope(stepExecution, new Callable() { + public Void call() throws Exception { + try { + base.evaluate(); + } + catch (Exception e) { + throw e; + } + catch (Throwable e) { + throw new Error(e); + } + return null; + } + }); + }; + }; + } + }; + + @Autowired + private ItemProcessor delegate; + + @Test + public void testMultiExecution() throws Exception { + processor.setDelegate(delegate); + processor.setTaskExecutor(new SimpleAsyncTaskExecutor()); + List> list = new ArrayList<>(); + for (int count = 0; count < 10; count++) { + list.add(processor.process("foo" + count)); + } + for (Future future : list) { + String value = future.get(); + /** + * This delegate is a Spring Integration MessagingGateway. It can easily + * return null because of a timeout, but that will be treated by Batch as a + * filtered item, whereas it is really more like a skip. So we have to throw + * an exception in the processor if an unexpected null value comes back. + */ + assertNotNull(value); + assertTrue(value.matches("foo.*foo.*")); + } + } + + @MessageEndpoint + public static class Doubler { + + @ServiceActivator + public String cat(String value, @Header(value = "stepExecution.jobExecution.jobParameters.getLong('factor')", + required = false) Integer input) { + long factor = input == null ? 1 : input; + for (int i = 1; i < factor; i++) { + value += value; + } + return value; + } + + } + +} diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/ChunkMessageItemWriterIntegrationTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/ChunkMessageItemWriterIntegrationTests.java index 45e04d143..526cda85e 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/ChunkMessageItemWriterIntegrationTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/ChunkMessageItemWriterIntegrationTests.java @@ -1,331 +1,330 @@ -/* - * Copyright 2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.integration.chunk; - -import java.util.Arrays; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobInstance; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.Step; -import org.springframework.batch.core.StepContribution; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.job.SimpleJob; -import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException; -import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException; -import org.springframework.batch.core.repository.JobRepository; -import org.springframework.batch.core.repository.JobRestartException; -import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; -import org.springframework.batch.core.step.factory.SimpleStepFactoryBean; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.support.ListItemReader; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.integration.core.MessagingTemplate; -import org.springframework.jdbc.datasource.DataSourceTransactionManager; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageChannel; -import org.springframework.messaging.PollableChannel; -import org.springframework.messaging.support.GenericMessage; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.util.StringUtils; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -public class ChunkMessageItemWriterIntegrationTests { - - private final ChunkMessageChannelItemWriter writer = new ChunkMessageChannelItemWriter<>(); - - @Autowired - @Qualifier("requests") - private MessageChannel requests; - - @Autowired - @Qualifier("replies") - private PollableChannel replies; - - private final SimpleStepFactoryBean factory = new SimpleStepFactoryBean<>(); - - private JobRepository jobRepository; - - private static long jobCounter; - - @Before - public void setUp() throws Exception { - EmbeddedDatabase embeddedDatabase = new EmbeddedDatabaseBuilder() - .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("/org/springframework/batch/core/schema-hsqldb.sql") - .build(); - DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(embeddedDatabase); - JobRepositoryFactoryBean repositoryFactoryBean = new JobRepositoryFactoryBean(); - repositoryFactoryBean.setDataSource(embeddedDatabase); - repositoryFactoryBean.setTransactionManager(transactionManager); - repositoryFactoryBean.afterPropertiesSet(); - jobRepository = repositoryFactoryBean.getObject(); - factory.setJobRepository(jobRepository); - factory.setTransactionManager(transactionManager); - factory.setBeanName("step"); - factory.setItemWriter(writer); - factory.setCommitInterval(4); - - MessagingTemplate gateway = new MessagingTemplate(); - writer.setMessagingOperations(gateway); - - gateway.setDefaultChannel(requests); - writer.setReplyChannel(replies); - gateway.setReceiveTimeout(100); - - TestItemWriter.count = 0; - - // Drain queues - Message message = replies.receive(10); - while (message != null) { - System.err.println(message); - message = replies.receive(10); - } - - } - - @After - public void tearDown() { - while (replies.receive(10L) != null) { - } - } - - @Test - public void testOpenWithNoState() throws Exception { - writer.open(new ExecutionContext()); - } - - @Test - public void testUpdateAndOpenWithState() throws Exception { - ExecutionContext executionContext = new ExecutionContext(); - writer.update(executionContext); - writer.open(executionContext); - assertEquals(0, executionContext.getInt(ChunkMessageChannelItemWriter.EXPECTED)); - assertEquals(0, executionContext.getInt(ChunkMessageChannelItemWriter.ACTUAL)); - } - - @Test - public void testVanillaIteration() throws Exception { - - factory.setItemReader(new ListItemReader<>(Arrays.asList(StringUtils - .commaDelimitedListToStringArray("1,2,3,4,5,6")))); - - Step step = factory.getObject(); - - StepExecution stepExecution = getStepExecution(step); - step.execute(stepExecution); - - waitForResults(6, 10); - - assertEquals(6, TestItemWriter.count); - assertEquals(6, stepExecution.getReadCount()); - - } - - @Test - public void testSimulatedRestart() throws Exception { - - factory.setItemReader(new ListItemReader<>(Arrays.asList(StringUtils - .commaDelimitedListToStringArray("1,2,3,4,5,6")))); - - Step step = factory.getObject(); - - StepExecution stepExecution = getStepExecution(step); - - // Set up context with two messages (chunks) in the backlog - stepExecution.getExecutionContext().putInt(ChunkMessageChannelItemWriter.EXPECTED, 6); - stepExecution.getExecutionContext().putInt(ChunkMessageChannelItemWriter.ACTUAL, 4); - // And make the back log real - requests.send(getSimpleMessage("foo", stepExecution.getJobExecution().getJobId())); - requests.send(getSimpleMessage("bar", stepExecution.getJobExecution().getJobId())); - step.execute(stepExecution); - - waitForResults(8, 10); - - assertEquals(8, TestItemWriter.count); - assertEquals(6, stepExecution.getReadCount()); - - } - - @Test - public void testSimulatedRestartWithBadMessagesFromAnotherJob() throws Exception { - - factory.setItemReader(new ListItemReader<>(Arrays.asList(StringUtils - .commaDelimitedListToStringArray("1,2,3,4,5,6")))); - - Step step = factory.getObject(); - - StepExecution stepExecution = getStepExecution(step); - - // Set up context with two messages (chunks) in the backlog - stepExecution.getExecutionContext().putInt(ChunkMessageChannelItemWriter.EXPECTED, 3); - stepExecution.getExecutionContext().putInt(ChunkMessageChannelItemWriter.ACTUAL, 2); - - // Speed up the eventual failure - writer.setMaxWaitTimeouts(2); - - // And make the back log real - requests.send(getSimpleMessage("foo", 4321L)); - step.execute(stepExecution); - assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); - assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution.getExitStatus().getExitCode()); - String message = stepExecution.getExitStatus().getExitDescription(); - assertTrue("Message does not contain 'wrong job': " + message, message.contains("wrong job")); - - waitForResults(1, 10); - - assertEquals(1, TestItemWriter.count); - assertEquals(0, stepExecution.getReadCount()); - - } - - @SuppressWarnings({"unchecked", "rawtypes"}) - private GenericMessage getSimpleMessage(String string, Long jobId) { - StepContribution stepContribution = new JobExecution(new JobInstance(0L, "job"), new JobParameters()) - .createStepExecution("step").createStepContribution(); - ChunkRequest chunk = new ChunkRequest(0, StringUtils.commaDelimitedListToSet(string), jobId, stepContribution); - GenericMessage message = new GenericMessage<>(chunk); - return message; - } - - @Test - public void testEarlyCompletionSignalledInHandler() throws Exception { - - factory.setItemReader(new ListItemReader<>(Arrays.asList(StringUtils - .commaDelimitedListToStringArray("1,fail,3,4,5,6")))); - factory.setCommitInterval(2); - - Step step = factory.getObject(); - - StepExecution stepExecution = getStepExecution(step); - step.execute(stepExecution); - assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); - assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution.getExitStatus().getExitCode()); - String message = stepExecution.getExitStatus().getExitDescription(); - assertTrue("Message does not contain 'fail': " + message, message.contains("fail")); - - waitForResults(2, 10); - - // The number of items processed is actually between 1 and 6, because - // the one that failed might have been processed out of order. - assertTrue(1 <= TestItemWriter.count); - assertTrue(6 >= TestItemWriter.count); - // But it should fail the step in any case - assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); - - } - - @Test - public void testSimulatedRestartWithNoBacklog() throws Exception { - - factory.setItemReader(new ListItemReader<>(Arrays.asList(StringUtils - .commaDelimitedListToStringArray("1,2,3,4,5,6")))); - - Step step = factory.getObject(); - - StepExecution stepExecution = getStepExecution(step); - - // Set up expectation of three messages (chunks) in the backlog - stepExecution.getExecutionContext().putInt(ChunkMessageChannelItemWriter.EXPECTED, 6); - stepExecution.getExecutionContext().putInt(ChunkMessageChannelItemWriter.ACTUAL, 3); - - writer.setMaxWaitTimeouts(2); - - /* - * With no backlog we process all the items, but the listener can't - * reconcile the expected number of items with the actual. An infinite - * loop would be bad, so the best we can do is fail as fast as possible. - */ - step.execute(stepExecution); - assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); - assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution.getExitStatus().getExitCode()); - String message = stepExecution.getExitStatus().getExitDescription(); - assertTrue("Message did not contain 'timed out': " + message, message.toLowerCase().contains("timed out")); - - assertEquals(0, TestItemWriter.count); - assertEquals(0, stepExecution.getReadCount()); - - } - - /** - * This one is flakey - we try to force it to wait until after the step to - * finish processing just by waiting for long enough. - */ - @Test - public void testFailureInStepListener() throws Exception { - - factory.setItemReader(new ListItemReader<>(Arrays.asList(StringUtils - .commaDelimitedListToStringArray("wait,fail,3,4,5,6")))); - - Step step = factory.getObject(); - - StepExecution stepExecution = getStepExecution(step); - step.execute(stepExecution); - - waitForResults(2, 10); - - // The number of items processed is actually between 1 and 6, because - // the one that failed might have been processed out of order. - assertTrue(1 <= TestItemWriter.count); - assertTrue(6 >= TestItemWriter.count); - - assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); - assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution.getExitStatus().getExitCode()); - - String exitDescription = stepExecution.getExitStatus().getExitDescription(); - assertTrue("Exit description does not contain exception type name: " + exitDescription, exitDescription - .contains(AsynchronousFailureException.class.getName())); - - } - - // TODO : test non-dispatch of empty chunk - - private void waitForResults(int expected, int maxWait) throws InterruptedException { - int count = 0; - while (TestItemWriter.count < expected && count < maxWait) { - count++; - Thread.sleep(10); - } - } - - private StepExecution getStepExecution(Step step) throws JobExecutionAlreadyRunningException, JobRestartException, - JobInstanceAlreadyCompleteException { - SimpleJob job = new SimpleJob(); - job.setName("job"); - JobExecution jobExecution = jobRepository.createJobExecution(job.getName(), new JobParametersBuilder().addLong( - "job.counter", jobCounter++).toJobParameters()); - StepExecution stepExecution = jobExecution.createStepExecution(step.getName()); - jobRepository.add(stepExecution); - return stepExecution; - } - -} +/* + * Copyright 2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.integration.chunk; + +import java.util.Arrays; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobInstance; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.JobParametersBuilder; +import org.springframework.batch.core.Step; +import org.springframework.batch.core.StepContribution; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.job.SimpleJob; +import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException; +import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.core.repository.JobRestartException; +import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; +import org.springframework.batch.core.step.factory.SimpleStepFactoryBean; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.support.ListItemReader; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.integration.core.MessagingTemplate; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.messaging.Message; +import org.springframework.messaging.MessageChannel; +import org.springframework.messaging.PollableChannel; +import org.springframework.messaging.support.GenericMessage; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.util.StringUtils; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class ChunkMessageItemWriterIntegrationTests { + + private final ChunkMessageChannelItemWriter writer = new ChunkMessageChannelItemWriter<>(); + + @Autowired + @Qualifier("requests") + private MessageChannel requests; + + @Autowired + @Qualifier("replies") + private PollableChannel replies; + + private final SimpleStepFactoryBean factory = new SimpleStepFactoryBean<>(); + + private JobRepository jobRepository; + + private static long jobCounter; + + @Before + public void setUp() throws Exception { + EmbeddedDatabase embeddedDatabase = new EmbeddedDatabaseBuilder() + .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") + .addScript("/org/springframework/batch/core/schema-hsqldb.sql").build(); + DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(embeddedDatabase); + JobRepositoryFactoryBean repositoryFactoryBean = new JobRepositoryFactoryBean(); + repositoryFactoryBean.setDataSource(embeddedDatabase); + repositoryFactoryBean.setTransactionManager(transactionManager); + repositoryFactoryBean.afterPropertiesSet(); + jobRepository = repositoryFactoryBean.getObject(); + factory.setJobRepository(jobRepository); + factory.setTransactionManager(transactionManager); + factory.setBeanName("step"); + factory.setItemWriter(writer); + factory.setCommitInterval(4); + + MessagingTemplate gateway = new MessagingTemplate(); + writer.setMessagingOperations(gateway); + + gateway.setDefaultChannel(requests); + writer.setReplyChannel(replies); + gateway.setReceiveTimeout(100); + + TestItemWriter.count = 0; + + // Drain queues + Message message = replies.receive(10); + while (message != null) { + System.err.println(message); + message = replies.receive(10); + } + + } + + @After + public void tearDown() { + while (replies.receive(10L) != null) { + } + } + + @Test + public void testOpenWithNoState() throws Exception { + writer.open(new ExecutionContext()); + } + + @Test + public void testUpdateAndOpenWithState() throws Exception { + ExecutionContext executionContext = new ExecutionContext(); + writer.update(executionContext); + writer.open(executionContext); + assertEquals(0, executionContext.getInt(ChunkMessageChannelItemWriter.EXPECTED)); + assertEquals(0, executionContext.getInt(ChunkMessageChannelItemWriter.ACTUAL)); + } + + @Test + public void testVanillaIteration() throws Exception { + + factory.setItemReader( + new ListItemReader<>(Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,2,3,4,5,6")))); + + Step step = factory.getObject(); + + StepExecution stepExecution = getStepExecution(step); + step.execute(stepExecution); + + waitForResults(6, 10); + + assertEquals(6, TestItemWriter.count); + assertEquals(6, stepExecution.getReadCount()); + + } + + @Test + public void testSimulatedRestart() throws Exception { + + factory.setItemReader( + new ListItemReader<>(Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,2,3,4,5,6")))); + + Step step = factory.getObject(); + + StepExecution stepExecution = getStepExecution(step); + + // Set up context with two messages (chunks) in the backlog + stepExecution.getExecutionContext().putInt(ChunkMessageChannelItemWriter.EXPECTED, 6); + stepExecution.getExecutionContext().putInt(ChunkMessageChannelItemWriter.ACTUAL, 4); + // And make the back log real + requests.send(getSimpleMessage("foo", stepExecution.getJobExecution().getJobId())); + requests.send(getSimpleMessage("bar", stepExecution.getJobExecution().getJobId())); + step.execute(stepExecution); + + waitForResults(8, 10); + + assertEquals(8, TestItemWriter.count); + assertEquals(6, stepExecution.getReadCount()); + + } + + @Test + public void testSimulatedRestartWithBadMessagesFromAnotherJob() throws Exception { + + factory.setItemReader( + new ListItemReader<>(Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,2,3,4,5,6")))); + + Step step = factory.getObject(); + + StepExecution stepExecution = getStepExecution(step); + + // Set up context with two messages (chunks) in the backlog + stepExecution.getExecutionContext().putInt(ChunkMessageChannelItemWriter.EXPECTED, 3); + stepExecution.getExecutionContext().putInt(ChunkMessageChannelItemWriter.ACTUAL, 2); + + // Speed up the eventual failure + writer.setMaxWaitTimeouts(2); + + // And make the back log real + requests.send(getSimpleMessage("foo", 4321L)); + step.execute(stepExecution); + assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); + assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution.getExitStatus().getExitCode()); + String message = stepExecution.getExitStatus().getExitDescription(); + assertTrue("Message does not contain 'wrong job': " + message, message.contains("wrong job")); + + waitForResults(1, 10); + + assertEquals(1, TestItemWriter.count); + assertEquals(0, stepExecution.getReadCount()); + + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + private GenericMessage getSimpleMessage(String string, Long jobId) { + StepContribution stepContribution = new JobExecution(new JobInstance(0L, "job"), new JobParameters()) + .createStepExecution("step").createStepContribution(); + ChunkRequest chunk = new ChunkRequest(0, StringUtils.commaDelimitedListToSet(string), jobId, stepContribution); + GenericMessage message = new GenericMessage<>(chunk); + return message; + } + + @Test + public void testEarlyCompletionSignalledInHandler() throws Exception { + + factory.setItemReader( + new ListItemReader<>(Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,fail,3,4,5,6")))); + factory.setCommitInterval(2); + + Step step = factory.getObject(); + + StepExecution stepExecution = getStepExecution(step); + step.execute(stepExecution); + assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); + assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution.getExitStatus().getExitCode()); + String message = stepExecution.getExitStatus().getExitDescription(); + assertTrue("Message does not contain 'fail': " + message, message.contains("fail")); + + waitForResults(2, 10); + + // The number of items processed is actually between 1 and 6, because + // the one that failed might have been processed out of order. + assertTrue(1 <= TestItemWriter.count); + assertTrue(6 >= TestItemWriter.count); + // But it should fail the step in any case + assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); + + } + + @Test + public void testSimulatedRestartWithNoBacklog() throws Exception { + + factory.setItemReader( + new ListItemReader<>(Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,2,3,4,5,6")))); + + Step step = factory.getObject(); + + StepExecution stepExecution = getStepExecution(step); + + // Set up expectation of three messages (chunks) in the backlog + stepExecution.getExecutionContext().putInt(ChunkMessageChannelItemWriter.EXPECTED, 6); + stepExecution.getExecutionContext().putInt(ChunkMessageChannelItemWriter.ACTUAL, 3); + + writer.setMaxWaitTimeouts(2); + + /* + * With no backlog we process all the items, but the listener can't reconcile the + * expected number of items with the actual. An infinite loop would be bad, so the + * best we can do is fail as fast as possible. + */ + step.execute(stepExecution); + assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); + assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution.getExitStatus().getExitCode()); + String message = stepExecution.getExitStatus().getExitDescription(); + assertTrue("Message did not contain 'timed out': " + message, message.toLowerCase().contains("timed out")); + + assertEquals(0, TestItemWriter.count); + assertEquals(0, stepExecution.getReadCount()); + + } + + /** + * This one is flakey - we try to force it to wait until after the step to finish + * processing just by waiting for long enough. + */ + @Test + public void testFailureInStepListener() throws Exception { + + factory.setItemReader( + new ListItemReader<>(Arrays.asList(StringUtils.commaDelimitedListToStringArray("wait,fail,3,4,5,6")))); + + Step step = factory.getObject(); + + StepExecution stepExecution = getStepExecution(step); + step.execute(stepExecution); + + waitForResults(2, 10); + + // The number of items processed is actually between 1 and 6, because + // the one that failed might have been processed out of order. + assertTrue(1 <= TestItemWriter.count); + assertTrue(6 >= TestItemWriter.count); + + assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); + assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution.getExitStatus().getExitCode()); + + String exitDescription = stepExecution.getExitStatus().getExitDescription(); + assertTrue("Exit description does not contain exception type name: " + exitDescription, + exitDescription.contains(AsynchronousFailureException.class.getName())); + + } + + // TODO : test non-dispatch of empty chunk + + private void waitForResults(int expected, int maxWait) throws InterruptedException { + int count = 0; + while (TestItemWriter.count < expected && count < maxWait) { + count++; + Thread.sleep(10); + } + } + + private StepExecution getStepExecution(Step step) + throws JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException { + SimpleJob job = new SimpleJob(); + job.setName("job"); + JobExecution jobExecution = jobRepository.createJobExecution(job.getName(), + new JobParametersBuilder().addLong("job.counter", jobCounter++).toJobParameters()); + StepExecution stepExecution = jobExecution.createStepExecution(step.getName()); + jobRepository.add(stepExecution); + return stepExecution; + } + +} diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/ChunkProcessorChunkHandlerTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/ChunkProcessorChunkHandlerTests.java index 2b729ee7a..e0271fd1c 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/ChunkProcessorChunkHandlerTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/ChunkProcessorChunkHandlerTests.java @@ -1,35 +1,35 @@ -package org.springframework.batch.integration.chunk; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; -import org.springframework.batch.core.StepContribution; -import org.springframework.batch.core.step.item.Chunk; -import org.springframework.batch.core.step.item.ChunkProcessor; -import org.springframework.batch.test.MetaDataInstanceFactory; -import org.springframework.util.StringUtils; - -public class ChunkProcessorChunkHandlerTests { - - private ChunkProcessorChunkHandler handler = new ChunkProcessorChunkHandler<>(); - - protected int count = 0; - - @Test - public void testVanillaHandleChunk() throws Exception { - handler.setChunkProcessor(new ChunkProcessor() { - public void process(StepContribution contribution, Chunk chunk) throws Exception { - count += chunk.size(); - } - }); - StepContribution stepContribution = MetaDataInstanceFactory.createStepExecution().createStepContribution(); - ChunkResponse response = handler.handleChunk(new ChunkRequest<>(0, StringUtils - .commaDelimitedListToSet("foo,bar"), 12L, stepContribution)); - assertEquals(stepContribution, response.getStepContribution()); - assertEquals(12, response.getJobId().longValue()); - assertTrue(response.isSuccessful()); - assertEquals(2, count); - } - -} +package org.springframework.batch.integration.chunk; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.springframework.batch.core.StepContribution; +import org.springframework.batch.core.step.item.Chunk; +import org.springframework.batch.core.step.item.ChunkProcessor; +import org.springframework.batch.test.MetaDataInstanceFactory; +import org.springframework.util.StringUtils; + +public class ChunkProcessorChunkHandlerTests { + + private ChunkProcessorChunkHandler handler = new ChunkProcessorChunkHandler<>(); + + protected int count = 0; + + @Test + public void testVanillaHandleChunk() throws Exception { + handler.setChunkProcessor(new ChunkProcessor() { + public void process(StepContribution contribution, Chunk chunk) throws Exception { + count += chunk.size(); + } + }); + StepContribution stepContribution = MetaDataInstanceFactory.createStepExecution().createStepContribution(); + ChunkResponse response = handler.handleChunk( + new ChunkRequest<>(0, StringUtils.commaDelimitedListToSet("foo,bar"), 12L, stepContribution)); + assertEquals(stepContribution, response.getStepContribution()); + assertEquals(12, response.getJobId().longValue()); + assertTrue(response.isSuccessful()); + assertEquals(2, count); + } + +} diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/ChunkRequestTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/ChunkRequestTests.java index f51c51cf2..ae273d459 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/ChunkRequestTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/ChunkRequestTests.java @@ -1,66 +1,66 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.integration.chunk; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import java.util.Arrays; - -import org.junit.Test; -import org.springframework.batch.test.MetaDataInstanceFactory; -import org.springframework.util.SerializationUtils; - -/** - * @author Dave Syer - * - */ -public class ChunkRequestTests { - - private ChunkRequest request = new ChunkRequest<>(0, Arrays.asList("foo", "bar"), - 111L, MetaDataInstanceFactory.createStepExecution().createStepContribution()); - - @Test - public void testGetJobId() { - assertEquals(111L, request.getJobId()); - } - - @Test - public void testGetItems() { - assertEquals(2, request.getItems().size()); - } - - @Test - public void testGetStepContribution() { - assertNotNull(request.getStepContribution()); - } - - @Test - public void testToString() { - System.err.println(request.toString()); - } - - @Test - public void testSerializable() throws Exception { - @SuppressWarnings("unchecked") - ChunkRequest result = (ChunkRequest) SerializationUtils.deserialize(SerializationUtils - .serialize(request)); - assertNotNull(result.getStepContribution()); - assertEquals(111L, result.getJobId()); - assertEquals(2, result.getItems().size()); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.integration.chunk; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.util.Arrays; + +import org.junit.Test; +import org.springframework.batch.test.MetaDataInstanceFactory; +import org.springframework.util.SerializationUtils; + +/** + * @author Dave Syer + * + */ +public class ChunkRequestTests { + + private ChunkRequest request = new ChunkRequest<>(0, Arrays.asList("foo", "bar"), 111L, + MetaDataInstanceFactory.createStepExecution().createStepContribution()); + + @Test + public void testGetJobId() { + assertEquals(111L, request.getJobId()); + } + + @Test + public void testGetItems() { + assertEquals(2, request.getItems().size()); + } + + @Test + public void testGetStepContribution() { + assertNotNull(request.getStepContribution()); + } + + @Test + public void testToString() { + System.err.println(request.toString()); + } + + @Test + public void testSerializable() throws Exception { + @SuppressWarnings("unchecked") + ChunkRequest result = (ChunkRequest) SerializationUtils + .deserialize(SerializationUtils.serialize(request)); + assertNotNull(result.getStepContribution()); + assertEquals(111L, result.getJobId()); + assertEquals(2, result.getItems().size()); + } + +} diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/ChunkResponseTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/ChunkResponseTests.java index 43f813b35..16eeed4f1 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/ChunkResponseTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/ChunkResponseTests.java @@ -1,56 +1,56 @@ -/* - * Copyright 2006-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.integration.chunk; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import org.junit.Test; -import org.springframework.batch.test.MetaDataInstanceFactory; -import org.springframework.util.SerializationUtils; - -/** - * @author Dave Syer - * - */ -public class ChunkResponseTests { - - private ChunkResponse response = new ChunkResponse(0, 111L, MetaDataInstanceFactory.createStepExecution() - .createStepContribution()); - - @Test - public void testGetJobId() { - assertEquals(Long.valueOf(111L), response.getJobId()); - } - - @Test - public void testGetStepContribution() { - assertNotNull(response.getStepContribution()); - } - - @Test - public void testToString() { - System.err.println(response.toString()); - } - - @Test - public void testSerializable() throws Exception { - ChunkResponse result = (ChunkResponse) SerializationUtils.deserialize(SerializationUtils.serialize(response)); - assertNotNull(result.getStepContribution()); - assertEquals(Long.valueOf(111L), result.getJobId()); - } - -} +/* + * Copyright 2006-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.integration.chunk; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.junit.Test; +import org.springframework.batch.test.MetaDataInstanceFactory; +import org.springframework.util.SerializationUtils; + +/** + * @author Dave Syer + * + */ +public class ChunkResponseTests { + + private ChunkResponse response = new ChunkResponse(0, 111L, + MetaDataInstanceFactory.createStepExecution().createStepContribution()); + + @Test + public void testGetJobId() { + assertEquals(Long.valueOf(111L), response.getJobId()); + } + + @Test + public void testGetStepContribution() { + assertNotNull(response.getStepContribution()); + } + + @Test + public void testToString() { + System.err.println(response.toString()); + } + + @Test + public void testSerializable() throws Exception { + ChunkResponse result = (ChunkResponse) SerializationUtils.deserialize(SerializationUtils.serialize(response)); + assertNotNull(result.getStepContribution()); + assertEquals(Long.valueOf(111L), result.getJobId()); + } + +} diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/MessageSourcePollerInterceptorTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/MessageSourcePollerInterceptorTests.java index a2d5a167b..40f2f753b 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/MessageSourcePollerInterceptorTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/MessageSourcePollerInterceptorTests.java @@ -50,6 +50,7 @@ public class MessageSourcePollerInterceptorTests { public Message receive() { return new GenericMessage<>(payload); } + } } diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/RemoteChunkFaultTolerantStepIntegrationTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/RemoteChunkFaultTolerantStepIntegrationTests.java index ebc2b45e6..bce367b8c 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/RemoteChunkFaultTolerantStepIntegrationTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/RemoteChunkFaultTolerantStepIntegrationTests.java @@ -1,89 +1,90 @@ -package org.springframework.batch.integration.chunk; - -import static org.junit.Assert.assertEquals; - -import java.util.Collections; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameter; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.launch.JobLauncher; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.messaging.Message; -import org.springframework.messaging.PollableChannel; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -public class RemoteChunkFaultTolerantStepIntegrationTests { - - @Autowired - private JobLauncher jobLauncher; - - @Autowired - private Job job; - - @Autowired - private PollableChannel replies; - - @Before - public void drain() { - Message message = replies.receive(100L); - while (message!=null) { - // System.err.println(message); - message = replies.receive(100L); - } - } - - @Test - public void testFailedStep() throws Exception { - JobExecution jobExecution = jobLauncher.run(job, new JobParameters(Collections.singletonMap("item.three", - new JobParameter("unsupported")))); - assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); - StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next(); - assertEquals(9, stepExecution.getReadCount()); - // In principle the write count could be more than 2 and less than 9... - assertEquals(7, stepExecution.getWriteCount()); - } - - @Test - public void testFailedStepOnError() throws Exception { - JobExecution jobExecution = jobLauncher.run(job, new JobParameters(Collections.singletonMap("item.three", - new JobParameter("error")))); - assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); - StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next(); - assertEquals(9, stepExecution.getReadCount()); - // In principle the write count could be more than 2 and less than 9... - assertEquals(7, stepExecution.getWriteCount()); - } - - @Test - public void testSunnyDayFaultTolerant() throws Exception { - JobExecution jobExecution = jobLauncher.run(job, new JobParameters(Collections.singletonMap("item.three", - new JobParameter("3")))); - assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); - StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next(); - assertEquals(9, stepExecution.getReadCount()); - assertEquals(9, stepExecution.getWriteCount()); - } - - @Test - public void testSkipsInWriter() throws Exception { - JobExecution jobExecution = jobLauncher.run(job, new JobParametersBuilder().addString("item.three", "fail") - .addLong("run.id", 1L).toJobParameters()); - assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); - StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next(); - assertEquals(9, stepExecution.getReadCount()); - assertEquals(7, stepExecution.getWriteCount()); - // The whole chunk gets skipped... - assertEquals(2, stepExecution.getWriteSkipCount()); - } -} +package org.springframework.batch.integration.chunk; + +import static org.junit.Assert.assertEquals; + +import java.util.Collections; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.Job; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobParameter; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.JobParametersBuilder; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.messaging.Message; +import org.springframework.messaging.PollableChannel; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class RemoteChunkFaultTolerantStepIntegrationTests { + + @Autowired + private JobLauncher jobLauncher; + + @Autowired + private Job job; + + @Autowired + private PollableChannel replies; + + @Before + public void drain() { + Message message = replies.receive(100L); + while (message != null) { + // System.err.println(message); + message = replies.receive(100L); + } + } + + @Test + public void testFailedStep() throws Exception { + JobExecution jobExecution = jobLauncher.run(job, + new JobParameters(Collections.singletonMap("item.three", new JobParameter("unsupported")))); + assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); + StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next(); + assertEquals(9, stepExecution.getReadCount()); + // In principle the write count could be more than 2 and less than 9... + assertEquals(7, stepExecution.getWriteCount()); + } + + @Test + public void testFailedStepOnError() throws Exception { + JobExecution jobExecution = jobLauncher.run(job, + new JobParameters(Collections.singletonMap("item.three", new JobParameter("error")))); + assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); + StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next(); + assertEquals(9, stepExecution.getReadCount()); + // In principle the write count could be more than 2 and less than 9... + assertEquals(7, stepExecution.getWriteCount()); + } + + @Test + public void testSunnyDayFaultTolerant() throws Exception { + JobExecution jobExecution = jobLauncher.run(job, + new JobParameters(Collections.singletonMap("item.three", new JobParameter("3")))); + assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); + StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next(); + assertEquals(9, stepExecution.getReadCount()); + assertEquals(9, stepExecution.getWriteCount()); + } + + @Test + public void testSkipsInWriter() throws Exception { + JobExecution jobExecution = jobLauncher.run(job, + new JobParametersBuilder().addString("item.three", "fail").addLong("run.id", 1L).toJobParameters()); + assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); + StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next(); + assertEquals(9, stepExecution.getReadCount()); + assertEquals(7, stepExecution.getWriteCount()); + // The whole chunk gets skipped... + assertEquals(2, stepExecution.getWriteSkipCount()); + } + +} diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/RemoteChunkFaultTolerantStepJdbcIntegrationTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/RemoteChunkFaultTolerantStepJdbcIntegrationTests.java index 373d8a193..7ff88d296 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/RemoteChunkFaultTolerantStepJdbcIntegrationTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/RemoteChunkFaultTolerantStepJdbcIntegrationTests.java @@ -1,94 +1,96 @@ -package org.springframework.batch.integration.chunk; - -import static org.junit.Assert.assertEquals; - -import java.util.Collections; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameter; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.launch.JobLauncher; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.messaging.Message; -import org.springframework.messaging.PollableChannel; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -public class RemoteChunkFaultTolerantStepJdbcIntegrationTests { - - @Autowired - private JobLauncher jobLauncher; - - @Autowired - private Job job; - - @Autowired - private PollableChannel replies; - - @Before - public void drain() { - Message message = replies.receive(100L); - while (message!=null) { - message = replies.receive(100L); - } - } - - @Test - @DirtiesContext - public void testFailedStep() throws Exception { - JobExecution jobExecution = jobLauncher.run(job, new JobParameters(Collections.singletonMap("item.three", - new JobParameter("unsupported")))); - assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); - StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next(); - assertEquals(9, stepExecution.getReadCount()); - // In principle the write count could be more than 2 and less than 9... - assertEquals(7, stepExecution.getWriteCount()); - } - - @Test - @DirtiesContext - public void testFailedStepOnError() throws Exception { - JobExecution jobExecution = jobLauncher.run(job, new JobParameters(Collections.singletonMap("item.three", - new JobParameter("error")))); - assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); - StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next(); - assertEquals(9, stepExecution.getReadCount()); - // In principle the write count could be more than 2 and less than 9... - assertEquals(7, stepExecution.getWriteCount()); - } - - @Test - @DirtiesContext - public void testSunnyDayFaultTolerant() throws Exception { - JobExecution jobExecution = jobLauncher.run(job, new JobParameters(Collections.singletonMap("item.three", - new JobParameter("3")))); - assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); - StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next(); - assertEquals(9, stepExecution.getReadCount()); - assertEquals(9, stepExecution.getWriteCount()); - } - - @Test - @DirtiesContext - public void testSkipsInWriter() throws Exception { - JobExecution jobExecution = jobLauncher.run(job, new JobParametersBuilder().addString("item.three", "fail") - .addLong("run.id", 1L).toJobParameters()); - // System.err.println(new SimpleJdbcTemplate(dataSource).queryForList("SELECT * FROM INT_MESSAGE_GROUP")); - assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); - StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next(); - assertEquals(9, stepExecution.getReadCount()); - assertEquals(7, stepExecution.getWriteCount()); - // The whole chunk gets skipped... - assertEquals(2, stepExecution.getWriteSkipCount()); - } -} +package org.springframework.batch.integration.chunk; + +import static org.junit.Assert.assertEquals; + +import java.util.Collections; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.Job; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobParameter; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.JobParametersBuilder; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.messaging.Message; +import org.springframework.messaging.PollableChannel; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class RemoteChunkFaultTolerantStepJdbcIntegrationTests { + + @Autowired + private JobLauncher jobLauncher; + + @Autowired + private Job job; + + @Autowired + private PollableChannel replies; + + @Before + public void drain() { + Message message = replies.receive(100L); + while (message != null) { + message = replies.receive(100L); + } + } + + @Test + @DirtiesContext + public void testFailedStep() throws Exception { + JobExecution jobExecution = jobLauncher.run(job, + new JobParameters(Collections.singletonMap("item.three", new JobParameter("unsupported")))); + assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); + StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next(); + assertEquals(9, stepExecution.getReadCount()); + // In principle the write count could be more than 2 and less than 9... + assertEquals(7, stepExecution.getWriteCount()); + } + + @Test + @DirtiesContext + public void testFailedStepOnError() throws Exception { + JobExecution jobExecution = jobLauncher.run(job, + new JobParameters(Collections.singletonMap("item.three", new JobParameter("error")))); + assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); + StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next(); + assertEquals(9, stepExecution.getReadCount()); + // In principle the write count could be more than 2 and less than 9... + assertEquals(7, stepExecution.getWriteCount()); + } + + @Test + @DirtiesContext + public void testSunnyDayFaultTolerant() throws Exception { + JobExecution jobExecution = jobLauncher.run(job, + new JobParameters(Collections.singletonMap("item.three", new JobParameter("3")))); + assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); + StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next(); + assertEquals(9, stepExecution.getReadCount()); + assertEquals(9, stepExecution.getWriteCount()); + } + + @Test + @DirtiesContext + public void testSkipsInWriter() throws Exception { + JobExecution jobExecution = jobLauncher.run(job, + new JobParametersBuilder().addString("item.three", "fail").addLong("run.id", 1L).toJobParameters()); + // System.err.println(new SimpleJdbcTemplate(dataSource).queryForList("SELECT * + // FROM INT_MESSAGE_GROUP")); + assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); + StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next(); + assertEquals(9, stepExecution.getReadCount()); + assertEquals(7, stepExecution.getWriteCount()); + // The whole chunk gets skipped... + assertEquals(2, stepExecution.getWriteSkipCount()); + } + +} diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/RemoteChunkFaultTolerantStepJmsIntegrationTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/RemoteChunkFaultTolerantStepJmsIntegrationTests.java index 6391c1af8..c0c36e4e4 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/RemoteChunkFaultTolerantStepJmsIntegrationTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/RemoteChunkFaultTolerantStepJmsIntegrationTests.java @@ -1,83 +1,84 @@ -package org.springframework.batch.integration.chunk; - -import static org.junit.Assert.assertEquals; - -import java.io.File; -import java.util.Collections; - -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameter; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.launch.JobLauncher; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.util.FileSystemUtils; - -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -@DirtiesContext -public class RemoteChunkFaultTolerantStepJmsIntegrationTests { - - @BeforeClass - public static void clear() { - FileSystemUtils.deleteRecursively(new File("activemq-data")); - } - - @Autowired - private JobLauncher jobLauncher; - - @Autowired - private Job job; - - @Test - public void testFailedStep() throws Exception { - JobExecution jobExecution = jobLauncher.run(job, new JobParameters(Collections.singletonMap("item.three", - new JobParameter("unsupported")))); - assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); - StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next(); - assertEquals(9, stepExecution.getReadCount()); - // In principle the write count could be more than 2 and less than 9... - assertEquals(7, stepExecution.getWriteCount()); - } - - @Test - public void testFailedStepOnError() throws Exception { - JobExecution jobExecution = jobLauncher.run(job, new JobParameters(Collections.singletonMap("item.three", - new JobParameter("error")))); - assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); - StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next(); - assertEquals(9, stepExecution.getReadCount()); - // In principle the write count could be more than 2 and less than 9... - assertEquals(7, stepExecution.getWriteCount()); - } - - @Test - public void testSunnyDayFaultTolerant() throws Exception { - JobExecution jobExecution = jobLauncher.run(job, new JobParameters(Collections.singletonMap("item.three", - new JobParameter("3")))); - assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); - StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next(); - assertEquals(9, stepExecution.getReadCount()); - assertEquals(9, stepExecution.getWriteCount()); - } - - @Test - public void testSkipsInWriter() throws Exception { - JobExecution jobExecution = jobLauncher.run(job, new JobParametersBuilder().addString("item.three", "fail") - .addLong("run.id", 1L).toJobParameters()); - assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); - StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next(); - assertEquals(9, stepExecution.getReadCount()); - assertEquals(7, stepExecution.getWriteCount()); - assertEquals(2, stepExecution.getWriteSkipCount()); - } -} +package org.springframework.batch.integration.chunk; + +import static org.junit.Assert.assertEquals; + +import java.io.File; +import java.util.Collections; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.Job; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobParameter; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.JobParametersBuilder; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.util.FileSystemUtils; + +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +@DirtiesContext +public class RemoteChunkFaultTolerantStepJmsIntegrationTests { + + @BeforeClass + public static void clear() { + FileSystemUtils.deleteRecursively(new File("activemq-data")); + } + + @Autowired + private JobLauncher jobLauncher; + + @Autowired + private Job job; + + @Test + public void testFailedStep() throws Exception { + JobExecution jobExecution = jobLauncher.run(job, + new JobParameters(Collections.singletonMap("item.three", new JobParameter("unsupported")))); + assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); + StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next(); + assertEquals(9, stepExecution.getReadCount()); + // In principle the write count could be more than 2 and less than 9... + assertEquals(7, stepExecution.getWriteCount()); + } + + @Test + public void testFailedStepOnError() throws Exception { + JobExecution jobExecution = jobLauncher.run(job, + new JobParameters(Collections.singletonMap("item.three", new JobParameter("error")))); + assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); + StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next(); + assertEquals(9, stepExecution.getReadCount()); + // In principle the write count could be more than 2 and less than 9... + assertEquals(7, stepExecution.getWriteCount()); + } + + @Test + public void testSunnyDayFaultTolerant() throws Exception { + JobExecution jobExecution = jobLauncher.run(job, + new JobParameters(Collections.singletonMap("item.three", new JobParameter("3")))); + assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); + StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next(); + assertEquals(9, stepExecution.getReadCount()); + assertEquals(9, stepExecution.getWriteCount()); + } + + @Test + public void testSkipsInWriter() throws Exception { + JobExecution jobExecution = jobLauncher.run(job, + new JobParametersBuilder().addString("item.three", "fail").addLong("run.id", 1L).toJobParameters()); + assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); + StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next(); + assertEquals(9, stepExecution.getReadCount()); + assertEquals(7, stepExecution.getWriteCount()); + assertEquals(2, stepExecution.getWriteSkipCount()); + } + +} diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/RemoteChunkStepIntegrationTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/RemoteChunkStepIntegrationTests.java index 0086e1672..1c1237ec9 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/RemoteChunkStepIntegrationTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/RemoteChunkStepIntegrationTests.java @@ -1,51 +1,51 @@ -package org.springframework.batch.integration.chunk; - -import static org.junit.Assert.assertEquals; - -import java.util.Collections; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameter; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.launch.JobLauncher; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -public class RemoteChunkStepIntegrationTests { - - @Autowired - private JobLauncher jobLauncher; - - @Autowired - private Job job; - - @Test - public void testSunnyDaySimpleStep() throws Exception { - JobExecution jobExecution = jobLauncher.run(job, new JobParameters(Collections.singletonMap("item.three", - new JobParameter("3")))); - assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); - StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next(); - assertEquals(9, stepExecution.getReadCount()); - assertEquals(9, stepExecution.getWriteCount()); - } - - @Test - public void testFailedStep() throws Exception { - JobExecution jobExecution = jobLauncher.run(job, new JobParameters(Collections.singletonMap("item.three", - new JobParameter("fail")))); - assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); - StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next(); - assertEquals(9, stepExecution.getReadCount()); - // In principle the write count could be more than 2 and less than 9... - assertEquals(7, stepExecution.getWriteCount()); - } - -} +package org.springframework.batch.integration.chunk; + +import static org.junit.Assert.assertEquals; + +import java.util.Collections; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.Job; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobParameter; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class RemoteChunkStepIntegrationTests { + + @Autowired + private JobLauncher jobLauncher; + + @Autowired + private Job job; + + @Test + public void testSunnyDaySimpleStep() throws Exception { + JobExecution jobExecution = jobLauncher.run(job, + new JobParameters(Collections.singletonMap("item.three", new JobParameter("3")))); + assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); + StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next(); + assertEquals(9, stepExecution.getReadCount()); + assertEquals(9, stepExecution.getWriteCount()); + } + + @Test + public void testFailedStep() throws Exception { + JobExecution jobExecution = jobLauncher.run(job, + new JobParameters(Collections.singletonMap("item.three", new JobParameter("fail")))); + assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); + StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next(); + assertEquals(9, stepExecution.getReadCount()); + // In principle the write count could be more than 2 and less than 9... + assertEquals(7, stepExecution.getWriteCount()); + } + +} diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/RemoteChunkingManagerStepBuilderTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/RemoteChunkingManagerStepBuilderTests.java index 190eab9dc..a12b411b6 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/RemoteChunkingManagerStepBuilderTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/RemoteChunkingManagerStepBuilderTests.java @@ -76,16 +76,19 @@ import static org.mockito.Mockito.when; * @author Mahmoud Ben Hassine */ @RunWith(SpringRunner.class) -@ContextConfiguration(classes = {RemoteChunkingManagerStepBuilderTests.BatchConfiguration.class}) +@ContextConfiguration(classes = { RemoteChunkingManagerStepBuilderTests.BatchConfiguration.class }) public class RemoteChunkingManagerStepBuilderTests { @Autowired private JobRepository jobRepository; + @Autowired private PlatformTransactionManager transactionManager; private PollableChannel inputChannel = new QueueChannel(); + private DirectChannel outputChannel = new DirectChannel(); + private ItemReader itemReader = new ListItemReader<>(Arrays.asList("a", "b", "c")); @Test @@ -153,48 +156,40 @@ public class RemoteChunkingManagerStepBuilderTests { @Test public void eitherOutputChannelOrMessagingTemplateMustBeProvided() { // given - RemoteChunkingManagerStepBuilder builder = new RemoteChunkingManagerStepBuilder("step") - .inputChannel(this.inputChannel) - .outputChannel(new DirectChannel()) + RemoteChunkingManagerStepBuilder builder = new RemoteChunkingManagerStepBuilder( + "step").inputChannel(this.inputChannel).outputChannel(new DirectChannel()) .messagingTemplate(new MessagingTemplate()); // when final Exception expectedException = Assert.assertThrows(IllegalStateException.class, builder::build); // then - assertThat(expectedException).hasMessage("You must specify either an outputChannel or a messagingTemplate but not both."); + assertThat(expectedException) + .hasMessage("You must specify either an outputChannel or a messagingTemplate but not both."); } @Test public void testUnsupportedOperationExceptionWhenSpecifyingAnItemWriter() { // when final Exception expectedException = Assert.assertThrows(UnsupportedOperationException.class, - () -> new RemoteChunkingManagerStepBuilder("step") - .reader(this.itemReader) - .writer(items -> { }) - .repository(this.jobRepository) - .transactionManager(this.transactionManager) - .inputChannel(this.inputChannel) - .outputChannel(this.outputChannel) - .build()); + () -> new RemoteChunkingManagerStepBuilder("step").reader(this.itemReader) + .writer(items -> { + }).repository(this.jobRepository).transactionManager(this.transactionManager) + .inputChannel(this.inputChannel).outputChannel(this.outputChannel).build()); // then - assertThat(expectedException).hasMessage("When configuring a manager " + - "step for remote chunking, the item writer will be automatically " + - "set to an instance of ChunkMessageChannelItemWriter. " + - "The item writer must not be provided in this case."); + assertThat(expectedException).hasMessage( + "When configuring a manager " + "step for remote chunking, the item writer will be automatically " + + "set to an instance of ChunkMessageChannelItemWriter. " + + "The item writer must not be provided in this case."); } @Test public void testManagerStepCreation() { // when - TaskletStep taskletStep = new RemoteChunkingManagerStepBuilder("step") - .reader(this.itemReader) - .repository(this.jobRepository) - .transactionManager(this.transactionManager) - .inputChannel(this.inputChannel) - .outputChannel(this.outputChannel) - .build(); + TaskletStep taskletStep = new RemoteChunkingManagerStepBuilder("step").reader(this.itemReader) + .repository(this.jobRepository).transactionManager(this.transactionManager) + .inputChannel(this.inputChannel).outputChannel(this.outputChannel).build(); // then Assert.assertNotNull(taskletStep); @@ -204,7 +199,7 @@ public class RemoteChunkingManagerStepBuilderTests { * The following test is to cover setters that override those from parent builders. */ @Test - @SuppressWarnings({"unchecked", "rawtypes"}) + @SuppressWarnings({ "unchecked", "rawtypes" }) public void testSetters() throws Exception { // when DefaultTransactionAttribute transactionAttribute = new DefaultTransactionAttribute(); @@ -226,7 +221,7 @@ public class RemoteChunkingManagerStepBuilderTests { ItemProcessor itemProcessor = item -> { System.out.println("processing item " + item); - if(item.equals("b")) { + if (item.equals("b")) { throw new Exception("b was found"); } else { @@ -237,21 +232,22 @@ public class RemoteChunkingManagerStepBuilderTests { ItemReader itemReader = new ItemReader() { int count = 0; + List items = Arrays.asList("a", "b", "c", "d", "d", "e", "f", "g", "h", "i"); @Nullable @Override public String read() throws Exception { System.out.println(">> count == " + count); - if(count == 6) { + if (count == 6) { count++; throw new IOException("6th item"); } - else if(count == 7) { + else if (count == 7) { count++; throw new RuntimeException("7th item"); } - else if(count < items.size()){ + else if (count < items.size()) { String item = items.get(count++); System.out.println(">> item read was " + item); return item; @@ -262,38 +258,16 @@ public class RemoteChunkingManagerStepBuilderTests { } }; - TaskletStep taskletStep = new RemoteChunkingManagerStepBuilder("step") - .reader(itemReader) - .readerIsTransactionalQueue() - .processor(itemProcessor) - .repository(this.jobRepository) - .transactionManager(this.transactionManager) - .transactionAttribute(transactionAttribute) - .inputChannel(this.inputChannel) - .outputChannel(this.outputChannel) - .listener(annotatedListener) - .listener(skipListener) - .listener(chunkListener) - .listener(stepExecutionListener) - .listener(itemReadListener) - .listener(itemWriteListener) - .listener(retryListener) - .skip(Exception.class) - .noSkip(RuntimeException.class) - .skipLimit(10) - .retry(IOException.class) - .noRetry(RuntimeException.class) - .retryLimit(10) - .retryContextCache(retryCache) - .noRollback(Exception.class) - .startLimit(3) - .allowStartIfComplete(true) - .stepOperations(stepOperations) - .chunk(3) - .backOffPolicy(backOffPolicy) - .stream(stream) - .keyGenerator(Object::hashCode) - .build(); + TaskletStep taskletStep = new RemoteChunkingManagerStepBuilder("step").reader(itemReader) + .readerIsTransactionalQueue().processor(itemProcessor).repository(this.jobRepository) + .transactionManager(this.transactionManager).transactionAttribute(transactionAttribute) + .inputChannel(this.inputChannel).outputChannel(this.outputChannel).listener(annotatedListener) + .listener(skipListener).listener(chunkListener).listener(stepExecutionListener) + .listener(itemReadListener).listener(itemWriteListener).listener(retryListener).skip(Exception.class) + .noSkip(RuntimeException.class).skipLimit(10).retry(IOException.class).noRetry(RuntimeException.class) + .retryLimit(10).retryContextCache(retryCache).noRollback(Exception.class).startLimit(3) + .allowStartIfComplete(true).stepOperations(stepOperations).chunk(3).backOffPolicy(backOffPolicy) + .stream(stream).keyGenerator(Object::hashCode).build(); JobExecution jobExecution = this.jobRepository.createJobExecution("job1", new JobParameters()); StepExecution stepExecution = new StepExecution("step1", jobExecution); @@ -307,8 +281,10 @@ public class RemoteChunkingManagerStepBuilderTests { SimpleChunkProvider provider = (SimpleChunkProvider) ReflectionTestUtils.getField(tasklet, "chunkProvider"); SimpleChunkProcessor processor = (SimpleChunkProcessor) ReflectionTestUtils.getField(tasklet, "chunkProcessor"); ItemWriter itemWriter = (ItemWriter) ReflectionTestUtils.getField(processor, "itemWriter"); - MessagingTemplate messagingTemplate = (MessagingTemplate) ReflectionTestUtils.getField(itemWriter, "messagingGateway"); - CompositeItemStream compositeItemStream = (CompositeItemStream) ReflectionTestUtils.getField(taskletStep, "stream"); + MessagingTemplate messagingTemplate = (MessagingTemplate) ReflectionTestUtils.getField(itemWriter, + "messagingGateway"); + CompositeItemStream compositeItemStream = (CompositeItemStream) ReflectionTestUtils.getField(taskletStep, + "stream"); Assert.assertEquals(ReflectionTestUtils.getField(provider, "itemReader"), itemReader); Assert.assertFalse((Boolean) ReflectionTestUtils.getField(tasklet, "buffering")); @@ -324,7 +300,7 @@ public class RemoteChunkingManagerStepBuilderTests { Object stepOperationsUsed = ReflectionTestUtils.getField(taskletStep, "stepOperations"); Assert.assertEquals(stepOperationsUsed, stepOperations); - Assert.assertEquals(((List)ReflectionTestUtils.getField(compositeItemStream, "streams")).size(), 2); + Assert.assertEquals(((List) ReflectionTestUtils.getField(compositeItemStream, "streams")).size(), 2); Assert.assertNotNull(ReflectionTestUtils.getField(processor, "keyGenerator")); verify(skipListener, atLeastOnce()).onSkipInProcess(any(), any()); @@ -344,11 +320,8 @@ public class RemoteChunkingManagerStepBuilderTests { @Bean public DataSource dataSource() { - return new EmbeddedDatabaseBuilder() - .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("/org/springframework/batch/core/schema-hsqldb.sql") - .generateUniqueName(true) - .build(); + return new EmbeddedDatabaseBuilder().addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") + .addScript("/org/springframework/batch/core/schema-hsqldb.sql").generateUniqueName(true).build(); } @Bean @@ -357,4 +330,5 @@ public class RemoteChunkingManagerStepBuilderTests { } } + } diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/RemoteChunkingWorkerBuilderTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/RemoteChunkingWorkerBuilderTests.java index 2d51f5672..86ce97185 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/RemoteChunkingWorkerBuilderTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/RemoteChunkingWorkerBuilderTests.java @@ -32,7 +32,9 @@ import static org.assertj.core.api.Assertions.assertThat; public class RemoteChunkingWorkerBuilderTests { private ItemProcessor itemProcessor = new PassThroughItemProcessor<>(); - private ItemWriter itemWriter = items -> { }; + + private ItemWriter itemWriter = items -> { + }; @Test public void itemProcessorMustNotBeNull() { @@ -90,7 +92,8 @@ public class RemoteChunkingWorkerBuilderTests { public void testMandatoryInputChannel() { // given RemoteChunkingWorkerBuilder builder = new RemoteChunkingWorkerBuilder() - .itemWriter(items -> { }); + .itemWriter(items -> { + }); // when final Exception expectedException = Assert.assertThrows(IllegalArgumentException.class, builder::build); @@ -103,9 +106,8 @@ public class RemoteChunkingWorkerBuilderTests { public void testMandatoryOutputChannel() { // given RemoteChunkingWorkerBuilder builder = new RemoteChunkingWorkerBuilder() - .itemWriter(items -> { }) - .inputChannel(new DirectChannel()); - + .itemWriter(items -> { + }).inputChannel(new DirectChannel()); // when final Exception expectedException = Assert.assertThrows(IllegalArgumentException.class, builder::build); @@ -120,9 +122,7 @@ public class RemoteChunkingWorkerBuilderTests { DirectChannel inputChannel = new DirectChannel(); DirectChannel outputChannel = new DirectChannel(); RemoteChunkingWorkerBuilder builder = new RemoteChunkingWorkerBuilder() - .itemProcessor(this.itemProcessor) - .itemWriter(this.itemWriter) - .inputChannel(inputChannel) + .itemProcessor(this.itemProcessor).itemWriter(this.itemWriter).inputChannel(inputChannel) .outputChannel(outputChannel); // when diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/TestItemReader.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/TestItemReader.java index e3c0be7e6..878a64e4f 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/TestItemReader.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/TestItemReader.java @@ -1,72 +1,72 @@ -package org.springframework.batch.integration.chunk; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.ParseException; -import org.springframework.batch.item.UnexpectedInputException; -import org.springframework.lang.Nullable; -import org.springframework.stereotype.Component; - -@Component -public class TestItemReader implements ItemReader { - - private static final Log logger = LogFactory.getLog(TestItemReader.class); - - /** - * Counts the number of chunks processed in the handler. - */ - public volatile int count = 0; - - /** - * Item that causes failure in handler. - */ - public final static String FAIL_ON = "bad"; - - /** - * Item that causes handler to wait to simulate delayed processing. - */ - public static final String WAIT_ON = "wait"; - - private List items = new ArrayList<>(); - - /** - * @param items the items to set - */ - public void setItems(List items) { - this.items = items; - } - - @Nullable - public T read() throws Exception, UnexpectedInputException, ParseException { - - if (count>=items.size()) { - return null; - } - - T item = items.get(count++); - - logger.debug("Reading "+item); - - if (item.equals(WAIT_ON)) { - try { - Thread.sleep(200); - } - catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new RuntimeException("Unexpected interruption.", e); - } - } - - if (item.equals(FAIL_ON)) { - throw new IllegalStateException("Planned failure on: " + FAIL_ON); - } - - return item; - - } - -} +package org.springframework.batch.integration.chunk; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ParseException; +import org.springframework.batch.item.UnexpectedInputException; +import org.springframework.lang.Nullable; +import org.springframework.stereotype.Component; + +@Component +public class TestItemReader implements ItemReader { + + private static final Log logger = LogFactory.getLog(TestItemReader.class); + + /** + * Counts the number of chunks processed in the handler. + */ + public volatile int count = 0; + + /** + * Item that causes failure in handler. + */ + public final static String FAIL_ON = "bad"; + + /** + * Item that causes handler to wait to simulate delayed processing. + */ + public static final String WAIT_ON = "wait"; + + private List items = new ArrayList<>(); + + /** + * @param items the items to set + */ + public void setItems(List items) { + this.items = items; + } + + @Nullable + public T read() throws Exception, UnexpectedInputException, ParseException { + + if (count >= items.size()) { + return null; + } + + T item = items.get(count++); + + logger.debug("Reading " + item); + + if (item.equals(WAIT_ON)) { + try { + Thread.sleep(200); + } + catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException("Unexpected interruption.", e); + } + } + + if (item.equals(FAIL_ON)) { + throw new IllegalStateException("Planned failure on: " + FAIL_ON); + } + + return item; + + } + +} diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/TestItemWriter.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/TestItemWriter.java index e4519ca6e..1dcec0903 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/TestItemWriter.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/chunk/TestItemWriter.java @@ -1,74 +1,74 @@ -package org.springframework.batch.integration.chunk; - -import java.util.List; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.batch.item.ItemWriter; -import org.springframework.stereotype.Component; - -@Component -public class TestItemWriter implements ItemWriter { - - private static final Log logger = LogFactory.getLog(TestItemWriter.class); - - /** - * Counts the number of chunks processed in the handler. - */ - public volatile static int count = 0; - - /** - * Item that causes failure in handler. - */ - public final static String FAIL_ON = "fail"; - - /** - * Item that causes error in handler. - */ - public final static String UNSUPPORTED_ON = "unsupported"; - - /** - * Item that causes error in handler. - */ - public final static String ERROR_ON = "error"; - - /** - * Item that causes handler to wait to simulate delayed processing. - */ - public static final String WAIT_ON = "wait"; - - public void write(List items) throws Exception { - - for (T item : items) { - - count++; - - logger.debug("Writing: " + item); - - if (item.equals(WAIT_ON)) { - try { - Thread.sleep(200); - } - catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new RuntimeException("Unexpected interruption.", e); - } - } - - if (item.equals(FAIL_ON)) { - throw new IllegalStateException("Planned failure on: " + FAIL_ON); - } - - if (item.equals(UNSUPPORTED_ON)) { - throw new UnsupportedOperationException("Planned failure on: " + UNSUPPORTED_ON); - } - - if (item.equals(ERROR_ON)) { - throw new Error("Planned failure on: " + ERROR_ON); - } - - } - - } - -} +package org.springframework.batch.integration.chunk; + +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.batch.item.ItemWriter; +import org.springframework.stereotype.Component; + +@Component +public class TestItemWriter implements ItemWriter { + + private static final Log logger = LogFactory.getLog(TestItemWriter.class); + + /** + * Counts the number of chunks processed in the handler. + */ + public volatile static int count = 0; + + /** + * Item that causes failure in handler. + */ + public final static String FAIL_ON = "fail"; + + /** + * Item that causes error in handler. + */ + public final static String UNSUPPORTED_ON = "unsupported"; + + /** + * Item that causes error in handler. + */ + public final static String ERROR_ON = "error"; + + /** + * Item that causes handler to wait to simulate delayed processing. + */ + public static final String WAIT_ON = "wait"; + + public void write(List items) throws Exception { + + for (T item : items) { + + count++; + + logger.debug("Writing: " + item); + + if (item.equals(WAIT_ON)) { + try { + Thread.sleep(200); + } + catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException("Unexpected interruption.", e); + } + } + + if (item.equals(FAIL_ON)) { + throw new IllegalStateException("Planned failure on: " + FAIL_ON); + } + + if (item.equals(UNSUPPORTED_ON)) { + throw new UnsupportedOperationException("Planned failure on: " + UNSUPPORTED_ON); + } + + if (item.equals(ERROR_ON)) { + throw new Error("Planned failure on: " + ERROR_ON); + } + + } + + } + +} diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/config/xml/JobLauncherParserTestsConfiguration.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/config/xml/JobLauncherParserTestsConfiguration.java index 79639234a..1c854c237 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/config/xml/JobLauncherParserTestsConfiguration.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/config/xml/JobLauncherParserTestsConfiguration.java @@ -20,7 +20,6 @@ import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; /** - * * @author Gunnar Hillert * @author Mahmoud Ben Hassine * @since 1.3 @@ -30,13 +29,10 @@ import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; @EnableBatchProcessing public class JobLauncherParserTestsConfiguration { - @Bean - public DataSource dataSource() { - return new EmbeddedDatabaseBuilder() - .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("/org/springframework/batch/core/schema-hsqldb.sql") - .generateUniqueName(true) - .build(); - } + @Bean + public DataSource dataSource() { + return new EmbeddedDatabaseBuilder().addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") + .addScript("/org/springframework/batch/core/schema-hsqldb.sql").generateUniqueName(true).build(); + } } diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/config/xml/JobLaunchingGatewayParserTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/config/xml/JobLaunchingGatewayParserTests.java index 7106c72bd..f0759679c 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/config/xml/JobLaunchingGatewayParserTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/config/xml/JobLaunchingGatewayParserTests.java @@ -32,7 +32,6 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; /** - * * @author Gunnar Hillert * @since 1.3 * @@ -47,17 +46,20 @@ public class JobLaunchingGatewayParserTests { public void testGatewayParser() throws Exception { setUp("JobLaunchingGatewayParserTests-context.xml", getClass()); - final AbstractMessageChannel inputChannel = TestUtils.getPropertyValue(this.consumer, "inputChannel", AbstractMessageChannel.class); + final AbstractMessageChannel inputChannel = TestUtils.getPropertyValue(this.consumer, "inputChannel", + AbstractMessageChannel.class); assertEquals("requestChannel", inputChannel.getComponentName()); - final JobLaunchingMessageHandler jobLaunchingMessageHandler = TestUtils.getPropertyValue(this.consumer, "handler.jobLaunchingMessageHandler", JobLaunchingMessageHandler.class); + final JobLaunchingMessageHandler jobLaunchingMessageHandler = TestUtils.getPropertyValue(this.consumer, + "handler.jobLaunchingMessageHandler", JobLaunchingMessageHandler.class); assertNotNull(jobLaunchingMessageHandler); - final MessagingTemplate messagingTemplate = TestUtils.getPropertyValue(this.consumer, "handler.messagingTemplate", MessagingTemplate.class); + final MessagingTemplate messagingTemplate = TestUtils.getPropertyValue(this.consumer, + "handler.messagingTemplate", MessagingTemplate.class); final Long sendTimeout = TestUtils.getPropertyValue(messagingTemplate, "sendTimeout", Long.class); - assertEquals("Wrong sendTimeout", Long.valueOf(123L), sendTimeout); + assertEquals("Wrong sendTimeout", Long.valueOf(123L), sendTimeout); assertFalse(this.consumer.isRunning()); } @@ -66,10 +68,11 @@ public class JobLaunchingGatewayParserTests { setUp("JobLaunchingGatewayParserTestsRunning-context.xml", getClass()); assertTrue(this.consumer.isRunning()); - final MessagingTemplate messagingTemplate = TestUtils.getPropertyValue(this.consumer, "handler.messagingTemplate", MessagingTemplate.class); + final MessagingTemplate messagingTemplate = TestUtils.getPropertyValue(this.consumer, + "handler.messagingTemplate", MessagingTemplate.class); final Long sendTimeout = TestUtils.getPropertyValue(messagingTemplate, "sendTimeout", Long.class); - assertEquals("Wrong sendTimeout", Long.valueOf(-1L), sendTimeout); + assertEquals("Wrong sendTimeout", Long.valueOf(-1L), sendTimeout); } @Test @@ -77,7 +80,7 @@ public class JobLaunchingGatewayParserTests { try { setUp("JobLaunchingGatewayParserTestsNoJobLauncher-context.xml", getClass()); } - catch(BeanCreationException e) { + catch (BeanCreationException e) { assertEquals("No bean named 'jobLauncher' available", e.getCause().getMessage()); return; } @@ -88,24 +91,26 @@ public class JobLaunchingGatewayParserTests { public void testJobLaunchingGatewayWithEnableBatchProcessing() throws Exception { setUp("JobLaunchingGatewayParserTestsWithEnableBatchProcessing-context.xml", getClass()); - final JobLaunchingMessageHandler jobLaunchingMessageHandler = TestUtils.getPropertyValue(this.consumer, "handler.jobLaunchingMessageHandler", JobLaunchingMessageHandler.class); + final JobLaunchingMessageHandler jobLaunchingMessageHandler = TestUtils.getPropertyValue(this.consumer, + "handler.jobLaunchingMessageHandler", JobLaunchingMessageHandler.class); assertNotNull(jobLaunchingMessageHandler); - final JobLauncher jobLauncher = TestUtils.getPropertyValue(jobLaunchingMessageHandler, "jobLauncher", JobLauncher.class); + final JobLauncher jobLauncher = TestUtils.getPropertyValue(jobLaunchingMessageHandler, "jobLauncher", + JobLauncher.class); assertNotNull(jobLauncher); } @After - public void tearDown(){ - if(context != null){ + public void tearDown() { + if (context != null) { context.close(); } } - public void setUp(String name, Class cls){ - context = new ClassPathXmlApplicationContext(name, cls); - consumer = this.context.getBean("batchjobExecutor", EventDrivenConsumer.class); + public void setUp(String name, Class cls) { + context = new ClassPathXmlApplicationContext(name, cls); + consumer = this.context.getBean("batchjobExecutor", EventDrivenConsumer.class); } } diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/config/xml/RemoteChunkingParserTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/config/xml/RemoteChunkingParserTests.java index 0643b0728..d88acded8 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/config/xml/RemoteChunkingParserTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/config/xml/RemoteChunkingParserTests.java @@ -43,8 +43,8 @@ import static org.junit.Assert.fail; /** *

      - * Test cases for the {@link RemoteChunkingWorkerParser} - * and {@link RemoteChunkingManagerParser}. + * Test cases for the {@link RemoteChunkingWorkerParser} and + * {@link RemoteChunkingManagerParser}. *

      * * @author Chris Schaefer @@ -57,47 +57,54 @@ public class RemoteChunkingParserTests { @SuppressWarnings("rawtypes") @Test public void testRemoteChunkingWorkerParserWithProcessorDefined() { - ApplicationContext applicationContext = - new ClassPathXmlApplicationContext("/org/springframework/batch/integration/config/xml/RemoteChunkingWorkerParserTests.xml"); + ApplicationContext applicationContext = new ClassPathXmlApplicationContext( + "/org/springframework/batch/integration/config/xml/RemoteChunkingWorkerParserTests.xml"); ChunkHandler chunkHandler = applicationContext.getBean(ChunkProcessorChunkHandler.class); - ChunkProcessor chunkProcessor = (SimpleChunkProcessor) TestUtils.getPropertyValue(chunkHandler, "chunkProcessor"); + ChunkProcessor chunkProcessor = (SimpleChunkProcessor) TestUtils.getPropertyValue(chunkHandler, + "chunkProcessor"); assertNotNull("ChunkProcessor must not be null", chunkProcessor); ItemWriter itemWriter = (ItemWriter) TestUtils.getPropertyValue(chunkProcessor, "itemWriter"); assertNotNull("ChunkProcessor ItemWriter must not be null", itemWriter); assertTrue("Got wrong instance of ItemWriter", itemWriter instanceof Writer); - ItemProcessor itemProcessor = (ItemProcessor) TestUtils.getPropertyValue(chunkProcessor, "itemProcessor"); + ItemProcessor itemProcessor = (ItemProcessor) TestUtils + .getPropertyValue(chunkProcessor, "itemProcessor"); assertNotNull("ChunkProcessor ItemWriter must not be null", itemProcessor); assertTrue("Got wrong instance of ItemProcessor", itemProcessor instanceof Processor); FactoryBean serviceActivatorFactoryBean = applicationContext.getBean(ServiceActivatorFactoryBean.class); assertNotNull("ServiceActivatorFactoryBean must not be null", serviceActivatorFactoryBean); - assertNotNull("Output channel name must not be null", TestUtils.getPropertyValue(serviceActivatorFactoryBean, "outputChannelName")); + assertNotNull("Output channel name must not be null", + TestUtils.getPropertyValue(serviceActivatorFactoryBean, "outputChannelName")); MessageChannel inputChannel = applicationContext.getBean("requests", MessageChannel.class); assertNotNull("Input channel must not be null", inputChannel); String targetMethodName = (String) TestUtils.getPropertyValue(serviceActivatorFactoryBean, "targetMethodName"); assertNotNull("Target method name must not be null", targetMethodName); - assertTrue("Target method name must be handleChunk, got: " + targetMethodName, "handleChunk".equals(targetMethodName)); + assertTrue("Target method name must be handleChunk, got: " + targetMethodName, + "handleChunk".equals(targetMethodName)); - ChunkHandler targetObject = (ChunkHandler) TestUtils.getPropertyValue(serviceActivatorFactoryBean, "targetObject"); + ChunkHandler targetObject = (ChunkHandler) TestUtils.getPropertyValue(serviceActivatorFactoryBean, + "targetObject"); assertNotNull("Target object must not be null", targetObject); } @SuppressWarnings("rawtypes") @Test public void testRemoteChunkingWorkerParserWithProcessorNotDefined() { - ApplicationContext applicationContext = - new ClassPathXmlApplicationContext("/org/springframework/batch/integration/config/xml/RemoteChunkingWorkerParserNoProcessorTests.xml"); + ApplicationContext applicationContext = new ClassPathXmlApplicationContext( + "/org/springframework/batch/integration/config/xml/RemoteChunkingWorkerParserNoProcessorTests.xml"); ChunkHandler chunkHandler = applicationContext.getBean(ChunkProcessorChunkHandler.class); - ChunkProcessor chunkProcessor = (SimpleChunkProcessor) TestUtils.getPropertyValue(chunkHandler, "chunkProcessor"); + ChunkProcessor chunkProcessor = (SimpleChunkProcessor) TestUtils.getPropertyValue(chunkHandler, + "chunkProcessor"); assertNotNull("ChunkProcessor must not be null", chunkProcessor); - ItemProcessor itemProcessor = (ItemProcessor) TestUtils.getPropertyValue(chunkProcessor, "itemProcessor"); + ItemProcessor itemProcessor = (ItemProcessor) TestUtils + .getPropertyValue(chunkProcessor, "itemProcessor"); assertNotNull("ChunkProcessor ItemWriter must not be null", itemProcessor); assertTrue("Got wrong instance of ItemProcessor", itemProcessor instanceof PassThroughItemProcessor); } @@ -105,15 +112,18 @@ public class RemoteChunkingParserTests { @SuppressWarnings("rawtypes") @Test public void testRemoteChunkingManagerParser() { - ApplicationContext applicationContext = - new ClassPathXmlApplicationContext("/org/springframework/batch/integration/config/xml/RemoteChunkingManagerParserTests.xml"); + ApplicationContext applicationContext = new ClassPathXmlApplicationContext( + "/org/springframework/batch/integration/config/xml/RemoteChunkingManagerParserTests.xml"); ItemWriter itemWriter = applicationContext.getBean("itemWriter", ChunkMessageChannelItemWriter.class); - assertNotNull("Messaging template must not be null", TestUtils.getPropertyValue(itemWriter, "messagingGateway")); + assertNotNull("Messaging template must not be null", + TestUtils.getPropertyValue(itemWriter, "messagingGateway")); assertNotNull("Reply channel must not be null", TestUtils.getPropertyValue(itemWriter, "replyChannel")); - FactoryBean remoteChunkingHandlerFactoryBean = applicationContext.getBean(RemoteChunkHandlerFactoryBean.class); - assertNotNull("Chunk writer must not be null", TestUtils.getPropertyValue(remoteChunkingHandlerFactoryBean, "chunkWriter")); + FactoryBean remoteChunkingHandlerFactoryBean = applicationContext + .getBean(RemoteChunkHandlerFactoryBean.class); + assertNotNull("Chunk writer must not be null", + TestUtils.getPropertyValue(remoteChunkingHandlerFactoryBean, "chunkWriter")); assertNotNull("Step must not be null", TestUtils.getPropertyValue(remoteChunkingHandlerFactoryBean, "step")); } @@ -121,13 +131,16 @@ public class RemoteChunkingParserTests { public void testRemoteChunkingManagerIdAttrAssert() throws Exception { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(); applicationContext.setValidating(false); - applicationContext.setConfigLocation("/org/springframework/batch/integration/config/xml/RemoteChunkingManagerParserMissingIdAttrTests.xml"); + applicationContext.setConfigLocation( + "/org/springframework/batch/integration/config/xml/RemoteChunkingManagerParserMissingIdAttrTests.xml"); try { applicationContext.refresh(); fail(); - } catch (BeanDefinitionStoreException e) { - assertTrue("Nested exception must be of type IllegalArgumentException", e.getCause() instanceof IllegalArgumentException); + } + catch (BeanDefinitionStoreException e) { + assertTrue("Nested exception must be of type IllegalArgumentException", + e.getCause() instanceof IllegalArgumentException); IllegalArgumentException iae = (IllegalArgumentException) e.getCause(); @@ -140,17 +153,21 @@ public class RemoteChunkingParserTests { public void testRemoteChunkingManagerMessageTemplateAttrAssert() throws Exception { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(); applicationContext.setValidating(false); - applicationContext.setConfigLocation("/org/springframework/batch/integration/config/xml/RemoteChunkingManagerParserMissingMessageTemplateAttrTests.xml"); + applicationContext.setConfigLocation( + "/org/springframework/batch/integration/config/xml/RemoteChunkingManagerParserMissingMessageTemplateAttrTests.xml"); try { applicationContext.refresh(); fail(); - } catch (BeanDefinitionStoreException e) { - assertTrue("Nested exception must be of type IllegalArgumentException", e.getCause() instanceof IllegalArgumentException); + } + catch (BeanDefinitionStoreException e) { + assertTrue("Nested exception must be of type IllegalArgumentException", + e.getCause() instanceof IllegalArgumentException); IllegalArgumentException iae = (IllegalArgumentException) e.getCause(); - assertTrue("Expected: " + "The message-template attribute must be specified" + " but got: " + iae.getMessage(), + assertTrue( + "Expected: " + "The message-template attribute must be specified" + " but got: " + iae.getMessage(), "The message-template attribute must be specified".equals(iae.getMessage())); } } @@ -159,13 +176,16 @@ public class RemoteChunkingParserTests { public void testRemoteChunkingManagerStepAttrAssert() throws Exception { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(); applicationContext.setValidating(false); - applicationContext.setConfigLocation("/org/springframework/batch/integration/config/xml/RemoteChunkingManagerParserMissingStepAttrTests.xml"); + applicationContext.setConfigLocation( + "/org/springframework/batch/integration/config/xml/RemoteChunkingManagerParserMissingStepAttrTests.xml"); try { applicationContext.refresh(); fail(); - } catch (BeanDefinitionStoreException e) { - assertTrue("Nested exception must be of type IllegalArgumentException", e.getCause() instanceof IllegalArgumentException); + } + catch (BeanDefinitionStoreException e) { + assertTrue("Nested exception must be of type IllegalArgumentException", + e.getCause() instanceof IllegalArgumentException); IllegalArgumentException iae = (IllegalArgumentException) e.getCause(); @@ -178,13 +198,16 @@ public class RemoteChunkingParserTests { public void testRemoteChunkingManagerReplyChannelAttrAssert() throws Exception { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(); applicationContext.setValidating(false); - applicationContext.setConfigLocation("/org/springframework/batch/integration/config/xml/RemoteChunkingManagerParserMissingReplyChannelAttrTests.xml"); + applicationContext.setConfigLocation( + "/org/springframework/batch/integration/config/xml/RemoteChunkingManagerParserMissingReplyChannelAttrTests.xml"); try { applicationContext.refresh(); fail(); - } catch (BeanDefinitionStoreException e) { - assertTrue("Nested exception must be of type IllegalArgumentException", e.getCause() instanceof IllegalArgumentException); + } + catch (BeanDefinitionStoreException e) { + assertTrue("Nested exception must be of type IllegalArgumentException", + e.getCause() instanceof IllegalArgumentException); IllegalArgumentException iae = (IllegalArgumentException) e.getCause(); @@ -197,13 +220,16 @@ public class RemoteChunkingParserTests { public void testRemoteChunkingWorkerIdAttrAssert() throws Exception { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(); applicationContext.setValidating(false); - applicationContext.setConfigLocation("/org/springframework/batch/integration/config/xml/RemoteChunkingWorkerParserMissingIdAttrTests.xml"); + applicationContext.setConfigLocation( + "/org/springframework/batch/integration/config/xml/RemoteChunkingWorkerParserMissingIdAttrTests.xml"); try { applicationContext.refresh(); fail(); - } catch (BeanDefinitionStoreException e) { - assertTrue("Nested exception must be of type IllegalArgumentException", e.getCause() instanceof IllegalArgumentException); + } + catch (BeanDefinitionStoreException e) { + assertTrue("Nested exception must be of type IllegalArgumentException", + e.getCause() instanceof IllegalArgumentException); IllegalArgumentException iae = (IllegalArgumentException) e.getCause(); @@ -216,13 +242,16 @@ public class RemoteChunkingParserTests { public void testRemoteChunkingWorkerInputChannelAttrAssert() throws Exception { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(); applicationContext.setValidating(false); - applicationContext.setConfigLocation("/org/springframework/batch/integration/config/xml/RemoteChunkingWorkerParserMissingInputChannelAttrTests.xml"); + applicationContext.setConfigLocation( + "/org/springframework/batch/integration/config/xml/RemoteChunkingWorkerParserMissingInputChannelAttrTests.xml"); try { applicationContext.refresh(); fail(); - } catch (BeanDefinitionStoreException e) { - assertTrue("Nested exception must be of type IllegalArgumentException", e.getCause() instanceof IllegalArgumentException); + } + catch (BeanDefinitionStoreException e) { + assertTrue("Nested exception must be of type IllegalArgumentException", + e.getCause() instanceof IllegalArgumentException); IllegalArgumentException iae = (IllegalArgumentException) e.getCause(); @@ -235,13 +264,16 @@ public class RemoteChunkingParserTests { public void testRemoteChunkingWorkerItemWriterAttrAssert() throws Exception { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(); applicationContext.setValidating(false); - applicationContext.setConfigLocation("/org/springframework/batch/integration/config/xml/RemoteChunkingWorkerParserMissingItemWriterAttrTests.xml"); + applicationContext.setConfigLocation( + "/org/springframework/batch/integration/config/xml/RemoteChunkingWorkerParserMissingItemWriterAttrTests.xml"); try { applicationContext.refresh(); fail(); - } catch (BeanDefinitionStoreException e) { - assertTrue("Nested exception must be of type IllegalArgumentException", e.getCause() instanceof IllegalArgumentException); + } + catch (BeanDefinitionStoreException e) { + assertTrue("Nested exception must be of type IllegalArgumentException", + e.getCause() instanceof IllegalArgumentException); IllegalArgumentException iae = (IllegalArgumentException) e.getCause(); @@ -254,33 +286,42 @@ public class RemoteChunkingParserTests { public void testRemoteChunkingWorkerOutputChannelAttrAssert() throws Exception { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(); applicationContext.setValidating(false); - applicationContext.setConfigLocation("/org/springframework/batch/integration/config/xml/RemoteChunkingWorkerParserMissingOutputChannelAttrTests.xml"); + applicationContext.setConfigLocation( + "/org/springframework/batch/integration/config/xml/RemoteChunkingWorkerParserMissingOutputChannelAttrTests.xml"); try { applicationContext.refresh(); fail(); - } catch (BeanDefinitionStoreException e) { - assertTrue("Nested exception must be of type IllegalArgumentException", e.getCause() instanceof IllegalArgumentException); + } + catch (BeanDefinitionStoreException e) { + assertTrue("Nested exception must be of type IllegalArgumentException", + e.getCause() instanceof IllegalArgumentException); IllegalArgumentException iae = (IllegalArgumentException) e.getCause(); - assertTrue("Expected: " + "The output-channel attribute must be specified" + " but got: " + iae.getMessage(), + assertTrue( + "Expected: " + "The output-channel attribute must be specified" + " but got: " + iae.getMessage(), "The output-channel attribute must be specified".equals(iae.getMessage())); } } private static class Writer implements ItemWriter { + @Override public void write(List items) throws Exception { // } + } private static class Processor implements ItemProcessor { + @Nullable @Override public String process(String item) throws Exception { return item; } + } + } diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/file/FileToMessagesJobIntegrationTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/file/FileToMessagesJobIntegrationTests.java index 624e5ab54..9c079f8b4 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/file/FileToMessagesJobIntegrationTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/file/FileToMessagesJobIntegrationTests.java @@ -1,75 +1,75 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.integration.file; - -import static org.junit.Assert.assertEquals; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.launch.JobLauncher; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHandler; -import org.springframework.messaging.SubscribableChannel; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -/** - * @author Dave Syer - * - */ -@ContextConfiguration() -@RunWith(SpringJUnit4ClassRunner.class) -public class FileToMessagesJobIntegrationTests implements MessageHandler { - - @Autowired - @Qualifier("requests") - private SubscribableChannel requests; - - @Autowired - private Job job; - - @Autowired - private JobLauncher jobLauncher; - - int count = 0; - - public void handleMessage(Message message) { - count++; - } - - @Before - public void setUp() { - requests.subscribe(this); - } - - @Test - public void testFileSent() throws Exception { - - JobExecution execution = jobLauncher.run(job, new JobParametersBuilder().addLong("time.stamp", - System.currentTimeMillis()).toJobParameters()); - assertEquals(BatchStatus.COMPLETED, execution.getStatus()); - // 2 chunks sent to channel (5 items and commit-interval=3) - assertEquals(2, count); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.integration.file; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.Job; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobParametersBuilder; +import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.messaging.Message; +import org.springframework.messaging.MessageHandler; +import org.springframework.messaging.SubscribableChannel; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Dave Syer + * + */ +@ContextConfiguration() +@RunWith(SpringJUnit4ClassRunner.class) +public class FileToMessagesJobIntegrationTests implements MessageHandler { + + @Autowired + @Qualifier("requests") + private SubscribableChannel requests; + + @Autowired + private Job job; + + @Autowired + private JobLauncher jobLauncher; + + int count = 0; + + public void handleMessage(Message message) { + count++; + } + + @Before + public void setUp() { + requests.subscribe(this); + } + + @Test + public void testFileSent() throws Exception { + + JobExecution execution = jobLauncher.run(job, + new JobParametersBuilder().addLong("time.stamp", System.currentTimeMillis()).toJobParameters()); + assertEquals(BatchStatus.COMPLETED, execution.getStatus()); + // 2 chunks sent to channel (5 items and commit-interval=3) + assertEquals(2, count); + } + +} diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/file/ResourceSplitterIntegrationTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/file/ResourceSplitterIntegrationTests.java index 06deb93fc..f83f8d325 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/file/ResourceSplitterIntegrationTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/file/ResourceSplitterIntegrationTests.java @@ -1,80 +1,80 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.integration.file; - -import static org.junit.Assert.assertNotNull; - -import java.util.Arrays; -import java.util.List; - -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.core.io.Resource; -import org.springframework.integration.annotation.MessageEndpoint; -import org.springframework.integration.annotation.Splitter; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageChannel; -import org.springframework.messaging.PollableChannel; -import org.springframework.messaging.support.GenericMessage; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -/** - * @author Dave Syer - * - */ -@ContextConfiguration() -@RunWith(SpringJUnit4ClassRunner.class) -@MessageEndpoint -public class ResourceSplitterIntegrationTests { - - @Autowired - @Qualifier("resources") - private MessageChannel resources; - - @Autowired - @Qualifier("requests") - private PollableChannel requests; - - /* - * This is so cool (but see INT-190)... - * - * The incoming message is a Resource pattern, and it is converted to the - * correct payload type with Spring's default strategy - */ - @Splitter(inputChannel = "resources", outputChannel = "requests") - public Resource[] handle(Resource[] message) { - List list = Arrays.asList(message); - System.err.println(list); - return message; - } - - @SuppressWarnings("unchecked") - @Test - @Ignore //FIXME - // This broke with Integration 2.0 in a milestone, so watch out when upgrading... - public void testVanillaConversion() throws Exception { - resources.send(new GenericMessage<>("classpath:*-context.xml")); - Message message = (Message) requests.receive(200L); - assertNotNull(message); - message = (Message) requests.receive(100L); - assertNotNull(message); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.integration.file; + +import static org.junit.Assert.assertNotNull; + +import java.util.Arrays; +import java.util.List; + +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.core.io.Resource; +import org.springframework.integration.annotation.MessageEndpoint; +import org.springframework.integration.annotation.Splitter; +import org.springframework.messaging.Message; +import org.springframework.messaging.MessageChannel; +import org.springframework.messaging.PollableChannel; +import org.springframework.messaging.support.GenericMessage; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Dave Syer + * + */ +@ContextConfiguration() +@RunWith(SpringJUnit4ClassRunner.class) +@MessageEndpoint +public class ResourceSplitterIntegrationTests { + + @Autowired + @Qualifier("resources") + private MessageChannel resources; + + @Autowired + @Qualifier("requests") + private PollableChannel requests; + + /* + * This is so cool (but see INT-190)... + * + * The incoming message is a Resource pattern, and it is converted to the correct + * payload type with Spring's default strategy + */ + @Splitter(inputChannel = "resources", outputChannel = "requests") + public Resource[] handle(Resource[] message) { + List list = Arrays.asList(message); + System.err.println(list); + return message; + } + + @SuppressWarnings("unchecked") + @Test + @Ignore // FIXME + // This broke with Integration 2.0 in a milestone, so watch out when upgrading... + public void testVanillaConversion() throws Exception { + resources.send(new GenericMessage<>("classpath:*-context.xml")); + Message message = (Message) requests.receive(200L); + assertNotNull(message); + message = (Message) requests.receive(100L); + assertNotNull(message); + } + +} diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/item/MessagingGatewayIntegrationTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/item/MessagingGatewayIntegrationTests.java index 922044c13..3a36bf111 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/item/MessagingGatewayIntegrationTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/item/MessagingGatewayIntegrationTests.java @@ -1,143 +1,147 @@ -/* - * Copyright 2006-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.integration.item; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - -import java.util.Arrays; -import java.util.List; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.item.ItemProcessor; -import org.springframework.batch.item.ItemWriter; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.integration.annotation.MessageEndpoint; -import org.springframework.integration.annotation.ServiceActivator; -import org.springframework.integration.annotation.Splitter; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -/** - * Test case showing the use of a MessagingGateway to provide an ItemWriter or - * ItemProcessor to Spring Batch that is hooked directly into a Spring - * Integration MessageChannel. - * - * @author Dave Syer - * @author Mahmoud Ben Hassine - * - */ -@ContextConfiguration -@RunWith(SpringJUnit4ClassRunner.class) -public class MessagingGatewayIntegrationTests { - - @Autowired - private ItemProcessor processor; - - @Autowired - private ItemWriter writer; - - /** - * Just for the sake of being able to make assertions. - */ - @Autowired - private EndService service; - - /** - * Just for the sake of being able to make assertions. - */ - @Autowired - private SplitService splitter; - - @Test - public void testProcessor() throws Exception { - String result = processor.process("foo"); - assertEquals("foo: 0: 1", result); - assertNull(processor.process("filter")); - } - - @Test - public void testWriter() throws Exception { - writer.write(Arrays.asList("foo", "bar", "spam")); - assertEquals(3, splitter.count); - assertEquals(3, service.count); - } - - /** - * This service is wrapped into an ItemProcessor and used to transform - * items. This is where the main business processing could take place in a - * real application. To suppress output the service activator can just - * return null (same as an ItemProcessor) but remember to set the reply - * timeout in the gateway. - * - * @author Dave Syer - * - */ - @MessageEndpoint - public static class Activator { - private int count; - - @ServiceActivator - public String transform(String input) { - if (input.equals("filter")) { - return null; - } - return input + ": " + (count++); - } - } - - /** - * The Splitter is wrapped into an ItemWriter and used to relay items to its - * output channel. This one is completely trivial, it just passes the items - * on as they are. More complex splitters might filter or enhance the items - * before passing them on. - * - * @author Dave Syer - * - */ - @MessageEndpoint - public static class SplitService { - // Just for assertions in the test case - private int count; - - @Splitter - public List split(List input) { - count += input.size(); - return input; - } - } - - /** - * This is just used to trap the messages sent by the ItemWriter and make an - * assertion about them in the test case. In a real application this - * would be the output stage and/or business processing. - * - * @author Dave Syer - * - */ - @MessageEndpoint - public static class EndService { - private int count; - - @ServiceActivator - public void service(String input) { - count++; - return; - } - } - -} +/* + * Copyright 2006-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.integration.item; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import java.util.Arrays; +import java.util.List; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.item.ItemProcessor; +import org.springframework.batch.item.ItemWriter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.integration.annotation.MessageEndpoint; +import org.springframework.integration.annotation.ServiceActivator; +import org.springframework.integration.annotation.Splitter; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * Test case showing the use of a MessagingGateway to provide an ItemWriter or + * ItemProcessor to Spring Batch that is hooked directly into a Spring Integration + * MessageChannel. + * + * @author Dave Syer + * @author Mahmoud Ben Hassine + * + */ +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class MessagingGatewayIntegrationTests { + + @Autowired + private ItemProcessor processor; + + @Autowired + private ItemWriter writer; + + /** + * Just for the sake of being able to make assertions. + */ + @Autowired + private EndService service; + + /** + * Just for the sake of being able to make assertions. + */ + @Autowired + private SplitService splitter; + + @Test + public void testProcessor() throws Exception { + String result = processor.process("foo"); + assertEquals("foo: 0: 1", result); + assertNull(processor.process("filter")); + } + + @Test + public void testWriter() throws Exception { + writer.write(Arrays.asList("foo", "bar", "spam")); + assertEquals(3, splitter.count); + assertEquals(3, service.count); + } + + /** + * This service is wrapped into an ItemProcessor and used to transform items. This is + * where the main business processing could take place in a real application. To + * suppress output the service activator can just return null (same as an + * ItemProcessor) but remember to set the reply timeout in the gateway. + * + * @author Dave Syer + * + */ + @MessageEndpoint + public static class Activator { + + private int count; + + @ServiceActivator + public String transform(String input) { + if (input.equals("filter")) { + return null; + } + return input + ": " + (count++); + } + + } + + /** + * The Splitter is wrapped into an ItemWriter and used to relay items to its output + * channel. This one is completely trivial, it just passes the items on as they are. + * More complex splitters might filter or enhance the items before passing them on. + * + * @author Dave Syer + * + */ + @MessageEndpoint + public static class SplitService { + + // Just for assertions in the test case + private int count; + + @Splitter + public List split(List input) { + count += input.size(); + return input; + } + + } + + /** + * This is just used to trap the messages sent by the ItemWriter and make an assertion + * about them in the test case. In a real application this would be the output stage + * and/or business processing. + * + * @author Dave Syer + * + */ + @MessageEndpoint + public static class EndService { + + private int count; + + @ServiceActivator + public void service(String input) { + count++; + return; + } + + } + +} diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/launch/JobLaunchingGatewayIntegrationTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/launch/JobLaunchingGatewayIntegrationTests.java index 8c50abc9d..8104d87a2 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/launch/JobLaunchingGatewayIntegrationTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/launch/JobLaunchingGatewayIntegrationTests.java @@ -49,7 +49,6 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; /** - * * @author Gunnar Hillert * @since 1.3 * @@ -77,7 +76,7 @@ public class JobLaunchingGatewayIntegrationTests { @Before public void setUp() { Object message = ""; - while (message!=null) { + while (message != null) { message = responseChannel.receive(10L); } } @@ -86,8 +85,7 @@ public class JobLaunchingGatewayIntegrationTests { @DirtiesContext @SuppressWarnings("unchecked") public void testNoReply() { - GenericMessage trigger = new GenericMessage<>(new JobLaunchRequest(job, - new JobParameters())); + GenericMessage trigger = new GenericMessage<>(new JobLaunchRequest(job, new JobParameters())); try { requestChannel.send(trigger); fail(); @@ -110,8 +108,8 @@ public class JobLaunchingGatewayIntegrationTests { Map map = new HashMap<>(); map.put(MessageHeaders.REPLY_CHANNEL, "response"); MessageHeaders headers = new MessageHeaders(map); - GenericMessage trigger = new GenericMessage<>(new JobLaunchRequest(job, - builder.toJobParameters()), headers); + GenericMessage trigger = new GenericMessage<>( + new JobLaunchRequest(job, builder.toJobParameters()), headers); requestChannel.send(trigger); Message executionMessage = (Message) responseChannel.receive(1000); @@ -152,8 +150,8 @@ public class JobLaunchingGatewayIntegrationTests { Map map = new HashMap<>(); map.put(MessageHeaders.REPLY_CHANNEL, "response"); MessageHeaders headers = new MessageHeaders(map); - GenericMessage trigger = new GenericMessage<>(new JobLaunchRequest(testJob, - builder.toJobParameters()), headers); + GenericMessage trigger = new GenericMessage<>( + new JobLaunchRequest(testJob, builder.toJobParameters()), headers); requestChannel.send(trigger); Message executionMessage = (Message) responseChannel.receive(1000); @@ -166,4 +164,5 @@ public class JobLaunchingGatewayIntegrationTests { assertEquals(ExitStatus.FAILED.getExitCode(), execution.getExitStatus().getExitCode()); } + } diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/launch/JobLaunchingGatewayTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/launch/JobLaunchingGatewayTests.java index d33d8c61a..c883774ea 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/launch/JobLaunchingGatewayTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/launch/JobLaunchingGatewayTests.java @@ -32,7 +32,6 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; /** - * * @author Gunnar Hillert * @since 1.3 * @@ -42,12 +41,12 @@ public class JobLaunchingGatewayTests { @Test public void testExceptionRaised() throws Exception { - final Message message = MessageBuilder.withPayload(new JobLaunchRequest(new JobSupport("testJob"), - new JobParameters())).build(); + final Message message = MessageBuilder + .withPayload(new JobLaunchRequest(new JobSupport("testJob"), new JobParameters())).build(); final JobLauncher jobLauncher = mock(JobLauncher.class); when(jobLauncher.run(any(Job.class), any(JobParameters.class))) - .thenThrow(new JobParametersInvalidException("This is a JobExecutionException.")); + .thenThrow(new JobParametersInvalidException("This is a JobExecutionException.")); JobLaunchingGateway jobLaunchingGateway = new JobLaunchingGateway(jobLauncher); @@ -62,4 +61,5 @@ public class JobLaunchingGatewayTests { fail("Expecting a MessageHandlingException to be thrown."); } + } diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/launch/JobLaunchingMessageHandlerIntegrationTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/launch/JobLaunchingMessageHandlerIntegrationTests.java index fb8ea90c6..10ea0ef64 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/launch/JobLaunchingMessageHandlerIntegrationTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/launch/JobLaunchingMessageHandlerIntegrationTests.java @@ -43,7 +43,7 @@ public class JobLaunchingMessageHandlerIntegrationTests { @Before public void setUp() { Object message = ""; - while (message!=null) { + while (message != null) { message = responseChannel.receive(10L); } } @@ -52,8 +52,7 @@ public class JobLaunchingMessageHandlerIntegrationTests { @DirtiesContext @SuppressWarnings("unchecked") public void testNoReply() { - GenericMessage trigger = new GenericMessage<>(new JobLaunchRequest(job, - new JobParameters())); + GenericMessage trigger = new GenericMessage<>(new JobLaunchRequest(job, new JobParameters())); try { requestChannel.send(trigger); } @@ -75,8 +74,8 @@ public class JobLaunchingMessageHandlerIntegrationTests { Map map = new HashMap<>(); map.put(MessageHeaders.REPLY_CHANNEL, "response"); MessageHeaders headers = new MessageHeaders(map); - GenericMessage trigger = new GenericMessage<>(new JobLaunchRequest(job, - builder.toJobParameters()), headers); + GenericMessage trigger = new GenericMessage<>( + new JobLaunchRequest(job, builder.toJobParameters()), headers); requestChannel.send(trigger); Message executionMessage = (Message) responseChannel.receive(1000); diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/launch/JobLaunchingMessageHandlerTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/launch/JobLaunchingMessageHandlerTests.java index 6500d017e..091e5ac19 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/launch/JobLaunchingMessageHandlerTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/launch/JobLaunchingMessageHandlerTests.java @@ -31,7 +31,7 @@ public class JobLaunchingMessageHandlerTests extends AbstractJUnit4SpringContext } @Test - public void testSimpleDelivery() throws Exception{ + public void testSimpleDelivery() throws Exception { messageHandler.launch(new JobLaunchRequest(new JobSupport("testjob"), null)); assertEquals("Wrong job count", 1, jobLauncher.jobs.size()); @@ -47,7 +47,7 @@ public class JobLaunchingMessageHandlerTests extends AbstractJUnit4SpringContext AtomicLong jobId = new AtomicLong(); - public JobExecution run(Job job, JobParameters jobParameters){ + public JobExecution run(Job job, JobParameters jobParameters) { jobs.add(job); parameters.add(jobParameters); return new JobExecution(new JobInstance(jobId.getAndIncrement(), job.getName()), jobParameters); diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/launch/JobRequestConverter.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/launch/JobRequestConverter.java index 42b0253f9..1e8fc548e 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/launch/JobRequestConverter.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/launch/JobRequestConverter.java @@ -30,7 +30,8 @@ public class JobRequestConverter { @ServiceActivator public JobLaunchRequest convert(String jobName) { Properties properties = new Properties(); - return new JobLaunchRequest(new JobSupport(jobName), new DefaultJobParametersConverter().getJobParameters(properties)); + return new JobLaunchRequest(new JobSupport(jobName), + new DefaultJobParametersConverter().getJobParameters(properties)); } } diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/BeanFactoryStepLocatorTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/BeanFactoryStepLocatorTests.java index 049a2c897..64c11945b 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/BeanFactoryStepLocatorTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/BeanFactoryStepLocatorTests.java @@ -1,57 +1,58 @@ -package org.springframework.batch.integration.partition; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import org.junit.Test; -import org.springframework.batch.core.JobInterruptedException; -import org.springframework.batch.core.Step; -import org.springframework.batch.core.StepExecution; -import org.springframework.beans.factory.support.DefaultListableBeanFactory; - - -public class BeanFactoryStepLocatorTests { - - private BeanFactoryStepLocator stepLocator = new BeanFactoryStepLocator(); - private DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); - - @Test - public void testGetStep() throws Exception { - beanFactory.registerSingleton("foo", new StubStep("foo")); - stepLocator.setBeanFactory(beanFactory); - assertNotNull(stepLocator.getStep("foo")); - } - - @Test - public void testGetStepNames() throws Exception { - beanFactory.registerSingleton("foo", new StubStep("foo")); - beanFactory.registerSingleton("bar", new StubStep("bar")); - stepLocator.setBeanFactory(beanFactory); - assertEquals(2, stepLocator.getStepNames().size()); - } - - private static final class StubStep implements Step { - - private String name; - - public StubStep(String name) { - this.name = name; - } - - public void execute(StepExecution stepExecution) throws JobInterruptedException { - } - - public String getName() { - return name; - } - - public int getStartLimit() { - return 0; - } - - public boolean isAllowStartIfComplete() { - return false; - } - } - -} +package org.springframework.batch.integration.partition; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.junit.Test; +import org.springframework.batch.core.JobInterruptedException; +import org.springframework.batch.core.Step; +import org.springframework.batch.core.StepExecution; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; + +public class BeanFactoryStepLocatorTests { + + private BeanFactoryStepLocator stepLocator = new BeanFactoryStepLocator(); + + private DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); + + @Test + public void testGetStep() throws Exception { + beanFactory.registerSingleton("foo", new StubStep("foo")); + stepLocator.setBeanFactory(beanFactory); + assertNotNull(stepLocator.getStep("foo")); + } + + @Test + public void testGetStepNames() throws Exception { + beanFactory.registerSingleton("foo", new StubStep("foo")); + beanFactory.registerSingleton("bar", new StubStep("bar")); + stepLocator.setBeanFactory(beanFactory); + assertEquals(2, stepLocator.getStepNames().size()); + } + + private static final class StubStep implements Step { + + private String name; + + public StubStep(String name) { + this.name = name; + } + + public void execute(StepExecution stepExecution) throws JobInterruptedException { + } + + public String getName() { + return name; + } + + public int getStartLimit() { + return 0; + } + + public boolean isAllowStartIfComplete() { + return false; + } + + } + +} diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/ExampleItemReader.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/ExampleItemReader.java index 3509c78c8..d1d714ede 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/ExampleItemReader.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/ExampleItemReader.java @@ -1,59 +1,59 @@ -package org.springframework.batch.integration.partition; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.ItemStream; -import org.springframework.batch.item.ItemStreamException; -import org.springframework.lang.Nullable; - -/** - * {@link ItemReader} with hard-coded input data. - */ -public class ExampleItemReader implements ItemReader, ItemStream { - - private Log logger = LogFactory.getLog(getClass()); - - private String[] input = { "Hello", "world!", "Go", "on", "punk", "make", "my", "day!" }; - - private int index = 0; - - public static volatile boolean fail = false; - - /** - * Reads next record from input - */ - @Nullable - public String read() throws Exception { - if (index >= input.length) { - return null; - } - logger.info(String.format("Processing input index=%s, item=%s, in (%s)", index, input[index], this)); - if (fail && index == 4) { - synchronized (ExampleItemReader.class) { - if (fail) { - // Only fail once per flag setting... - fail = false; - logger.info(String.format("Throwing exception index=%s, item=%s, in (%s)", index, input[index], - this)); - index++; - throw new RuntimeException("Planned failure"); - } - } - } - return input[index++]; - } - - public void close() throws ItemStreamException { - } - - public void open(ExecutionContext executionContext) throws ItemStreamException { - index = (int) executionContext.getLong("POSITION", 0); - } - - public void update(ExecutionContext executionContext) throws ItemStreamException { - executionContext.putLong("POSITION", index); - } - -} +package org.springframework.batch.integration.partition; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemStream; +import org.springframework.batch.item.ItemStreamException; +import org.springframework.lang.Nullable; + +/** + * {@link ItemReader} with hard-coded input data. + */ +public class ExampleItemReader implements ItemReader, ItemStream { + + private Log logger = LogFactory.getLog(getClass()); + + private String[] input = { "Hello", "world!", "Go", "on", "punk", "make", "my", "day!" }; + + private int index = 0; + + public static volatile boolean fail = false; + + /** + * Reads next record from input + */ + @Nullable + public String read() throws Exception { + if (index >= input.length) { + return null; + } + logger.info(String.format("Processing input index=%s, item=%s, in (%s)", index, input[index], this)); + if (fail && index == 4) { + synchronized (ExampleItemReader.class) { + if (fail) { + // Only fail once per flag setting... + fail = false; + logger.info( + String.format("Throwing exception index=%s, item=%s, in (%s)", index, input[index], this)); + index++; + throw new RuntimeException("Planned failure"); + } + } + } + return input[index++]; + } + + public void close() throws ItemStreamException { + } + + public void open(ExecutionContext executionContext) throws ItemStreamException { + index = (int) executionContext.getLong("POSITION", 0); + } + + public void update(ExecutionContext executionContext) throws ItemStreamException { + executionContext.putLong("POSITION", index); + } + +} diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/ExampleItemReaderTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/ExampleItemReaderTests.java index 3f2a7f96e..bb322cb3b 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/ExampleItemReaderTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/ExampleItemReaderTests.java @@ -1,70 +1,70 @@ -package org.springframework.batch.integration.partition; - -import static org.junit.Assert.*; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.springframework.batch.item.ExecutionContext; - -public class ExampleItemReaderTests { - - private ExampleItemReader reader = new ExampleItemReader(); - - @Before - @After - public void ensureFailFlagUnset() { - ExampleItemReader.fail = false; - } - - @Test - public void testRead() throws Exception { - int count = 0; - while (reader.read()!=null) { - count++; - } - assertEquals(8, count); - } - - @Test - public void testOpen() throws Exception { - ExecutionContext context = new ExecutionContext(); - for (int i=0; i<4; i++) { - reader.read(); - } - reader.update(context); - reader.open(context); - int count = 0; - while (reader.read()!=null) { - count++; - } - assertEquals(4, count); - } - - @Test - public void testFailAndRestart() throws Exception { - ExecutionContext context = new ExecutionContext(); - ExampleItemReader.fail = true; - for (int i=0; i<4; i++) { - reader.read(); - reader.update(context); - } - try { - reader.read(); - reader.update(context); - fail("Expected Exception"); - } - catch (Exception e) { - // expected - assertEquals("Planned failure", e.getMessage()); - } - assertFalse(ExampleItemReader.fail); - reader.open(context); - int count = 0; - while (reader.read()!=null) { - count++; - } - assertEquals(4, count); - } - -} +package org.springframework.batch.integration.partition; + +import static org.junit.Assert.*; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.springframework.batch.item.ExecutionContext; + +public class ExampleItemReaderTests { + + private ExampleItemReader reader = new ExampleItemReader(); + + @Before + @After + public void ensureFailFlagUnset() { + ExampleItemReader.fail = false; + } + + @Test + public void testRead() throws Exception { + int count = 0; + while (reader.read() != null) { + count++; + } + assertEquals(8, count); + } + + @Test + public void testOpen() throws Exception { + ExecutionContext context = new ExecutionContext(); + for (int i = 0; i < 4; i++) { + reader.read(); + } + reader.update(context); + reader.open(context); + int count = 0; + while (reader.read() != null) { + count++; + } + assertEquals(4, count); + } + + @Test + public void testFailAndRestart() throws Exception { + ExecutionContext context = new ExecutionContext(); + ExampleItemReader.fail = true; + for (int i = 0; i < 4; i++) { + reader.read(); + reader.update(context); + } + try { + reader.read(); + reader.update(context); + fail("Expected Exception"); + } + catch (Exception e) { + // expected + assertEquals("Planned failure", e.getMessage()); + } + assertFalse(ExampleItemReader.fail); + reader.open(context); + int count = 0; + while (reader.read() != null) { + count++; + } + assertEquals(4, count); + } + +} diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/ExampleItemWriter.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/ExampleItemWriter.java index fd3965190..59a9fb7e4 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/ExampleItemWriter.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/ExampleItemWriter.java @@ -1,23 +1,23 @@ -package org.springframework.batch.integration.partition; - -import java.util.List; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.batch.item.ItemWriter; - -/** - * Dummy {@link ItemWriter} which only logs data it receives. - */ -public class ExampleItemWriter implements ItemWriter { - - private static final Log log = LogFactory.getLog(ExampleItemWriter.class); - - /** - * @see ItemWriter#write(List) - */ - public void write(List data) throws Exception { - log.info(data); - } - -} +package org.springframework.batch.integration.partition; + +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.batch.item.ItemWriter; + +/** + * Dummy {@link ItemWriter} which only logs data it receives. + */ +public class ExampleItemWriter implements ItemWriter { + + private static final Log log = LogFactory.getLog(ExampleItemWriter.class); + + /** + * @see ItemWriter#write(List) + */ + public void write(List data) throws Exception { + log.info(data); + } + +} diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/JmsIntegrationTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/JmsIntegrationTests.java index 10c90d587..44acc5c87 100755 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/JmsIntegrationTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/JmsIntegrationTests.java @@ -1,11 +1,11 @@ /* * Copyright 2006-2007 the original author or authors. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at - * + * * https://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. @@ -37,7 +37,7 @@ import static org.junit.Assert.assertNotNull; /** * @author Dave Syer - * + * */ @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) @@ -68,14 +68,17 @@ public class JmsIntegrationTests { int after = jobInstances.size(); assertEquals(1, after - before); JobExecution jobExecution = jobExplorer.getJobExecutions(jobInstances.get(jobInstances.size() - 1)).get(0); - assertEquals(jobExecution.getExitStatus().getExitDescription(), BatchStatus.COMPLETED, jobExecution.getStatus()); + assertEquals(jobExecution.getExitStatus().getExitDescription(), BatchStatus.COMPLETED, + jobExecution.getStatus()); assertEquals(3, jobExecution.getStepExecutions().size()); for (StepExecution stepExecution : jobExecution.getStepExecutions()) { - // BATCH-1703: we are using a map dao so the step executions in the job execution are old and we need to + // BATCH-1703: we are using a map dao so the step executions in the job + // execution are old and we need to // pull them back out of the repository... stepExecution = jobExplorer.getStepExecution(jobExecution.getId(), stepExecution.getId()); logger.debug("" + stepExecution); assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); } } + } diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/MessageChannelPartitionHandlerTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/MessageChannelPartitionHandlerTests.java index 1b32e1db1..492e33b95 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/MessageChannelPartitionHandlerTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/MessageChannelPartitionHandlerTests.java @@ -45,7 +45,6 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; /** - * * @author Will Schipp * @author Michael Minella * @author Mahmoud Ben Hassine @@ -57,68 +56,71 @@ public class MessageChannelPartitionHandlerTests { @Test public void testNoPartitions() throws Exception { - //execute with no default set + // execute with no default set messageChannelPartitionHandler = new MessageChannelPartitionHandler(); - //mock + // mock StepExecution managerStepExecution = mock(StepExecution.class); StepExecutionSplitter stepExecutionSplitter = mock(StepExecutionSplitter.class); - //execute - Collection executions = messageChannelPartitionHandler.handle(stepExecutionSplitter, managerStepExecution); - //verify + // execute + Collection executions = messageChannelPartitionHandler.handle(stepExecutionSplitter, + managerStepExecution); + // verify assertTrue(executions.isEmpty()); } - @SuppressWarnings({"unchecked", "rawtypes"}) + @SuppressWarnings({ "unchecked", "rawtypes" }) @Test public void testHandleNoReply() throws Exception { - //execute with no default set + // execute with no default set messageChannelPartitionHandler = new MessageChannelPartitionHandler(); - //mock + // mock StepExecution managerStepExecution = mock(StepExecution.class); StepExecutionSplitter stepExecutionSplitter = mock(StepExecutionSplitter.class); MessagingTemplate operations = mock(MessagingTemplate.class); Message message = mock(Message.class); - //when + // when HashSet stepExecutions = new HashSet<>(); stepExecutions.add(new StepExecution("step1", new JobExecution(5L))); when(stepExecutionSplitter.split(any(StepExecution.class), eq(1))).thenReturn(stepExecutions); when(message.getPayload()).thenReturn(Collections.emptyList()); when(operations.receive((PollableChannel) any())).thenReturn(message); - //set + // set messageChannelPartitionHandler.setMessagingOperations(operations); - //execute - Collection executions = messageChannelPartitionHandler.handle(stepExecutionSplitter, managerStepExecution); - //verify + // execute + Collection executions = messageChannelPartitionHandler.handle(stepExecutionSplitter, + managerStepExecution); + // verify assertNotNull(executions); assertTrue(executions.isEmpty()); } - @SuppressWarnings({"unchecked", "rawtypes"}) + @SuppressWarnings({ "unchecked", "rawtypes" }) @Test public void testHandleWithReplyChannel() throws Exception { - //execute with no default set + // execute with no default set messageChannelPartitionHandler = new MessageChannelPartitionHandler(); - //mock + // mock StepExecution managerStepExecution = mock(StepExecution.class); StepExecutionSplitter stepExecutionSplitter = mock(StepExecutionSplitter.class); MessagingTemplate operations = mock(MessagingTemplate.class); Message message = mock(Message.class); PollableChannel replyChannel = mock(PollableChannel.class); - //when + // when HashSet stepExecutions = new HashSet<>(); stepExecutions.add(new StepExecution("step1", new JobExecution(5L))); when(stepExecutionSplitter.split(any(StepExecution.class), eq(1))).thenReturn(stepExecutions); when(message.getPayload()).thenReturn(Collections.emptyList()); when(operations.receive(replyChannel)).thenReturn(message); - //set + // set messageChannelPartitionHandler.setMessagingOperations(operations); messageChannelPartitionHandler.setReplyChannel(replyChannel); - //execute - Collection executions = messageChannelPartitionHandler.handle(stepExecutionSplitter, managerStepExecution); - //verify + // execute + Collection executions = messageChannelPartitionHandler.handle(stepExecutionSplitter, + managerStepExecution); + // verify assertNotNull(executions); assertTrue(executions.isEmpty()); @@ -127,36 +129,36 @@ public class MessageChannelPartitionHandlerTests { @SuppressWarnings("rawtypes") @Test(expected = MessageTimeoutException.class) public void messageReceiveTimeout() throws Exception { - //execute with no default set + // execute with no default set messageChannelPartitionHandler = new MessageChannelPartitionHandler(); - //mock + // mock StepExecution managerStepExecution = mock(StepExecution.class); StepExecutionSplitter stepExecutionSplitter = mock(StepExecutionSplitter.class); MessagingTemplate operations = mock(MessagingTemplate.class); Message message = mock(Message.class); - //when + // when HashSet stepExecutions = new HashSet<>(); stepExecutions.add(new StepExecution("step1", new JobExecution(5L))); when(stepExecutionSplitter.split(any(StepExecution.class), eq(1))).thenReturn(stepExecutions); when(message.getPayload()).thenReturn(Collections.emptyList()); - //set + // set messageChannelPartitionHandler.setMessagingOperations(operations); - //execute + // execute messageChannelPartitionHandler.handle(stepExecutionSplitter, managerStepExecution); } @Test public void testHandleWithJobRepositoryPolling() throws Exception { - //execute with no default set + // execute with no default set messageChannelPartitionHandler = new MessageChannelPartitionHandler(); - //mock + // mock JobExecution jobExecution = new JobExecution(5L, new JobParameters()); StepExecution managerStepExecution = new StepExecution("step1", jobExecution, 1L); StepExecutionSplitter stepExecutionSplitter = mock(StepExecutionSplitter.class); MessagingTemplate operations = mock(MessagingTemplate.class); JobExplorer jobExplorer = mock(JobExplorer.class); - //when + // when HashSet stepExecutions = new HashSet<>(); StepExecution partition1 = new StepExecution("step1:partition1", jobExecution, 2L); StepExecution partition2 = new StepExecution("step1:partition2", jobExecution, 3L); @@ -170,39 +172,41 @@ public class MessageChannelPartitionHandlerTests { stepExecutions.add(partition2); stepExecutions.add(partition3); when(stepExecutionSplitter.split(any(StepExecution.class), eq(1))).thenReturn(stepExecutions); - when(jobExplorer.getStepExecution(eq(5L), any(Long.class))).thenReturn(partition2, partition1, partition3, partition3, partition3, partition3, partition4); + when(jobExplorer.getStepExecution(eq(5L), any(Long.class))).thenReturn(partition2, partition1, partition3, + partition3, partition3, partition3, partition4); - //set + // set messageChannelPartitionHandler.setMessagingOperations(operations); messageChannelPartitionHandler.setJobExplorer(jobExplorer); messageChannelPartitionHandler.setStepName("step1"); messageChannelPartitionHandler.setPollInterval(500L); messageChannelPartitionHandler.afterPropertiesSet(); - //execute - Collection executions = messageChannelPartitionHandler.handle(stepExecutionSplitter, managerStepExecution); - //verify + // execute + Collection executions = messageChannelPartitionHandler.handle(stepExecutionSplitter, + managerStepExecution); + // verify assertNotNull(executions); assertEquals(3, executions.size()); assertTrue(executions.contains(partition1)); assertTrue(executions.contains(partition2)); assertTrue(executions.contains(partition4)); - //verify + // verify verify(operations, times(3)).send(any(Message.class)); } @Test(expected = TimeoutException.class) public void testHandleWithJobRepositoryPollingTimeout() throws Exception { - //execute with no default set + // execute with no default set messageChannelPartitionHandler = new MessageChannelPartitionHandler(); - //mock + // mock JobExecution jobExecution = new JobExecution(5L, new JobParameters()); StepExecution managerStepExecution = new StepExecution("step1", jobExecution, 1L); StepExecutionSplitter stepExecutionSplitter = mock(StepExecutionSplitter.class); MessagingTemplate operations = mock(MessagingTemplate.class); JobExplorer jobExplorer = mock(JobExplorer.class); - //when + // when HashSet stepExecutions = new HashSet<>(); StepExecution partition1 = new StepExecution("step1:partition1", jobExecution, 2L); StepExecution partition2 = new StepExecution("step1:partition2", jobExecution, 3L); @@ -216,14 +220,15 @@ public class MessageChannelPartitionHandlerTests { when(stepExecutionSplitter.split(any(StepExecution.class), eq(1))).thenReturn(stepExecutions); when(jobExplorer.getStepExecution(eq(5L), any(Long.class))).thenReturn(partition2, partition1, partition3); - //set + // set messageChannelPartitionHandler.setMessagingOperations(operations); messageChannelPartitionHandler.setJobExplorer(jobExplorer); messageChannelPartitionHandler.setStepName("step1"); messageChannelPartitionHandler.setTimeout(1000L); messageChannelPartitionHandler.afterPropertiesSet(); - //execute + // execute messageChannelPartitionHandler.handle(stepExecutionSplitter, managerStepExecution); } + } diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/PollingIntegrationTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/PollingIntegrationTests.java index 4b75489f2..373075b75 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/PollingIntegrationTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/PollingIntegrationTests.java @@ -36,7 +36,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * @author Dave Syer - * + * */ @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) @@ -47,7 +47,7 @@ public class PollingIntegrationTests { @Autowired private Job job; - + @Autowired private JobExplorer jobExplorer; @@ -62,8 +62,8 @@ public class PollingIntegrationTests { assertNotNull(jobLauncher.run(job, new JobParameters())); List jobInstances = jobExplorer.getJobInstances(job.getName(), 0, 100); int after = jobInstances.size(); - assertEquals(1, after-before); - JobExecution jobExecution = jobExplorer.getJobExecutions(jobInstances.get(jobInstances.size()-1)).get(0); + assertEquals(1, after - before); + JobExecution jobExecution = jobExplorer.getJobExecutions(jobInstances.get(jobInstances.size() - 1)).get(0); assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); assertEquals(3, jobExecution.getStepExecutions().size()); } diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/RemotePartitioningManagerStepBuilderTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/RemotePartitioningManagerStepBuilderTests.java index c08b9faaf..8f7527d97 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/RemotePartitioningManagerStepBuilderTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/RemotePartitioningManagerStepBuilderTests.java @@ -46,7 +46,7 @@ import static org.springframework.test.util.ReflectionTestUtils.getField; * @author Mahmoud Ben Hassine */ @RunWith(SpringRunner.class) -@ContextConfiguration(classes = {RemotePartitioningManagerStepBuilderTests.BatchConfiguration.class}) +@ContextConfiguration(classes = { RemotePartitioningManagerStepBuilderTests.BatchConfiguration.class }) public class RemotePartitioningManagerStepBuilderTests { @Autowired @@ -121,15 +121,14 @@ public class RemotePartitioningManagerStepBuilderTests { public void eitherOutputChannelOrMessagingTemplateMustBeProvided() { // given RemotePartitioningManagerStepBuilder builder = new RemotePartitioningManagerStepBuilder("step") - .outputChannel(new DirectChannel()) - .messagingTemplate(new MessagingTemplate()); + .outputChannel(new DirectChannel()).messagingTemplate(new MessagingTemplate()); // when - final Exception expectedException = Assert.assertThrows(IllegalStateException.class, - builder::build); + final Exception expectedException = Assert.assertThrows(IllegalStateException.class, builder::build); // then - assertThat(expectedException).hasMessage("You must specify either an outputChannel or a messagingTemplate but not both."); + assertThat(expectedException) + .hasMessage("You must specify either an outputChannel or a messagingTemplate but not both."); } @Test @@ -143,11 +142,10 @@ public class RemotePartitioningManagerStepBuilderTests { () -> builder.partitionHandler(partitionHandler)); // then - assertThat(expectedException).hasMessage("When configuring a manager step " + - "for remote partitioning using the RemotePartitioningManagerStepBuilder, " + - "the partition handler will be automatically set to an instance " + - "of MessageChannelPartitionHandler. The partition handler must " + - "not be provided in this case."); + assertThat(expectedException).hasMessage("When configuring a manager step " + + "for remote partitioning using the RemotePartitioningManagerStepBuilder, " + + "the partition handler will be automatically set to an instance " + + "of MessageChannelPartitionHandler. The partition handler must " + "not be provided in this case."); } @Test @@ -159,20 +157,14 @@ public class RemotePartitioningManagerStepBuilderTests { long pollInterval = 5000L; DirectChannel outputChannel = new DirectChannel(); Partitioner partitioner = Mockito.mock(Partitioner.class); - StepExecutionAggregator stepExecutionAggregator = (result, executions) -> { }; + StepExecutionAggregator stepExecutionAggregator = (result, executions) -> { + }; // when - Step step = new RemotePartitioningManagerStepBuilder("managerStep") - .repository(jobRepository) - .outputChannel(outputChannel) - .partitioner("workerStep", partitioner) - .gridSize(gridSize) - .pollInterval(pollInterval) - .timeout(timeout) - .startLimit(startLimit) - .aggregator(stepExecutionAggregator) - .allowStartIfComplete(true) - .build(); + Step step = new RemotePartitioningManagerStepBuilder("managerStep").repository(jobRepository) + .outputChannel(outputChannel).partitioner("workerStep", partitioner).gridSize(gridSize) + .pollInterval(pollInterval).timeout(timeout).startLimit(startLimit).aggregator(stepExecutionAggregator) + .allowStartIfComplete(true).build(); // then Assert.assertNotNull(step); @@ -202,18 +194,13 @@ public class RemotePartitioningManagerStepBuilderTests { int startLimit = 3; DirectChannel outputChannel = new DirectChannel(); Partitioner partitioner = Mockito.mock(Partitioner.class); - StepExecutionAggregator stepExecutionAggregator = (result, executions) -> { }; + StepExecutionAggregator stepExecutionAggregator = (result, executions) -> { + }; // when - Step step = new RemotePartitioningManagerStepBuilder("managerStep") - .repository(jobRepository) - .outputChannel(outputChannel) - .partitioner("workerStep", partitioner) - .gridSize(gridSize) - .startLimit(startLimit) - .aggregator(stepExecutionAggregator) - .allowStartIfComplete(true) - .build(); + Step step = new RemotePartitioningManagerStepBuilder("managerStep").repository(jobRepository) + .outputChannel(outputChannel).partitioner("workerStep", partitioner).gridSize(gridSize) + .startLimit(startLimit).aggregator(stepExecutionAggregator).allowStartIfComplete(true).build(); // then Assert.assertNotNull(step); @@ -244,12 +231,10 @@ public class RemotePartitioningManagerStepBuilderTests { @Bean public DataSource dataSource() { - return new EmbeddedDatabaseBuilder() - .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("/org/springframework/batch/core/schema-hsqldb.sql") - .generateUniqueName(true) - .build(); + return new EmbeddedDatabaseBuilder().addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") + .addScript("/org/springframework/batch/core/schema-hsqldb.sql").generateUniqueName(true).build(); } } + } diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/RemotePartitioningWorkerStepBuilderTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/RemotePartitioningWorkerStepBuilderTests.java index 7fc002513..ecb9e1ccc 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/RemotePartitioningWorkerStepBuilderTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/RemotePartitioningWorkerStepBuilderTests.java @@ -39,7 +39,8 @@ public class RemotePartitioningWorkerStepBuilderTests { final RemotePartitioningWorkerStepBuilder builder = new RemotePartitioningWorkerStepBuilder("step"); // when - final Exception expectedException = Assert.assertThrows(IllegalArgumentException.class, () -> builder.inputChannel(null)); + final Exception expectedException = Assert.assertThrows(IllegalArgumentException.class, + () -> builder.inputChannel(null)); // then assertThat(expectedException).hasMessage("inputChannel must not be null"); @@ -51,7 +52,8 @@ public class RemotePartitioningWorkerStepBuilderTests { final RemotePartitioningWorkerStepBuilder builder = new RemotePartitioningWorkerStepBuilder("step"); // when - final Exception expectedException = Assert.assertThrows(IllegalArgumentException.class, () -> builder.outputChannel(null)); + final Exception expectedException = Assert.assertThrows(IllegalArgumentException.class, + () -> builder.outputChannel(null)); // then assertThat(expectedException).hasMessage("outputChannel must not be null"); @@ -63,7 +65,8 @@ public class RemotePartitioningWorkerStepBuilderTests { final RemotePartitioningWorkerStepBuilder builder = new RemotePartitioningWorkerStepBuilder("step"); // when - final Exception expectedException = Assert.assertThrows(IllegalArgumentException.class, () -> builder.jobExplorer(null)); + final Exception expectedException = Assert.assertThrows(IllegalArgumentException.class, + () -> builder.jobExplorer(null)); // then assertThat(expectedException).hasMessage("jobExplorer must not be null"); @@ -75,7 +78,8 @@ public class RemotePartitioningWorkerStepBuilderTests { final RemotePartitioningWorkerStepBuilder builder = new RemotePartitioningWorkerStepBuilder("step"); // when - final Exception expectedException = Assert.assertThrows(IllegalArgumentException.class, () -> builder.stepLocator(null)); + final Exception expectedException = Assert.assertThrows(IllegalArgumentException.class, + () -> builder.stepLocator(null)); // then assertThat(expectedException).hasMessage("stepLocator must not be null"); @@ -87,7 +91,8 @@ public class RemotePartitioningWorkerStepBuilderTests { final RemotePartitioningWorkerStepBuilder builder = new RemotePartitioningWorkerStepBuilder("step"); // when - final Exception expectedException = Assert.assertThrows(IllegalArgumentException.class, () -> builder.beanFactory(null)); + final Exception expectedException = Assert.assertThrows(IllegalArgumentException.class, + () -> builder.beanFactory(null)); // then assertThat(expectedException).hasMessage("beanFactory must not be null"); @@ -99,7 +104,8 @@ public class RemotePartitioningWorkerStepBuilderTests { final RemotePartitioningWorkerStepBuilder builder = new RemotePartitioningWorkerStepBuilder("step"); // when - final Exception expectedException = Assert.assertThrows(IllegalArgumentException.class, () -> builder.tasklet(this.tasklet)); + final Exception expectedException = Assert.assertThrows(IllegalArgumentException.class, + () -> builder.tasklet(this.tasklet)); // then assertThat(expectedException).hasMessage("An InputChannel must be provided"); @@ -113,7 +119,8 @@ public class RemotePartitioningWorkerStepBuilderTests { .inputChannel(inputChannel); // when - final Exception expectedException = Assert.assertThrows(IllegalArgumentException.class, () -> builder.tasklet(this.tasklet)); + final Exception expectedException = Assert.assertThrows(IllegalArgumentException.class, + () -> builder.tasklet(this.tasklet)); // then assertThat(expectedException).hasMessage("A JobExplorer must be provided"); diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/StepExecutionRequestTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/StepExecutionRequestTests.java index 2dc0b98b0..83c8e66bb 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/StepExecutionRequestTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/StepExecutionRequestTests.java @@ -46,7 +46,8 @@ public class StepExecutionRequestTests { @Test public void stepExecutionRequestShouldBeDeserializableWithJackson() throws IOException { // when - StepExecutionRequest deserializedRequest = this.objectMapper.readValue(SERIALIZED_REQUEST, StepExecutionRequest.class); + StepExecutionRequest deserializedRequest = this.objectMapper.readValue(SERIALIZED_REQUEST, + StepExecutionRequest.class); // then Assert.assertNotNull(deserializedRequest); @@ -54,4 +55,5 @@ public class StepExecutionRequestTests { Assert.assertEquals(1L, deserializedRequest.getJobExecutionId().longValue()); Assert.assertEquals(1L, deserializedRequest.getStepExecutionId().longValue()); } + } diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/VanillaIntegrationTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/VanillaIntegrationTests.java index 59f9bbaa3..469e05ece 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/VanillaIntegrationTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/partition/VanillaIntegrationTests.java @@ -35,7 +35,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * @author Dave Syer - * + * */ @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) @@ -46,7 +46,7 @@ public class VanillaIntegrationTests { @Autowired private Job job; - + @Autowired private JobExplorer jobExplorer; @@ -61,8 +61,8 @@ public class VanillaIntegrationTests { assertNotNull(jobLauncher.run(job, new JobParameters())); List jobInstances = jobExplorer.getJobInstances(job.getName(), 0, 100); int after = jobInstances.size(); - assertEquals(1, after-before); - JobExecution jobExecution = jobExplorer.getJobExecutions(jobInstances.get(jobInstances.size()-1)).get(0); + assertEquals(1, after - before); + JobExecution jobExecution = jobExplorer.getJobExecutions(jobInstances.get(jobInstances.size() - 1)).get(0); assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); assertEquals(3, jobExecution.getStepExecutions().size()); } diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/retry/RepeatTransactionalPollingIntegrationTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/retry/RepeatTransactionalPollingIntegrationTests.java index b25e69836..665885eb2 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/retry/RepeatTransactionalPollingIntegrationTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/retry/RepeatTransactionalPollingIntegrationTests.java @@ -30,17 +30,17 @@ public class RepeatTransactionalPollingIntegrationTests implements ApplicationCo private Log logger = LogFactory.getLog(getClass()); private static List processed = new ArrayList<>(); - + private static List expected; private static List handled = new ArrayList<>(); - + private static List list = new ArrayList<>(); private Lifecycle bus; private volatile static int count = 0; - + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { bus = (Lifecycle) applicationContext; } @@ -48,8 +48,8 @@ public class RepeatTransactionalPollingIntegrationTests implements ApplicationCo public String process(String message) { String result = message + ": " + count; logger.debug("Handling: " + message); - if (count expected = Arrays.asList(StringUtils.commaDelimitedListToStringArray("a,b,c,d")); service.setExpected(expected); waitForResults(lifecycle, expected.size(), 60); @@ -80,11 +80,12 @@ public class RetryRepeatTransactionalPollingIntegrationTests implements Applicat @Test @DirtiesContext public void testRollback() throws Exception { - list = TransactionAwareProxyFactory.createTransactionalList(Arrays.asList(StringUtils - .commaDelimitedListToStringArray("a,b,fail,d,e,f,g,h,j,k"))); + list = TransactionAwareProxyFactory.createTransactionalList( + Arrays.asList(StringUtils.commaDelimitedListToStringArray("a,b,fail,d,e,f,g,h,j,k"))); List expected = Arrays.asList(StringUtils.commaDelimitedListToStringArray("a,b,fail,fail,d,e,f")); service.setExpected(expected); - waitForResults(lifecycle, expected.size(), 60); // (a,b), (fail), (fail), ([fail],d), (e,f) + waitForResults(lifecycle, expected.size(), 60); // (a,b), (fail), (fail), + // ([fail],d), (e,f) System.err.println(service.getProcessed()); assertEquals(7, service.getProcessed().size()); // a,b,fail,fail,d,e,f assertEquals(1, recoverer.getRecovered().size()); // fail diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/retry/RetryTransactionalPollingIntegrationTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/retry/RetryTransactionalPollingIntegrationTests.java index 4bf38174b..012a4ea89 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/retry/RetryTransactionalPollingIntegrationTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/retry/RetryTransactionalPollingIntegrationTests.java @@ -56,7 +56,8 @@ public class RetryTransactionalPollingIntegrationTests implements ApplicationCon if (list.isEmpty()) { return null; } - // This happens in a transaction and the list is transactional so if it rolls back the same item comes back + // This happens in a transaction and the list is transactional so if it rolls back + // the same item comes back // again at the head of the list return list.remove(0); } @@ -69,8 +70,8 @@ public class RetryTransactionalPollingIntegrationTests implements ApplicationCon @Test @DirtiesContext public void testSunnyDay() throws Exception { - list = TransactionAwareProxyFactory.createTransactionalList(Arrays.asList(StringUtils - .commaDelimitedListToStringArray("a,b,c,d,e,f,g,h,j,k"))); + list = TransactionAwareProxyFactory.createTransactionalList( + Arrays.asList(StringUtils.commaDelimitedListToStringArray("a,b,c,d,e,f,g,h,j,k"))); List expected = Arrays.asList(StringUtils.commaDelimitedListToStringArray("a,b,c,d")); service.setExpected(expected); waitForResults(bus, expected.size(), 60); @@ -81,8 +82,8 @@ public class RetryTransactionalPollingIntegrationTests implements ApplicationCon @Test @DirtiesContext public void testRollback() throws Exception { - list = TransactionAwareProxyFactory.createTransactionalList(Arrays.asList(StringUtils - .commaDelimitedListToStringArray("a,b,fail,d,e,f,g,h,j,k"))); + list = TransactionAwareProxyFactory.createTransactionalList( + Arrays.asList(StringUtils.commaDelimitedListToStringArray("a,b,fail,d,e,f,g,h,j,k"))); List expected = Arrays.asList(StringUtils.commaDelimitedListToStringArray("a,b,fail,fail,d,e")); service.setExpected(expected); diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/retry/SimpleRecoverer.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/retry/SimpleRecoverer.java index 681899abb..33dc85614 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/retry/SimpleRecoverer.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/retry/SimpleRecoverer.java @@ -34,4 +34,5 @@ public final class SimpleRecoverer implements MethodInvocationRecoverer recovered.add(payload); return null; } + } \ No newline at end of file diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/retry/TransactionalPollingIntegrationTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/retry/TransactionalPollingIntegrationTests.java index e57fd7ceb..aa988588b 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/retry/TransactionalPollingIntegrationTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/retry/TransactionalPollingIntegrationTests.java @@ -87,12 +87,13 @@ public class TransactionalPollingIntegrationTests implements ApplicationContextA @DirtiesContext public void testSunnyDay() throws Exception { try { - list = TransactionAwareProxyFactory.createTransactionalList(Arrays.asList(StringUtils - .commaDelimitedListToStringArray("a,b,c,d,e,f,g,h,j,k"))); + list = TransactionAwareProxyFactory.createTransactionalList( + Arrays.asList(StringUtils.commaDelimitedListToStringArray("a,b,c,d,e,f,g,h,j,k"))); expected = Arrays.asList(StringUtils.commaDelimitedListToStringArray("a,b,c,d")); waitForResults(bus, 4, 60); assertEquals(expected, processed); - } catch (Throwable t) { + } + catch (Throwable t) { System.out.println(t.getMessage()); t.printStackTrace(); } @@ -101,8 +102,8 @@ public class TransactionalPollingIntegrationTests implements ApplicationContextA @Test @DirtiesContext public void testRollback() throws Exception { - list = TransactionAwareProxyFactory.createTransactionalList(Arrays.asList(StringUtils - .commaDelimitedListToStringArray("a,b,fail,d,e,f,g,h,j,k"))); + list = TransactionAwareProxyFactory.createTransactionalList( + Arrays.asList(StringUtils.commaDelimitedListToStringArray("a,b,fail,d,e,f,g,h,j,k"))); expected = Arrays.asList(StringUtils.commaDelimitedListToStringArray("a,b,fail,fail")); waitForResults(bus, 4, 30); assertEquals(expected, processed); diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/step/StepGatewayIntegrationTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/step/StepGatewayIntegrationTests.java index f2a9217bd..84df2ead8 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/step/StepGatewayIntegrationTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/step/StepGatewayIntegrationTests.java @@ -1,73 +1,74 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.integration.step; - -import static org.junit.Assert.assertEquals; - -import org.junit.After; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.launch.JobLauncher; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -/** - * @author Dave Syer - * - */ -@ContextConfiguration() -@RunWith(SpringJUnit4ClassRunner.class) -public class StepGatewayIntegrationTests { - - @Autowired - private JobLauncher jobLauncher; - - @Autowired - @Qualifier("job") - private Job job; - - @Autowired - private TestTasklet tasklet; - - @After - public void clear() { - tasklet.setFail(false); - } - - @Test - public void testLaunchJob() throws Exception { - JobExecution jobExecution = jobLauncher.run(job, new JobParameters()); - assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); - assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus()); - } - - @Test - public void testLaunchFailedJob() throws Exception { - tasklet.setFail(true); - JobExecution jobExecution = jobLauncher.run(job, new JobParametersBuilder().addLong("run.id", 2L).toJobParameters()); - assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); - assertEquals(ExitStatus.FAILED, jobExecution.getExitStatus()); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.integration.step; + +import static org.junit.Assert.assertEquals; + +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.Job; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.JobParametersBuilder; +import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Dave Syer + * + */ +@ContextConfiguration() +@RunWith(SpringJUnit4ClassRunner.class) +public class StepGatewayIntegrationTests { + + @Autowired + private JobLauncher jobLauncher; + + @Autowired + @Qualifier("job") + private Job job; + + @Autowired + private TestTasklet tasklet; + + @After + public void clear() { + tasklet.setFail(false); + } + + @Test + public void testLaunchJob() throws Exception { + JobExecution jobExecution = jobLauncher.run(job, new JobParameters()); + assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); + assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus()); + } + + @Test + public void testLaunchFailedJob() throws Exception { + tasklet.setFail(true); + JobExecution jobExecution = jobLauncher.run(job, + new JobParametersBuilder().addLong("run.id", 2L).toJobParameters()); + assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); + assertEquals(ExitStatus.FAILED, jobExecution.getExitStatus()); + } + +} diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/integration/step/TestTasklet.java b/spring-batch-integration/src/test/java/org/springframework/batch/integration/step/TestTasklet.java index e47a33619..8307332cf 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/integration/step/TestTasklet.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/integration/step/TestTasklet.java @@ -1,44 +1,44 @@ -/* - * Copyright 2006-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.integration.step; - -import org.springframework.batch.core.StepContribution; -import org.springframework.batch.core.scope.context.ChunkContext; -import org.springframework.batch.core.step.tasklet.Tasklet; -import org.springframework.batch.repeat.RepeatStatus; -import org.springframework.lang.Nullable; - -/** - * @author Dave Syer - * - */ -public class TestTasklet implements Tasklet { - - private boolean fail = false; - - public void setFail(boolean fail) { - this.fail = fail; - } - - @Nullable - public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { - if (fail) { - throw new IllegalStateException("Planned Tasklet failure"); - } - return RepeatStatus.FINISHED; - } - -} +/* + * Copyright 2006-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.integration.step; + +import org.springframework.batch.core.StepContribution; +import org.springframework.batch.core.scope.context.ChunkContext; +import org.springframework.batch.core.step.tasklet.Tasklet; +import org.springframework.batch.repeat.RepeatStatus; +import org.springframework.lang.Nullable; + +/** + * @author Dave Syer + * + */ +public class TestTasklet implements Tasklet { + + private boolean fail = false; + + public void setFail(boolean fail) { + this.fail = fail; + } + + @Nullable + public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { + if (fail) { + throw new IllegalStateException("Planned Tasklet failure"); + } + return RepeatStatus.FINISHED; + } + +} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/common/ColumnRangePartitioner.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/common/ColumnRangePartitioner.java index 616b49cec..ac30c9e7b 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/common/ColumnRangePartitioner.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/common/ColumnRangePartitioner.java @@ -1,106 +1,103 @@ -/* - * Copyright 2009-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.sample.common; - -import java.util.HashMap; -import java.util.Map; - -import javax.sql.DataSource; - -import org.springframework.batch.core.partition.support.Partitioner; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.jdbc.core.JdbcOperations; -import org.springframework.jdbc.core.JdbcTemplate; - -/** - * Simple minded partitioner for a range of values of a column in a database - * table. Works best if the values are uniformly distributed (e.g. - * auto-generated primary key values). - * - * @author Dave Syer - * - */ -public class ColumnRangePartitioner implements Partitioner { - - private JdbcOperations jdbcTemplate; - - private String table; - - private String column; - - /** - * The name of the SQL table the data are in. - * - * @param table the name of the table - */ - public void setTable(String table) { - this.table = table; - } - - /** - * The name of the column to partition. - * - * @param column the column name. - */ - public void setColumn(String column) { - this.column = column; - } - - /** - * The data source for connecting to the database. - * - * @param dataSource a {@link DataSource} - */ - public void setDataSource(DataSource dataSource) { - jdbcTemplate = new JdbcTemplate(dataSource); - } - - /** - * Partition a database table assuming that the data in the column specified - * are uniformly distributed. The execution context values will have keys - * minValue and maxValue specifying the range of - * values to consider in each partition. - * - * @see Partitioner#partition(int) - */ - @Override - public Map partition(int gridSize) { - int min = jdbcTemplate.queryForObject("SELECT MIN(" + column + ") from " + table, Integer.class); - int max = jdbcTemplate.queryForObject("SELECT MAX(" + column + ") from " + table, Integer.class); - int targetSize = (max - min) / gridSize + 1; - - Map result = new HashMap<>(); - int number = 0; - int start = min; - int end = start + targetSize - 1; - - while (start <= max) { - ExecutionContext value = new ExecutionContext(); - result.put("partition" + number, value); - - if (end >= max) { - end = max; - } - value.putInt("minValue", start); - value.putInt("maxValue", end); - start += targetSize; - end += targetSize; - number++; - } - - return result; - } -} +/* + * Copyright 2009-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.sample.common; + +import java.util.HashMap; +import java.util.Map; + +import javax.sql.DataSource; + +import org.springframework.batch.core.partition.support.Partitioner; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.jdbc.core.JdbcOperations; +import org.springframework.jdbc.core.JdbcTemplate; + +/** + * Simple minded partitioner for a range of values of a column in a database table. Works + * best if the values are uniformly distributed (e.g. auto-generated primary key values). + * + * @author Dave Syer + * + */ +public class ColumnRangePartitioner implements Partitioner { + + private JdbcOperations jdbcTemplate; + + private String table; + + private String column; + + /** + * The name of the SQL table the data are in. + * @param table the name of the table + */ + public void setTable(String table) { + this.table = table; + } + + /** + * The name of the column to partition. + * @param column the column name. + */ + public void setColumn(String column) { + this.column = column; + } + + /** + * The data source for connecting to the database. + * @param dataSource a {@link DataSource} + */ + public void setDataSource(DataSource dataSource) { + jdbcTemplate = new JdbcTemplate(dataSource); + } + + /** + * Partition a database table assuming that the data in the column specified are + * uniformly distributed. The execution context values will have keys + * minValue and maxValue specifying the range of values to + * consider in each partition. + * + * @see Partitioner#partition(int) + */ + @Override + public Map partition(int gridSize) { + int min = jdbcTemplate.queryForObject("SELECT MIN(" + column + ") from " + table, Integer.class); + int max = jdbcTemplate.queryForObject("SELECT MAX(" + column + ") from " + table, Integer.class); + int targetSize = (max - min) / gridSize + 1; + + Map result = new HashMap<>(); + int number = 0; + int start = min; + int end = start + targetSize - 1; + + while (start <= max) { + ExecutionContext value = new ExecutionContext(); + result.put("partition" + number, value); + + if (end >= max) { + end = max; + } + value.putInt("minValue", start); + value.putInt("maxValue", end); + start += targetSize; + end += targetSize; + number++; + } + + return result; + } + +} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/common/InfiniteLoopReader.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/common/InfiniteLoopReader.java index 3b03efb2a..76fe9a952 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/common/InfiniteLoopReader.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/common/InfiniteLoopReader.java @@ -20,11 +20,11 @@ import org.springframework.batch.item.ItemReader; import org.springframework.lang.Nullable; /** - * ItemReader implementation that will continually return a new object. It's - * generally useful for testing interruption. - * + * ItemReader implementation that will continually return a new object. It's generally + * useful for testing interruption. + * * @author Lucas Ward - * + * */ public class InfiniteLoopReader implements ItemReader { @@ -33,4 +33,5 @@ public class InfiniteLoopReader implements ItemReader { public Object read() throws Exception { return new Object(); } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/common/InfiniteLoopWriter.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/common/InfiniteLoopWriter.java index e29c8790e..fa55d3925 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/common/InfiniteLoopWriter.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/common/InfiniteLoopWriter.java @@ -25,18 +25,19 @@ import org.springframework.batch.core.StepExecutionListener; import org.springframework.batch.item.ItemWriter; /** - * Simple module implementation that will always return true to indicate that - * processing should continue. This is useful for testing graceful shutdown of - * jobs. - * + * Simple module implementation that will always return true to indicate that processing + * should continue. This is useful for testing graceful shutdown of jobs. + * * @author Lucas Ward * @author Mahmoud Ben Hassine - * + * */ public class InfiniteLoopWriter implements StepExecutionListener, ItemWriter { + private static final Log LOG = LogFactory.getLog(InfiniteLoopWriter.class); private StepExecution stepExecution; + private int count = 0; /** @@ -66,4 +67,5 @@ public class InfiniteLoopWriter implements StepExecutionListener, ItemWriter item type - * - * @see StagingItemReader - * @see StagingItemProcessor - * - * @author Robert Kasanicky - */ -public class ProcessIndicatorItemWrapper { - - private long id; - - private T item; - - public ProcessIndicatorItemWrapper(long id, T item) { - this.id = id; - this.item = item; - } - - /** - * @return id identifying the input data (typically row in database) - */ - public long getId() { - return id; - } - - /** - * @return item (domain object for business processing) - */ - public T getItem() { - return item; - } -} +/* + * Copyright 2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.sample.common; + +/** + * Item wrapper useful in "process indicator" usecase, where input is marked as processed + * by the processor/writer. This requires passing a technical identifier of the input data + * so that it can be modified in later stages. + * + * @param item type + * @see StagingItemReader + * @see StagingItemProcessor + * @author Robert Kasanicky + */ +public class ProcessIndicatorItemWrapper { + + private long id; + + private T item; + + public ProcessIndicatorItemWrapper(long id, T item) { + this.id = id; + this.item = item; + } + + /** + * @return id identifying the input data (typically row in database) + */ + public long getId() { + return id; + } + + /** + * @return item (domain object for business processing) + */ + public T getItem() { + return item; + } + +} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/common/StagingItemListener.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/common/StagingItemListener.java index 5785416be..7bff52b4d 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/common/StagingItemListener.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/common/StagingItemListener.java @@ -27,8 +27,7 @@ import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.util.Assert; /** - * Thread-safe database {@link ItemReader} implementing the process indicator - * pattern. + * Thread-safe database {@link ItemReader} implementing the process indicator pattern. */ public class StagingItemListener extends StepListenerSupport implements InitializingBean { diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/common/StagingItemProcessor.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/common/StagingItemProcessor.java index ffd3d323f..a3a615109 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/common/StagingItemProcessor.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/common/StagingItemProcessor.java @@ -1,74 +1,72 @@ -/* - * Copyright 2009-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.sample.common; - -import javax.sql.DataSource; - -import org.springframework.batch.item.ItemProcessor; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.dao.OptimisticLockingFailureException; -import org.springframework.jdbc.core.JdbcOperations; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.lang.Nullable; -import org.springframework.util.Assert; - -/** - * Marks the input row as 'processed'. (This change will rollback if there is - * problem later) - * - * @param item type - * - * @see StagingItemReader - * @see StagingItemWriter - * @see ProcessIndicatorItemWrapper - * - * @author Robert Kasanicky - */ -public class StagingItemProcessor implements ItemProcessor, T>, InitializingBean { - - private JdbcOperations jdbcTemplate; - - public void setJdbcTemplate(JdbcOperations jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; - } - - public void setDataSource(DataSource dataSource) { - this.jdbcTemplate = new JdbcTemplate(dataSource); - } - - @Override - public void afterPropertiesSet() throws Exception { - Assert.notNull(jdbcTemplate, "Either jdbcTemplate or dataSource must be set"); - } - - /** - * Use the technical identifier to mark the input row as processed and - * return unwrapped item. - */ - @Nullable - @Override - public T process(ProcessIndicatorItemWrapper wrapper) throws Exception { - - int count = jdbcTemplate.update("UPDATE BATCH_STAGING SET PROCESSED=? WHERE ID=? AND PROCESSED=?", - StagingItemWriter.DONE, wrapper.getId(), StagingItemWriter.NEW); - if (count != 1) { - throw new OptimisticLockingFailureException("The staging record with ID=" + wrapper.getId() - + " was updated concurrently when trying to mark as complete (updated " + count + " records."); - } - return wrapper.getItem(); - } - -} +/* + * Copyright 2009-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.sample.common; + +import javax.sql.DataSource; + +import org.springframework.batch.item.ItemProcessor; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.dao.OptimisticLockingFailureException; +import org.springframework.jdbc.core.JdbcOperations; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; + +/** + * Marks the input row as 'processed'. (This change will rollback if there is problem + * later) + * + * @param item type + * @see StagingItemReader + * @see StagingItemWriter + * @see ProcessIndicatorItemWrapper + * @author Robert Kasanicky + */ +public class StagingItemProcessor implements ItemProcessor, T>, InitializingBean { + + private JdbcOperations jdbcTemplate; + + public void setJdbcTemplate(JdbcOperations jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + public void setDataSource(DataSource dataSource) { + this.jdbcTemplate = new JdbcTemplate(dataSource); + } + + @Override + public void afterPropertiesSet() throws Exception { + Assert.notNull(jdbcTemplate, "Either jdbcTemplate or dataSource must be set"); + } + + /** + * Use the technical identifier to mark the input row as processed and return + * unwrapped item. + */ + @Nullable + @Override + public T process(ProcessIndicatorItemWrapper wrapper) throws Exception { + + int count = jdbcTemplate.update("UPDATE BATCH_STAGING SET PROCESSED=? WHERE ID=? AND PROCESSED=?", + StagingItemWriter.DONE, wrapper.getId(), StagingItemWriter.NEW); + if (count != 1) { + throw new OptimisticLockingFailureException("The staging record with ID=" + wrapper.getId() + + " was updated concurrently when trying to mark as complete (updated " + count + " records."); + } + return wrapper.getItem(); + } + +} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/common/StagingItemReader.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/common/StagingItemReader.java index bd8c0ed4f..3650dacae 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/common/StagingItemReader.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/common/StagingItemReader.java @@ -41,13 +41,12 @@ import org.springframework.util.Assert; import org.springframework.util.SerializationUtils; /** - * Thread-safe database {@link ItemReader} implementing the process indicator - * pattern. + * Thread-safe database {@link ItemReader} implementing the process indicator pattern. * * To achieve restartability use together with {@link StagingItemProcessor}. */ -public class StagingItemReader implements ItemReader>, StepExecutionListener, -InitializingBean, DisposableBean { +public class StagingItemReader + implements ItemReader>, StepExecutionListener, InitializingBean, DisposableBean { private static Log logger = LogFactory.getLog(StagingItemReader.class); @@ -119,12 +118,12 @@ InitializingBean, DisposableBean { @SuppressWarnings("unchecked") T result = (T) jdbcTemplate.queryForObject("SELECT VALUE FROM BATCH_STAGING WHERE ID=?", new RowMapper() { - @Override - public Object mapRow(ResultSet rs, int rowNum) throws SQLException { - byte[] blob = rs.getBytes(1); - return SerializationUtils.deserialize(blob); - } - }, id); + @Override + public Object mapRow(ResultSet rs, int rowNum) throws SQLException { + byte[] blob = rs.getBytes(1); + return SerializationUtils.deserialize(blob); + } + }, id); return new ProcessIndicatorItemWrapper<>(id, result); } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/common/StagingItemWriter.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/common/StagingItemWriter.java index 74957c029..7c052710f 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/common/StagingItemWriter.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/common/StagingItemWriter.java @@ -60,7 +60,6 @@ public class StagingItemWriter extends JdbcDaoSupport implements StepExecutio /** * Setter for the key generator for the staging table. - * * @param incrementer the {@link DataFieldMaxValueIncrementer} to set */ public void setIncrementer(DataFieldMaxValueIncrementer incrementer) { @@ -78,29 +77,28 @@ public class StagingItemWriter extends JdbcDaoSupport implements StepExecutio getJdbcTemplate().batchUpdate("INSERT into BATCH_STAGING (ID, JOB_ID, VALUE, PROCESSED) values (?,?,?,?)", new BatchPreparedStatementSetter() { - @Override - public int getBatchSize() { - return items.size(); - } + @Override + public int getBatchSize() { + return items.size(); + } - @Override - public void setValues(PreparedStatement ps, int i) throws SQLException { - Assert.state(itemIterator.nextIndex() == i, "Item ordering must be preserved in batch sql update"); + @Override + public void setValues(PreparedStatement ps, int i) throws SQLException { + Assert.state(itemIterator.nextIndex() == i, + "Item ordering must be preserved in batch sql update"); - ps.setLong(1, incrementer.nextLongValue()); - ps.setLong(2, stepExecution.getJobExecution().getJobId()); - ps.setBytes(3, SerializationUtils.serialize(itemIterator.next())); - ps.setString(4, NEW); - } - }); + ps.setLong(1, incrementer.nextLongValue()); + ps.setLong(2, stepExecution.getJobExecution().getJobId()); + ps.setBytes(3, SerializationUtils.serialize(itemIterator.next())); + ps.setString(4, NEW); + } + }); } /* * (non-Javadoc) * - * @see - * org.springframework.batch.core.domain.StepListener#afterStep(StepExecution - * ) + * @see org.springframework.batch.core.domain.StepListener#afterStep(StepExecution ) */ @Nullable @Override @@ -118,4 +116,5 @@ public class StagingItemWriter extends JdbcDaoSupport implements StepExecutio public void beforeStep(StepExecution stepExecution) { this.stepExecution = stepExecution; } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/config/DataSourceConfiguration.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/config/DataSourceConfiguration.java index 2de333feb..758bb2a4b 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/config/DataSourceConfiguration.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/config/DataSourceConfiguration.java @@ -37,22 +37,22 @@ import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator; @Configuration @PropertySource("classpath:/batch-hsql.properties") public class DataSourceConfiguration { - + @Autowired private Environment environment; - + @Autowired private ResourceLoader resourceLoader; - + @PostConstruct protected void initialize() { ResourceDatabasePopulator populator = new ResourceDatabasePopulator(); populator.addScript(resourceLoader.getResource(environment.getProperty("batch.schema.script"))); populator.setContinueOnError(true); - DatabasePopulatorUtils.execute(populator , dataSource()); + DatabasePopulatorUtils.execute(populator, dataSource()); } - - @Bean(destroyMethod="close") + + @Bean(destroyMethod = "close") public DataSource dataSource() { BasicDataSource dataSource = new BasicDataSource(); dataSource.setDriverClassName(environment.getProperty("batch.jdbc.driver")); diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/config/RetrySampleConfiguration.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/config/RetrySampleConfiguration.java index 4cb611735..717fc850e 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/config/RetrySampleConfiguration.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/config/RetrySampleConfiguration.java @@ -32,7 +32,7 @@ import org.springframework.context.annotation.Configuration; /** * @author Dave Syer * @author Mahmoud Ben Hassine - * + * */ @Configuration @EnableBatchProcessing @@ -51,7 +51,7 @@ public class RetrySampleConfiguration { @Bean protected Step step() { - return steps.get("step"). chunk(1).reader(reader()).writer(writer()).faultTolerant() + return steps.get("step").chunk(1).reader(reader()).writer(writer()).faultTolerant() .retry(Exception.class).retryLimit(3).build(); } @@ -66,4 +66,5 @@ public class RetrySampleConfiguration { protected ItemWriter writer() { return new RetrySampleItemWriter<>(); } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/data/CustomerCreditCrudRepository.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/data/CustomerCreditCrudRepository.java index 8593bdba7..a808ab811 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/data/CustomerCreditCrudRepository.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/data/CustomerCreditCrudRepository.java @@ -20,4 +20,5 @@ import org.springframework.batch.sample.domain.trade.CustomerCredit; import org.springframework.data.repository.CrudRepository; public interface CustomerCreditCrudRepository extends CrudRepository { + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/data/CustomerCreditPagingAndSortingRepository.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/data/CustomerCreditPagingAndSortingRepository.java index 5f2bf7a26..1ef93e44d 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/data/CustomerCreditPagingAndSortingRepository.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/data/CustomerCreditPagingAndSortingRepository.java @@ -22,6 +22,8 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.repository.PagingAndSortingRepository; -public interface CustomerCreditPagingAndSortingRepository extends PagingAndSortingRepository{ +public interface CustomerCreditPagingAndSortingRepository extends PagingAndSortingRepository { + Page findByCreditGreaterThan(BigDecimal credit, Pageable request); + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/Game.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/Game.java index a9d003b88..fc01d0d03 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/Game.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/Game.java @@ -20,209 +20,251 @@ import java.io.Serializable; @SuppressWarnings("serial") public class Game implements Serializable { - + private String id; + private int year; + private String team; + private int week; + private String opponent; + private int completes; + private int attempts; + private int passingYards; + private int passingTd; + private int interceptions; + private int rushes; + private int rushYards; + private int receptions; + private int receptionYards; + private int totalTd; + /** * @return the id */ public String getId() { return id; } + /** * @return the year */ public int getYear() { return year; } + /** * @return the team */ public String getTeam() { return team; } + /** * @return the week */ public int getWeek() { return week; } + /** * @return the opponent */ public String getOpponent() { return opponent; } + /** * @return the completes */ public int getCompletes() { return completes; } + /** * @return the attempts */ public int getAttempts() { return attempts; } + /** * @return the passingYards */ public int getPassingYards() { return passingYards; } + /** * @return the passingTd */ public int getPassingTd() { return passingTd; } + /** * @return the interceptions */ public int getInterceptions() { return interceptions; } + /** * @return the rushes */ public int getRushes() { return rushes; } + /** * @return the rushYards */ public int getRushYards() { return rushYards; } + /** * @return the receptions */ public int getReceptions() { return receptions; } + /** * @return the receptionYards */ public int getReceptionYards() { return receptionYards; } + /** * @return the totalTd */ public int getTotalTd() { return totalTd; } + /** * @param id the id to set */ public void setId(String id) { this.id = id; } + /** * @param year the year to set */ public void setYear(int year) { this.year = year; } + /** * @param team the team to set */ public void setTeam(String team) { this.team = team; } + /** * @param week the week to set */ public void setWeek(int week) { this.week = week; } + /** * @param opponent the opponent to set */ public void setOpponent(String opponent) { this.opponent = opponent; } + /** * @param completes the completes to set */ public void setCompletes(int completes) { this.completes = completes; } + /** * @param attempts the attempts to set */ public void setAttempts(int attempts) { this.attempts = attempts; } + /** * @param passingYards the passingYards to set */ public void setPassingYards(int passingYards) { this.passingYards = passingYards; } + /** * @param passingTd the passingTd to set */ public void setPassingTd(int passingTd) { this.passingTd = passingTd; } + /** * @param interceptions the interceptions to set */ public void setInterceptions(int interceptions) { this.interceptions = interceptions; } + /** * @param rushes the rushes to set */ public void setRushes(int rushes) { this.rushes = rushes; } + /** * @param rushYards the rushYards to set */ public void setRushYards(int rushYards) { this.rushYards = rushYards; } + /** * @param receptions the receptions to set */ public void setReceptions(int receptions) { this.receptions = receptions; } + /** * @param receptionYards the receptionYards to set */ public void setReceptionYards(int receptionYards) { this.receptionYards = receptionYards; } + /** * @param totalTd the totalTd to set */ public void setTotalTd(int totalTd) { this.totalTd = totalTd; } - - + @Override public String toString() { - return "Game: ID=" + id + " " + team + " vs. " + opponent + - " - " + year; + return "Game: ID=" + id + " " + team + " vs. " + opponent + " - " + year; } @Override @@ -232,6 +274,7 @@ public class Game implements Serializable { result = prime * result + ((id == null) ? 0 : id.hashCode()); return result; } + @Override public boolean equals(Object obj) { if (this == obj) { @@ -255,5 +298,5 @@ public class Game implements Serializable { return true; } - + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/Player.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/Player.java index ac13f7c4c..92a2c6a7c 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/Player.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/Player.java @@ -20,63 +20,72 @@ import java.io.Serializable; @SuppressWarnings("serial") public class Player implements Serializable { - - private String id; - private String lastName; - private String firstName; - private String position; - private int birthYear; + + private String id; + + private String lastName; + + private String firstName; + + private String position; + + private int birthYear; + private int debutYear; - + @Override public String toString() { - - return "PLAYER:id=" + id + ",Last Name=" + lastName + - ",First Name=" + firstName + ",Position=" + position + - ",Birth Year=" + birthYear + ",DebutYear=" + - debutYear; + + return "PLAYER:id=" + id + ",Last Name=" + lastName + ",First Name=" + firstName + ",Position=" + position + + ",Birth Year=" + birthYear + ",DebutYear=" + debutYear; } - + public String getId() { return id; } + public String getLastName() { return lastName; } + public String getFirstName() { return firstName; } + public String getPosition() { return position; } + public int getBirthYear() { return birthYear; } + public int getDebutYear() { return debutYear; } + public void setId(String id) { this.id = id; } + public void setLastName(String lastName) { this.lastName = lastName; } + public void setFirstName(String firstName) { this.firstName = firstName; } + public void setPosition(String position) { this.position = position; } + public void setBirthYear(int birthYear) { this.birthYear = birthYear; } + public void setDebutYear(int debutYear) { this.debutYear = debutYear; } - - - - - } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/PlayerDao.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/PlayerDao.java index 8fd687fc3..4f72f8652 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/PlayerDao.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/PlayerDao.java @@ -16,11 +16,11 @@ package org.springframework.batch.sample.domain.football; - /** * Interface for writing {@link Player} objects to arbitrary output. */ public interface PlayerDao { void savePlayer(Player player); + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/PlayerSummary.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/PlayerSummary.java index f92d96d9d..e27775813 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/PlayerSummary.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/PlayerSummary.java @@ -16,103 +16,137 @@ package org.springframework.batch.sample.domain.football; /** - * Domain object representing the summary of a given Player's - * year. - * + * Domain object representing the summary of a given Player's year. + * * @author Lucas Ward */ public class PlayerSummary { + private String id; + private int year; + private int completes; + private int attempts; + private int passingYards; + private int passingTd; + private int interceptions; + private int rushes; + private int rushYards; + private int receptions; + private int receptionYards; + private int totalTd; - + public String getId() { return id; } + public void setId(String id) { this.id = id; } + public int getYear() { return year; } + public void setYear(int year) { this.year = year; } + public int getCompletes() { return completes; } + public void setCompletes(int completes) { this.completes = completes; } + public int getAttempts() { return attempts; } + public void setAttempts(int attempts) { this.attempts = attempts; } + public int getPassingYards() { return passingYards; } + public void setPassingYards(int passingYards) { this.passingYards = passingYards; } + public int getPassingTd() { return passingTd; } + public void setPassingTd(int passingTd) { this.passingTd = passingTd; } + public int getInterceptions() { return interceptions; } + public void setInterceptions(int interceptions) { this.interceptions = interceptions; } + public int getRushes() { return rushes; } + public void setRushes(int rushes) { this.rushes = rushes; } + public int getRushYards() { return rushYards; } + public void setRushYards(int rushYards) { this.rushYards = rushYards; } + public int getReceptions() { return receptions; } + public void setReceptions(int receptions) { this.receptions = receptions; } + public int getReceptionYards() { return receptionYards; } + public void setReceptionYards(int receptionYards) { this.receptionYards = receptionYards; } + public int getTotalTd() { return totalTd; } + public void setTotalTd(int totalTd) { this.totalTd = totalTd; } @Override public String toString() { - return "Player Summary: ID=" + id + " Year=" + year + "[" + completes + ";" + attempts + ";" + passingYards + - ";" + passingTd + ";" + interceptions + ";" + rushes + ";" + rushYards + ";" + receptions + - ";" + receptionYards + ";" + totalTd; + return "Player Summary: ID=" + id + " Year=" + year + "[" + completes + ";" + attempts + ";" + passingYards + + ";" + passingTd + ";" + interceptions + ";" + rushes + ";" + rushYards + ";" + receptions + ";" + + receptionYards + ";" + totalTd; } @Override @@ -146,4 +180,5 @@ public class PlayerSummary { return true; } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/FootballExceptionHandler.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/FootballExceptionHandler.java index 420dd450d..90f8861f0 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/FootballExceptionHandler.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/FootballExceptionHandler.java @@ -23,16 +23,15 @@ import org.springframework.batch.repeat.exception.ExceptionHandler; public class FootballExceptionHandler implements ExceptionHandler { - private static final Log logger = LogFactory - .getLog(FootballExceptionHandler.class); + private static final Log logger = LogFactory.getLog(FootballExceptionHandler.class); @Override - public void handleException(RepeatContext context, Throwable throwable) - throws Throwable { + public void handleException(RepeatContext context, Throwable throwable) throws Throwable { if (!(throwable instanceof NumberFormatException)) { throw throwable; - } else { + } + else { logger.error("Number Format Exception!", throwable); } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/GameFieldSetMapper.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/GameFieldSetMapper.java index 0851e650b..4e0d44e24 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/GameFieldSetMapper.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/GameFieldSetMapper.java @@ -24,11 +24,11 @@ public class GameFieldSetMapper implements FieldSetMapper { @Override public Game mapFieldSet(FieldSet fs) { - - if(fs == null){ + + if (fs == null) { return null; } - + Game game = new Game(); game.setId(fs.readString("id")); game.setYear(fs.readInt("year")); @@ -45,7 +45,7 @@ public class GameFieldSetMapper implements FieldSetMapper { game.setReceptions(fs.readInt("receptions", 0)); game.setReceptionYards(fs.readInt("receptionYards")); game.setTotalTd(fs.readInt("totalTd")); - + return game; } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/JdbcGameDao.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/JdbcGameDao.java index c0215e4ba..5eac26b36 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/JdbcGameDao.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/JdbcGameDao.java @@ -42,14 +42,14 @@ public class JdbcGameDao extends JdbcDaoSupport implements ItemWriter { for (Game game : games) { - SqlParameterSource values = new MapSqlParameterSource().addValue("player_id", game.getId()).addValue( - "year_no", game.getYear()).addValue("team", game.getTeam()).addValue("week", game.getWeek()) - .addValue("opponent", game.getOpponent()).addValue("completes", game.getCompletes()).addValue( - "attempts", game.getAttempts()).addValue("passing_yards", game.getPassingYards()).addValue( - "passing_td", game.getPassingTd()).addValue("interceptions", game.getInterceptions()) - .addValue("rushes", game.getRushes()).addValue("rush_yards", game.getRushYards()).addValue( - "receptions", game.getReceptions()).addValue("receptions_yards", game.getReceptionYards()) - .addValue("total_td", game.getTotalTd()); + SqlParameterSource values = new MapSqlParameterSource().addValue("player_id", game.getId()) + .addValue("year_no", game.getYear()).addValue("team", game.getTeam()) + .addValue("week", game.getWeek()).addValue("opponent", game.getOpponent()) + .addValue("completes", game.getCompletes()).addValue("attempts", game.getAttempts()) + .addValue("passing_yards", game.getPassingYards()).addValue("passing_td", game.getPassingTd()) + .addValue("interceptions", game.getInterceptions()).addValue("rushes", game.getRushes()) + .addValue("rush_yards", game.getRushYards()).addValue("receptions", game.getReceptions()) + .addValue("receptions_yards", game.getReceptionYards()).addValue("total_td", game.getTotalTd()); this.insertGame.execute(values); } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/JdbcPlayerDao.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/JdbcPlayerDao.java index 179186e1f..ecc0260b5 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/JdbcPlayerDao.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/JdbcPlayerDao.java @@ -28,20 +28,20 @@ import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; * @author Lucas Ward * */ -public class JdbcPlayerDao implements PlayerDao { +public class JdbcPlayerDao implements PlayerDao { - public static final String INSERT_PLAYER = - "INSERT into PLAYERS (player_id, last_name, first_name, pos, year_of_birth, year_drafted)" + - " values (:id, :lastName, :firstName, :position, :birthYear, :debutYear)"; + public static final String INSERT_PLAYER = "INSERT into PLAYERS (player_id, last_name, first_name, pos, year_of_birth, year_drafted)" + + " values (:id, :lastName, :firstName, :position, :birthYear, :debutYear)"; - private NamedParameterJdbcOperations namedParameterJdbcTemplate; + private NamedParameterJdbcOperations namedParameterJdbcTemplate; - @Override + @Override public void savePlayer(Player player) { - namedParameterJdbcTemplate.update(INSERT_PLAYER, new BeanPropertySqlParameterSource(player)); + namedParameterJdbcTemplate.update(INSERT_PLAYER, new BeanPropertySqlParameterSource(player)); + } + + public void setDataSource(DataSource dataSource) { + this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource); } - public void setDataSource(DataSource dataSource) { - this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource); - } } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/JdbcPlayerSummaryDao.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/JdbcPlayerSummaryDao.java index 270713707..3ebf7707e 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/JdbcPlayerSummaryDao.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/JdbcPlayerSummaryDao.java @@ -33,26 +33,27 @@ public class JdbcPlayerSummaryDao implements ItemWriter { + "values(:id, :year, :completes, :attempts, :passingYards, :passingTd, " + ":interceptions, :rushes, :rushYards, :receptions, :receptionYards, :totalTd)"; - private NamedParameterJdbcOperations namedParameterJdbcTemplate; + private NamedParameterJdbcOperations namedParameterJdbcTemplate; @Override public void write(List summaries) { for (PlayerSummary summary : summaries) { - MapSqlParameterSource args = new MapSqlParameterSource().addValue("id", summary.getId()).addValue("year", - summary.getYear()).addValue("completes", summary.getCompletes()).addValue("attempts", - summary.getAttempts()).addValue("passingYards", summary.getPassingYards()).addValue("passingTd", - summary.getPassingTd()).addValue("interceptions", summary.getInterceptions()).addValue("rushes", - summary.getRushes()).addValue("rushYards", summary.getRushYards()).addValue("receptions", - summary.getReceptions()).addValue("receptionYards", summary.getReceptionYards()).addValue( - "totalTd", summary.getTotalTd()); + MapSqlParameterSource args = new MapSqlParameterSource().addValue("id", summary.getId()) + .addValue("year", summary.getYear()).addValue("completes", summary.getCompletes()) + .addValue("attempts", summary.getAttempts()).addValue("passingYards", summary.getPassingYards()) + .addValue("passingTd", summary.getPassingTd()).addValue("interceptions", summary.getInterceptions()) + .addValue("rushes", summary.getRushes()).addValue("rushYards", summary.getRushYards()) + .addValue("receptions", summary.getReceptions()) + .addValue("receptionYards", summary.getReceptionYards()).addValue("totalTd", summary.getTotalTd()); - namedParameterJdbcTemplate.update(INSERT_SUMMARY, args); + namedParameterJdbcTemplate.update(INSERT_SUMMARY, args); } } - public void setDataSource(DataSource dataSource) { - this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource); - } + public void setDataSource(DataSource dataSource) { + this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource); + } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerFieldSetMapper.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerFieldSetMapper.java index 536608517..8b9a545db 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerFieldSetMapper.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerFieldSetMapper.java @@ -24,11 +24,11 @@ public class PlayerFieldSetMapper implements FieldSetMapper { @Override public Player mapFieldSet(FieldSet fs) { - - if(fs == null){ + + if (fs == null) { return null; } - + Player player = new Player(); player.setId(fs.readString("ID")); player.setLastName(fs.readString("lastName")); @@ -36,9 +36,8 @@ public class PlayerFieldSetMapper implements FieldSetMapper { player.setPosition(fs.readString("position")); player.setDebutYear(fs.readInt("debutYear")); player.setBirthYear(fs.readInt("birthYear")); - + return player; } - } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerSummaryMapper.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerSummaryMapper.java index 27c48f820..1dc5b0078 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerSummaryMapper.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerSummaryMapper.java @@ -22,22 +22,25 @@ import org.springframework.batch.sample.domain.football.PlayerSummary; import org.springframework.jdbc.core.RowMapper; /** - * RowMapper used to map a ResultSet to a {@link org.springframework.batch.sample.domain.football.PlayerSummary} - * + * RowMapper used to map a ResultSet to a + * {@link org.springframework.batch.sample.domain.football.PlayerSummary} + * * @author Lucas Ward * @author Mahmoud Ben Hassine * */ public class PlayerSummaryMapper implements RowMapper { - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.springframework.jdbc.core.RowMapper#mapRow(java.sql.ResultSet, int) */ @Override public PlayerSummary mapRow(ResultSet rs, int rowNum) throws SQLException { - + PlayerSummary summary = new PlayerSummary(); - + summary.setId(rs.getString(1)); summary.setYear(rs.getInt(2)); summary.setCompletes(rs.getInt(3)); @@ -50,7 +53,7 @@ public class PlayerSummaryMapper implements RowMapper { summary.setReceptions(rs.getInt(10)); summary.setReceptionYards(rs.getInt(11)); summary.setTotalTd(rs.getInt(12)); - + return summary; } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerSummaryRowMapper.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerSummaryRowMapper.java index 96cde00f7..33eb01cd4 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerSummaryRowMapper.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/football/internal/PlayerSummaryRowMapper.java @@ -22,22 +22,25 @@ import org.springframework.batch.sample.domain.football.PlayerSummary; import org.springframework.jdbc.core.RowMapper; /** - * RowMapper used to map a ResultSet to a {@link org.springframework.batch.sample.domain.football.PlayerSummary} - * + * RowMapper used to map a ResultSet to a + * {@link org.springframework.batch.sample.domain.football.PlayerSummary} + * * @author Lucas Ward * @author Mahmoud Ben Hassine * */ public class PlayerSummaryRowMapper implements RowMapper { - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.springframework.jdbc.core.RowMapper#mapRow(java.sql.ResultSet, int) */ @Override public PlayerSummary mapRow(ResultSet rs, int rowNum) throws SQLException { - + PlayerSummary summary = new PlayerSummary(); - + summary.setId(rs.getString(1)); summary.setYear(rs.getInt(2)); summary.setCompletes(rs.getInt(3)); @@ -50,7 +53,7 @@ public class PlayerSummaryRowMapper implements RowMapper { summary.setReceptions(rs.getInt(10)); summary.setReceptionYards(rs.getInt(11)); summary.setTotalTd(rs.getInt(12)); - + return summary; } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/mail/User.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/mail/User.java index b9817a28a..9066ebc15 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/mail/User.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/mail/User.java @@ -18,44 +18,47 @@ package org.springframework.batch.sample.domain.mail; /** * @author Dan Garrette * @author Dave Syer - * * @since 2.1 */ public class User { - private int id; - private String name; - private String email; - public User() { - } + private int id; - public User( int id, String name, String email ) { - this.id = id; - this.name = name; - this.email = email; - } + private String name; - public int getId() { - return id; - } + private String email; - public void setId( int id ) { - this.id = id; - } + public User() { + } - public String getName() { - return name; - } + public User(int id, String name, String email) { + this.id = id; + this.name = name; + this.email = email; + } - public void setName( String name ) { - this.name = name; - } + public int getId() { + return id; + } - public String getEmail() { - return email; - } + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } - public void setEmail( String email ) { - this.email = email; - } } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/mail/internal/TestMailErrorHandler.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/mail/internal/TestMailErrorHandler.java index 405d0beee..37b7ae0b6 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/mail/internal/TestMailErrorHandler.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/mail/internal/TestMailErrorHandler.java @@ -18,23 +18,21 @@ package org.springframework.batch.sample.domain.mail.internal; import java.util.ArrayList; import java.util.List; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.batch.item.mail.MailErrorHandler; import org.springframework.mail.MailMessage; /** - * This handler prints out failed messages with their exceptions. It also - * maintains a list of all failed messages it receives for lookup later by an - * assertion. - * + * This handler prints out failed messages with their exceptions. It also maintains a list + * of all failed messages it receives for lookup later by an assertion. + * * @author Dan Garrette * @author Dave Syer - * * @since 2.1 */ public class TestMailErrorHandler implements MailErrorHandler { + private static final Log LOGGER = LogFactory.getLog(TestMailErrorHandler.class); private List failedMessages = new ArrayList<>(); @@ -52,4 +50,5 @@ public class TestMailErrorHandler implements MailErrorHandler { public void clear() { this.failedMessages.clear(); } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/mail/internal/TestMailSender.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/mail/internal/TestMailSender.java index bf763a807..30ba0a298 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/mail/internal/TestMailSender.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/mail/internal/TestMailSender.java @@ -31,7 +31,6 @@ import org.springframework.mail.SimpleMailMessage; * @author Dan Garrette * @author Dave Syer * @author Mahmoud Ben Hassine - * * @since 2.1 */ public class TestMailSender implements MailSender { diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/mail/internal/UserMailItemProcessor.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/mail/internal/UserMailItemProcessor.java index 347c40059..8aefc9058 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/mail/internal/UserMailItemProcessor.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/mail/internal/UserMailItemProcessor.java @@ -25,24 +25,23 @@ import org.springframework.mail.SimpleMailMessage; /** * @author Dan Garrette * @author Dave Syer - * * @since 2.1 */ -public class UserMailItemProcessor implements - ItemProcessor { +public class UserMailItemProcessor implements ItemProcessor { - /** - * @see org.springframework.batch.item.ItemProcessor#process(java.lang.Object) - */ - @Nullable + /** + * @see org.springframework.batch.item.ItemProcessor#process(java.lang.Object) + */ + @Nullable @Override - public SimpleMailMessage process( User user ) throws Exception { - SimpleMailMessage message = new SimpleMailMessage(); - message.setTo( user.getEmail() ); - message.setFrom( "communications@thecompany.com" ); - message.setSubject( user.getName() + "'s Account Info" ); - message.setSentDate( new Date() ); - message.setText( "Hello " + user.getName() ); - return message; - } + public SimpleMailMessage process(User user) throws Exception { + SimpleMailMessage message = new SimpleMailMessage(); + message.setTo(user.getEmail()); + message.setFrom("communications@thecompany.com"); + message.setSubject(user.getName() + "'s Account Info"); + message.setSentDate(new Date()); + message.setText("Hello " + user.getName()); + return message; + } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/multiline/AggregateItem.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/multiline/AggregateItem.java index 2820d415f..0318ee021 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/multiline/AggregateItem.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/multiline/AggregateItem.java @@ -16,15 +16,15 @@ package org.springframework.batch.sample.domain.multiline; /** - * A wrapper type for an item that is used by {@link AggregateItemReader} to - * identify the start and end of an aggregate record. - * + * A wrapper type for an item that is used by {@link AggregateItemReader} to identify the + * start and end of an aggregate record. + * * @see AggregateItemReader - * * @author Dave Syer - * + * */ public class AggregateItem { + @SuppressWarnings("rawtypes") private static final AggregateItem FOOTER = new AggregateItem(false, true) { @Override @@ -81,7 +81,6 @@ public class AggregateItem { /** * Accessor for the wrapped item. - * * @return the wrapped item * @throws IllegalStateException if called on a record for which either * {@link #isHeader()} or {@link #isFooter()} answers true. diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/multiline/AggregateItemFieldSetMapper.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/multiline/AggregateItemFieldSetMapper.java index 51cc52ed3..5fe6427df 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/multiline/AggregateItemFieldSetMapper.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/multiline/AggregateItemFieldSetMapper.java @@ -22,12 +22,11 @@ import org.springframework.util.Assert; import org.springframework.validation.BindException; /** - * Delegating mapper to convert form a vanilla {@link FieldSetMapper} to one - * that returns {@link AggregateItem} instances for consumption by the - * {@link AggregateItemReader}. - * + * Delegating mapper to convert form a vanilla {@link FieldSetMapper} to one that returns + * {@link AggregateItem} instances for consumption by the {@link AggregateItemReader}. + * * @author Dave Syer - * + * */ public class AggregateItemFieldSetMapper implements FieldSetMapper>, InitializingBean { @@ -46,10 +45,8 @@ public class AggregateItemFieldSetMapper implements FieldSetMapper implements FieldSetMapper implements FieldSetMapperis*().

      - * - * This class is thread-safe (it can be used concurrently by multiple threads) - * as long as the {@link ItemReader} is also thread-safe. - * + * An {@link ItemReader} that delivers a list as its item, storing up objects from the + * injected {@link ItemReader} until they are ready to be packed out as a collection. This + * class must be used as a wrapper for a custom {@link ItemReader} that can identify the + * record boundaries. The custom reader should mark the beginning and end of records by + * returning an {@link AggregateItem} which responds true to its query methods + * is*().
      + *
      + * + * This class is thread-safe (it can be used concurrently by multiple threads) as long as + * the {@link ItemReader} is also thread-safe. + * * @see AggregateItem#isHeader() * @see AggregateItem#isFooter() - * * @author Dave Syer - * + * */ public class AggregateItemReader implements ItemReader> { + private static final Log LOG = LogFactory.getLog(AggregateItemReader.class); private ItemReader> itemReader; @@ -102,14 +102,15 @@ public class AggregateItemReader implements ItemReader> { } /** - * Private class for temporary state management while item is being - * collected. - * + * Private class for temporary state management while item is being collected. + * * @author Dave Syer - * + * */ private class ResultHolder { + private List records = new ArrayList<>(); + private boolean exhausted = false; public List getRecords() { @@ -127,5 +128,7 @@ public class AggregateItemReader implements ItemReader> { public void setExhausted(boolean exhausted) { this.exhausted = exhausted; } + } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/Address.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/Address.java index f9ad86a95..f50b023fb 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/Address.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/Address.java @@ -17,6 +17,7 @@ package org.springframework.batch.sample.domain.order; public class Address { + public static final String LINE_ID_BILLING_ADDR = "BAD"; public static final String LINE_ID_SHIPPING_ADDR = "SAD"; @@ -146,4 +147,5 @@ public class Address { return true; } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/BillingInfo.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/BillingInfo.java index 971fa4bcc..796ba0e20 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/BillingInfo.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/BillingInfo.java @@ -16,8 +16,8 @@ package org.springframework.batch.sample.domain.order; - public class BillingInfo { + public static final String LINE_ID_BILLING_INFO = "BIN"; private String paymentId; @@ -85,4 +85,5 @@ public class BillingInfo { return true; } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/Customer.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/Customer.java index 523165070..4f0400344 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/Customer.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/Customer.java @@ -16,8 +16,8 @@ package org.springframework.batch.sample.domain.order; - public class Customer { + public static final String LINE_ID_BUSINESS_CUST = "BCU"; public static final String LINE_ID_NON_BUSINESS_CUST = "NCU"; diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/LineItem.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/LineItem.java index 3e90916cf..f587ab505 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/LineItem.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/LineItem.java @@ -19,80 +19,88 @@ package org.springframework.batch.sample.domain.order; import java.math.BigDecimal; public class LineItem { - public static final String LINE_ID_ITEM = "LIT"; - private long itemId; - private BigDecimal price; - private BigDecimal discountPerc; - private BigDecimal discountAmount; - private BigDecimal shippingPrice; - private BigDecimal handlingPrice; - private int quantity; - private BigDecimal totalPrice; + public static final String LINE_ID_ITEM = "LIT"; - public BigDecimal getDiscountAmount() { - return discountAmount; - } + private long itemId; - public void setDiscountAmount(BigDecimal discountAmount) { - this.discountAmount = discountAmount; - } + private BigDecimal price; - public BigDecimal getDiscountPerc() { - return discountPerc; - } + private BigDecimal discountPerc; - public void setDiscountPerc(BigDecimal discountPerc) { - this.discountPerc = discountPerc; - } + private BigDecimal discountAmount; - public BigDecimal getHandlingPrice() { - return handlingPrice; - } + private BigDecimal shippingPrice; - public void setHandlingPrice(BigDecimal handlingPrice) { - this.handlingPrice = handlingPrice; - } + private BigDecimal handlingPrice; - public long getItemId() { - return itemId; - } + private int quantity; - public void setItemId(long itemId) { - this.itemId = itemId; - } + private BigDecimal totalPrice; - public BigDecimal getPrice() { - return price; - } + public BigDecimal getDiscountAmount() { + return discountAmount; + } - public void setPrice(BigDecimal price) { - this.price = price; - } + public void setDiscountAmount(BigDecimal discountAmount) { + this.discountAmount = discountAmount; + } - public int getQuantity() { - return quantity; - } + public BigDecimal getDiscountPerc() { + return discountPerc; + } - public void setQuantity(int quantity) { - this.quantity = quantity; - } + public void setDiscountPerc(BigDecimal discountPerc) { + this.discountPerc = discountPerc; + } - public BigDecimal getShippingPrice() { - return shippingPrice; - } + public BigDecimal getHandlingPrice() { + return handlingPrice; + } - public void setShippingPrice(BigDecimal shippingPrice) { - this.shippingPrice = shippingPrice; - } + public void setHandlingPrice(BigDecimal handlingPrice) { + this.handlingPrice = handlingPrice; + } - public BigDecimal getTotalPrice() { - return totalPrice; - } + public long getItemId() { + return itemId; + } - public void setTotalPrice(BigDecimal totalPrice) { - this.totalPrice = totalPrice; - } + public void setItemId(long itemId) { + this.itemId = itemId; + } + + public BigDecimal getPrice() { + return price; + } + + public void setPrice(BigDecimal price) { + this.price = price; + } + + public int getQuantity() { + return quantity; + } + + public void setQuantity(int quantity) { + this.quantity = quantity; + } + + public BigDecimal getShippingPrice() { + return shippingPrice; + } + + public void setShippingPrice(BigDecimal shippingPrice) { + this.shippingPrice = shippingPrice; + } + + public BigDecimal getTotalPrice() { + return totalPrice; + } + + public void setTotalPrice(BigDecimal totalPrice) { + this.totalPrice = totalPrice; + } @Override public String toString() { @@ -134,4 +142,5 @@ public class LineItem { return true; } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/Order.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/Order.java index e5fa9ee97..f2bb615a9 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/Order.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/Order.java @@ -21,6 +21,7 @@ import java.util.Date; import java.util.List; public class Order { + public static final String LINE_ID_HEADER = "HEA"; public static final String LINE_ID_FOOTER = "FOT"; @@ -250,4 +251,5 @@ public class Order { return true; } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/ShippingInfo.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/ShippingInfo.java index 51aeb8c92..623401800 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/ShippingInfo.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/ShippingInfo.java @@ -16,8 +16,8 @@ package org.springframework.batch.sample.domain.order; - public class ShippingInfo { + public static final String LINE_ID_SHIPPING_INFO = "SIN"; private String shipperId; @@ -99,4 +99,5 @@ public class ShippingInfo { return true; } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/OrderItemReader.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/OrderItemReader.java index b358434ed..ad9086dfd 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/OrderItemReader.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/OrderItemReader.java @@ -33,9 +33,10 @@ import org.springframework.lang.Nullable; /** * @author peter.zozom - * + * */ public class OrderItemReader implements ItemReader { + private static Log log = LogFactory.getLog(OrderItemReader.class); private Order order; @@ -153,7 +154,7 @@ public class OrderItemReader implements ItemReader { /** * @param fieldSetReader reads lines from the file converting them to - * {@link FieldSet}. + * {@link FieldSet}. */ public void setFieldSetReader(ItemReader
      fieldSetReader) { this.fieldSetReader = fieldSetReader; diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/OrderLineAggregator.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/OrderLineAggregator.java index 9991b54c5..dbb5c4c3c 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/OrderLineAggregator.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/OrderLineAggregator.java @@ -24,7 +24,7 @@ import org.springframework.batch.sample.domain.order.Order; /** * Converts Order object to a list of strings. - * + * * @author Dave Syer * @author Dan Garrette */ @@ -54,9 +54,8 @@ public class OrderLineAggregator implements LineAggregator { /** * Set aggregators for all types of lines in the output file - * * @param aggregators Map of LineAggregators used to map the various record types for - * each order + * each order */ public void setAggregators(Map> aggregators) { this.aggregators = aggregators; diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/extractor/AddressFieldExtractor.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/extractor/AddressFieldExtractor.java index 0b61d84fd..66faab80a 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/extractor/AddressFieldExtractor.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/extractor/AddressFieldExtractor.java @@ -1,34 +1,34 @@ -/* - * Copyright 2009-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.sample.domain.order.internal.extractor; - -import org.springframework.batch.item.file.transform.FieldExtractor; -import org.springframework.batch.sample.domain.order.Address; -import org.springframework.batch.sample.domain.order.Order; - -/** - * @author Dan Garrette - * @since 2.0.1 - */ -public class AddressFieldExtractor implements FieldExtractor { - - @Override - public Object[] extract(Order order) { - Address address = order.getBillingAddress(); - return new Object[] { "ADDRESS:", address.getAddrLine1(), address.getCity(), address.getZipCode() }; - } - -} +/* + * Copyright 2009-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.sample.domain.order.internal.extractor; + +import org.springframework.batch.item.file.transform.FieldExtractor; +import org.springframework.batch.sample.domain.order.Address; +import org.springframework.batch.sample.domain.order.Order; + +/** + * @author Dan Garrette + * @since 2.0.1 + */ +public class AddressFieldExtractor implements FieldExtractor { + + @Override + public Object[] extract(Order order) { + Address address = order.getBillingAddress(); + return new Object[] { "ADDRESS:", address.getAddrLine1(), address.getCity(), address.getZipCode() }; + } + +} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/extractor/BillingInfoFieldExtractor.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/extractor/BillingInfoFieldExtractor.java index d2f94e7f6..320f8cc86 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/extractor/BillingInfoFieldExtractor.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/extractor/BillingInfoFieldExtractor.java @@ -1,34 +1,34 @@ -/* - * Copyright 2009-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.sample.domain.order.internal.extractor; - -import org.springframework.batch.item.file.transform.FieldExtractor; -import org.springframework.batch.sample.domain.order.BillingInfo; -import org.springframework.batch.sample.domain.order.Order; - -/** - * @author Dan Garrette - * @since 2.0.1 - */ -public class BillingInfoFieldExtractor implements FieldExtractor { - - @Override - public Object[] extract(Order order) { - BillingInfo billingInfo = order.getBilling(); - return new Object[] { "BILLING:", billingInfo.getPaymentId(), billingInfo.getPaymentDesc() }; - } - -} +/* + * Copyright 2009-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.sample.domain.order.internal.extractor; + +import org.springframework.batch.item.file.transform.FieldExtractor; +import org.springframework.batch.sample.domain.order.BillingInfo; +import org.springframework.batch.sample.domain.order.Order; + +/** + * @author Dan Garrette + * @since 2.0.1 + */ +public class BillingInfoFieldExtractor implements FieldExtractor { + + @Override + public Object[] extract(Order order) { + BillingInfo billingInfo = order.getBilling(); + return new Object[] { "BILLING:", billingInfo.getPaymentId(), billingInfo.getPaymentDesc() }; + } + +} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/extractor/CustomerFieldExtractor.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/extractor/CustomerFieldExtractor.java index 3411cd88b..28a3df132 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/extractor/CustomerFieldExtractor.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/extractor/CustomerFieldExtractor.java @@ -1,39 +1,39 @@ -/* - * Copyright 2009-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.sample.domain.order.internal.extractor; - -import org.springframework.batch.item.file.transform.FieldExtractor; -import org.springframework.batch.sample.domain.order.Customer; -import org.springframework.batch.sample.domain.order.Order; - -/** - * @author Dan Garrette - * @since 2.0.1 - */ -public class CustomerFieldExtractor implements FieldExtractor { - - @Override - public Object[] extract(Order order) { - Customer customer = order.getCustomer(); - return new Object[] { "CUSTOMER:", customer.getRegistrationId(), emptyIfNull(customer.getFirstName()), - emptyIfNull(customer.getMiddleName()), emptyIfNull(customer.getLastName()) }; - } - - private String emptyIfNull(String s) { - return s != null ? s : ""; - } - -} +/* + * Copyright 2009-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.sample.domain.order.internal.extractor; + +import org.springframework.batch.item.file.transform.FieldExtractor; +import org.springframework.batch.sample.domain.order.Customer; +import org.springframework.batch.sample.domain.order.Order; + +/** + * @author Dan Garrette + * @since 2.0.1 + */ +public class CustomerFieldExtractor implements FieldExtractor { + + @Override + public Object[] extract(Order order) { + Customer customer = order.getCustomer(); + return new Object[] { "CUSTOMER:", customer.getRegistrationId(), emptyIfNull(customer.getFirstName()), + emptyIfNull(customer.getMiddleName()), emptyIfNull(customer.getLastName()) }; + } + + private String emptyIfNull(String s) { + return s != null ? s : ""; + } + +} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/extractor/FooterFieldExtractor.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/extractor/FooterFieldExtractor.java index 6937c490d..a67ed0501 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/extractor/FooterFieldExtractor.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/extractor/FooterFieldExtractor.java @@ -1,32 +1,32 @@ -/* - * Copyright 2009-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.sample.domain.order.internal.extractor; - -import org.springframework.batch.item.file.transform.FieldExtractor; -import org.springframework.batch.sample.domain.order.Order; - -/** - * @author Dan Garrette - * @since 2.0.1 - */ -public class FooterFieldExtractor implements FieldExtractor { - - @Override - public Object[] extract(Order order) { - return new Object[] { "END_ORDER:", order.getTotalPrice() }; - } - -} +/* + * Copyright 2009-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.sample.domain.order.internal.extractor; + +import org.springframework.batch.item.file.transform.FieldExtractor; +import org.springframework.batch.sample.domain.order.Order; + +/** + * @author Dan Garrette + * @since 2.0.1 + */ +public class FooterFieldExtractor implements FieldExtractor { + + @Override + public Object[] extract(Order order) { + return new Object[] { "END_ORDER:", order.getTotalPrice() }; + } + +} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/extractor/HeaderFieldExtractor.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/extractor/HeaderFieldExtractor.java index 4497e3af1..bc8cebda4 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/extractor/HeaderFieldExtractor.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/extractor/HeaderFieldExtractor.java @@ -1,34 +1,36 @@ -/* - * Copyright 2009-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.sample.domain.order.internal.extractor; - -import java.text.SimpleDateFormat; - -import org.springframework.batch.item.file.transform.FieldExtractor; -import org.springframework.batch.sample.domain.order.Order; - -/** - * @author Dan Garrette - * @since 2.0.1 - */ -public class HeaderFieldExtractor implements FieldExtractor { - private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd"); - - @Override - public Object[] extract(Order order) { - return new Object[] { "BEGIN_ORDER:", order.getOrderId(), dateFormat.format(order.getOrderDate()) }; - } -} +/* + * Copyright 2009-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.sample.domain.order.internal.extractor; + +import java.text.SimpleDateFormat; + +import org.springframework.batch.item.file.transform.FieldExtractor; +import org.springframework.batch.sample.domain.order.Order; + +/** + * @author Dan Garrette + * @since 2.0.1 + */ +public class HeaderFieldExtractor implements FieldExtractor { + + private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd"); + + @Override + public Object[] extract(Order order) { + return new Object[] { "BEGIN_ORDER:", order.getOrderId(), dateFormat.format(order.getOrderDate()) }; + } + +} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/extractor/LineItemFieldExtractor.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/extractor/LineItemFieldExtractor.java index abbf93d57..951ccc280 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/extractor/LineItemFieldExtractor.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/extractor/LineItemFieldExtractor.java @@ -1,32 +1,32 @@ -/* - * Copyright 2009-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.sample.domain.order.internal.extractor; - -import org.springframework.batch.item.file.transform.FieldExtractor; -import org.springframework.batch.sample.domain.order.LineItem; - -/** - * @author Dan Garrette - * @since 2.0.1 - */ -public class LineItemFieldExtractor implements FieldExtractor { - - @Override - public Object[] extract(LineItem item) { - return new Object[] { "ITEM:", item.getItemId(), item.getPrice() }; - } - -} +/* + * Copyright 2009-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.sample.domain.order.internal.extractor; + +import org.springframework.batch.item.file.transform.FieldExtractor; +import org.springframework.batch.sample.domain.order.LineItem; + +/** + * @author Dan Garrette + * @since 2.0.1 + */ +public class LineItemFieldExtractor implements FieldExtractor { + + @Override + public Object[] extract(LineItem item) { + return new Object[] { "ITEM:", item.getItemId(), item.getPrice() }; + } + +} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/mapper/AddressFieldSetMapper.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/mapper/AddressFieldSetMapper.java index 9c82cd4d1..475e359c8 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/mapper/AddressFieldSetMapper.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/mapper/AddressFieldSetMapper.java @@ -23,11 +23,17 @@ import org.springframework.batch.sample.domain.order.Address; public class AddressFieldSetMapper implements FieldSetMapper
      { public static final String ADDRESSEE_COLUMN = "ADDRESSEE"; + public static final String ADDRESS_LINE1_COLUMN = "ADDR_LINE1"; + public static final String ADDRESS_LINE2_COLUMN = "ADDR_LINE2"; + public static final String CITY_COLUMN = "CITY"; + public static final String ZIP_CODE_COLUMN = "ZIP_CODE"; + public static final String STATE_COLUMN = "STATE"; + public static final String COUNTRY_COLUMN = "COUNTRY"; @Override @@ -44,4 +50,5 @@ public class AddressFieldSetMapper implements FieldSetMapper
      { return address; } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/mapper/BillingFieldSetMapper.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/mapper/BillingFieldSetMapper.java index e86e11d17..60e2145fb 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/mapper/BillingFieldSetMapper.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/mapper/BillingFieldSetMapper.java @@ -23,6 +23,7 @@ import org.springframework.batch.sample.domain.order.BillingInfo; public class BillingFieldSetMapper implements FieldSetMapper { public static final String PAYMENT_TYPE_ID_COLUMN = "PAYMENT_TYPE_ID"; + public static final String PAYMENT_DESC_COLUMN = "PAYMENT_DESC"; @Override @@ -34,4 +35,5 @@ public class BillingFieldSetMapper implements FieldSetMapper { return info; } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/mapper/CustomerFieldSetMapper.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/mapper/CustomerFieldSetMapper.java index d4149d769..b691a81e8 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/mapper/CustomerFieldSetMapper.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/mapper/CustomerFieldSetMapper.java @@ -23,13 +23,21 @@ import org.springframework.batch.sample.domain.order.Customer; public class CustomerFieldSetMapper implements FieldSetMapper { public static final String LINE_ID_COLUMN = "LINE_ID"; + public static final String COMPANY_NAME_COLUMN = "COMPANY_NAME"; + public static final String LAST_NAME_COLUMN = "LAST_NAME"; + public static final String FIRST_NAME_COLUMN = "FIRST_NAME"; + public static final String MIDDLE_NAME_COLUMN = "MIDDLE_NAME"; + public static final String TRUE_SYMBOL = "T"; + public static final String REGISTERED_COLUMN = "REGISTERED"; + public static final String REG_ID_COLUMN = "REG_ID"; + public static final String VIP_COLUMN = "VIP"; @Override @@ -54,4 +62,5 @@ public class CustomerFieldSetMapper implements FieldSetMapper { return customer; } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/mapper/HeaderFieldSetMapper.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/mapper/HeaderFieldSetMapper.java index 1410ce7d2..a978d1145 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/mapper/HeaderFieldSetMapper.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/mapper/HeaderFieldSetMapper.java @@ -23,6 +23,7 @@ import org.springframework.batch.sample.domain.order.Order; public class HeaderFieldSetMapper implements FieldSetMapper { public static final String ORDER_ID_COLUMN = "ORDER_ID"; + public static final String ORDER_DATE_COLUMN = "ORDER_DATE"; @Override @@ -33,4 +34,5 @@ public class HeaderFieldSetMapper implements FieldSetMapper { return order; } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/mapper/OrderItemFieldSetMapper.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/mapper/OrderItemFieldSetMapper.java index f738ec339..3029ee964 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/mapper/OrderItemFieldSetMapper.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/mapper/OrderItemFieldSetMapper.java @@ -23,12 +23,19 @@ import org.springframework.batch.sample.domain.order.LineItem; public class OrderItemFieldSetMapper implements FieldSetMapper { public static final String TOTAL_PRICE_COLUMN = "TOTAL_PRICE"; + public static final String QUANTITY_COLUMN = "QUANTITY"; + public static final String HANDLING_PRICE_COLUMN = "HANDLING_PRICE"; + public static final String SHIPPING_PRICE_COLUMN = "SHIPPING_PRICE"; + public static final String DISCOUNT_AMOUNT_COLUMN = "DISCOUNT_AMOUNT"; + public static final String DISCOUNT_PERC_COLUMN = "DISCOUNT_PERC"; + public static final String PRICE_COLUMN = "PRICE"; + public static final String ITEM_ID_COLUMN = "ITEM_ID"; @Override @@ -46,4 +53,5 @@ public class OrderItemFieldSetMapper implements FieldSetMapper { return item; } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/mapper/ShippingFieldSetMapper.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/mapper/ShippingFieldSetMapper.java index 9b4526807..7a6daeea1 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/mapper/ShippingFieldSetMapper.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/mapper/ShippingFieldSetMapper.java @@ -23,7 +23,9 @@ import org.springframework.batch.sample.domain.order.ShippingInfo; public class ShippingFieldSetMapper implements FieldSetMapper { public static final String ADDITIONAL_SHIPPING_INFO_COLUMN = "ADDITIONAL_SHIPPING_INFO"; + public static final String SHIPPING_TYPE_ID_COLUMN = "SHIPPING_TYPE_ID"; + public static final String SHIPPER_ID_COLUMN = "SHIPPER_ID"; @Override @@ -36,4 +38,5 @@ public class ShippingFieldSetMapper implements FieldSetMapper { return info; } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/validator/OrderValidator.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/validator/OrderValidator.java index c7801cc78..0f6e4ab90 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/validator/OrderValidator.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/validator/OrderValidator.java @@ -34,13 +34,21 @@ import org.springframework.validation.Validator; public class OrderValidator implements Validator { private static final List CARD_TYPES = new ArrayList<>(); + private static final List SHIPPER_IDS = new ArrayList<>(); + private static final List SHIPPER_TYPES = new ArrayList<>(); + private static final long MAX_ID = 9999999999L; + private static final BigDecimal BD_MIN = new BigDecimal("0.0"); + private static final BigDecimal BD_MAX = new BigDecimal("99999999.99"); + private static final BigDecimal BD_PERC_MAX = new BigDecimal("100.0"); + private static final int MAX_QUANTITY = 9999; + private static final BigDecimal BD_100 = new BigDecimal("100.00"); static { @@ -71,11 +79,12 @@ public class OrderValidator implements Validator { Order item = null; try { item = (Order) arg0; - } catch (ClassCastException cce) { + } + catch (ClassCastException cce) { errors.reject("Incorrect type"); } - if(item != null) { + if (item != null) { validateOrder(item, errors); validateCustomer(item.getCustomer(), errors); validateAddress(item.getBillingAddress(), errors, "billingAddress"); @@ -96,34 +105,45 @@ public class OrderValidator implements Validator { boolean totalPrices = true; for (LineItem lineItem : lineItems) { - if(lineItem.getItemId() <= 0 || lineItem.getItemId() > MAX_ID) { + if (lineItem.getItemId() <= 0 || lineItem.getItemId() > MAX_ID) { ids = false; } - if((BD_MIN.compareTo(lineItem.getPrice()) > 0) || (BD_MAX.compareTo(lineItem.getPrice()) < 0)) { + if ((BD_MIN.compareTo(lineItem.getPrice()) > 0) || (BD_MAX.compareTo(lineItem.getPrice()) < 0)) { prices = false; } if (BD_MIN.compareTo(lineItem.getDiscountPerc()) != 0) { - //DiscountPerc must be between 0.0 and 100.0 + // DiscountPerc must be between 0.0 and 100.0 if ((BD_MIN.compareTo(lineItem.getDiscountPerc()) > 0) || (BD_PERC_MAX.compareTo(lineItem.getDiscountPerc()) < 0) - || (BD_MIN.compareTo(lineItem.getDiscountAmount()) != 0)) { //only one of DiscountAmount and DiscountPerc should be non-zero + || (BD_MIN.compareTo(lineItem.getDiscountAmount()) != 0)) { // only + // one + // of + // DiscountAmount + // and + // DiscountPerc + // should + // be + // non-zero discounts = false; } - } else { - //DiscountAmount must be between 0.0 and item.price + } + else { + // DiscountAmount must be between 0.0 and item.price if ((BD_MIN.compareTo(lineItem.getDiscountAmount()) > 0) || (lineItem.getPrice().compareTo(lineItem.getDiscountAmount()) < 0)) { discounts = false; } } - if ((BD_MIN.compareTo(lineItem.getShippingPrice()) > 0) || (BD_MAX.compareTo(lineItem.getShippingPrice()) < 0)) { + if ((BD_MIN.compareTo(lineItem.getShippingPrice()) > 0) + || (BD_MAX.compareTo(lineItem.getShippingPrice()) < 0)) { shippingPrices = false; } - if ((BD_MIN.compareTo(lineItem.getHandlingPrice()) > 0) || (BD_MAX.compareTo(lineItem.getHandlingPrice()) < 0)) { + if ((BD_MIN.compareTo(lineItem.getHandlingPrice()) > 0) + || (BD_MAX.compareTo(lineItem.getHandlingPrice()) < 0)) { handlingPrices = false; } @@ -131,33 +151,29 @@ public class OrderValidator implements Validator { quantities = false; } - - if ((BD_MIN.compareTo(lineItem.getTotalPrice()) > 0) - || (BD_MAX.compareTo(lineItem.getTotalPrice()) < 0)) { + if ((BD_MIN.compareTo(lineItem.getTotalPrice()) > 0) || (BD_MAX.compareTo(lineItem.getTotalPrice()) < 0)) { totalPrices = false; } - //calculate total price + // calculate total price - //discount coefficient = (100.00 - discountPerc) / 100.00 - BigDecimal coef = BD_100.subtract(lineItem.getDiscountPerc()) - .divide(BD_100, 4, RoundingMode.HALF_UP); + // discount coefficient = (100.00 - discountPerc) / 100.00 + BigDecimal coef = BD_100.subtract(lineItem.getDiscountPerc()).divide(BD_100, 4, RoundingMode.HALF_UP); - //discountedPrice = (price * coefficient) - discountAmount - //at least one of discountPerc and discountAmount is 0 - this is validated by ValidateDiscountsFunction - BigDecimal discountedPrice = lineItem.getPrice().multiply(coef) - .subtract(lineItem.getDiscountAmount()); + // discountedPrice = (price * coefficient) - discountAmount + // at least one of discountPerc and discountAmount is 0 - this is validated by + // ValidateDiscountsFunction + BigDecimal discountedPrice = lineItem.getPrice().multiply(coef).subtract(lineItem.getDiscountAmount()); - //price for single item = discountedPrice + shipping + handling + // price for single item = discountedPrice + shipping + handling BigDecimal singleItemPrice = discountedPrice.add(lineItem.getShippingPrice()) .add(lineItem.getHandlingPrice()); - //total price = singleItemPrice * quantity + // total price = singleItemPrice * quantity BigDecimal quantity = new BigDecimal(lineItem.getQuantity()); - BigDecimal totalPrice = singleItemPrice.multiply(quantity) - .setScale(2, RoundingMode.HALF_UP); + BigDecimal totalPrice = singleItemPrice.multiply(quantity).setScale(2, RoundingMode.HALF_UP); - //calculatedPrice should equal to item.totalPrice + // calculatedPrice should equal to item.totalPrice if (totalPrice.compareTo(lineItem.getTotalPrice()) != 0) { totalPrices = false; } @@ -165,126 +181,132 @@ public class OrderValidator implements Validator { String lineItemsFieldName = "lineItems"; - if(!ids) { + if (!ids) { errors.rejectValue(lineItemsFieldName, "error.lineitems.id"); } - if(!prices) { + if (!prices) { errors.rejectValue(lineItemsFieldName, "error.lineitems.price"); } - if(!discounts) { + if (!discounts) { errors.rejectValue(lineItemsFieldName, "error.lineitems.discount"); } - if(!shippingPrices) { + if (!shippingPrices) { errors.rejectValue(lineItemsFieldName, "error.lineitems.shipping"); } - if(!handlingPrices) { + if (!handlingPrices) { errors.rejectValue(lineItemsFieldName, "error.lineitems.handling"); } - if(!quantities) { + if (!quantities) { errors.rejectValue(lineItemsFieldName, "error.lineitems.quantity"); } - if(!totalPrices) { + if (!totalPrices) { errors.rejectValue(lineItemsFieldName, "error.lineitems.totalprice"); } } protected void validateShipping(ShippingInfo shipping, Errors errors) { - if(!SHIPPER_IDS.contains(shipping.getShipperId())) { + if (!SHIPPER_IDS.contains(shipping.getShipperId())) { errors.rejectValue("shipping.shipperId", "error.shipping.shipper"); } - if(!SHIPPER_TYPES.contains(shipping.getShippingTypeId())) { + if (!SHIPPER_TYPES.contains(shipping.getShippingTypeId())) { errors.rejectValue("shipping.shippingTypeId", "error.shipping.type"); } - if(StringUtils.hasText(shipping.getShippingInfo())) { - validateStringLength(shipping.getShippingInfo(), errors, "shipping.shippingInfo", "error.shipping.shippinginfo.length", 100); + if (StringUtils.hasText(shipping.getShippingInfo())) { + validateStringLength(shipping.getShippingInfo(), errors, "shipping.shippingInfo", + "error.shipping.shippinginfo.length", 100); } } protected void validatePayment(BillingInfo billing, Errors errors) { - if(!CARD_TYPES.contains(billing.getPaymentId())) { + if (!CARD_TYPES.contains(billing.getPaymentId())) { errors.rejectValue("billing.paymentId", "error.billing.type"); } - if(!billing.getPaymentDesc().matches("[A-Z]{4}-[0-9]{10,11}")) { + if (!billing.getPaymentDesc().matches("[A-Z]{4}-[0-9]{10,11}")) { errors.rejectValue("billing.paymentDesc", "error.billing.desc"); } } - protected void validateAddress(Address address, Errors errors, - String prefix) { - if(address != null) { - if(StringUtils.hasText(address.getAddressee())) { - validateStringLength(address.getAddressee(), errors, prefix + ".addressee", "error.baddress.addresse.length", 60); + protected void validateAddress(Address address, Errors errors, String prefix) { + if (address != null) { + if (StringUtils.hasText(address.getAddressee())) { + validateStringLength(address.getAddressee(), errors, prefix + ".addressee", + "error.baddress.addresse.length", 60); } - validateStringLength(address.getAddrLine1(), errors, prefix + ".addrLine1", "error.baddress.addrline1.length", 50); + validateStringLength(address.getAddrLine1(), errors, prefix + ".addrLine1", + "error.baddress.addrline1.length", 50); - if(StringUtils.hasText(address.getAddrLine2())) { - validateStringLength(address.getAddrLine2(), errors, prefix + ".addrLine2", "error.baddress.addrline2.length", 50); + if (StringUtils.hasText(address.getAddrLine2())) { + validateStringLength(address.getAddrLine2(), errors, prefix + ".addrLine2", + "error.baddress.addrline2.length", 50); } validateStringLength(address.getCity(), errors, prefix + ".city", "error.baddress.city.length", 30); validateStringLength(address.getZipCode(), errors, prefix + ".zipCode", "error.baddress.zipcode.length", 5); - if(StringUtils.hasText(address.getZipCode()) && !address.getZipCode().matches("[0-9]{5}")) { + if (StringUtils.hasText(address.getZipCode()) && !address.getZipCode().matches("[0-9]{5}")) { errors.rejectValue(prefix + ".zipCode", "error.baddress.zipcode.format"); } - if((!StringUtils.hasText(address.getState()) && ("United States".equals(address.getCountry())) || StringUtils.hasText(address.getState()) && address.getState().length() != 2)) { + if ((!StringUtils.hasText(address.getState()) && ("United States".equals(address.getCountry())) + || StringUtils.hasText(address.getState()) && address.getState().length() != 2)) { errors.rejectValue(prefix + ".state", "error.baddress.state.length"); } - validateStringLength(address.getCountry(), errors, prefix + ".country", "error.baddress.country.length", 50); + validateStringLength(address.getCountry(), errors, prefix + ".country", "error.baddress.country.length", + 50); } } - protected void validateStringLength(String string, Errors errors, - String field, String message, int length) { - if(!StringUtils.hasText(string) || string.length() > length) { + protected void validateStringLength(String string, Errors errors, String field, String message, int length) { + if (!StringUtils.hasText(string) || string.length() > length) { errors.rejectValue(field, message); } } protected void validateCustomer(Customer customer, Errors errors) { - if(!customer.isRegistered() && customer.isBusinessCustomer()) { + if (!customer.isRegistered() && customer.isBusinessCustomer()) { errors.rejectValue("customer.registered", "error.customer.registration"); } - if(!StringUtils.hasText(customer.getCompanyName()) && customer.isBusinessCustomer()) { + if (!StringUtils.hasText(customer.getCompanyName()) && customer.isBusinessCustomer()) { errors.rejectValue("customer.companyName", "error.customer.companyname"); } - if(!StringUtils.hasText(customer.getFirstName()) && !customer.isBusinessCustomer()) { + if (!StringUtils.hasText(customer.getFirstName()) && !customer.isBusinessCustomer()) { errors.rejectValue("customer.firstName", "error.customer.firstname"); } - if(!StringUtils.hasText(customer.getLastName()) && !customer.isBusinessCustomer()) { + if (!StringUtils.hasText(customer.getLastName()) && !customer.isBusinessCustomer()) { errors.rejectValue("customer.lastName", "error.customer.lastname"); } - if(customer.isRegistered() && (customer.getRegistrationId() < 0 || customer.getRegistrationId() >= 99999999L)) { + if (customer.isRegistered() + && (customer.getRegistrationId() < 0 || customer.getRegistrationId() >= 99999999L)) { errors.rejectValue("customer.registrationId", "error.customer.registrationid"); } } protected void validateOrder(Order item, Errors errors) { - if(item.getOrderId() < 0 || item.getOrderId() > 9999999999L) { + if (item.getOrderId() < 0 || item.getOrderId() > 9999999999L) { errors.rejectValue("orderId", "error.order.id"); } - if(new Date().compareTo(item.getOrderDate()) < 0) { + if (new Date().compareTo(item.getOrderDate()) < 0) { errors.rejectValue("orderDate", "error.order.date.future"); } - if(item.getLineItems() != null && item.getTotalLines() != item.getLineItems().size()) { + if (item.getLineItems() != null && item.getTotalLines() != item.getLineItems().size()) { errors.rejectValue("totalLines", "error.order.lines.badcount"); } } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/xml/Customer.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/xml/Customer.java index 2d711fd4d..69b08bf6f 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/xml/Customer.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/xml/Customer.java @@ -18,10 +18,11 @@ package org.springframework.batch.sample.domain.order.internal.xml; /** * An XML customer. - * + * * This is a complex type. */ public class Customer { + private String name; private String address; diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/xml/LineItem.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/xml/LineItem.java index 5a497431b..83f0fd56c 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/xml/LineItem.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/xml/LineItem.java @@ -16,47 +16,51 @@ package org.springframework.batch.sample.domain.order.internal.xml; - /** * An XML line-item. * * This is a complex type. */ public class LineItem { - private String description; - private double perUnitOunces; - private double price; - private int quantity; - public String getDescription() { - return description; - } + private String description; - public void setDescription(String description) { - this.description = description; - } + private double perUnitOunces; - public double getPerUnitOunces() { - return perUnitOunces; - } + private double price; - public void setPerUnitOunces(double perUnitOunces) { - this.perUnitOunces = perUnitOunces; - } + private int quantity; - public double getPrice() { - return price; - } + public String getDescription() { + return description; + } - public void setPrice(double price) { - this.price = price; - } + public void setDescription(String description) { + this.description = description; + } - public int getQuantity() { - return quantity; - } + public double getPerUnitOunces() { + return perUnitOunces; + } + + public void setPerUnitOunces(double perUnitOunces) { + this.perUnitOunces = perUnitOunces; + } + + public double getPrice() { + return price; + } + + public void setPrice(double price) { + this.price = price; + } + + public int getQuantity() { + return quantity; + } + + public void setQuantity(int quantity) { + this.quantity = quantity; + } - public void setQuantity(int quantity) { - this.quantity = quantity; - } } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/xml/Order.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/xml/Order.java index 0e076b09a..cd51369d1 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/xml/Order.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/xml/Order.java @@ -21,10 +21,11 @@ import java.util.List; /** * An XML order. - * + * * This is a complex type. */ public class Order { + private Customer customer; private Date date; diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/xml/Shipper.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/xml/Shipper.java index 5761515ee..9fe8905f5 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/xml/Shipper.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/xml/Shipper.java @@ -16,29 +16,31 @@ package org.springframework.batch.sample.domain.order.internal.xml; - /** * An XML shipper. * * This is a complex type. */ public class Shipper { - private String name; - private double perOunceRate; - public String getName() { - return name; - } + private String name; - public void setName(String name) { - this.name = name; - } + private double perOunceRate; - public double getPerOunceRate() { - return perOunceRate; - } + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public double getPerOunceRate() { + return perOunceRate; + } + + public void setPerOunceRate(double perOunceRate) { + this.perOunceRate = perOunceRate; + } - public void setPerOunceRate(double perOunceRate) { - this.perOunceRate = perOunceRate; - } } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/person/Child.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/person/Child.java index 8abea70db..d6d444857 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/person/Child.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/person/Child.java @@ -16,13 +16,14 @@ package org.springframework.batch.sample.domain.person; public class Child { + private String name; - - public void setName(String name){ + + public void setName(String name) { this.name = name; } - - public String getName(){ + + public String getName() { return name; } @@ -66,4 +67,5 @@ public class Child { return true; } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/person/Person.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/person/Person.java index 3430a33bd..f9babfab4 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/person/Person.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/person/Person.java @@ -22,11 +22,17 @@ import java.util.List; import org.springframework.batch.sample.domain.order.Address; public class Person { + private String title = ""; + private String firstName = ""; + private String last_name = ""; + private int age = 0; + private Address address = new Address(); + private List children = new ArrayList<>(); public Person() { @@ -206,4 +212,5 @@ public class Person { return true; } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/person/PersonService.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/person/PersonService.java index 78b45b69f..590f2b57d 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/person/PersonService.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/person/PersonService.java @@ -25,15 +25,17 @@ import org.springframework.batch.sample.domain.order.Address; * Custom class that contains logic that would normally be be contained in * {@link org.springframework.batch.item.ItemReader} and * {@link org.springframework.batch.item.ItemWriter}. - * + * * @author tomas.slanina * @author Robert Kasanicky * @author Mahmoud Ben Hassine */ public class PersonService { + private static final int GENERATION_LIMIT = 10; private int generatedCounter = 0; + private int processedCounter = 0; public Person getData() { @@ -62,8 +64,8 @@ public class PersonService { } /* - * Badly designed method signature which accepts multiple implicitly related - * arguments instead of a single Person argument. + * Badly designed method signature which accepts multiple implicitly related arguments + * instead of a single Person argument. */ public void processPerson(String name, String city) { processedCounter++; @@ -76,4 +78,5 @@ public class PersonService { public int getReceivedCount() { return processedCounter; } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/person/internal/PersonWriter.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/person/internal/PersonWriter.java index 2400d7846..4e402fae1 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/person/internal/PersonWriter.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/person/internal/PersonWriter.java @@ -24,12 +24,14 @@ import org.springframework.batch.item.ItemWriter; import org.springframework.batch.sample.domain.person.Person; public class PersonWriter implements ItemWriter { - private static Log log = LogFactory.getLog(PersonWriter.class); - - @Override + + private static Log log = LogFactory.getLog(PersonWriter.class); + + @Override public void write(List data) { - if (log.isDebugEnabled()) { - log.debug("Processing: " + data); - } - } + if (log.isDebugEnabled()) { + log.debug("Processing: " + data); + } + } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/CompositeCustomerUpdateLineTokenizer.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/CompositeCustomerUpdateLineTokenizer.java index fed1bbfe3..7923b1c31 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/CompositeCustomerUpdateLineTokenizer.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/CompositeCustomerUpdateLineTokenizer.java @@ -23,11 +23,11 @@ import org.springframework.batch.item.file.transform.LineTokenizer; import org.springframework.lang.Nullable; /** - * Composite {@link LineTokenizer} that delegates the tokenization of a line to one of two potential - * tokenizers. The file format in this case uses one character, either F, A, U, or D to indicate - * whether or not the line is an a footer record, or a customer add, update, or delete, and - * will delegate accordingly. - * + * Composite {@link LineTokenizer} that delegates the tokenization of a line to one of two + * potential tokenizers. The file format in this case uses one character, either F, A, U, + * or D to indicate whether or not the line is an a footer record, or a customer add, + * update, or delete, and will delegate accordingly. + * * @author Lucas Ward * @author Mahmoud Ben Hassine * @since 2.0 @@ -35,62 +35,69 @@ import org.springframework.lang.Nullable; public class CompositeCustomerUpdateLineTokenizer implements StepExecutionListener, LineTokenizer { private LineTokenizer customerTokenizer; + private LineTokenizer footerTokenizer; + private StepExecution stepExecution; - - /* (non-Javadoc) - * @see org.springframework.batch.item.file.transform.LineTokenizer#tokenize(java.lang.String) + + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.item.file.transform.LineTokenizer#tokenize(java.lang. + * String) */ @Override public FieldSet tokenize(@Nullable String line) { - - if(line.charAt(0) == 'F'){ - //line starts with F, so the footer tokenizer should tokenize it. + + if (line.charAt(0) == 'F') { + // line starts with F, so the footer tokenizer should tokenize it. FieldSet fs = footerTokenizer.tokenize(line); long customerUpdateTotal = stepExecution.getReadCount(); long fileUpdateTotal = fs.readLong(1); - if(customerUpdateTotal != fileUpdateTotal){ - throw new IllegalStateException("The total number of customer updates in the file footer does not match the " + - "number entered File footer total: [" + fileUpdateTotal + "] Total encountered during processing: [" + - customerUpdateTotal + "]"); + if (customerUpdateTotal != fileUpdateTotal) { + throw new IllegalStateException( + "The total number of customer updates in the file footer does not match the " + + "number entered File footer total: [" + fileUpdateTotal + + "] Total encountered during processing: [" + customerUpdateTotal + "]"); } - else{ - //return null, because the footer indicates an end of processing. + else { + // return null, because the footer indicates an end of processing. return null; } } - else if(line.charAt(0) == 'A' || line.charAt(0) == 'U' || line.charAt(0) == 'D'){ - //line starts with A,U, or D, so it must be a customer operation. + else if (line.charAt(0) == 'A' || line.charAt(0) == 'U' || line.charAt(0) == 'D') { + // line starts with A,U, or D, so it must be a customer operation. return customerTokenizer.tokenize(line); } - else{ - //If the line doesn't start with any of the characters above, it must obviously be invalid. + else { + // If the line doesn't start with any of the characters above, it must + // obviously be invalid. throw new IllegalArgumentException("Invalid line encountered for tokenizing: " + line); } } - + @Override public void beforeStep(StepExecution stepExecution) { this.stepExecution = stepExecution; } /** - * Set the {@link LineTokenizer} that will be used to tokenize any lines that begin with - * A, U, or D, and are thus a customer operation. - * + * Set the {@link LineTokenizer} that will be used to tokenize any lines that begin + * with A, U, or D, and are thus a customer operation. * @param customerTokenizer tokenizer to delegate to for customer operation records */ public void setCustomerTokenizer(LineTokenizer customerTokenizer) { this.customerTokenizer = customerTokenizer; } - + /** - * Set the {@link LineTokenizer} that will be used to tokenize any lines that being with - * F and is thus a footer record. - * + * Set the {@link LineTokenizer} that will be used to tokenize any lines that being + * with F and is thus a footer record. * @param footerTokenizer tokenizer to delegate to for footer records */ public void setFooterTokenizer(LineTokenizer footerTokenizer) { this.footerTokenizer = footerTokenizer; } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/CustomerCreditDao.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/CustomerCreditDao.java index 4147d096a..114476a80 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/CustomerCreditDao.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/CustomerCreditDao.java @@ -16,7 +16,6 @@ package org.springframework.batch.sample.domain.trade; - /** * Interface for writing customer's credit information to output. * diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/CustomerDao.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/CustomerDao.java index 3612c46d0..6b88a01cd 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/CustomerDao.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/CustomerDao.java @@ -27,6 +27,7 @@ public interface CustomerDao { CustomerCredit getCustomerByName(String name); void insertCustomer(String name, BigDecimal credit); - + void updateCustomer(String name, BigDecimal credit); + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/CustomerDebit.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/CustomerDebit.java index 48979adbc..350a77251 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/CustomerDebit.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/CustomerDebit.java @@ -18,39 +18,40 @@ package org.springframework.batch.sample.domain.trade; import java.math.BigDecimal; - public class CustomerDebit { - private String name; - private BigDecimal debit; - public CustomerDebit() { - } + private String name; - CustomerDebit(String name, BigDecimal debit) { - this.name = name; - this.debit = debit; - } + private BigDecimal debit; - public BigDecimal getDebit() { - return debit; - } + public CustomerDebit() { + } - public void setDebit(BigDecimal debit) { - this.debit = debit; - } + CustomerDebit(String name, BigDecimal debit) { + this.name = name; + this.debit = debit; + } - public String getName() { - return name; - } + public BigDecimal getDebit() { + return debit; + } - public void setName(String name) { - this.name = name; - } + public void setDebit(BigDecimal debit) { + this.debit = debit; + } - @Override + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override public String toString() { - return "CustomerDebit [name=" + name + ", debit=" + debit + "]"; - } + return "CustomerDebit [name=" + name + ", debit=" + debit + "]"; + } @Override public int hashCode() { @@ -92,4 +93,5 @@ public class CustomerDebit { return true; } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/CustomerDebitDao.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/CustomerDebitDao.java index 2ff153302..8d1b26d09 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/CustomerDebitDao.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/CustomerDebitDao.java @@ -16,13 +16,13 @@ package org.springframework.batch.sample.domain.trade; - /** * Interface for writing {@link CustomerDebitDao} object to arbitrary output. - * + * * @author Robert.Kasanicky */ public interface CustomerDebitDao { void write(CustomerDebit customerDebit); + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/CustomerOperation.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/CustomerOperation.java index 40d229fc0..87f1e64c2 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/CustomerOperation.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/CustomerOperation.java @@ -20,39 +20,41 @@ import java.util.HashMap; import java.util.Map; /** - * Enum representing on of 3 possible actions on a customer update: - * Add, update, or delete - * + * Enum representing on of 3 possible actions on a customer update: Add, update, or delete + * * @author Lucas Ward * */ public enum CustomerOperation { + ADD('A'), UPDATE('U'), DELETE('D'); - + private final char code; - private static final Map CODE_MAP; - + + private static final Map CODE_MAP; + private CustomerOperation(char code) { this.code = code; } - - static{ + + static { CODE_MAP = new HashMap<>(); - for(CustomerOperation operation:values()){ + for (CustomerOperation operation : values()) { CODE_MAP.put(operation.getCode(), operation); } } - - public static CustomerOperation fromCode(char code){ - if(CODE_MAP.containsKey(code)){ + + public static CustomerOperation fromCode(char code) { + if (CODE_MAP.containsKey(code)) { return CODE_MAP.get(code); } - else{ + else { throw new IllegalArgumentException("Invalid code: [" + code + "]"); } } - + public char getCode() { return code; } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/CustomerUpdate.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/CustomerUpdate.java index 6559e090b..86b215755 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/CustomerUpdate.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/CustomerUpdate.java @@ -19,21 +19,24 @@ package org.springframework.batch.sample.domain.trade; import java.math.BigDecimal; /** - * Immutable Value Object representing an update to the customer as stored in the database. - * This object has the customer name, credit amount, and the operation to be performed - * on them. In the case of an add, a new customer will be entered with the appropriate - * credit. In the case of an update, the customer's credit is considered an absolute update. - * Deletes are currently not supported, but can still be read in from a file. - * + * Immutable Value Object representing an update to the customer as stored in the + * database. This object has the customer name, credit amount, and the operation to be + * performed on them. In the case of an add, a new customer will be entered with the + * appropriate credit. In the case of an update, the customer's credit is considered an + * absolute update. Deletes are currently not supported, but can still be read in from a + * file. + * * @author Lucas Ward * @since 2.0 */ public class CustomerUpdate { private final CustomerOperation operation; + private final String customerName; + private final BigDecimal credit; - + public CustomerUpdate(CustomerOperation operation, String customerName, BigDecimal credit) { this.operation = operation; this.customerName = customerName; @@ -51,9 +54,11 @@ public class CustomerUpdate { public BigDecimal getCredit() { return credit; } - + @Override public String toString() { - return "Customer Update, name: [" + customerName + "], operation: [" + operation + "], credit: [" + credit + "]"; + return "Customer Update, name: [" + customerName + "], operation: [" + operation + "], credit: [" + credit + + "]"; } + } \ No newline at end of file diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/CustomerUpdateProcessor.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/CustomerUpdateProcessor.java index 7ffe0df4e..e41e86d19 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/CustomerUpdateProcessor.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/CustomerUpdateProcessor.java @@ -25,52 +25,53 @@ import org.springframework.lang.Nullable; * @author Lucas Ward * */ -public class CustomerUpdateProcessor implements ItemProcessor{ +public class CustomerUpdateProcessor implements ItemProcessor { private CustomerDao customerDao; + private InvalidCustomerLogger invalidCustomerLogger; - + @Nullable @Override public CustomerUpdate process(CustomerUpdate item) throws Exception { - - if(item.getOperation() == DELETE){ - //delete is not supported + + if (item.getOperation() == DELETE) { + // delete is not supported invalidCustomerLogger.log(item); return null; } - + CustomerCredit customerCredit = customerDao.getCustomerByName(item.getCustomerName()); - - if(item.getOperation() == ADD && customerCredit == null){ + + if (item.getOperation() == ADD && customerCredit == null) { return item; } - else if(item.getOperation() == ADD && customerCredit != null){ - //veto processing + else if (item.getOperation() == ADD && customerCredit != null) { + // veto processing invalidCustomerLogger.log(item); return null; } - - if(item.getOperation() == UPDATE && customerCredit != null){ + + if (item.getOperation() == UPDATE && customerCredit != null) { return item; } - else if(item.getOperation() == UPDATE && customerCredit == null){ - //veto processing + else if (item.getOperation() == UPDATE && customerCredit == null) { + // veto processing invalidCustomerLogger.log(item); return null; } - - //if an item makes it through all these checks it can be assumed to be bad, logged, and skipped + + // if an item makes it through all these checks it can be assumed to be bad, + // logged, and skipped invalidCustomerLogger.log(item); return null; } - + public void setCustomerDao(CustomerDao customerDao) { this.customerDao = customerDao; } - - public void setInvalidCustomerLogger( - InvalidCustomerLogger invalidCustomerLogger) { + + public void setInvalidCustomerLogger(InvalidCustomerLogger invalidCustomerLogger) { this.invalidCustomerLogger = invalidCustomerLogger; } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/CustomerUpdateWriter.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/CustomerUpdateWriter.java index 3a9d0f99f..03b0fc078 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/CustomerUpdateWriter.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/CustomerUpdateWriter.java @@ -27,21 +27,21 @@ import org.springframework.batch.item.ItemWriter; public class CustomerUpdateWriter implements ItemWriter { private CustomerDao customerDao; - + @Override public void write(List items) throws Exception { - for(CustomerUpdate customerUpdate : items){ - if(customerUpdate.getOperation() == CustomerOperation.ADD){ + for (CustomerUpdate customerUpdate : items) { + if (customerUpdate.getOperation() == CustomerOperation.ADD) { customerDao.insertCustomer(customerUpdate.getCustomerName(), customerUpdate.getCredit()); } - else if(customerUpdate.getOperation() == CustomerOperation.UPDATE){ + else if (customerUpdate.getOperation() == CustomerOperation.UPDATE) { customerDao.updateCustomer(customerUpdate.getCustomerName(), customerUpdate.getCredit()); } } - - //flush and/or clear resources + + // flush and/or clear resources } - + public void setCustomerDao(CustomerDao customerDao) { this.customerDao = customerDao; } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/InvalidCustomerLogger.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/InvalidCustomerLogger.java index 111df2538..f9c2cb986 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/InvalidCustomerLogger.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/InvalidCustomerLogger.java @@ -17,15 +17,14 @@ package org.springframework.batch.sample.domain.trade; /** - * Interface for logging invalid customers. Customers may need to be logged because - * they already existed when attempted to be added. Or a non existent customer was - * updated. - * + * Interface for logging invalid customers. Customers may need to be logged because they + * already existed when attempted to be added. Or a non existent customer was updated. + * * @author Lucas Ward * */ public interface InvalidCustomerLogger { void log(CustomerUpdate customerUpdate); - + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/Trade.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/Trade.java index e31d16d33..5d7c112f7 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/Trade.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/Trade.java @@ -19,41 +19,46 @@ package org.springframework.batch.sample.domain.trade; import java.io.Serializable; import java.math.BigDecimal; - /** * @author Rob Harrop * @author Dave Syer */ @SuppressWarnings("serial") public class Trade implements Serializable { - private String isin = ""; - private long quantity = 0; - private BigDecimal price = BigDecimal.ZERO; - private String customer = ""; + + private String isin = ""; + + private long quantity = 0; + + private BigDecimal price = BigDecimal.ZERO; + + private String customer = ""; + private Long id; + private long version = 0; - public Trade() { - } - - public Trade(String isin, long quantity, BigDecimal price, String customer){ - this.isin = isin; - this.quantity = quantity; - this.price = price; - this.customer = customer; - } + public Trade() { + } - /** + public Trade(String isin, long quantity, BigDecimal price, String customer) { + this.isin = isin; + this.quantity = quantity; + this.price = price; + this.customer = customer; + } + + /** * @param id id of the trade */ public Trade(long id) { this.id = id; } - + public long getId() { return id; } - + public void setId(long id) { this.id = id; } @@ -83,26 +88,26 @@ public class Trade implements Serializable { } public String getIsin() { - return isin; - } + return isin; + } - public BigDecimal getPrice() { - return price; - } + public BigDecimal getPrice() { + return price; + } - public long getQuantity() { - return quantity; - } + public long getQuantity() { + return quantity; + } - public String getCustomer() { - return customer; - } + public String getCustomer() { + return customer; + } - @Override + @Override public String toString() { - return "Trade: [isin=" + this.isin + ",quantity=" + this.quantity + ",price=" - + this.price + ",customer=" + this.customer + "]"; - } + return "Trade: [isin=" + this.isin + ",quantity=" + this.quantity + ",price=" + this.price + ",customer=" + + this.customer + "]"; + } @Override public int hashCode() { @@ -160,4 +165,5 @@ public class Trade implements Serializable { } return true; } - } + +} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/TradeDao.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/TradeDao.java index 9bc5d3135..ebf87d86b 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/TradeDao.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/TradeDao.java @@ -16,16 +16,16 @@ package org.springframework.batch.sample.domain.trade; - /** * Interface for writing a Trade object to an arbitrary output. - * + * * @author Robert Kasanicky */ public interface TradeDao { + /* - * Write a trade object to some kind of output, different implementations - * can write to file, database etc. + * Write a trade object to some kind of output, different implementations can write to + * file, database etc. */ void writeTrade(Trade trade); diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/CommonsLoggingInvalidCustomerLogger.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/CommonsLoggingInvalidCustomerLogger.java index fc402cc12..4d4a1bea6 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/CommonsLoggingInvalidCustomerLogger.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/CommonsLoggingInvalidCustomerLogger.java @@ -27,13 +27,18 @@ import org.springframework.batch.sample.domain.trade.InvalidCustomerLogger; * */ public class CommonsLoggingInvalidCustomerLogger implements InvalidCustomerLogger { + protected static final Log LOG = LogFactory.getLog(CommandLineJobRunner.class); - /* (non-Javadoc) - * @see org.springframework.batch.sample.domain.trade.InvalidCustomerLogger#log(org.springframework.batch.sample.domain.trade.CustomerUpdate) + /* + * (non-Javadoc) + * + * @see org.springframework.batch.sample.domain.trade.InvalidCustomerLogger#log(org. + * springframework.batch.sample.domain.trade.CustomerUpdate) */ @Override public void log(CustomerUpdate customerUpdate) { LOG.error("invalid customer encountered: [ " + customerUpdate + "]"); } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/CustomerCreditFieldSetMapper.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/CustomerCreditFieldSetMapper.java index 3e625e0a7..f71ceb100 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/CustomerCreditFieldSetMapper.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/CustomerCreditFieldSetMapper.java @@ -25,8 +25,11 @@ import org.springframework.batch.sample.domain.trade.CustomerCredit; * @since 2.0 */ public class CustomerCreditFieldSetMapper implements FieldSetMapper { + public static final int ID_COLUMN = 0; + public static final int NAME_COLUMN = 1; + public static final int CREDIT_COLUMN = 2; @Override @@ -38,4 +41,5 @@ public class CustomerCreditFieldSetMapper implements FieldSetMapper { + public static final BigDecimal FIXED_AMOUNT = new BigDecimal("5"); @Nullable @@ -35,4 +36,5 @@ public class CustomerCreditIncreaseProcessor implements ItemProcessor { diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/CustomerCreditRowMapper.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/CustomerCreditRowMapper.java index 0434ee58a..218047de8 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/CustomerCreditRowMapper.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/CustomerCreditRowMapper.java @@ -23,20 +23,22 @@ import org.springframework.batch.sample.domain.trade.CustomerCredit; import org.springframework.jdbc.core.RowMapper; public class CustomerCreditRowMapper implements RowMapper { - + public static final String ID_COLUMN = "id"; + public static final String NAME_COLUMN = "name"; + public static final String CREDIT_COLUMN = "credit"; @Override public CustomerCredit mapRow(ResultSet rs, int rowNum) throws SQLException { - CustomerCredit customerCredit = new CustomerCredit(); + CustomerCredit customerCredit = new CustomerCredit(); - customerCredit.setId(rs.getInt(ID_COLUMN)); - customerCredit.setName(rs.getString(NAME_COLUMN)); - customerCredit.setCredit(rs.getBigDecimal(CREDIT_COLUMN)); + customerCredit.setId(rs.getInt(ID_COLUMN)); + customerCredit.setName(rs.getString(NAME_COLUMN)); + customerCredit.setCredit(rs.getBigDecimal(CREDIT_COLUMN)); - return customerCredit; + return customerCredit; } } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/CustomerCreditUpdatePreparedStatementSetter.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/CustomerCreditUpdatePreparedStatementSetter.java index badb95379..3c10cd6f8 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/CustomerCreditUpdatePreparedStatementSetter.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/CustomerCreditUpdatePreparedStatementSetter.java @@ -28,14 +28,20 @@ import org.springframework.batch.sample.domain.trade.CustomerCredit; * */ public class CustomerCreditUpdatePreparedStatementSetter implements ItemPreparedStatementSetter { + public static final BigDecimal FIXED_AMOUNT = new BigDecimal(1000); - /* (non-Javadoc) - * @see org.springframework.batch.io.support.ItemPreparedStatementSetter#setValues(java.lang.Object, java.sql.PreparedStatement) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.io.support.ItemPreparedStatementSetter#setValues(java. + * lang.Object, java.sql.PreparedStatement) */ @Override public void setValues(CustomerCredit customerCredit, PreparedStatement ps) throws SQLException { ps.setBigDecimal(1, customerCredit.getCredit().add(FIXED_AMOUNT)); ps.setLong(2, customerCredit.getId()); } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/CustomerCreditUpdateWriter.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/CustomerCreditUpdateWriter.java index 3fdf66ec1..0058afeec 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/CustomerCreditUpdateWriter.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/CustomerCreditUpdateWriter.java @@ -23,6 +23,7 @@ import org.springframework.batch.sample.domain.trade.CustomerCredit; import org.springframework.batch.sample.domain.trade.CustomerCreditDao; public class CustomerCreditUpdateWriter implements ItemWriter { + private double creditFilter = 800; private CustomerCreditDao dao; @@ -43,4 +44,5 @@ public class CustomerCreditUpdateWriter implements ItemWriter { public void setDao(CustomerCreditDao dao) { this.dao = dao; } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/CustomerDebitRowMapper.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/CustomerDebitRowMapper.java index b4e84df5b..2cd5417fb 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/CustomerDebitRowMapper.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/CustomerDebitRowMapper.java @@ -22,20 +22,20 @@ import java.sql.SQLException; import org.springframework.batch.sample.domain.trade.CustomerDebit; import org.springframework.jdbc.core.RowMapper; - public class CustomerDebitRowMapper implements RowMapper { - + public static final String CUSTOMER_COLUMN = "customer"; + public static final String PRICE_COLUMN = "price"; - - @Override - public CustomerDebit mapRow(ResultSet rs, int ignoredRowNumber) - throws SQLException { - CustomerDebit customerDebit = new CustomerDebit(); - customerDebit.setName(rs.getString(CUSTOMER_COLUMN)); - customerDebit.setDebit(rs.getBigDecimal(PRICE_COLUMN)); + @Override + public CustomerDebit mapRow(ResultSet rs, int ignoredRowNumber) throws SQLException { + CustomerDebit customerDebit = new CustomerDebit(); + + customerDebit.setName(rs.getString(CUSTOMER_COLUMN)); + customerDebit.setDebit(rs.getBigDecimal(PRICE_COLUMN)); + + return customerDebit; + } - return customerDebit; - } } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/CustomerUpdateWriter.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/CustomerUpdateWriter.java index 3fd5a6806..bb7c827a8 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/CustomerUpdateWriter.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/CustomerUpdateWriter.java @@ -24,9 +24,8 @@ import org.springframework.batch.sample.domain.trade.CustomerDebitDao; import org.springframework.batch.sample.domain.trade.Trade; /** - * Transforms Trade to a CustomerDebit and asks DAO delegate to write the - * result. - * + * Transforms Trade to a CustomerDebit and asks DAO delegate to write the result. + * * @author Robert Kasanicky */ public class CustomerUpdateWriter implements ItemWriter { @@ -46,4 +45,5 @@ public class CustomerUpdateWriter implements ItemWriter { public void setDao(CustomerDebitDao outputSource) { this.dao = outputSource; } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/FlatFileCustomerCreditDao.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/FlatFileCustomerCreditDao.java index 91fd9464b..6ee22cc50 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/FlatFileCustomerCreditDao.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/FlatFileCustomerCreditDao.java @@ -31,8 +31,7 @@ import org.springframework.beans.factory.DisposableBean; * @see CustomerCreditDao * @author Robert Kasanicky */ -public class FlatFileCustomerCreditDao implements CustomerCreditDao, - DisposableBean { +public class FlatFileCustomerCreditDao implements CustomerCreditDao, DisposableBean { private ItemWriter itemWriter; @@ -47,8 +46,7 @@ public class FlatFileCustomerCreditDao implements CustomerCreditDao, open(new ExecutionContext()); } - String line = "" + customerCredit.getName() + separator - + customerCredit.getCredit(); + String line = "" + customerCredit.getName() + separator + customerCredit.getCredit(); itemWriter.write(Collections.singletonList(line)); } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/GeneratingTradeItemReader.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/GeneratingTradeItemReader.java index aa738b2f7..ab1a3c7ab 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/GeneratingTradeItemReader.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/GeneratingTradeItemReader.java @@ -24,13 +24,13 @@ import org.springframework.lang.Nullable; /** * Generates configurable number of {@link Trade} items. - * + * * @author Robert Kasanicky */ public class GeneratingTradeItemReader implements ItemReader { private int limit = 1; - + private int counter = 0; @Nullable @@ -38,18 +38,14 @@ public class GeneratingTradeItemReader implements ItemReader { public Trade read() throws Exception { if (counter < limit) { counter++; - return new Trade( - "isin" + counter, - counter, - new BigDecimal(counter), - "customer" + counter); + return new Trade("isin" + counter, counter, new BigDecimal(counter), "customer" + counter); } return null; } /** - * @param limit number of items that will be generated - * (null returned on consecutive calls). + * @param limit number of items that will be generated (null returned on consecutive + * calls). */ public void setLimit(int limit) { this.limit = limit; @@ -63,8 +59,8 @@ public class GeneratingTradeItemReader implements ItemReader { return limit; } - public void resetCounter() - { + public void resetCounter() { this.counter = 0; } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/HibernateAwareCustomerCreditItemWriter.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/HibernateAwareCustomerCreditItemWriter.java index fc8bd6abb..2746f2c85 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/HibernateAwareCustomerCreditItemWriter.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/HibernateAwareCustomerCreditItemWriter.java @@ -26,8 +26,8 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; /** - * Delegates writing to a custom DAO and flushes + clears hibernate session to - * fulfill the {@link ItemWriter} contract. + * Delegates writing to a custom DAO and flushes + clears hibernate session to fulfill the + * {@link ItemWriter} contract. * * @author Robert Kasanicky * @author Michael Minella diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/HibernateCreditDao.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/HibernateCreditDao.java index cf6af264b..b6857d87f 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/HibernateCreditDao.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/HibernateCreditDao.java @@ -30,11 +30,12 @@ import org.springframework.batch.sample.domain.trade.CustomerCreditDao; * @author Dave Syer * */ -public class HibernateCreditDao implements - CustomerCreditDao, RepeatListener { +public class HibernateCreditDao implements CustomerCreditDao, RepeatListener { private int failOnFlush = -1; + private List errors = new ArrayList<>(); + private SessionFactory sessionFactory; public void setSessionFactory(SessionFactory sessionFactory) { @@ -43,7 +44,6 @@ public class HibernateCreditDao implements /** * Public accessor for the errors property. - * * @return the errors - a list of Throwable instances */ public List getErrors() { @@ -53,7 +53,9 @@ public class HibernateCreditDao implements /* * (non-Javadoc) * - * @see org.springframework.batch.sample.domain.trade.internal.CustomerCreditWriter#write(org.springframework.batch.sample.domain.CustomerCredit) + * @see + * org.springframework.batch.sample.domain.trade.internal.CustomerCreditWriter#write( + * org.springframework.batch.sample.domain.CustomerCredit) */ @Override public void writeCredit(CustomerCredit customerCredit) { @@ -64,7 +66,8 @@ public class HibernateCreditDao implements newCredit.setName(customerCredit.getName()); newCredit.setCredit(customerCredit.getCredit()); sessionFactory.getCurrentSession().save(newCredit); - } else { + } + else { sessionFactory.getCurrentSession().update(customerCredit); } } @@ -80,9 +83,7 @@ public class HibernateCreditDao implements /** * Public setter for the failOnFlush property. - * - * @param failOnFlush - * the ID of the record you want to fail on flush (for testing) + * @param failOnFlush the ID of the record you want to fail on flush (for testing) */ public void setFailOnFlush(int failOnFlush) { this.failOnFlush = failOnFlush; @@ -93,29 +94,45 @@ public class HibernateCreditDao implements errors.add(e); } - /* (non-Javadoc) - * @see org.springframework.batch.repeat.RepeatInterceptor#after(org.springframework.batch.repeat.RepeatContext, org.springframework.batch.repeat.ExitStatus) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.repeat.RepeatInterceptor#after(org.springframework.batch. + * repeat.RepeatContext, org.springframework.batch.repeat.ExitStatus) */ @Override public void after(RepeatContext context, RepeatStatus result) { } - /* (non-Javadoc) - * @see org.springframework.batch.repeat.RepeatInterceptor#before(org.springframework.batch.repeat.RepeatContext) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.repeat.RepeatInterceptor#before(org.springframework.batch + * .repeat.RepeatContext) */ @Override public void before(RepeatContext context) { } - /* (non-Javadoc) - * @see org.springframework.batch.repeat.RepeatInterceptor#close(org.springframework.batch.repeat.RepeatContext) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.repeat.RepeatInterceptor#close(org.springframework.batch. + * repeat.RepeatContext) */ @Override public void close(RepeatContext context) { } - /* (non-Javadoc) - * @see org.springframework.batch.repeat.RepeatInterceptor#open(org.springframework.batch.repeat.RepeatContext) + /* + * (non-Javadoc) + * + * @see + * org.springframework.batch.repeat.RepeatInterceptor#open(org.springframework.batch. + * repeat.RepeatContext) */ @Override public void open(RepeatContext context) { diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/JdbcCustomerDao.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/JdbcCustomerDao.java index faadc3b21..c2245b3bb 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/JdbcCustomerDao.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/JdbcCustomerDao.java @@ -29,48 +29,49 @@ import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer * @author Mahmoud Ben Hassine * */ -public class JdbcCustomerDao extends JdbcDaoSupport implements CustomerDao{ +public class JdbcCustomerDao extends JdbcDaoSupport implements CustomerDao { private static final String GET_CUSTOMER_BY_NAME = "SELECT ID, NAME, CREDIT from CUSTOMER where NAME = ?"; + private static final String INSERT_CUSTOMER = "INSERT into CUSTOMER(ID, NAME, CREDIT) values(?,?,?)"; + private static final String UPDATE_CUSTOMER = "UPDATE CUSTOMER set CREDIT = ? where NAME = ?"; - + private DataFieldMaxValueIncrementer incrementer; - + public void setIncrementer(DataFieldMaxValueIncrementer incrementer) { this.incrementer = incrementer; } - + @Override public CustomerCredit getCustomerByName(String name) { - - List customers = getJdbcTemplate().query(GET_CUSTOMER_BY_NAME, - (rs, rowNum) -> { - CustomerCredit customer = new CustomerCredit(); - customer.setName(rs.getString("NAME")); - customer.setId(rs.getInt("ID")); - customer.setCredit(rs.getBigDecimal("CREDIT")); - return customer; - }, name); - - if(customers.size() == 0){ + + List customers = getJdbcTemplate().query(GET_CUSTOMER_BY_NAME, (rs, rowNum) -> { + CustomerCredit customer = new CustomerCredit(); + customer.setName(rs.getString("NAME")); + customer.setId(rs.getInt("ID")); + customer.setCredit(rs.getBigDecimal("CREDIT")); + return customer; + }, name); + + if (customers.size() == 0) { return null; } - else{ + else { return customers.get(0); } - + } @Override public void insertCustomer(String name, BigDecimal credit) { - - getJdbcTemplate().update(INSERT_CUSTOMER, new Object[]{incrementer.nextIntValue(), name, credit}); + + getJdbcTemplate().update(INSERT_CUSTOMER, new Object[] { incrementer.nextIntValue(), name, credit }); } @Override public void updateCustomer(String name, BigDecimal credit) { - getJdbcTemplate().update(UPDATE_CUSTOMER, new Object[]{credit, name}); + getJdbcTemplate().update(UPDATE_CUSTOMER, new Object[] { credit, name }); } } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/JdbcCustomerDebitDao.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/JdbcCustomerDebitDao.java index 704470e10..df79adb69 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/JdbcCustomerDebitDao.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/JdbcCustomerDebitDao.java @@ -24,7 +24,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcOperations; import org.springframework.jdbc.core.JdbcTemplate; - /** * Reduces customer's credit by the provided amount. * @@ -32,18 +31,18 @@ import org.springframework.jdbc.core.JdbcTemplate; */ public class JdbcCustomerDebitDao implements CustomerDebitDao { - private static final String UPDATE_CREDIT = "UPDATE CUSTOMER SET credit= credit-? WHERE name=?"; + private static final String UPDATE_CREDIT = "UPDATE CUSTOMER SET credit= credit-? WHERE name=?"; - private JdbcOperations jdbcTemplate; + private JdbcOperations jdbcTemplate; - @Override + @Override public void write(CustomerDebit customerDebit) { - jdbcTemplate.update(UPDATE_CREDIT, customerDebit.getDebit(), customerDebit.getName()); - } + jdbcTemplate.update(UPDATE_CREDIT, customerDebit.getDebit(), customerDebit.getName()); + } - @Autowired + @Autowired public void setDataSource(DataSource dataSource) { - this.jdbcTemplate = new JdbcTemplate(dataSource); - } + this.jdbcTemplate = new JdbcTemplate(dataSource); + } } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/JdbcTradeDao.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/JdbcTradeDao.java index d38f2247c..c9a02359c 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/JdbcTradeDao.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/JdbcTradeDao.java @@ -26,49 +26,49 @@ import org.springframework.jdbc.core.JdbcOperations; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer; - /** * Writes a Trade object to a database * * @author Robert Kasanicky */ public class JdbcTradeDao implements TradeDao { + private Log log = LogFactory.getLog(JdbcTradeDao.class); - /** - * template for inserting a row - */ - private static final String INSERT_TRADE_RECORD = "INSERT INTO TRADE (id, version, isin, quantity, price, customer) VALUES (?, 0, ?, ? ,?, ?)"; - /** - * handles the processing of SQL query - */ - private JdbcOperations jdbcTemplate; + /** + * template for inserting a row + */ + private static final String INSERT_TRADE_RECORD = "INSERT INTO TRADE (id, version, isin, quantity, price, customer) VALUES (?, 0, ?, ? ,?, ?)"; - /** - * database is not expected to be setup for auto increment - */ - private DataFieldMaxValueIncrementer incrementer; + /** + * handles the processing of SQL query + */ + private JdbcOperations jdbcTemplate; - /** - * @see TradeDao - */ - @Override + /** + * database is not expected to be setup for auto increment + */ + private DataFieldMaxValueIncrementer incrementer; + + /** + * @see TradeDao + */ + @Override public void writeTrade(Trade trade) { - Long id = incrementer.nextLongValue(); - if (log.isDebugEnabled()) { - log.debug("Processing: " + trade); - } - jdbcTemplate.update(INSERT_TRADE_RECORD, - id, trade.getIsin(), trade.getQuantity(), trade.getPrice(), + Long id = incrementer.nextLongValue(); + if (log.isDebugEnabled()) { + log.debug("Processing: " + trade); + } + jdbcTemplate.update(INSERT_TRADE_RECORD, id, trade.getIsin(), trade.getQuantity(), trade.getPrice(), trade.getCustomer()); - } + } - public void setDataSource(DataSource dataSource) { - this.jdbcTemplate = new JdbcTemplate(dataSource); - } + public void setDataSource(DataSource dataSource) { + this.jdbcTemplate = new JdbcTemplate(dataSource); + } - public void setIncrementer(DataFieldMaxValueIncrementer incrementer) { - this.incrementer = incrementer; - } + public void setIncrementer(DataFieldMaxValueIncrementer incrementer) { + this.incrementer = incrementer; + } } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/TradeFieldSetMapper.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/TradeFieldSetMapper.java index a698bd2ad..45f4f140c 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/TradeFieldSetMapper.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/TradeFieldSetMapper.java @@ -20,24 +20,26 @@ import org.springframework.batch.item.file.mapping.FieldSetMapper; import org.springframework.batch.item.file.transform.FieldSet; import org.springframework.batch.sample.domain.trade.Trade; - - public class TradeFieldSetMapper implements FieldSetMapper { - + public static final int ISIN_COLUMN = 0; + public static final int QUANTITY_COLUMN = 1; + public static final int PRICE_COLUMN = 2; + public static final int CUSTOMER_COLUMN = 3; - - @Override + + @Override public Trade mapFieldSet(FieldSet fieldSet) { - - Trade trade = new Trade(); - trade.setIsin(fieldSet.readString(ISIN_COLUMN)); - trade.setQuantity(fieldSet.readLong(QUANTITY_COLUMN)); - trade.setPrice(fieldSet.readBigDecimal(PRICE_COLUMN)); - trade.setCustomer(fieldSet.readString(CUSTOMER_COLUMN)); - - return trade; - } + + Trade trade = new Trade(); + trade.setIsin(fieldSet.readString(ISIN_COLUMN)); + trade.setQuantity(fieldSet.readLong(QUANTITY_COLUMN)); + trade.setPrice(fieldSet.readBigDecimal(PRICE_COLUMN)); + trade.setCustomer(fieldSet.readString(CUSTOMER_COLUMN)); + + return trade; + } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/TradeProcessor.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/TradeProcessor.java index f7e616e04..461ee5384 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/TradeProcessor.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/TradeProcessor.java @@ -29,12 +29,11 @@ public class TradeProcessor implements ItemProcessor { private int failure = -1; private int index = 0; - + private Trade failedItem = null; /** * Public setter for the index on which failure should occur. - * * @param failure the failure to set */ public void setValidationFailure(int failure) { @@ -50,4 +49,5 @@ public class TradeProcessor implements ItemProcessor { } return item; } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/TradeRowMapper.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/TradeRowMapper.java index d4f970bf4..4f2a8c657 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/TradeRowMapper.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/TradeRowMapper.java @@ -23,24 +23,29 @@ import org.springframework.batch.sample.domain.trade.Trade; import org.springframework.jdbc.core.RowMapper; public class TradeRowMapper implements RowMapper { - + public static final int ISIN_COLUMN = 1; + public static final int QUANTITY_COLUMN = 2; + public static final int PRICE_COLUMN = 3; + public static final int CUSTOMER_COLUMN = 4; + public static final int ID_COLUMN = 5; + public static final int VERSION_COLUMN = 6; @Override public Trade mapRow(ResultSet rs, int rowNum) throws SQLException { Trade trade = new Trade(rs.getLong(ID_COLUMN)); - + trade.setIsin(rs.getString(ISIN_COLUMN)); trade.setQuantity(rs.getLong(QUANTITY_COLUMN)); trade.setPrice(rs.getBigDecimal(PRICE_COLUMN)); trade.setCustomer(rs.getString(CUSTOMER_COLUMN)); trade.setVersion(rs.getInt(VERSION_COLUMN)); - + return trade; } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/TradeWriter.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/TradeWriter.java index 5c3fe8b4b..eed0b305e 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/TradeWriter.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/TradeWriter.java @@ -32,8 +32,8 @@ import org.springframework.batch.sample.domain.trade.TradeDao; import org.springframework.util.Assert; /** - * Delegates the actual writing to custom DAO delegate. Allows configurable - * exception raising for testing skip and restart. + * Delegates the actual writing to custom DAO delegate. Allows configurable exception + * raising for testing skip and restart. */ public class TradeWriter extends ItemStreamSupport implements ItemWriter { @@ -56,7 +56,8 @@ public class TradeWriter extends ItemStreamSupport implements ItemWriter dao.writeTrade(trade); - Assert.notNull(trade.getPrice(), "price must not be null"); // There must be a price to total + Assert.notNull(trade.getPrice(), "price must not be null"); // There must be a + // price to total if (this.failingCustomers.contains(trade.getCustomer())) { throw new WriteFailedException("Something unexpected happened!"); @@ -100,10 +101,10 @@ public class TradeWriter extends ItemStreamSupport implements ItemWriter /** * Public setter for the customers on which failure should occur. - * * @param failingCustomers The customers to fail on */ public void setFailingCustomers(List failingCustomers) { this.failingCustomers = failingCustomers; } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/validator/TradeValidator.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/validator/TradeValidator.java index 2e0fe71f6..18d1a1fac 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/validator/TradeValidator.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/validator/TradeValidator.java @@ -23,17 +23,19 @@ import org.springframework.batch.sample.domain.trade.Trade; * @author Michael Minella */ public class TradeValidator implements Validator { - @Override - public boolean supports(Class clazz) { - return clazz.equals(Trade.class); - } - @Override - public void validate(Object target, Errors errors) { - Trade trade = (Trade) target; + @Override + public boolean supports(Class clazz) { + return clazz.equals(Trade.class); + } + + @Override + public void validate(Object target, Errors errors) { + Trade trade = (Trade) target; + + if (trade.getIsin().length() >= 13) { + errors.rejectValue("isin", "isin_length"); + } + } - if(trade.getIsin().length() >= 13) { - errors.rejectValue("isin", "isin_length"); - } - } } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/jmx/JobExecutionNotificationPublisher.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/jmx/JobExecutionNotificationPublisher.java index b00f8138d..4aa260ad1 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/jmx/JobExecutionNotificationPublisher.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/jmx/JobExecutionNotificationPublisher.java @@ -27,11 +27,13 @@ import org.springframework.jmx.export.notification.NotificationPublisherAware; /** * JMX notification broadcaster - * + * * @author Dave Syer * @since 1.0 */ -public class JobExecutionNotificationPublisher implements ApplicationListener, NotificationPublisherAware { +public class JobExecutionNotificationPublisher + implements ApplicationListener, NotificationPublisherAware { + private static final Log LOG = LogFactory.getLog(JobExecutionNotificationPublisher.class); private NotificationPublisher notificationPublisher; @@ -40,7 +42,7 @@ public class JobExecutionNotificationPublisher implements ApplicationListener getConfigurations(); - + Object getJobConfiguration(String path); - + Object getProperty(String path); void setProperty(String path, String value); diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/loop/GeneratingTradeResettingListener.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/loop/GeneratingTradeResettingListener.java index 6db174887..1161b76a8 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/loop/GeneratingTradeResettingListener.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/loop/GeneratingTradeResettingListener.java @@ -24,9 +24,8 @@ import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** - * This listener resets the count of its GeneratingTradeItemReader after the - * step. - * + * This listener resets the count of its GeneratingTradeItemReader after the step. + * * @author Dan Garrette * @author Mahmoud Ben Hassine * @since 2.0 @@ -50,4 +49,5 @@ public class GeneratingTradeResettingListener implements StepExecutionListener, public void afterPropertiesSet() throws Exception { Assert.notNull(this.reader, "The 'reader' must be set."); } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/loop/LimitDecider.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/loop/LimitDecider.java index d98e68d33..a8000a19a 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/loop/LimitDecider.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/loop/LimitDecider.java @@ -22,9 +22,9 @@ import org.springframework.batch.core.job.flow.JobExecutionDecider; import org.springframework.lang.Nullable; /** - * This decider will return "CONTINUE" until the limit it reached, at which - * point it will return "COMPLETE". - * + * This decider will return "CONTINUE" until the limit it reached, at which point it will + * return "COMPLETE". + * * @author Dan Garrette * @since 2.0 */ @@ -50,4 +50,5 @@ public class LimitDecider implements JobExecutionDecider { public void setLimit(int limit) { this.limit = limit; } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/metrics/BatchMetricsApplication.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/metrics/BatchMetricsApplication.java index eb6e2aa23..52409bc81 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/metrics/BatchMetricsApplication.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/metrics/BatchMetricsApplication.java @@ -11,12 +11,13 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; @EnableScheduling @EnableBatchProcessing -@Import({Job1Configuration.class, Job2Configuration.class, JobScheduler.class, PrometheusConfiguration.class}) +@Import({ Job1Configuration.class, Job2Configuration.class, JobScheduler.class, PrometheusConfiguration.class }) @PropertySource("metrics-sample.properties") public class BatchMetricsApplication { public static void main(String[] args) { - AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BatchMetricsApplication.class); + AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext( + BatchMetricsApplication.class); applicationContext.start(); } @@ -28,4 +29,3 @@ public class BatchMetricsApplication { } } - diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/metrics/Job1Configuration.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/metrics/Job1Configuration.java index 406c4dbc2..129e66070 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/metrics/Job1Configuration.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/metrics/Job1Configuration.java @@ -14,7 +14,9 @@ import org.springframework.context.annotation.Configuration; public class Job1Configuration { private Random random; + private JobBuilderFactory jobs; + private StepBuilderFactory steps; public Job1Configuration(JobBuilderFactory jobs, StepBuilderFactory steps) { @@ -25,38 +27,31 @@ public class Job1Configuration { @Bean public Job job1() { - return jobs.get("job1") - .start(step1()) - .next(step2()) - .build(); + return jobs.get("job1").start(step1()).next(step2()).build(); } @Bean public Step step1() { - return steps.get("step1") - .tasklet((contribution, chunkContext) -> { - System.out.println("hello"); - // simulate processing time - Thread.sleep(random.nextInt(3000)); - return RepeatStatus.FINISHED; - }) - .build(); + return steps.get("step1").tasklet((contribution, chunkContext) -> { + System.out.println("hello"); + // simulate processing time + Thread.sleep(random.nextInt(3000)); + return RepeatStatus.FINISHED; + }).build(); } @Bean public Step step2() { - return steps.get("step2") - .tasklet((contribution, chunkContext) -> { - System.out.println("world"); - // simulate step failure - int nextInt = random.nextInt(3000); - Thread.sleep(nextInt); - if (nextInt % 5 == 0) { - throw new Exception("Boom!"); - } - return RepeatStatus.FINISHED; - }) - .build(); + return steps.get("step2").tasklet((contribution, chunkContext) -> { + System.out.println("world"); + // simulate step failure + int nextInt = random.nextInt(3000); + Thread.sleep(nextInt); + if (nextInt % 5 == 0) { + throw new Exception("Boom!"); + } + return RepeatStatus.FINISHED; + }).build(); } } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/metrics/Job2Configuration.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/metrics/Job2Configuration.java index fe1289109..bf6865b82 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/metrics/Job2Configuration.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/metrics/Job2Configuration.java @@ -18,7 +18,9 @@ import org.springframework.context.annotation.Configuration; public class Job2Configuration { private Random random; + private JobBuilderFactory jobs; + private StepBuilderFactory steps; public Job2Configuration(JobBuilderFactory jobs, StepBuilderFactory steps) { @@ -29,18 +31,12 @@ public class Job2Configuration { @Bean public Job job2() { - return jobs.get("job2") - .start(step()) - .build(); + return jobs.get("job2").start(step()).build(); } @Bean public Step step() { - return steps.get("step1") - .chunk(3) - .reader(itemReader()) - .writer(itemWriter()) - .build(); + return steps.get("step1").chunk(3).reader(itemReader()).writer(itemWriter()).build(); } @Bean diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/metrics/JobScheduler.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/metrics/JobScheduler.java index 43382b1f7..ab5e6d4f2 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/metrics/JobScheduler.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/metrics/JobScheduler.java @@ -12,7 +12,9 @@ import org.springframework.stereotype.Component; public class JobScheduler { private final Job job1; + private final Job job2; + private final JobLauncher jobLauncher; @Autowired @@ -22,19 +24,17 @@ public class JobScheduler { this.jobLauncher = jobLauncher; } - @Scheduled(cron="*/10 * * * * *") + @Scheduled(cron = "*/10 * * * * *") public void launchJob1() throws Exception { - JobParameters jobParameters = new JobParametersBuilder() - .addLong("time", System.currentTimeMillis()) + JobParameters jobParameters = new JobParametersBuilder().addLong("time", System.currentTimeMillis()) .toJobParameters(); jobLauncher.run(job1, jobParameters); } - @Scheduled(cron="*/15 * * * * *") + @Scheduled(cron = "*/15 * * * * *") public void launchJob2() throws Exception { - JobParameters jobParameters = new JobParametersBuilder() - .addLong("time", System.currentTimeMillis()) + JobParameters jobParameters = new JobParametersBuilder().addLong("time", System.currentTimeMillis()) .toJobParameters(); jobLauncher.run(job2, jobParameters); diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/metrics/PrometheusConfiguration.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/metrics/PrometheusConfiguration.java index e14d676b0..0a5f611a3 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/metrics/PrometheusConfiguration.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/metrics/PrometheusConfiguration.java @@ -46,7 +46,9 @@ public class PrometheusConfiguration { private String prometheusPushGatewayUrl; private Map groupingKey = new HashMap<>(); + private PushGateway pushGateway; + private CollectorRegistry collectorRegistry; @PostConstruct @@ -62,7 +64,8 @@ public class PrometheusConfiguration { public void pushMetrics() { try { pushGateway.pushAdd(collectorRegistry, prometheusJobName, groupingKey); - } catch (Throwable ex) { + } + catch (Throwable ex) { LOGGER.error("Unable to push metrics to Prometheus Push Gateway", ex); } } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/mongodb/DeletionJobConfiguration.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/mongodb/DeletionJobConfiguration.java index 93b509942..6528ecad9 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/mongodb/DeletionJobConfiguration.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/mongodb/DeletionJobConfiguration.java @@ -35,15 +35,16 @@ import org.springframework.data.mongodb.core.query.Query; import static org.springframework.data.mongodb.core.query.Criteria.where; /** - * This job will remove document "foo3" from collection "person_out" - * using {@link MongoItemWriter#setDelete(boolean)}. + * This job will remove document "foo3" from collection "person_out" using + * {@link MongoItemWriter#setDelete(boolean)}. * - * @author Mahmoud Ben Hassine + * @author Mahmoud Ben Hassine */ @EnableBatchProcessing public class DeletionJobConfiguration { private JobBuilderFactory jobBuilderFactory; + private StepBuilderFactory stepBuilderFactory; public DeletionJobConfiguration(JobBuilderFactory jobBuilderFactory, StepBuilderFactory stepBuilderFactory) { @@ -55,39 +56,26 @@ public class DeletionJobConfiguration { public MongoItemReader mongoPersonReader(MongoTemplate mongoTemplate) { Map sortOptions = new HashMap<>(); sortOptions.put("name", Sort.Direction.DESC); - return new MongoItemReaderBuilder() - .name("personItemReader") - .collection("person_out") - .targetType(Person.class) - .template(mongoTemplate) - .query(new Query().addCriteria(where("name").is("foo3"))) - .sorts(sortOptions) - .build(); + return new MongoItemReaderBuilder().name("personItemReader").collection("person_out") + .targetType(Person.class).template(mongoTemplate) + .query(new Query().addCriteria(where("name").is("foo3"))).sorts(sortOptions).build(); } @Bean public MongoItemWriter mongoPersonRemover(MongoTemplate mongoTemplate) { - return new MongoItemWriterBuilder() - .template(mongoTemplate) - .delete(true) - .collection("person_out") + return new MongoItemWriterBuilder().template(mongoTemplate).delete(true).collection("person_out") .build(); } @Bean public Step deletionStep(MongoItemReader mongoPersonReader, MongoItemWriter mongoPersonRemover) { - return this.stepBuilderFactory.get("step") - .chunk(2) - .reader(mongoPersonReader) - .writer(mongoPersonRemover) - .build(); + return this.stepBuilderFactory.get("step").chunk(2).reader(mongoPersonReader) + .writer(mongoPersonRemover).build(); } @Bean public Job deletionJob(Step deletionStep) { - return this.jobBuilderFactory.get("deletionJob") - .start(deletionStep) - .build(); + return this.jobBuilderFactory.get("deletionJob").start(deletionStep).build(); } } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/mongodb/InsertionJobConfiguration.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/mongodb/InsertionJobConfiguration.java index ce594143d..ae9c56e9d 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/mongodb/InsertionJobConfiguration.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/mongodb/InsertionJobConfiguration.java @@ -32,15 +32,16 @@ import org.springframework.data.domain.Sort; import org.springframework.data.mongodb.core.MongoTemplate; /** - * This job will copy documents from collection "person_in" into collection - * "person_out" using {@link MongoItemReader} and {@link MongoItemWriter}. + * This job will copy documents from collection "person_in" into collection "person_out" + * using {@link MongoItemReader} and {@link MongoItemWriter}. * - * @author Mahmoud Ben Hassine + * @author Mahmoud Ben Hassine */ @EnableBatchProcessing public class InsertionJobConfiguration { private JobBuilderFactory jobBuilderFactory; + private StepBuilderFactory stepBuilderFactory; public InsertionJobConfiguration(JobBuilderFactory jobBuilderFactory, StepBuilderFactory stepBuilderFactory) { @@ -52,38 +53,24 @@ public class InsertionJobConfiguration { public MongoItemReader mongoItemReader(MongoTemplate mongoTemplate) { Map sortOptions = new HashMap<>(); sortOptions.put("name", Sort.Direction.DESC); - return new MongoItemReaderBuilder() - .name("personItemReader") - .collection("person_in") - .targetType(Person.class) - .template(mongoTemplate) - .jsonQuery("{}") - .sorts(sortOptions) - .build(); + return new MongoItemReaderBuilder().name("personItemReader").collection("person_in") + .targetType(Person.class).template(mongoTemplate).jsonQuery("{}").sorts(sortOptions).build(); } @Bean public MongoItemWriter mongoItemWriter(MongoTemplate mongoTemplate) { - return new MongoItemWriterBuilder() - .template(mongoTemplate) - .collection("person_out") - .build(); + return new MongoItemWriterBuilder().template(mongoTemplate).collection("person_out").build(); } @Bean public Step step(MongoItemReader mongoItemReader, MongoItemWriter mongoItemWriter) { - return this.stepBuilderFactory.get("step") - .chunk(2) - .reader(mongoItemReader) - .writer(mongoItemWriter) - .build(); + return this.stepBuilderFactory.get("step").chunk(2).reader(mongoItemReader) + .writer(mongoItemWriter).build(); } @Bean public Job insertionJob(Step step) { - return this.jobBuilderFactory.get("insertionJob") - .start(step) - .build(); + return this.jobBuilderFactory.get("insertionJob").start(step).build(); } } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/mongodb/MongoDBConfiguration.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/mongodb/MongoDBConfiguration.java index d99dbcb6d..207079fd0 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/mongodb/MongoDBConfiguration.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/mongodb/MongoDBConfiguration.java @@ -39,8 +39,7 @@ public class MongoDBConfiguration { @Bean public MongoTemplate mongoTemplate() { - String connectionString = "mongodb://" + - this.mongodbHost + ":" + this.mongodbPort + "/" + this.mongodbDatabase; + String connectionString = "mongodb://" + this.mongodbHost + ":" + this.mongodbPort + "/" + this.mongodbDatabase; MongoClient mongoClient = MongoClients.create(connectionString); return new MongoTemplate(mongoClient, "test"); } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/mongodb/MongoDBSampleApp.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/mongodb/MongoDBSampleApp.java index 61b62b0b7..73e2ff69c 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/mongodb/MongoDBSampleApp.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/mongodb/MongoDBSampleApp.java @@ -29,21 +29,19 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext import org.springframework.data.mongodb.core.MongoTemplate; /** - * Ensure a MongoDB instance is running on "localhost:27017", - * otherwise modify mongodb-sample.properties file as needed. + * Ensure a MongoDB instance is running on "localhost:27017", otherwise modify + * mongodb-sample.properties file as needed. * - * If you use docker, you can run a mongo db server with: - * "docker run --name mongodb --rm -d -p 27017:27017 mongo" + * If you use docker, you can run a mongo db server with: "docker run --name mongodb --rm + * -d -p 27017:27017 mongo" * * @author Mahmoud Ben Hassine */ public class MongoDBSampleApp { public static void main(String[] args) throws Exception { - Class[] configurationClasses = { - InsertionJobConfiguration.class, - DeletionJobConfiguration.class, - MongoDBConfiguration.class}; + Class[] configurationClasses = { InsertionJobConfiguration.class, DeletionJobConfiguration.class, + MongoDBConfiguration.class }; ApplicationContext context = new AnnotationConfigApplicationContext(configurationClasses); MongoTemplate mongoTemplate = context.getBean(MongoTemplate.class); @@ -52,12 +50,8 @@ public class MongoDBSampleApp { MongoCollection personsOut = mongoTemplate.getCollection("person_out"); personsIn.deleteMany(new Document()); personsOut.deleteMany(new Document()); - personsIn.insertMany(Arrays.asList( - new Document("name", "foo1"), - new Document("name", "foo2"), - new Document("name", "foo3"), - new Document("name", "foo4")) - ); + personsIn.insertMany(Arrays.asList(new Document("name", "foo1"), new Document("name", "foo2"), + new Document("name", "foo3"), new Document("name", "foo4"))); // run the insertion job JobLauncher jobLauncher = context.getBean(JobLauncher.class); @@ -82,4 +76,5 @@ public class MongoDBSampleApp { System.out.println(person); } } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/mongodb/Person.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/mongodb/Person.java index 8fd9917b9..8dac2336a 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/mongodb/Person.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/mongodb/Person.java @@ -17,39 +17,38 @@ package org.springframework.batch.sample.mongodb; public class Person { - private String id; - private String name; + private String id; - public Person() { - } + private String name; - public Person(String name) { - this.name = name; - } + public Person() { + } - public String getId() { - return id; - } + public Person(String name) { + this.name = name; + } - // setter used for data binding if items to delete (with known IDs) - // are read from a flat file for example - public void setId(String id) { - this.id = id; - } + public String getId() { + return id; + } - public String getName() { - return name; - } + // setter used for data binding if items to delete (with known IDs) + // are read from a flat file for example + public void setId(String id) { + this.id = id; + } - public void setName(String name) { - this.name = name; - } + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public String toString() { + return "Person{" + "id='" + id + '\'' + ", name='" + name + '\'' + '}'; + } - @Override - public String toString() { - return "Person{" + - "id='" + id + '\'' + - ", name='" + name + '\'' + - '}'; - } } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/quartz/JobLauncherDetails.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/quartz/JobLauncherDetails.java index 81cb32ac0..2e91e26fe 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/quartz/JobLauncherDetails.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/quartz/JobLauncherDetails.java @@ -31,7 +31,7 @@ import org.springframework.scheduling.quartz.QuartzJobBean; /** * @author Dave Syer - * + * */ public class JobLauncherDetails extends QuartzJobBean { @@ -79,9 +79,9 @@ public class JobLauncherDetails extends QuartzJobBean { } /* - * Copy parameters that are of the correct type over to - * {@link JobParameters}, ignoring jobName. - * + * Copy parameters that are of the correct type over to {@link JobParameters}, + * ignoring jobName. + * * @return a {@link JobParameters} instance */ private JobParameters getJobParametersFromJobMap(Map jobDataMap) { @@ -98,7 +98,7 @@ public class JobLauncherDetails extends QuartzJobBean { builder.addDouble(key, ((Number) value).doubleValue()); } else if (value instanceof Integer || value instanceof Long) { - builder.addLong(key, ((Number)value).longValue()); + builder.addLong(key, ((Number) value).longValue()); } else if (value instanceof Date) { builder.addDate(key, (Date) value); diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/rabbitmq/amqp/AmqpMessageProducer.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/rabbitmq/amqp/AmqpMessageProducer.java index 8da6ca391..edf052bd9 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/rabbitmq/amqp/AmqpMessageProducer.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/rabbitmq/amqp/AmqpMessageProducer.java @@ -23,24 +23,29 @@ import org.springframework.context.support.ClassPathXmlApplicationContext; /** *

      - * Simple producer class that sends {@link String} messages to the configured queue to be processed. + * Simple producer class that sends {@link String} messages to the configured queue to be + * processed. *

      */ public final class AmqpMessageProducer { - private AmqpMessageProducer() {} - private static final int SEND_MESSAGE_COUNT = 10; - private static final String[] BEAN_CONFIG = { "classpath:/META-INF/spring/jobs/messaging/rabbitmq-beans.xml", - "classpath:/META-INF/spring/config-beans.xml" }; + private AmqpMessageProducer() { + } - public static void main(String[] args) { - ApplicationContext applicationContext = new ClassPathXmlApplicationContext(BEAN_CONFIG); - AmqpTemplate amqpTemplate = applicationContext.getBean("inboundAmqpTemplate", RabbitTemplate.class); + private static final int SEND_MESSAGE_COUNT = 10; - for (int i = 0; i < SEND_MESSAGE_COUNT; i++ ) { - amqpTemplate.convertAndSend("foo message: " + i); - } + private static final String[] BEAN_CONFIG = { "classpath:/META-INF/spring/jobs/messaging/rabbitmq-beans.xml", + "classpath:/META-INF/spring/config-beans.xml" }; + + public static void main(String[] args) { + ApplicationContext applicationContext = new ClassPathXmlApplicationContext(BEAN_CONFIG); + AmqpTemplate amqpTemplate = applicationContext.getBean("inboundAmqpTemplate", RabbitTemplate.class); + + for (int i = 0; i < SEND_MESSAGE_COUNT; i++) { + amqpTemplate.convertAndSend("foo message: " + i); + } + + ((ConfigurableApplicationContext) applicationContext).close(); + } - ((ConfigurableApplicationContext) applicationContext).close(); - } } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/rabbitmq/processor/MessageProcessor.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/rabbitmq/processor/MessageProcessor.java index 9b1fd9e85..e7aa7c2bf 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/rabbitmq/processor/MessageProcessor.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/rabbitmq/processor/MessageProcessor.java @@ -22,14 +22,16 @@ import java.util.Date; /** *

      - * Simple {@link ItemProcessor} implementation to append a "processed on" {@link Date} to a received message. + * Simple {@link ItemProcessor} implementation to append a "processed on" {@link Date} to + * a received message. *

      */ public class MessageProcessor implements ItemProcessor { - @Nullable + @Nullable @Override public String process(String message) throws Exception { - return "Message: \"" + message + "\" processed on: " + new Date(); - } + return "Message: \"" + message + "\" processed on: " + new Date(); + } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/remotechunking/DataSourceConfiguration.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/remotechunking/DataSourceConfiguration.java index 08fbe58e0..353f6c913 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/remotechunking/DataSourceConfiguration.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/remotechunking/DataSourceConfiguration.java @@ -31,11 +31,8 @@ public class DataSourceConfiguration { @Bean public DataSource dataSource() { - return new EmbeddedDatabaseBuilder() - .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("/org/springframework/batch/core/schema-hsqldb.sql") - .generateUniqueName(true) - .build(); + return new EmbeddedDatabaseBuilder().addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") + .addScript("/org/springframework/batch/core/schema-hsqldb.sql").generateUniqueName(true).build(); } @Bean diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/remotechunking/ManagerConfiguration.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/remotechunking/ManagerConfiguration.java index f3e54a789..652e63780 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/remotechunking/ManagerConfiguration.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/remotechunking/ManagerConfiguration.java @@ -41,9 +41,9 @@ import org.springframework.integration.dsl.IntegrationFlows; import org.springframework.integration.jms.dsl.Jms; /** - * This configuration class is for the manager side of the remote chunking sample. - * The manager step reads numbers from 1 to 6 and sends 2 chunks {1, 2, 3} and - * {4, 5, 6} to workers for processing and writing. + * This configuration class is for the manager side of the remote chunking sample. The + * manager step reads numbers from 1 to 6 and sends 2 chunks {1, 2, 3} and {4, 5, 6} to + * workers for processing and writing. * * @author Mahmoud Ben Hassine */ @@ -81,9 +81,7 @@ public class ManagerConfiguration { @Bean public IntegrationFlow outboundFlow(ActiveMQConnectionFactory connectionFactory) { - return IntegrationFlows - .from(requests()) - .handle(Jms.outboundAdapter(connectionFactory).destination("requests")) + return IntegrationFlows.from(requests()).handle(Jms.outboundAdapter(connectionFactory).destination("requests")) .get(); } @@ -97,10 +95,8 @@ public class ManagerConfiguration { @Bean public IntegrationFlow inboundFlow(ActiveMQConnectionFactory connectionFactory) { - return IntegrationFlows - .from(Jms.messageDrivenChannelAdapter(connectionFactory).destination("replies")) - .channel(replies()) - .get(); + return IntegrationFlows.from(Jms.messageDrivenChannelAdapter(connectionFactory).destination("replies")) + .channel(replies()).get(); } /* @@ -113,19 +109,13 @@ public class ManagerConfiguration { @Bean public TaskletStep managerStep() { - return this.managerStepBuilderFactory.get("managerStep") - .chunk(3) - .reader(itemReader()) - .outputChannel(requests()) - .inputChannel(replies()) - .build(); + return this.managerStepBuilderFactory.get("managerStep").chunk(3).reader(itemReader()) + .outputChannel(requests()).inputChannel(replies()).build(); } @Bean public Job remoteChunkingJob() { - return this.jobBuilderFactory.get("remoteChunkingJob") - .start(managerStep()) - .build(); + return this.jobBuilderFactory.get("remoteChunkingJob").start(managerStep()).build(); } } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/remotechunking/WorkerConfiguration.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/remotechunking/WorkerConfiguration.java index bfe3d0d6a..5fb997a12 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/remotechunking/WorkerConfiguration.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/remotechunking/WorkerConfiguration.java @@ -36,13 +36,13 @@ import org.springframework.integration.dsl.IntegrationFlows; import org.springframework.integration.jms.dsl.Jms; /** - * This configuration class is for the worker side of the remote chunking sample. - * It uses the {@link RemoteChunkingWorkerBuilder} to configure an - * {@link IntegrationFlow} in order to: + * This configuration class is for the worker side of the remote chunking sample. It uses + * the {@link RemoteChunkingWorkerBuilder} to configure an {@link IntegrationFlow} in + * order to: *
        - *
      • receive requests from the manager
      • - *
      • process chunks with the configured item processor and writer
      • - *
      • send replies to the manager
      • + *
      • receive requests from the manager
      • + *
      • process chunks with the configured item processor and writer
      • + *
      • send replies to the manager
      • *
      * * @author Mahmoud Ben Hassine @@ -78,10 +78,8 @@ public class WorkerConfiguration { @Bean public IntegrationFlow inboundFlow(ActiveMQConnectionFactory connectionFactory) { - return IntegrationFlows - .from(Jms.messageDrivenChannelAdapter(connectionFactory).destination("requests")) - .channel(requests()) - .get(); + return IntegrationFlows.from(Jms.messageDrivenChannelAdapter(connectionFactory).destination("requests")) + .channel(requests()).get(); } /* @@ -94,9 +92,7 @@ public class WorkerConfiguration { @Bean public IntegrationFlow outboundFlow(ActiveMQConnectionFactory connectionFactory) { - return IntegrationFlows - .from(replies()) - .handle(Jms.outboundAdapter(connectionFactory).destination("replies")) + return IntegrationFlows.from(replies()).handle(Jms.outboundAdapter(connectionFactory).destination("replies")) .get(); } @@ -122,12 +118,8 @@ public class WorkerConfiguration { @Bean public IntegrationFlow workerIntegrationFlow() { - return this.remoteChunkingWorkerBuilder - .itemProcessor(itemProcessor()) - .itemWriter(itemWriter()) - .inputChannel(requests()) - .outputChannel(replies()) - .build(); + return this.remoteChunkingWorkerBuilder.itemProcessor(itemProcessor()).itemWriter(itemWriter()) + .inputChannel(requests()).outputChannel(replies()).build(); } } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/remotepartitioning/aggregating/ManagerConfiguration.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/remotepartitioning/aggregating/ManagerConfiguration.java index ce118b620..9aa25b5d7 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/remotepartitioning/aggregating/ManagerConfiguration.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/remotepartitioning/aggregating/ManagerConfiguration.java @@ -35,15 +35,15 @@ import org.springframework.integration.dsl.IntegrationFlows; import org.springframework.integration.jms.dsl.Jms; /** - * This configuration class is for the manager side of the remote partitioning sample. - * The manager step will create 3 partitions for workers to process. + * This configuration class is for the manager side of the remote partitioning sample. The + * manager step will create 3 partitions for workers to process. * * @author Mahmoud Ben Hassine */ @Configuration @EnableBatchProcessing @EnableBatchIntegration -@Import(value = {DataSourceConfiguration.class, BrokerConfiguration.class}) +@Import(value = { DataSourceConfiguration.class, BrokerConfiguration.class }) public class ManagerConfiguration { private static final int GRID_SIZE = 3; @@ -52,9 +52,8 @@ public class ManagerConfiguration { private final RemotePartitioningManagerStepBuilderFactory managerStepBuilderFactory; - public ManagerConfiguration(JobBuilderFactory jobBuilderFactory, - RemotePartitioningManagerStepBuilderFactory managerStepBuilderFactory) { + RemotePartitioningManagerStepBuilderFactory managerStepBuilderFactory) { this.jobBuilderFactory = jobBuilderFactory; this.managerStepBuilderFactory = managerStepBuilderFactory; @@ -70,9 +69,7 @@ public class ManagerConfiguration { @Bean public IntegrationFlow outboundFlow(ActiveMQConnectionFactory connectionFactory) { - return IntegrationFlows - .from(requests()) - .handle(Jms.outboundAdapter(connectionFactory).destination("requests")) + return IntegrationFlows.from(requests()).handle(Jms.outboundAdapter(connectionFactory).destination("requests")) .get(); } @@ -86,10 +83,8 @@ public class ManagerConfiguration { @Bean public IntegrationFlow inboundFlow(ActiveMQConnectionFactory connectionFactory) { - return IntegrationFlows - .from(Jms.messageDrivenChannelAdapter(connectionFactory).destination("replies")) - .channel(replies()) - .get(); + return IntegrationFlows.from(Jms.messageDrivenChannelAdapter(connectionFactory).destination("replies")) + .channel(replies()).get(); } /* @@ -97,19 +92,13 @@ public class ManagerConfiguration { */ @Bean public Step managerStep() { - return this.managerStepBuilderFactory.get("managerStep") - .partitioner("workerStep", new BasicPartitioner()) - .gridSize(GRID_SIZE) - .outputChannel(requests()) - .inputChannel(replies()) - .build(); + return this.managerStepBuilderFactory.get("managerStep").partitioner("workerStep", new BasicPartitioner()) + .gridSize(GRID_SIZE).outputChannel(requests()).inputChannel(replies()).build(); } @Bean public Job remotePartitioningJob() { - return this.jobBuilderFactory.get("remotePartitioningJob") - .start(managerStep()) - .build(); + return this.jobBuilderFactory.get("remotePartitioningJob").start(managerStep()).build(); } } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/remotepartitioning/aggregating/WorkerConfiguration.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/remotepartitioning/aggregating/WorkerConfiguration.java index 7658feec5..0a07496a9 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/remotepartitioning/aggregating/WorkerConfiguration.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/remotepartitioning/aggregating/WorkerConfiguration.java @@ -36,20 +36,19 @@ import org.springframework.integration.dsl.IntegrationFlows; import org.springframework.integration.jms.dsl.Jms; /** - * This configuration class is for the worker side of the remote partitioning sample. - * Each worker will process a partition sent by the manager step. + * This configuration class is for the worker side of the remote partitioning sample. Each + * worker will process a partition sent by the manager step. * * @author Mahmoud Ben Hassine */ @Configuration @EnableBatchProcessing @EnableBatchIntegration -@Import(value = {DataSourceConfiguration.class, BrokerConfiguration.class}) +@Import(value = { DataSourceConfiguration.class, BrokerConfiguration.class }) public class WorkerConfiguration { private final RemotePartitioningWorkerStepBuilderFactory workerStepBuilderFactory; - public WorkerConfiguration(RemotePartitioningWorkerStepBuilderFactory workerStepBuilderFactory) { this.workerStepBuilderFactory = workerStepBuilderFactory; } @@ -64,10 +63,8 @@ public class WorkerConfiguration { @Bean public IntegrationFlow inboundFlow(ActiveMQConnectionFactory connectionFactory) { - return IntegrationFlows - .from(Jms.messageDrivenChannelAdapter(connectionFactory).destination("requests")) - .channel(requests()) - .get(); + return IntegrationFlows.from(Jms.messageDrivenChannelAdapter(connectionFactory).destination("requests")) + .channel(requests()).get(); } /* @@ -80,9 +77,7 @@ public class WorkerConfiguration { @Bean public IntegrationFlow outboundFlow(ActiveMQConnectionFactory connectionFactory) { - return IntegrationFlows - .from(replies()) - .handle(Jms.outboundAdapter(connectionFactory).destination("replies")) + return IntegrationFlows.from(replies()).handle(Jms.outboundAdapter(connectionFactory).destination("replies")) .get(); } @@ -91,11 +86,8 @@ public class WorkerConfiguration { */ @Bean public Step workerStep() { - return this.workerStepBuilderFactory.get("workerStep") - .inputChannel(requests()) - .outputChannel(replies()) - .tasklet(tasklet(null)) - .build(); + return this.workerStepBuilderFactory.get("workerStep").inputChannel(requests()).outputChannel(replies()) + .tasklet(tasklet(null)).build(); } @Bean diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/remotepartitioning/polling/ManagerConfiguration.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/remotepartitioning/polling/ManagerConfiguration.java index ca032809d..d28b49db4 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/remotepartitioning/polling/ManagerConfiguration.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/remotepartitioning/polling/ManagerConfiguration.java @@ -35,15 +35,15 @@ import org.springframework.integration.dsl.IntegrationFlows; import org.springframework.integration.jms.dsl.Jms; /** - * This configuration class is for the manager side of the remote partitioning sample. - * The manager step will create 3 partitions for workers to process. + * This configuration class is for the manager side of the remote partitioning sample. The + * manager step will create 3 partitions for workers to process. * * @author Mahmoud Ben Hassine */ @Configuration @EnableBatchProcessing @EnableBatchIntegration -@Import(value = {DataSourceConfiguration.class, BrokerConfiguration.class}) +@Import(value = { DataSourceConfiguration.class, BrokerConfiguration.class }) public class ManagerConfiguration { private static final int GRID_SIZE = 3; @@ -52,9 +52,8 @@ public class ManagerConfiguration { private final RemotePartitioningManagerStepBuilderFactory managerStepBuilderFactory; - public ManagerConfiguration(JobBuilderFactory jobBuilderFactory, - RemotePartitioningManagerStepBuilderFactory managerStepBuilderFactory) { + RemotePartitioningManagerStepBuilderFactory managerStepBuilderFactory) { this.jobBuilderFactory = jobBuilderFactory; this.managerStepBuilderFactory = managerStepBuilderFactory; @@ -70,9 +69,7 @@ public class ManagerConfiguration { @Bean public IntegrationFlow outboundFlow(ActiveMQConnectionFactory connectionFactory) { - return IntegrationFlows - .from(requests()) - .handle(Jms.outboundAdapter(connectionFactory).destination("requests")) + return IntegrationFlows.from(requests()).handle(Jms.outboundAdapter(connectionFactory).destination("requests")) .get(); } @@ -81,18 +78,13 @@ public class ManagerConfiguration { */ @Bean public Step managerStep() { - return this.managerStepBuilderFactory.get("managerStep") - .partitioner("workerStep", new BasicPartitioner()) - .gridSize(GRID_SIZE) - .outputChannel(requests()) - .build(); + return this.managerStepBuilderFactory.get("managerStep").partitioner("workerStep", new BasicPartitioner()) + .gridSize(GRID_SIZE).outputChannel(requests()).build(); } @Bean public Job remotePartitioningJob() { - return this.jobBuilderFactory.get("remotePartitioningJob") - .start(managerStep()) - .build(); + return this.jobBuilderFactory.get("remotePartitioningJob").start(managerStep()).build(); } } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/remotepartitioning/polling/WorkerConfiguration.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/remotepartitioning/polling/WorkerConfiguration.java index 310bec4a2..ddd50e56c 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/remotepartitioning/polling/WorkerConfiguration.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/remotepartitioning/polling/WorkerConfiguration.java @@ -36,20 +36,19 @@ import org.springframework.integration.dsl.IntegrationFlows; import org.springframework.integration.jms.dsl.Jms; /** - * This configuration class is for the worker side of the remote partitioning sample. - * Each worker will process a partition sent by the manager step. + * This configuration class is for the worker side of the remote partitioning sample. Each + * worker will process a partition sent by the manager step. * * @author Mahmoud Ben Hassine */ @Configuration @EnableBatchProcessing @EnableBatchIntegration -@Import(value = {DataSourceConfiguration.class, BrokerConfiguration.class}) +@Import(value = { DataSourceConfiguration.class, BrokerConfiguration.class }) public class WorkerConfiguration { private final RemotePartitioningWorkerStepBuilderFactory workerStepBuilderFactory; - public WorkerConfiguration(RemotePartitioningWorkerStepBuilderFactory workerStepBuilderFactory) { this.workerStepBuilderFactory = workerStepBuilderFactory; } @@ -64,10 +63,8 @@ public class WorkerConfiguration { @Bean public IntegrationFlow inboundFlow(ActiveMQConnectionFactory connectionFactory) { - return IntegrationFlows - .from(Jms.messageDrivenChannelAdapter(connectionFactory).destination("requests")) - .channel(requests()) - .get(); + return IntegrationFlows.from(Jms.messageDrivenChannelAdapter(connectionFactory).destination("requests")) + .channel(requests()).get(); } /* @@ -75,10 +72,7 @@ public class WorkerConfiguration { */ @Bean public Step workerStep() { - return this.workerStepBuilderFactory.get("workerStep") - .inputChannel(requests()) - .tasklet(tasklet(null)) - .build(); + return this.workerStepBuilderFactory.get("workerStep").inputChannel(requests()).tasklet(tasklet(null)).build(); } @Bean diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/skip/DataSourceConfiguration.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/skip/DataSourceConfiguration.java index 0d665bba6..2feaa1c8e 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/skip/DataSourceConfiguration.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/skip/DataSourceConfiguration.java @@ -24,13 +24,10 @@ import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; @Configuration public class DataSourceConfiguration { - @Bean - public DataSource dataSource() { - return new EmbeddedDatabaseBuilder() - .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("/org/springframework/batch/core/schema-hsqldb.sql") - .generateUniqueName(true) - .build(); - } + @Bean + public DataSource dataSource() { + return new EmbeddedDatabaseBuilder().addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") + .addScript("/org/springframework/batch/core/schema-hsqldb.sql").generateUniqueName(true).build(); + } } \ No newline at end of file diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/skip/SkippableExceptionDuringProcessSample.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/skip/SkippableExceptionDuringProcessSample.java index 52ce86c0b..2609fdb10 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/skip/SkippableExceptionDuringProcessSample.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/skip/SkippableExceptionDuringProcessSample.java @@ -44,7 +44,7 @@ public class SkippableExceptionDuringProcessSample { private final StepBuilderFactory stepBuilderFactory; public SkippableExceptionDuringProcessSample(JobBuilderFactory jobBuilderFactory, - StepBuilderFactory stepBuilderFactory) { + StepBuilderFactory stepBuilderFactory) { this.jobBuilderFactory = jobBuilderFactory; this.stepBuilderFactory = stepBuilderFactory; } @@ -85,22 +85,14 @@ public class SkippableExceptionDuringProcessSample { @Bean public Step step() { - return this.stepBuilderFactory.get("step") - .chunk(3) - .reader(itemReader()) - .processor(itemProcessor()) - .writer(itemWriter()) - .faultTolerant() - .skip(IllegalArgumentException.class) - .skipLimit(3) - .build(); + return this.stepBuilderFactory.get("step").chunk(3).reader(itemReader()) + .processor(itemProcessor()).writer(itemWriter()).faultTolerant().skip(IllegalArgumentException.class) + .skipLimit(3).build(); } @Bean public Job job() { - return this.jobBuilderFactory.get("job") - .start(step()) - .build(); + return this.jobBuilderFactory.get("job").start(step()).build(); } } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/skip/SkippableExceptionDuringReadSample.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/skip/SkippableExceptionDuringReadSample.java index 7bca512a2..8f15f901e 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/skip/SkippableExceptionDuringReadSample.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/skip/SkippableExceptionDuringReadSample.java @@ -44,7 +44,7 @@ public class SkippableExceptionDuringReadSample { private final StepBuilderFactory stepBuilderFactory; public SkippableExceptionDuringReadSample(JobBuilderFactory jobBuilderFactory, - StepBuilderFactory stepBuilderFactory) { + StepBuilderFactory stepBuilderFactory) { this.jobBuilderFactory = jobBuilderFactory; this.stepBuilderFactory = stepBuilderFactory; } @@ -85,22 +85,14 @@ public class SkippableExceptionDuringReadSample { @Bean public Step step() { - return this.stepBuilderFactory.get("step") - .chunk(3) - .reader(itemReader()) - .processor(itemProcessor()) - .writer(itemWriter()) - .faultTolerant() - .skip(IllegalArgumentException.class) - .skipLimit(3) - .build(); + return this.stepBuilderFactory.get("step").chunk(3).reader(itemReader()) + .processor(itemProcessor()).writer(itemWriter()).faultTolerant().skip(IllegalArgumentException.class) + .skipLimit(3).build(); } @Bean public Job job() { - return this.jobBuilderFactory.get("job") - .start(step()) - .build(); + return this.jobBuilderFactory.get("job").start(step()).build(); } } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/skip/SkippableExceptionDuringWriteSample.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/skip/SkippableExceptionDuringWriteSample.java index b75b73e68..b4298051c 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/skip/SkippableExceptionDuringWriteSample.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/skip/SkippableExceptionDuringWriteSample.java @@ -44,7 +44,7 @@ public class SkippableExceptionDuringWriteSample { private final StepBuilderFactory stepBuilderFactory; public SkippableExceptionDuringWriteSample(JobBuilderFactory jobBuilderFactory, - StepBuilderFactory stepBuilderFactory) { + StepBuilderFactory stepBuilderFactory) { this.jobBuilderFactory = jobBuilderFactory; this.stepBuilderFactory = stepBuilderFactory; } @@ -85,22 +85,14 @@ public class SkippableExceptionDuringWriteSample { @Bean public Step step() { - return this.stepBuilderFactory.get("step") - .chunk(3) - .reader(itemReader()) - .processor(itemProcessor()) - .writer(itemWriter()) - .faultTolerant() - .skip(IllegalArgumentException.class) - .skipLimit(3) - .build(); + return this.stepBuilderFactory.get("step").chunk(3).reader(itemReader()) + .processor(itemProcessor()).writer(itemWriter()).faultTolerant().skip(IllegalArgumentException.class) + .skipLimit(3).build(); } @Bean public Job job() { - return this.jobBuilderFactory.get("job") - .start(step()) - .build(); + return this.jobBuilderFactory.get("job").start(step()).build(); } } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/support/ExceptionThrowingItemReaderProxy.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/support/ExceptionThrowingItemReaderProxy.java index c0e4ae135..fcde2896b 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/support/ExceptionThrowingItemReaderProxy.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/support/ExceptionThrowingItemReaderProxy.java @@ -21,12 +21,12 @@ import org.springframework.batch.item.ItemReader; import org.springframework.lang.Nullable; /** - * Hacked {@link ItemReader} that throws exception on a given record number - * (useful for testing restart). - * + * Hacked {@link ItemReader} that throws exception on a given record number (useful for + * testing restart). + * * @author Robert Kasanicky * @author Lucas Ward - * + * */ public class ExceptionThrowingItemReaderProxy implements ItemReader { @@ -37,8 +37,8 @@ public class ExceptionThrowingItemReaderProxy implements ItemReader { private ItemReader delegate; /** - * @param throwExceptionOnRecordNumber The number of record on which - * exception should be thrown + * @param throwExceptionOnRecordNumber The number of record on which exception should + * be thrown */ public void setThrowExceptionOnRecordNumber(int throwExceptionOnRecordNumber) { this.throwExceptionOnRecordNumber = throwExceptionOnRecordNumber; diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/support/HeaderCopyCallback.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/support/HeaderCopyCallback.java index b2a9859a4..5a4e4f5ed 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/support/HeaderCopyCallback.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/support/HeaderCopyCallback.java @@ -24,13 +24,15 @@ import org.springframework.batch.item.file.LineCallbackHandler; import org.springframework.util.Assert; /** - * Designed to be registered with both {@link org.springframework.batch.item.file.FlatFileItemReader} - * and {@link org.springframework.batch.item.file.FlatFileItemWriter} and copy header line from input - * file to output file. + * Designed to be registered with both + * {@link org.springframework.batch.item.file.FlatFileItemReader} and + * {@link org.springframework.batch.item.file.FlatFileItemWriter} and copy header line + * from input file to output file. */ public class HeaderCopyCallback implements LineCallbackHandler, FlatFileHeaderCallback { + private String header = ""; - + @Override public void handleLine(String line) { Assert.notNull(line, "line must not be null"); @@ -41,4 +43,5 @@ public class HeaderCopyCallback implements LineCallbackHandler, FlatFileHeaderCa public void writeHeader(Writer writer) throws IOException { writer.write("header from input: " + header); } + } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/support/RetrySampleItemWriter.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/support/RetrySampleItemWriter.java index 169881605..22de74c95 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/support/RetrySampleItemWriter.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/support/RetrySampleItemWriter.java @@ -21,9 +21,8 @@ import java.util.List; import org.springframework.batch.item.ItemWriter; /** - * Simulates temporary output trouble - requires to retry 3 times to pass - * successfully. - * + * Simulates temporary output trouble - requires to retry 3 times to pass successfully. + * * @author Robert Kasanicky */ public class RetrySampleItemWriter implements ItemWriter { diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/support/SummaryFooterCallback.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/support/SummaryFooterCallback.java index f97f8c8df..da7e7bb83 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/support/SummaryFooterCallback.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/support/SummaryFooterCallback.java @@ -26,10 +26,10 @@ import org.springframework.batch.item.file.FlatFileFooterCallback; /** * Writes summary info in the footer of a file. */ -public class SummaryFooterCallback implements StepExecutionListener, FlatFileFooterCallback{ +public class SummaryFooterCallback implements StepExecutionListener, FlatFileFooterCallback { private StepExecution stepExecution; - + @Override public void writeFooter(Writer writer) throws IOException { writer.write("footer - number of items written: " + stepExecution.getWriteCount()); @@ -40,5 +40,4 @@ public class SummaryFooterCallback implements StepExecutionListener, FlatFileFoo this.stepExecution = stepExecution; } - } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/validation/ValidationSampleConfiguration.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/validation/ValidationSampleConfiguration.java index b378b0a99..50c38f1de 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/validation/ValidationSampleConfiguration.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/validation/ValidationSampleConfiguration.java @@ -70,28 +70,19 @@ public class ValidationSampleConfiguration { @Bean public Step step() throws Exception { - return this.steps.get("step") - .chunk(1) - .reader(itemReader()) - .processor(itemValidator()) - .writer(itemWriter()) - .build(); + return this.steps.get("step").chunk(1).reader(itemReader()).processor(itemValidator()) + .writer(itemWriter()).build(); } @Bean public Job job() throws Exception { - return this.jobs.get("job") - .start(step()) - .build(); + return this.jobs.get("job").start(step()).build(); } @Bean public DataSource dataSource() { - return new EmbeddedDatabaseBuilder() - .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("/org/springframework/batch/core/schema-hsqldb.sql") - .generateUniqueName(true) - .build(); + return new EmbeddedDatabaseBuilder().addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") + .addScript("/org/springframework/batch/core/schema-hsqldb.sql").generateUniqueName(true).build(); } } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/validation/domain/Person.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/validation/domain/Person.java index 2d9198251..a06fa8caf 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/validation/domain/Person.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/validation/domain/Person.java @@ -54,9 +54,7 @@ public class Person { @Override public String toString() { - return "Person{" + - "id=" + id + - ", name='" + name + '\'' + - '}'; + return "Person{" + "id=" + id + ", name='" + name + '\'' + '}'; } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/AMQPJobFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/AMQPJobFunctionalTests.java index e610d6f2e..bbbd58df1 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/AMQPJobFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/AMQPJobFunctionalTests.java @@ -26,20 +26,27 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** - *

      Ensure a RabbitMQ instance is running, modifying default.amqp.properties if needed. Execute the - * {@link org.springframework.batch.sample.rabbitmq.amqp.AmqpMessageProducer#main(String[])} method - * in order for messages will be written to the "test.inbound" queue.

      + *

      + * Ensure a RabbitMQ instance is running, modifying default.amqp.properties if needed. + * Execute the + * {@link org.springframework.batch.sample.rabbitmq.amqp.AmqpMessageProducer#main(String[])} + * method in order for messages will be written to the "test.inbound" queue. + *

      * - *

      Run this test and the job will read those messages, process them and write them to the "test.outbound" - * queue for inspection.

      -*/ + *

      + * Run this test and the job will read those messages, process them and write them to the + * "test.outbound" queue for inspection. + *

      + */ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/amqp-example-job.xml", "/job-runner-context.xml" }) +@ContextConfiguration( + locations = { "/simple-job-launcher-context.xml", "/jobs/amqp-example-job.xml", "/job-runner-context.xml" }) public class AMQPJobFunctionalTests { @Autowired private JobLauncherTestUtils jobLauncherTestUtils; + @Autowired private JobExplorer jobExplorer; diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/BeanWrapperMapperSampleJobFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/BeanWrapperMapperSampleJobFunctionalTests.java index cf9352d65..b78110164 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/BeanWrapperMapperSampleJobFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/BeanWrapperMapperSampleJobFunctionalTests.java @@ -27,7 +27,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/beanWrapperMapperSampleJob.xml", "/job-runner-context.xml" }) public class BeanWrapperMapperSampleJobFunctionalTests { - + @Autowired private JobLauncherTestUtils jobLauncherTestUtils; @@ -37,6 +37,5 @@ public class BeanWrapperMapperSampleJobFunctionalTests { jobLauncherTestUtils.launchJob(); } - } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/CompositeItemWriterSampleFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/CompositeItemWriterSampleFunctionalTests.java index c6cf0f34a..05bfb1ad5 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/CompositeItemWriterSampleFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/CompositeItemWriterSampleFunctionalTests.java @@ -40,9 +40,12 @@ import org.springframework.test.jdbc.JdbcTestUtils; import static org.junit.Assert.assertEquals; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/compositeItemWriterSampleJob.xml", "/job-runner-context.xml" }) +@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/compositeItemWriterSampleJob.xml", + "/job-runner-context.xml" }) public class CompositeItemWriterSampleFunctionalTests { + private static final String GET_TRADES = "SELECT isin, quantity, price, customer FROM TRADE order by isin"; + private static final String EXPECTED_OUTPUT_FILE = "Trade: [isin=UK21341EAH41,quantity=211,price=31.11,customer=customer1]" + "Trade: [isin=UK21341EAH42,quantity=212,price=32.11,customer=customer2]" + "Trade: [isin=UK21341EAH43,quantity=213,price=33.11,customer=customer3]" @@ -61,7 +64,7 @@ public class CompositeItemWriterSampleFunctionalTests { @Test public void testJobLaunch() throws Exception { - JdbcTestUtils.deleteFromTables(jdbcTemplate, "TRADE"); + JdbcTestUtils.deleteFromTables(jdbcTemplate, "TRADE"); int before = JdbcTestUtils.countRowsInTable(jdbcTemplate, "TRADE"); jobLauncherTestUtils.launchJob(); @@ -87,7 +90,7 @@ public class CompositeItemWriterSampleFunctionalTests { assertEquals(before + 5, after); - jdbcTemplate.query(GET_TRADES, new RowCallbackHandler() { + jdbcTemplate.query(GET_TRADES, new RowCallbackHandler() { private int activeRow = 0; @Override @@ -114,4 +117,5 @@ public class CompositeItemWriterSampleFunctionalTests { assertEquals(EXPECTED_OUTPUT_FILE, output); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/CustomerFilterJobFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/CustomerFilterJobFunctionalTests.java index 004536147..fd963336e 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/CustomerFilterJobFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/CustomerFilterJobFunctionalTests.java @@ -41,12 +41,18 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.jdbc.JdbcTestUtils; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/customerFilterJob.xml", "/job-runner-context.xml" }) +@ContextConfiguration( + locations = { "/simple-job-launcher-context.xml", "/jobs/customerFilterJob.xml", "/job-runner-context.xml" }) public class CustomerFilterJobFunctionalTests { + private static final String GET_CUSTOMERS = "select NAME, CREDIT from CUSTOMER order by NAME"; + private List customers; + private int activeRow = 0; + private JdbcTemplate jdbcTemplate; + private Map credits = new HashMap<>(); @Autowired @@ -61,7 +67,7 @@ public class CustomerFilterJobFunctionalTests { public void onSetUp() throws Exception { JdbcTestUtils.deleteFromTables(jdbcTemplate, "TRADE"); JdbcTestUtils.deleteFromTableWhere(jdbcTemplate, "CUSTOMER", "ID > 4"); - jdbcTemplate.update("update CUSTOMER set credit=100000"); + jdbcTemplate.update("update CUSTOMER set credit=100000"); List> list = jdbcTemplate.queryForList("select name, CREDIT from CUSTOMER"); @@ -72,20 +78,21 @@ public class CustomerFilterJobFunctionalTests { @After public void tearDown() throws Exception { - JdbcTestUtils.deleteFromTables(jdbcTemplate, "TRADE"); - JdbcTestUtils.deleteFromTableWhere(jdbcTemplate, "CUSTOMER", "ID > 4"); + JdbcTestUtils.deleteFromTables(jdbcTemplate, "TRADE"); + JdbcTestUtils.deleteFromTableWhere(jdbcTemplate, "CUSTOMER", "ID > 4"); } @Test public void testFilterJob() throws Exception { JobExecution jobExecution = jobLauncherTestUtils.launchJob(); - customers = Arrays.asList(new Customer("customer1", (credits.get("customer1"))), new Customer("customer2", - (credits.get("customer2"))), new Customer("customer3", 100500), new Customer("customer4", credits - .get("customer4")), new Customer("customer5", 32345), new Customer("customer6", 123456)); + customers = Arrays.asList(new Customer("customer1", (credits.get("customer1"))), + new Customer("customer2", (credits.get("customer2"))), new Customer("customer3", 100500), + new Customer("customer4", credits.get("customer4")), new Customer("customer5", 32345), + new Customer("customer6", 123456)); activeRow = 0; - jdbcTemplate.query(GET_CUSTOMERS, new RowCallbackHandler() { + jdbcTemplate.query(GET_CUSTOMERS, new RowCallbackHandler() { @Override public void processRow(ResultSet rs) throws SQLException { Customer customer = customers.get(activeRow++); @@ -108,7 +115,9 @@ public class CustomerFilterJobFunctionalTests { } private static class Customer { + private String name; + private double credit; public Customer(String name, double credit) { @@ -170,5 +179,7 @@ public class CustomerFilterJobFunctionalTests { return false; return true; } + } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/DatabaseShutdownFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/DatabaseShutdownFunctionalTests.java index dcf1e9ba8..2e3d3fca4 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/DatabaseShutdownFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/DatabaseShutdownFunctionalTests.java @@ -34,31 +34,32 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** - * Functional test for graceful shutdown. A batch container is started in a new thread, + * Functional test for graceful shutdown. A batch container is started in a new thread, * then it's stopped using {@link JobOperator#stop(long)}}. - * + * * @author Lucas Ward * @author Mahmoud Ben Hassine * */ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/infiniteLoopJob.xml", "/job-runner-context.xml" }) +@ContextConfiguration( + locations = { "/simple-job-launcher-context.xml", "/jobs/infiniteLoopJob.xml", "/job-runner-context.xml" }) public class DatabaseShutdownFunctionalTests { - + /** Logger */ protected final Log logger = LogFactory.getLog(getClass()); @Autowired private JobOperator jobOperator; - + @Autowired private JobLauncherTestUtils jobLauncherTestUtils; - + @Test public void testLaunchJob() throws Exception { JobExecution jobExecution = jobLauncherTestUtils.launchJob(); - + Thread.sleep(1000); assertEquals(BatchStatus.STARTED, jobExecution.getStatus()); @@ -66,17 +67,17 @@ public class DatabaseShutdownFunctionalTests { assertNotNull(jobExecution.getVersion()); jobOperator.stop(jobExecution.getId()); - + int count = 0; - while(jobExecution.isRunning() && count <= 10){ - logger.info("Checking for end time in JobExecution: count="+count); + while (jobExecution.isRunning() && count <= 10) { + logger.info("Checking for end time in JobExecution: count=" + count); Thread.sleep(100); count++; } - + assertFalse("Timed out waiting for job to end.", jobExecution.isRunning()); assertEquals(BatchStatus.STOPPED, jobExecution.getStatus()); } - + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/DelegatingJobFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/DelegatingJobFunctionalTests.java index c4aef3f4b..b4bea1cd4 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/DelegatingJobFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/DelegatingJobFunctionalTests.java @@ -27,7 +27,8 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/delegatingJob.xml", "/job-runner-context.xml" }) +@ContextConfiguration( + locations = { "/simple-job-launcher-context.xml", "/jobs/delegatingJob.xml", "/job-runner-context.xml" }) public class DelegatingJobFunctionalTests { @Autowired @@ -35,15 +36,15 @@ public class DelegatingJobFunctionalTests { @Autowired private PersonService personService; - + @Test public void testLaunchJob() throws Exception { - + jobLauncherTestUtils.launchJob(); - + assertTrue(personService.getReturnedCount() > 0); assertEquals(personService.getReturnedCount(), personService.getReceivedCount()); - + } - + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/FootballJobFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/FootballJobFunctionalTests.java index 506069607..64619f919 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/FootballJobFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/FootballJobFunctionalTests.java @@ -29,10 +29,13 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.jdbc.JdbcTestUtils; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/footballJob.xml", "/job-runner-context.xml" }) +@ContextConfiguration( + locations = { "/simple-job-launcher-context.xml", "/jobs/footballJob.xml", "/job-runner-context.xml" }) public class FootballJobFunctionalTests { + @Autowired private JobLauncherTestUtils jobLauncherTestUtils; + private JdbcTemplate jdbcTemplate; @Autowired @@ -49,4 +52,5 @@ public class FootballJobFunctionalTests { int count = JdbcTestUtils.countRowsInTable(jdbcTemplate, "PLAYER_SUMMARY"); assertTrue(count > 0); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/GracefulShutdownFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/GracefulShutdownFunctionalTests.java index 0083cf3e0..60bfd5494 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/GracefulShutdownFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/GracefulShutdownFunctionalTests.java @@ -35,15 +35,16 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** - * Functional test for graceful shutdown. A batch container is started in a new - * thread, then it's stopped using {@link JobOperator#stop(long)}. - * + * Functional test for graceful shutdown. A batch container is started in a new thread, + * then it's stopped using {@link JobOperator#stop(long)}. + * * @author Lucas Ward * @author Parikshit Dutta - * + * */ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/infiniteLoopJob.xml", "/job-runner-context.xml" }) +@ContextConfiguration( + locations = { "/simple-job-launcher-context.xml", "/jobs/infiniteLoopJob.xml", "/job-runner-context.xml" }) public class GracefulShutdownFunctionalTests { /** Logger */ @@ -80,4 +81,5 @@ public class GracefulShutdownFunctionalTests { assertFalse("Timed out waiting for job to end.", jobExecution.isRunning()); assertEquals(BatchStatus.STOPPED, jobExecution.getStatus()); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/GroovyJobFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/GroovyJobFunctionalTests.java index 2aa94e9a3..ddbe20d9a 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/GroovyJobFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/GroovyJobFunctionalTests.java @@ -32,8 +32,8 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/groovyJob.xml", - "/job-runner-context.xml" }) +@ContextConfiguration( + locations = { "/simple-job-launcher-context.xml", "/jobs/groovyJob.xml", "/job-runner-context.xml" }) public class GroovyJobFunctionalTests { @Autowired diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/HeaderFooterSampleFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/HeaderFooterSampleFunctionalTests.java index 511a9086a..c19e80790 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/HeaderFooterSampleFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/HeaderFooterSampleFunctionalTests.java @@ -1,73 +1,74 @@ -/* - * Copyright 2008-2014 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.sample; - -import static org.junit.Assert.assertTrue; - -import java.io.BufferedReader; -import java.io.FileReader; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.test.JobLauncherTestUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.core.io.Resource; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/headerFooterSample.xml", "/job-runner-context.xml" }) -public class HeaderFooterSampleFunctionalTests { - - @Autowired - @Qualifier("inputResource") - private Resource input; - - @Autowired - @Qualifier("outputResource") - private Resource output; - - @Autowired - private JobLauncherTestUtils jobLauncherTestUtils; - - @Test - public void testJob() throws Exception { - jobLauncherTestUtils.launchJob(); - - BufferedReader inputReader = new BufferedReader(new FileReader(input.getFile())); - BufferedReader outputReader = new BufferedReader(new FileReader(output.getFile())); - - // skip initial comment from input file - inputReader.readLine(); - - String line; - - int lineCount = 0; - while ((line = inputReader.readLine()) != null) { - lineCount++; - assertTrue("input line should correspond to output line", outputReader.readLine().contains(line)); - } - - // footer contains the item count - int itemCount = lineCount - 1; // minus 1 due to header line - assertTrue(outputReader.readLine().contains(String.valueOf(itemCount))); - - inputReader.close(); - outputReader.close(); - } - -} +/* + * Copyright 2008-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.sample; + +import static org.junit.Assert.assertTrue; + +import java.io.BufferedReader; +import java.io.FileReader; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.test.JobLauncherTestUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.core.io.Resource; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration( + locations = { "/simple-job-launcher-context.xml", "/jobs/headerFooterSample.xml", "/job-runner-context.xml" }) +public class HeaderFooterSampleFunctionalTests { + + @Autowired + @Qualifier("inputResource") + private Resource input; + + @Autowired + @Qualifier("outputResource") + private Resource output; + + @Autowired + private JobLauncherTestUtils jobLauncherTestUtils; + + @Test + public void testJob() throws Exception { + jobLauncherTestUtils.launchJob(); + + BufferedReader inputReader = new BufferedReader(new FileReader(input.getFile())); + BufferedReader outputReader = new BufferedReader(new FileReader(output.getFile())); + + // skip initial comment from input file + inputReader.readLine(); + + String line; + + int lineCount = 0; + while ((line = inputReader.readLine()) != null) { + lineCount++; + assertTrue("input line should correspond to output line", outputReader.readLine().contains(line)); + } + + // footer contains the item count + int itemCount = lineCount - 1; // minus 1 due to header line + assertTrue(outputReader.readLine().contains(String.valueOf(itemCount))); + + inputReader.close(); + outputReader.close(); + } + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/HibernateFailureJobFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/HibernateFailureJobFunctionalTests.java index 64a49fa95..6215d12fb 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/HibernateFailureJobFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/HibernateFailureJobFunctionalTests.java @@ -49,30 +49,37 @@ import org.springframework.transaction.support.TransactionCallback; import org.springframework.transaction.support.TransactionTemplate; /** - * Test for HibernateJob - checks that customer credit has been updated to - * expected value. + * Test for HibernateJob - checks that customer credit has been updated to expected value. * * @author Dave Syer * @author Mahmoud Ben Hassine */ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/hibernate-context.xml", "/jobs/hibernateJob.xml", - "/job-runner-context.xml" }) +@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/hibernate-context.xml", + "/jobs/hibernateJob.xml", "/job-runner-context.xml" }) public class HibernateFailureJobFunctionalTests { + private static final BigDecimal CREDIT_INCREASE = CustomerCreditIncreaseProcessor.FIXED_AMOUNT; + private static final String ALL_CUSTOMERS = "select * from CUSTOMER order by ID"; + private static final String CREDIT_COLUMN = "CREDIT"; - private static String[] customers = { "INSERT INTO CUSTOMER (id, version, name, credit) VALUES (1, 0, 'customer1', 100000)", + + private static String[] customers = { + "INSERT INTO CUSTOMER (id, version, name, credit) VALUES (1, 0, 'customer1', 100000)", "INSERT INTO CUSTOMER (id, version, name, credit) VALUES (2, 0, 'customer2', 100000)", "INSERT INTO CUSTOMER (id, version, name, credit) VALUES (3, 0, 'customer3', 100000)", - "INSERT INTO CUSTOMER (id, version, name, credit) VALUES (4, 0, 'customer4', 100000)"}; + "INSERT INTO CUSTOMER (id, version, name, credit) VALUES (4, 0, 'customer4', 100000)" }; protected static final String ID_COLUMN = "ID"; @Autowired private HibernateCreditDao writer; + private JdbcTemplate jdbcTemplate; + private PlatformTransactionManager transactionManager; + private List creditsBeforeUpdate; @Autowired @@ -97,11 +104,13 @@ public class HibernateFailureJobFunctionalTests { try { jobLauncherTestUtils.launchJob(params); - } catch (HibernateJdbcException e) { + } + catch (HibernateJdbcException e) { // This is what would happen if the flush happened outside the // RepeatContext: throw e; - } catch (UncategorizedSQLException e) { + } + catch (UncategorizedSQLException e) { // This is what would happen if the job wasn't configured to skip // exceptions at the step level. // assertEquals(1, writer.getErrors().size()); @@ -119,25 +128,26 @@ public class HibernateFailureJobFunctionalTests { */ protected void validatePreConditions() throws Exception { ensureState(); - creditsBeforeUpdate = new TransactionTemplate(transactionManager).execute(new TransactionCallback>() { - @Override - public List doInTransaction(TransactionStatus status) { - return jdbcTemplate.query(ALL_CUSTOMERS, new RowMapper() { + creditsBeforeUpdate = new TransactionTemplate(transactionManager) + .execute(new TransactionCallback>() { @Override - public BigDecimal mapRow(ResultSet rs, int rowNum) throws SQLException { - return rs.getBigDecimal(CREDIT_COLUMN); + public List doInTransaction(TransactionStatus status) { + return jdbcTemplate.query(ALL_CUSTOMERS, new RowMapper() { + @Override + public BigDecimal mapRow(ResultSet rs, int rowNum) throws SQLException { + return rs.getBigDecimal(CREDIT_COLUMN); + } + }); } }); - } - }); } /* * Ensure the state of the database is accurate by delete all the contents of the * customer table and reading the expected defaults. */ - private void ensureState(){ - new TransactionTemplate(transactionManager).execute(new TransactionCallback(){ + private void ensureState() { + new TransactionTemplate(transactionManager).execute(new TransactionCallback() { @Override public Void doInTransaction(TransactionStatus status) { @@ -159,7 +169,7 @@ public class HibernateFailureJobFunctionalTests { new TransactionTemplate(transactionManager).execute(new TransactionCallback() { @Override public Void doInTransaction(TransactionStatus status) { - jdbcTemplate.query(ALL_CUSTOMERS, new RowCallbackHandler() { + jdbcTemplate.query(ALL_CUSTOMERS, new RowCallbackHandler() { private int i = 0; @Override @@ -180,4 +190,5 @@ public class HibernateFailureJobFunctionalTests { assertEquals((creditsBeforeUpdate.size() - 1), matches.size()); assertFalse(matches.contains(new BigDecimal(2))); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/JobOperatorFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/JobOperatorFunctionalTests.java index c6fb2c3d7..ce0f86d5e 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/JobOperatorFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/JobOperatorFunctionalTests.java @@ -41,6 +41,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/infiniteLoopJob.xml" }) public class JobOperatorFunctionalTests { + private static final Log LOG = LogFactory.getLog(JobOperatorFunctionalTests.class); @Autowired @@ -90,10 +91,10 @@ public class JobOperatorFunctionalTests { Thread.sleep(1000); Set runningExecutions = operator.getRunningExecutions(job.getName()); - assertTrue("Wrong executions: " + runningExecutions + " expected: " + executionId, runningExecutions - .contains(executionId)); - assertTrue("Wrong summary: " + operator.getSummary(executionId), operator.getSummary(executionId).contains( - BatchStatus.STARTED.toString())); + assertTrue("Wrong executions: " + runningExecutions + " expected: " + executionId, + runningExecutions.contains(executionId)); + assertTrue("Wrong summary: " + operator.getSummary(executionId), + operator.getSummary(executionId).contains(BatchStatus.STARTED.toString())); operator.stop(executionId); @@ -105,10 +106,10 @@ public class JobOperatorFunctionalTests { } runningExecutions = operator.getRunningExecutions(job.getName()); - assertFalse("Wrong executions: " + runningExecutions + " expected: " + executionId, runningExecutions - .contains(executionId)); - assertTrue("Wrong summary: " + operator.getSummary(executionId), operator.getSummary(executionId).contains( - BatchStatus.STOPPED.toString())); + assertFalse("Wrong executions: " + runningExecutions + " expected: " + executionId, + runningExecutions.contains(executionId)); + assertTrue("Wrong summary: " + operator.getSummary(executionId), + operator.getSummary(executionId).contains(BatchStatus.STOPPED.toString())); // there is just a single step in the test job Map summaries = operator.getStepExecutionSummaries(executionId); @@ -146,10 +147,11 @@ public class JobOperatorFunctionalTests { running = operator.getSummary(exec1).contains("STARTED") && operator.getSummary(exec2).contains("STARTED"); } - assertTrue(String.format("Jobs not started: [%s] and [%s]", operator.getSummary(exec1), operator - .getSummary(exec1)), running); + assertTrue(String.format("Jobs not started: [%s] and [%s]", operator.getSummary(exec1), + operator.getSummary(exec1)), running); operator.stop(exec1); operator.stop(exec2); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/JobStepFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/JobStepFunctionalTests.java index acbe6f710..2cc6d95b5 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/JobStepFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/JobStepFunctionalTests.java @@ -40,8 +40,10 @@ import org.springframework.test.jdbc.JdbcTestUtils; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration public class JobStepFunctionalTests { + @Autowired private JobLauncherTestUtils jobLauncherTestUtils; + private JdbcTemplate jdbcTemplate; @Autowired @@ -51,13 +53,14 @@ public class JobStepFunctionalTests { @Test public void testJobLaunch() throws Exception { - JdbcTestUtils.deleteFromTables(jdbcTemplate, "TRADE"); + JdbcTestUtils.deleteFromTables(jdbcTemplate, "TRADE"); - jobLauncherTestUtils.launchJob(new DefaultJobParametersConverter() - .getJobParameters(PropertiesConverter - .stringToProperties("run.id(long)=1,parameter=true,run.date=20070122,input.file=classpath:data/fixedLengthImportJob/input/20070122.teststream.ImportTradeDataStep.txt"))); + jobLauncherTestUtils + .launchJob(new DefaultJobParametersConverter().getJobParameters(PropertiesConverter.stringToProperties( + "run.id(long)=1,parameter=true,run.date=20070122,input.file=classpath:data/fixedLengthImportJob/input/20070122.teststream.ImportTradeDataStep.txt"))); int after = JdbcTestUtils.countRowsInTable(jdbcTemplate, "TRADE"); assertEquals(5, after); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/JsonSupportIntegrationTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/JsonSupportIntegrationTests.java index ac3f44f04..390cae1ef 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/JsonSupportIntegrationTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/JsonSupportIntegrationTests.java @@ -58,13 +58,14 @@ import org.springframework.util.DigestUtils; public class JsonSupportIntegrationTests { private static final String INPUT_FILE_DIRECTORY = "src/test/resources/org/springframework/batch/item/json/"; + private static final String OUTPUT_FILE_DIRECTORY = "target/"; @Before public void setUp() throws Exception { Files.deleteIfExists(Paths.get("build", "trades.json")); } - + @Configuration @EnableBatchProcessing public static class JobConfiguration { @@ -77,47 +78,34 @@ public class JsonSupportIntegrationTests { @Bean public JsonItemReader itemReader() { - return new JsonItemReaderBuilder() - .name("tradesJsonItemReader") + return new JsonItemReaderBuilder().name("tradesJsonItemReader") .resource(new FileSystemResource(INPUT_FILE_DIRECTORY + "trades.json")) - .jsonObjectReader(new GsonJsonObjectReader<>(Trade.class)) - .build(); + .jsonObjectReader(new GsonJsonObjectReader<>(Trade.class)).build(); } @Bean public JsonFileItemWriter itemWriter() { return new JsonFileItemWriterBuilder() - .resource(new FileSystemResource(OUTPUT_FILE_DIRECTORY + "trades.json")) - .lineSeparator("\n") - .jsonObjectMarshaller(new JacksonJsonObjectMarshaller<>()) - .name("tradesJsonFileItemWriter") - .build(); + .resource(new FileSystemResource(OUTPUT_FILE_DIRECTORY + "trades.json")).lineSeparator("\n") + .jsonObjectMarshaller(new JacksonJsonObjectMarshaller<>()).name("tradesJsonFileItemWriter").build(); } @Bean public Step step() { - return steps.get("step") - .chunk(2) - .reader(itemReader()) - .writer(itemWriter()) - .build(); + return steps.get("step").chunk(2).reader(itemReader()).writer(itemWriter()).build(); } @Bean public Job job() { - return jobs.get("job") - .start(step()) - .build(); + return jobs.get("job").start(step()).build(); } @Bean public DataSource dataSource() { - return new EmbeddedDatabaseBuilder() - .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("/org/springframework/batch/core/schema-hsqldb.sql") - .generateUniqueName(true) - .build(); + return new EmbeddedDatabaseBuilder().addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") + .addScript("/org/springframework/batch/core/schema-hsqldb.sql").generateUniqueName(true).build(); } + } @Test @@ -128,8 +116,7 @@ public class JsonSupportIntegrationTests { JobExecution jobExecution = jobLauncher.run(job, new JobParameters()); Assert.assertEquals(ExitStatus.COMPLETED.getExitCode(), jobExecution.getExitStatus().getExitCode()); - assertFileEquals( - new File(INPUT_FILE_DIRECTORY + "trades.json"), + assertFileEquals(new File(INPUT_FILE_DIRECTORY + "trades.json"), new File(OUTPUT_FILE_DIRECTORY + "trades.json")); } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/LoopFlowSampleFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/LoopFlowSampleFunctionalTests.java index b68640fc5..9e6c76fdb 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/LoopFlowSampleFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/LoopFlowSampleFunctionalTests.java @@ -27,13 +27,13 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * Checks that expected number of items have been processed. - * + * * @author Dan Garrette * @since 2.0 */ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/loopFlowSample.xml", - "/job-runner-context.xml" }) +@ContextConfiguration( + locations = { "/simple-job-launcher-context.xml", "/jobs/loopFlowSample.xml", "/job-runner-context.xml" }) public class LoopFlowSampleFunctionalTests { @Autowired @@ -41,7 +41,7 @@ public class LoopFlowSampleFunctionalTests { @Autowired private JobLauncherTestUtils jobLauncherTestUtils; - + @Test public void testJobLaunch() throws Exception { jobLauncherTestUtils.launchJob(); diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/MailJobFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/MailJobFunctionalTests.java index 5c2b073c7..1ecf4d3a6 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/MailJobFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/MailJobFunctionalTests.java @@ -43,11 +43,11 @@ import org.springframework.test.jdbc.JdbcTestUtils; * @author Dan Garrette * @author Dave Syer * @author Mahmoud Ben Hassine - * * @Since 2.1 */ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/mailJob.xml", "/job-runner-context.xml" }) +@ContextConfiguration( + locations = { "/simple-job-launcher-context.xml", "/jobs/mailJob.xml", "/job-runner-context.xml" }) public class MailJobFunctionalTests { private static final String email = "to@company.com"; @@ -125,5 +125,4 @@ public class MailJobFunctionalTests { } } - } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/MultilineJobFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/MultilineJobFunctionalTests.java index da0ff7476..a84031219 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/MultilineJobFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/MultilineJobFunctionalTests.java @@ -31,13 +31,13 @@ import org.springframework.util.StringUtils; import static org.junit.Assert.assertEquals; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/multilineJob.xml", - "/job-runner-context.xml" }) +@ContextConfiguration( + locations = { "/simple-job-launcher-context.xml", "/jobs/multilineJob.xml", "/job-runner-context.xml" }) public class MultilineJobFunctionalTests { @Autowired private JobLauncherTestUtils jobLauncherTestUtils; - + // The output is grouped together in two lines, instead of all the // trades coming out on a single line. private static final String EXPECTED_RESULT = "[Trade: [isin=UK21341EAH45,quantity=978,price=98.34,customer=customer1], Trade: [isin=UK21341EAH46,quantity=112,price=18.12,customer=customer2]]" @@ -48,7 +48,8 @@ public class MultilineJobFunctionalTests { @Test public void testJobLaunch() throws Exception { jobLauncherTestUtils.launchJob(); - assertEquals(EXPECTED_RESULT, StringUtils.replace(IOUtils.toString(output.getInputStream(), "UTF-8"), System - .getProperty("line.separator"), "")); + assertEquals(EXPECTED_RESULT, StringUtils.replace(IOUtils.toString(output.getInputStream(), "UTF-8"), + System.getProperty("line.separator"), "")); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/MultilineOrderJobFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/MultilineOrderJobFunctionalTests.java index 69104416a..ef9458cb4 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/MultilineOrderJobFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/MultilineOrderJobFunctionalTests.java @@ -28,16 +28,17 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/multilineOrderJob.xml", - "/job-runner-context.xml" }) +@ContextConfiguration( + locations = { "/simple-job-launcher-context.xml", "/jobs/multilineOrderJob.xml", "/job-runner-context.xml" }) public class MultilineOrderJobFunctionalTests { private static final String ACTUAL = "target/test-outputs/multilineOrderOutput.txt"; + private static final String EXPECTED = "data/multilineOrderJob/result/multilineOrderOutput.txt"; @Autowired private JobLauncherTestUtils jobLauncherTestUtils; - + @Test public void testJobLaunch() throws Exception { jobLauncherTestUtils.launchJob(); diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/ParallelJobFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/ParallelJobFunctionalTests.java index c2b485a0d..1ee733c2c 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/ParallelJobFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/ParallelJobFunctionalTests.java @@ -32,8 +32,8 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/parallelJob.xml", - "/job-runner-context.xml" }) +@ContextConfiguration( + locations = { "/simple-job-launcher-context.xml", "/jobs/parallelJob.xml", "/job-runner-context.xml" }) public class ParallelJobFunctionalTests { @Autowired diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/PartitionFileJobFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/PartitionFileJobFunctionalTests.java index 4f4de9835..d3ec63643 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/PartitionFileJobFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/PartitionFileJobFunctionalTests.java @@ -43,15 +43,17 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/partitionFileJob.xml", - "/job-runner-context.xml" }) +@ContextConfiguration( + locations = { "/simple-job-launcher-context.xml", "/jobs/partitionFileJob.xml", "/job-runner-context.xml" }) public class PartitionFileJobFunctionalTests implements ApplicationContextAware { + @Autowired @Qualifier("inputTestReader") private ItemReader inputReader; @Autowired private JobLauncherTestUtils jobLauncherTestUtils; + private ApplicationContext applicationContext; @Override @@ -60,13 +62,12 @@ public class PartitionFileJobFunctionalTests implements ApplicationContextAware } /** - * Check the resulting credits correspond to inputs increased by fixed - * amount. + * Check the resulting credits correspond to inputs increased by fixed amount. */ @Test public void testUpdateCredit() throws Exception { - assertTrue("Define a prototype bean called 'outputTestReader' to check the output", applicationContext - .containsBeanDefinition("outputTestReader")); + assertTrue("Define a prototype bean called 'outputTestReader' to check the output", + applicationContext.containsBeanDefinition("outputTestReader")); open(inputReader); List inputs = new ArrayList<>(getCredits(inputReader)); @@ -124,4 +125,5 @@ public class PartitionFileJobFunctionalTests implements ApplicationContextAware ((ItemStream) reader).close(); } } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/PartitionJdbcJobFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/PartitionJdbcJobFunctionalTests.java index 9574a10e9..33ec74b77 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/PartitionJdbcJobFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/PartitionJdbcJobFunctionalTests.java @@ -43,15 +43,17 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/partitionJdbcJob.xml", - "/job-runner-context.xml" }) +@ContextConfiguration( + locations = { "/simple-job-launcher-context.xml", "/jobs/partitionJdbcJob.xml", "/job-runner-context.xml" }) public class PartitionJdbcJobFunctionalTests implements ApplicationContextAware { + @Autowired @Qualifier("inputTestReader") private ItemReader inputReader; @Autowired private JobLauncherTestUtils jobLauncherTestUtils; + private ApplicationContext applicationContext; @Override @@ -60,13 +62,12 @@ public class PartitionJdbcJobFunctionalTests implements ApplicationContextAware } /** - * Check the resulting credits correspond to inputs increased by fixed - * amount. + * Check the resulting credits correspond to inputs increased by fixed amount. */ @Test public void testUpdateCredit() throws Exception { - assertTrue("Define a prototype bean called 'outputTestReader' to check the output", applicationContext - .containsBeanDefinition("outputTestReader")); + assertTrue("Define a prototype bean called 'outputTestReader' to check the output", + applicationContext.containsBeanDefinition("outputTestReader")); open(inputReader); List inputs = new ArrayList<>(getCredits(inputReader)); @@ -123,4 +124,5 @@ public class PartitionJdbcJobFunctionalTests implements ApplicationContextAware ((ItemStream) reader).close(); } } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/RemoteChunkingJobFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/RemoteChunkingJobFunctionalTests.java index eb13a9945..424942de0 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/RemoteChunkingJobFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/RemoteChunkingJobFunctionalTests.java @@ -40,12 +40,13 @@ import org.springframework.test.context.junit4.SpringRunner; /** * The manager step of the job under test will read data and send chunks to the worker - * (started in {@link RemoteChunkingJobFunctionalTests#setUp()}) for processing and writing. + * (started in {@link RemoteChunkingJobFunctionalTests#setUp()}) for processing and + * writing. * * @author Mahmoud Ben Hassine */ @RunWith(SpringRunner.class) -@ContextConfiguration(classes = {JobRunnerConfiguration.class, ManagerConfiguration.class}) +@ContextConfiguration(classes = { JobRunnerConfiguration.class, ManagerConfiguration.class }) @PropertySource("classpath:remote-chunking.properties") public class RemoteChunkingJobFunctionalTests { @@ -60,13 +61,9 @@ public class RemoteChunkingJobFunctionalTests { @Before public void setUp() throws Exception { - Configuration configuration = - new ConfigurationImpl() - .addAcceptorConfiguration("jms", "tcp://localhost:61616") - .setPersistenceEnabled(false) - .setSecurityEnabled(false) - .setJMXManagementEnabled(false) - .setJournalDatasync(false); + Configuration configuration = new ConfigurationImpl().addAcceptorConfiguration("jms", "tcp://localhost:61616") + .setPersistenceEnabled(false).setSecurityEnabled(false).setJMXManagementEnabled(false) + .setJournalDatasync(false); this.brokerService = new EmbeddedActiveMQ().setConfiguration(configuration).start(); this.workerApplicationContext = new AnnotationConfigApplicationContext(WorkerConfiguration.class); } @@ -84,8 +81,8 @@ public class RemoteChunkingJobFunctionalTests { // then Assert.assertEquals(ExitStatus.COMPLETED.getExitCode(), jobExecution.getExitStatus().getExitCode()); - Assert.assertEquals( - "Waited for 2 results.", // the manager sent 2 chunks ({1, 2, 3} and {4, 5, 6}) to workers + Assert.assertEquals("Waited for 2 results.", // the manager sent 2 chunks ({1, 2, + // 3} and {4, 5, 6}) to workers jobExecution.getExitStatus().getExitDescription()); } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/RemotePartitioningJobFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/RemotePartitioningJobFunctionalTests.java index 13cc92319..163bb898c 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/RemotePartitioningJobFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/RemotePartitioningJobFunctionalTests.java @@ -65,13 +65,9 @@ public abstract class RemotePartitioningJobFunctionalTests { @Before public void setUp() throws Exception { - Configuration configuration = - new ConfigurationImpl() - .addAcceptorConfiguration("jms", "tcp://localhost:61617") - .setPersistenceEnabled(false) - .setSecurityEnabled(false) - .setJMXManagementEnabled(false) - .setJournalDatasync(false); + Configuration configuration = new ConfigurationImpl().addAcceptorConfiguration("jms", "tcp://localhost:61617") + .setPersistenceEnabled(false).setSecurityEnabled(false).setJMXManagementEnabled(false) + .setJournalDatasync(false); this.brokerService = new EmbeddedActiveMQ().setConfiguration(configuration).start(); ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator(); databasePopulator.addScript(new ClassPathResource("/org/springframework/batch/core/schema-drop-hsqldb.sql")); @@ -87,7 +83,8 @@ public abstract class RemotePartitioningJobFunctionalTests { // then Assert.assertEquals(ExitStatus.COMPLETED.getExitCode(), jobExecution.getExitStatus().getExitCode()); - Assert.assertEquals(4, jobExecution.getStepExecutions().size()); // manager + 3 workers + Assert.assertEquals(4, jobExecution.getStepExecutions().size()); // manager + 3 + // workers } @After diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/RemotePartitioningJobWithMessageAggregationFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/RemotePartitioningJobWithMessageAggregationFunctionalTests.java index c15507c79..8fa4950a4 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/RemotePartitioningJobWithMessageAggregationFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/RemotePartitioningJobWithMessageAggregationFunctionalTests.java @@ -21,12 +21,11 @@ import org.springframework.batch.sample.remotepartitioning.aggregating.WorkerCon import org.springframework.test.context.ContextConfiguration; /** - * The manager step of the job under test will create 3 partitions for workers - * to process. + * The manager step of the job under test will create 3 partitions for workers to process. * * @author Mahmoud Ben Hassine */ -@ContextConfiguration(classes = {JobRunnerConfiguration.class, ManagerConfiguration.class}) +@ContextConfiguration(classes = { JobRunnerConfiguration.class, ManagerConfiguration.class }) public class RemotePartitioningJobWithMessageAggregationFunctionalTests extends RemotePartitioningJobFunctionalTests { @Override diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/RemotePartitioningJobWithRepositoryPollingFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/RemotePartitioningJobWithRepositoryPollingFunctionalTests.java index cca8cfb4b..4e7e9e0de 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/RemotePartitioningJobWithRepositoryPollingFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/RemotePartitioningJobWithRepositoryPollingFunctionalTests.java @@ -21,12 +21,11 @@ import org.springframework.batch.sample.remotepartitioning.polling.WorkerConfigu import org.springframework.test.context.ContextConfiguration; /** - * The manager step of the job under test will create 3 partitions for workers - * to process. + * The manager step of the job under test will create 3 partitions for workers to process. * * @author Mahmoud Ben Hassine */ -@ContextConfiguration(classes = {JobRunnerConfiguration.class, ManagerConfiguration.class}) +@ContextConfiguration(classes = { JobRunnerConfiguration.class, ManagerConfiguration.class }) public class RemotePartitioningJobWithRepositoryPollingFunctionalTests extends RemotePartitioningJobFunctionalTests { @Override diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/RestartFileSampleFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/RestartFileSampleFunctionalTests.java index b42ec6429..53139af2d 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/RestartFileSampleFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/RestartFileSampleFunctionalTests.java @@ -39,8 +39,8 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; * @since 2.0 */ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/restartFileSampleJob.xml", - "/job-runner-context.xml" }) +@ContextConfiguration( + locations = { "/simple-job-launcher-context.xml", "/jobs/restartFileSampleJob.xml", "/job-runner-context.xml" }) public class RestartFileSampleFunctionalTests { @Autowired diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/RestartFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/RestartFunctionalTests.java index afe1d59b2..adea0bc07 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/RestartFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/RestartFunctionalTests.java @@ -42,9 +42,10 @@ import org.springframework.test.jdbc.JdbcTestUtils; * @author Mahmoud Ben Hassine */ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/restartSample.xml", - "/job-runner-context.xml" }) +@ContextConfiguration( + locations = { "/simple-job-launcher-context.xml", "/jobs/restartSample.xml", "/job-runner-context.xml" }) public class RestartFunctionalTests { + private JdbcTemplate jdbcTemplate; @Autowired @@ -61,12 +62,10 @@ public class RestartFunctionalTests { } /** - * Job fails on first run, because the module throws exception after - * processing more than half of the input. On the second run, the job should - * finish successfully, because it continues execution where the previous - * run stopped (module throws exception after fixed number of processed - * records). - * + * Job fails on first run, because the module throws exception after processing more + * than half of the input. On the second run, the job should finish successfully, + * because it continues execution where the previous run stopped (module throws + * exception after fixed number of processed records). * @throws Exception */ @Test @@ -99,8 +98,8 @@ public class RestartFunctionalTests { // load the application context and launch the job private JobExecution runJobForRestartTest() throws Exception { return jobLauncherTestUtils - .launchJob(new DefaultJobParametersConverter() - .getJobParameters(PropertiesConverter - .stringToProperties("run.id(long)=1,parameter=true,run.date=20070122,input.file=classpath:data/fixedLengthImportJob/input/20070122.teststream.ImportTradeDataStep.txt"))); + .launchJob(new DefaultJobParametersConverter().getJobParameters(PropertiesConverter.stringToProperties( + "run.id(long)=1,parameter=true,run.date=20070122,input.file=classpath:data/fixedLengthImportJob/input/20070122.teststream.ImportTradeDataStep.txt"))); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/RetrySampleConfigurationTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/RetrySampleConfigurationTests.java index 3284e50e5..c1b55d923 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/RetrySampleConfigurationTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/RetrySampleConfigurationTests.java @@ -31,28 +31,29 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * Checks that expected number of items have been processed. - * + * * @author Robert Kasanicky * @author Dave Syer */ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = { DataSourceConfiguration.class, RetrySampleConfiguration.class, JobRunnerConfiguration.class}) +@ContextConfiguration( + classes = { DataSourceConfiguration.class, RetrySampleConfiguration.class, JobRunnerConfiguration.class }) public class RetrySampleConfigurationTests { @Autowired private GeneratingTradeItemReader itemGenerator; - + @Autowired private RetrySampleItemWriter itemProcessor; - + @Autowired private JobLauncherTestUtils jobLauncherTestUtils; @Test public void testLaunchJob() throws Exception { jobLauncherTestUtils.launchJob(); - //items processed = items read + 2 exceptions - assertEquals(itemGenerator.getLimit()+2, itemProcessor.getCounter()); + // items processed = items read + 2 exceptions + assertEquals(itemGenerator.getLimit() + 2, itemProcessor.getCounter()); } - + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/RetrySampleFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/RetrySampleFunctionalTests.java index 8cb53b02d..3359d5907 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/RetrySampleFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/RetrySampleFunctionalTests.java @@ -28,28 +28,28 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * Checks that expected number of items have been processed. - * + * * @author Robert Kasanicky */ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/retrySample.xml", - "/job-runner-context.xml" }) +@ContextConfiguration( + locations = { "/simple-job-launcher-context.xml", "/jobs/retrySample.xml", "/job-runner-context.xml" }) public class RetrySampleFunctionalTests { @Autowired private GeneratingTradeItemReader itemGenerator; - + @Autowired private RetrySampleItemWriter itemProcessor; - + @Autowired private JobLauncherTestUtils jobLauncherTestUtils; @Test public void testLaunchJob() throws Exception { jobLauncherTestUtils.launchJob(); - //items processed = items read + 2 exceptions - assertEquals(itemGenerator.getLimit()+2, itemProcessor.getCounter()); + // items processed = items read + 2 exceptions + assertEquals(itemGenerator.getLimit() + 2, itemProcessor.getCounter()); } - + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/SkipSampleFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/SkipSampleFunctionalTests.java index 4066ac1f6..1a47cf9b3 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/SkipSampleFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/SkipSampleFunctionalTests.java @@ -58,8 +58,8 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** - * Error is encountered during writing - transaction is rolled back and the - * error item is skipped on second attempt to process the chunk. + * Error is encountered during writing - transaction is rolled back and the error item is + * skipped on second attempt to process the chunk. * * @author Robert Kasanicky * @author Dan Garrette @@ -90,7 +90,8 @@ public class SkipSampleFunctionalTests { public void setUp() { JdbcTestUtils.deleteFromTables(jdbcTemplate, "TRADE", "CUSTOMER"); for (int i = 1; i < 10; i++) { - jdbcTemplate.update("INSERT INTO CUSTOMER (ID, VERSION, NAME, CREDIT) VALUES (" + incrementer.nextIntValue() + ", 0, 'customer" + i + "', 100000)"); + jdbcTemplate.update("INSERT INTO CUSTOMER (ID, VERSION, NAME, CREDIT) VALUES (" + incrementer.nextIntValue() + + ", 0, 'customer" + i + "', 100000)"); } JdbcTestUtils.deleteFromTables(jdbcTemplate, "ERROR_LOG"); } @@ -101,31 +102,30 @@ public class SkipSampleFunctionalTests { * step1 *
        *
      • The step name is saved to the job execution context. - *
      • Read five records from flat file and insert them into the TRADE - * table. - *
      • One record will be invalid, and it will be skipped. Four records will - * be written to the database. - *
      • The skip will result in an exit status that directs the job to run - * the error logging step. + *
      • Read five records from flat file and insert them into the TRADE table. + *
      • One record will be invalid, and it will be skipped. Four records will be + * written to the database. + *
      • The skip will result in an exit status that directs the job to run the error + * logging step. *
      * errorPrint1 *
        - *
      • The error logging step will log one record using the step name from - * the job execution context. + *
      • The error logging step will log one record using the step name from the job + * execution context. *
      * step2 *
        *
      • The step name is saved to the job execution context. *
      • Read four records from the TRADE table and processes them. - *
      • One record will be invalid, and it will be skipped. Three records - * will be stored in the writer's "items" property. - *
      • The skip will result in an exit status that directs the job to run - * the error logging step. + *
      • One record will be invalid, and it will be skipped. Three records will be + * stored in the writer's "items" property. + *
      • The skip will result in an exit status that directs the job to run the error + * logging step. *
      * errorPrint2 *
        - *
      • The error logging step will log one record using the step name from - * the job execution context. + *
      • The error logging step will log one record using the step name from the job + * execution context. *
      *
      *
      @@ -134,8 +134,7 @@ public class SkipSampleFunctionalTests { * step1 *
        *
      • The step name is saved to the job execution context. - *
      • Read five records from flat file and insert them into the TRADE - * table. + *
      • Read five records from flat file and insert them into the TRADE table. *
      • No skips will occur. *
      • The exist status of SUCCESS will direct the job to step2. *
      @@ -189,9 +188,9 @@ public class SkipSampleFunctionalTests { } /* - * When a skippable exception is thrown during reading, the item is skipped - * from the chunk and is not passed to the chunk processor (So it will not be - * processed nor written). + * When a skippable exception is thrown during reading, the item is skipped from the + * chunk and is not passed to the chunk processor (So it will not be processed nor + * written). */ @Test public void testSkippableExceptionDuringRead() throws Exception { @@ -212,14 +211,15 @@ public class SkipSampleFunctionalTests { } /* - * When a skippable exception is thrown during processing, items will re-processed - * one by one and the faulty item will be skipped from the chunk (it will not be - * passed to the writer). + * When a skippable exception is thrown during processing, items will re-processed one + * by one and the faulty item will be skipped from the chunk (it will not be passed to + * the writer). */ @Test public void testSkippableExceptionDuringProcess() throws Exception { // given - ApplicationContext context = new AnnotationConfigApplicationContext(SkippableExceptionDuringProcessSample.class); + ApplicationContext context = new AnnotationConfigApplicationContext( + SkippableExceptionDuringProcessSample.class); JobLauncher jobLauncher = context.getBean(JobLauncher.class); Job job = context.getBean(Job.class); @@ -235,10 +235,11 @@ public class SkipSampleFunctionalTests { } /* - * When a skippable exception is thrown during writing, the item writer (which receives a chunk of items) - * does not know which item caused the issue. Hence, it will "scan" the chunk item by item - * and only the faulty item will be skipped (technically, the commit-interval will be re-set to 1 - * and each item will re-processed/re-written in its own transaction). + * When a skippable exception is thrown during writing, the item writer (which + * receives a chunk of items) does not know which item caused the issue. Hence, it + * will "scan" the chunk item by item and only the faulty item will be skipped + * (technically, the commit-interval will be re-set to 1 and each item will + * re-processed/re-written in its own transaction). */ @Test public void testSkippableExceptionDuringWrite() throws Exception { @@ -274,10 +275,12 @@ public class SkipSampleFunctionalTests { // Both steps contained skips assertEquals(2, JdbcTestUtils.countRowsInTable(jdbcTemplate, "ERROR_LOG")); - assertEquals("2 records were skipped!", jdbcTemplate.queryForObject( - "SELECT MESSAGE from ERROR_LOG where JOB_NAME = ? and STEP_NAME = ?", String.class, "skipJob", "step1")); - assertEquals("2 records were skipped!", jdbcTemplate.queryForObject( - "SELECT MESSAGE from ERROR_LOG where JOB_NAME = ? and STEP_NAME = ?", String.class, "skipJob", "step2")); + assertEquals("2 records were skipped!", + jdbcTemplate.queryForObject("SELECT MESSAGE from ERROR_LOG where JOB_NAME = ? and STEP_NAME = ?", + String.class, "skipJob", "step1")); + assertEquals("2 records were skipped!", + jdbcTemplate.queryForObject("SELECT MESSAGE from ERROR_LOG where JOB_NAME = ? and STEP_NAME = ?", + String.class, "skipJob", "step2")); System.err.println(jobExecution.getExecutionContext()); assertEquals(new BigDecimal("340.45"), jobExecution.getExecutionContext().get(TradeWriter.TOTAL_AMOUNT_KEY)); @@ -312,7 +315,6 @@ public class SkipSampleFunctionalTests { /** * Launch the entire job, including all steps, in order. - * * @return JobExecution, so that the test may validate the exit status */ public long launchJobWithIncrementer() { @@ -342,4 +344,5 @@ public class SkipSampleFunctionalTests { throw new RuntimeException(e); } } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/TaskletJobFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/TaskletJobFunctionalTests.java index be512f9a3..c75f29734 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/TaskletJobFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/TaskletJobFunctionalTests.java @@ -30,8 +30,8 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/taskletJob.xml", - "/job-runner-context.xml" }) +@ContextConfiguration( + locations = { "/simple-job-launcher-context.xml", "/jobs/taskletJob.xml", "/job-runner-context.xml" }) public class TaskletJobFunctionalTests { @Autowired @@ -39,13 +39,14 @@ public class TaskletJobFunctionalTests { @Test public void testLaunchJob() throws Exception { - JobExecution jobExecution = jobLauncherTestUtils.launchJob(new JobParametersBuilder().addString("value", "foo") - .toJobParameters()); + JobExecution jobExecution = jobLauncherTestUtils + .launchJob(new JobParametersBuilder().addString("value", "foo").toJobParameters()); assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); assertEquals("yes", jobExecution.getExecutionContext().getString("done")); } public static class TestBean { + private String value; public void setValue(String value) { @@ -58,19 +59,16 @@ public class TaskletJobFunctionalTests { assertEquals(3, integerValue.intValue()); assertEquals(3.14, doubleValue, 0.01); } + } - + public static class Task { - + public boolean doWork(ChunkContext chunkContext) { - chunkContext. - getStepContext(). - getStepExecution(). - getJobExecution(). - getExecutionContext().put("done", "yes"); + chunkContext.getStepContext().getStepExecution().getJobExecution().getExecutionContext().put("done", "yes"); return true; } - + } } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/TradeJobFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/TradeJobFunctionalTests.java index fc5adf27a..421f314c9 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/TradeJobFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/TradeJobFunctionalTests.java @@ -43,16 +43,22 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.jdbc.JdbcTestUtils; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/tradeJob.xml", - "/job-runner-context.xml" }) +@ContextConfiguration( + locations = { "/simple-job-launcher-context.xml", "/jobs/tradeJob.xml", "/job-runner-context.xml" }) public class TradeJobFunctionalTests { + private static final String GET_TRADES = "select ISIN, QUANTITY, PRICE, CUSTOMER, ID, VERSION from TRADE order by ISIN"; + private static final String GET_CUSTOMERS = "select NAME, CREDIT from CUSTOMER order by NAME"; private List customers; + private List trades; + private int activeRow = 0; + private JdbcTemplate jdbcTemplate; + private Map credits = new HashMap<>(); @Autowired @@ -65,7 +71,7 @@ public class TradeJobFunctionalTests { @Before public void onSetUp() throws Exception { - JdbcTestUtils.deleteFromTables(jdbcTemplate, "TRADE"); + JdbcTestUtils.deleteFromTables(jdbcTemplate, "TRADE"); List> list = jdbcTemplate.queryForList("select NAME, CREDIT from CUSTOMER"); for (Map map : list) { @@ -75,7 +81,7 @@ public class TradeJobFunctionalTests { @After public void tearDown() throws Exception { - JdbcTestUtils.deleteFromTables(jdbcTemplate, "TRADE"); + JdbcTestUtils.deleteFromTables(jdbcTemplate, "TRADE"); } @Test @@ -93,7 +99,7 @@ public class TradeJobFunctionalTests { new Trade("UK21341EAH48", 108, new BigDecimal("109.25"), "customer3"), new Trade("UK21341EAH49", 854, new BigDecimal("123.39"), "customer4")); - jdbcTemplate.query(GET_TRADES, new RowCallbackHandler() { + jdbcTemplate.query(GET_TRADES, new RowCallbackHandler() { @Override public void processRow(ResultSet rs) throws SQLException { Trade trade = trades.get(activeRow++); @@ -108,12 +114,12 @@ public class TradeJobFunctionalTests { assertEquals(activeRow, trades.size()); activeRow = 0; - jdbcTemplate.query(GET_CUSTOMERS, new RowCallbackHandler() { + jdbcTemplate.query(GET_CUSTOMERS, new RowCallbackHandler() { @Override public void processRow(ResultSet rs) throws SQLException { Customer customer = customers.get(activeRow++); - assertEquals(customer.getName(),rs.getString(1)); + assertEquals(customer.getName(), rs.getString(1)); assertEquals(customer.getCredit(), rs.getDouble(2), .01); } }); @@ -122,7 +128,9 @@ public class TradeJobFunctionalTests { } private static class Customer { + private String name; + private double credit; public Customer(String name, double credit) { @@ -169,9 +177,12 @@ public class TradeJobFunctionalTests { if (name == null) { if (other.name != null) return false; - } else if (!name.equals(other.name)) + } + else if (!name.equals(other.name)) return false; return true; } + } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/ColumnRangePartitionerTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/ColumnRangePartitionerTests.java index bea7615ec..ab2aa818a 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/ColumnRangePartitionerTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/ColumnRangePartitionerTests.java @@ -1,53 +1,53 @@ -/* - * Copyright 2009 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.sample.common; - -import static org.junit.Assert.assertEquals; - -import java.util.Map; - -import javax.sql.DataSource; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration -public class ColumnRangePartitionerTests { - - private DataSource dataSource; - - @Autowired - public void setDataSource(DataSource dataSource) { - this.dataSource = dataSource; - } - - private ColumnRangePartitioner partitioner = new ColumnRangePartitioner(); - - @Test - public void testPartition() { - partitioner.setDataSource(dataSource); - partitioner.setTable("CUSTOMER"); - partitioner.setColumn("ID"); - Map partition = partitioner.partition(2); - assertEquals(2, partition.size()); - } - -} +/* + * Copyright 2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.sample.common; + +import static org.junit.Assert.assertEquals; + +import java.util.Map; + +import javax.sql.DataSource; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration +public class ColumnRangePartitionerTests { + + private DataSource dataSource; + + @Autowired + public void setDataSource(DataSource dataSource) { + this.dataSource = dataSource; + } + + private ColumnRangePartitioner partitioner = new ColumnRangePartitioner(); + + @Test + public void testPartition() { + partitioner.setDataSource(dataSource); + partitioner.setTable("CUSTOMER"); + partitioner.setColumn("ID"); + Map partition = partitioner.partition(2); + assertEquals(2, partition.size()); + } + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/CustomItemReaderTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/CustomItemReaderTests.java index 3ab0ada6a..359928f1b 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/CustomItemReaderTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/CustomItemReaderTests.java @@ -30,16 +30,20 @@ import org.springframework.batch.item.ItemStreamException; import org.springframework.lang.Nullable; /** - * Unit test class that was used as part of the Reference Documentation. I'm only including it in the - * code to help keep the reference documentation up to date as the code base shifts. - * + * Unit test class that was used as part of the Reference Documentation. I'm only + * including it in the code to help keep the reference documentation up to date as the + * code base shifts. + * * @author Lucas Ward * */ public class CustomItemReaderTests { + private ItemReader itemReader; - - /* (non-Javadoc) + + /* + * (non-Javadoc) + * * @see junit.framework.TestCase#setUp() */ @Before @@ -48,38 +52,40 @@ public class CustomItemReaderTests { items.add("1"); items.add("2"); items.add("3"); - + itemReader = new CustomItemReader<>(items); } - + @Test - public void testRead() throws Exception{ + public void testRead() throws Exception { assertEquals("1", itemReader.read()); assertEquals("2", itemReader.read()); assertEquals("3", itemReader.read()); assertNull(itemReader.read()); } - + @Test - public void testRestart() throws Exception{ + public void testRestart() throws Exception { ExecutionContext executionContext = new ExecutionContext(); - ((ItemStream)itemReader).open(executionContext); + ((ItemStream) itemReader).open(executionContext); assertEquals("1", itemReader.read()); - ((ItemStream)itemReader).update(executionContext); + ((ItemStream) itemReader).update(executionContext); List items = new ArrayList<>(); items.add("1"); items.add("2"); items.add("3"); itemReader = new CustomItemReader<>(items); - - ((ItemStream)itemReader).open(executionContext); + + ((ItemStream) itemReader).open(executionContext); assertEquals("2", itemReader.read()); } public static class CustomItemReader implements ItemReader, ItemStream { + private static final String CURRENT_INDEX = "current.index"; private List items; + private int currentIndex = 0; public CustomItemReader(List items) { @@ -97,20 +103,23 @@ public class CustomItemReaderTests { @Override public void open(ExecutionContext executionContext) throws ItemStreamException { - if(executionContext.containsKey(CURRENT_INDEX)){ + if (executionContext.containsKey(CURRENT_INDEX)) { currentIndex = executionContext.getInt(CURRENT_INDEX); } - else{ + else { currentIndex = 0; } } @Override - public void close() throws ItemStreamException {} + public void close() throws ItemStreamException { + } @Override public void update(ExecutionContext executionContext) throws ItemStreamException { executionContext.putInt(CURRENT_INDEX, currentIndex); } + } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/CustomItemWriterTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/CustomItemWriterTests.java index 5d3d24b06..9a97b6e52 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/CustomItemWriterTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/CustomItemWriterTests.java @@ -26,24 +26,26 @@ import org.springframework.batch.item.ItemWriter; import org.springframework.batch.support.transaction.TransactionAwareProxyFactory; /** - * Unit test class that was used as part of the Reference Documentation. I'm - * only including it in the code to help keep the reference documentation up to - * date as the code base shifts. - * + * Unit test class that was used as part of the Reference Documentation. I'm only + * including it in the code to help keep the reference documentation up to date as the + * code base shifts. + * * @author Lucas Ward - * + * */ public class CustomItemWriterTests { + @Test public void testFlush() throws Exception { CustomItemWriter itemWriter = new CustomItemWriter<>(); itemWriter.write(Collections.singletonList("1")); assertEquals(1, itemWriter.getOutput().size()); - itemWriter.write(Arrays.asList("2","3")); + itemWriter.write(Arrays.asList("2", "3")); assertEquals(3, itemWriter.getOutput().size()); } public static class CustomItemWriter implements ItemWriter { + private List output = TransactionAwareProxyFactory.createTransactionalList(); @Override @@ -54,5 +56,7 @@ public class CustomItemWriterTests { public List getOutput() { return output; } + } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/ErrorLogTasklet.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/ErrorLogTasklet.java index 653a95fb5..98a698c3e 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/ErrorLogTasklet.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/ErrorLogTasklet.java @@ -35,9 +35,13 @@ import org.springframework.util.Assert; * @since 2.0 */ public class ErrorLogTasklet implements Tasklet, StepExecutionListener { + private JdbcOperations jdbcTemplate; + private String jobName; + private StepExecution stepExecution; + private String stepName; @Nullable @@ -45,7 +49,7 @@ public class ErrorLogTasklet implements Tasklet, StepExecutionListener { public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { Assert.notNull(this.stepName, "Step name not set. Either this class was not registered as a listener " + "or the key 'stepName' was not found in the Job's ExecutionContext."); - this.jdbcTemplate.update("insert into ERROR_LOG values (?, ?, '"+getSkipCount()+" records were skipped!')", + this.jdbcTemplate.update("insert into ERROR_LOG values (?, ?, '" + getSkipCount() + " records were skipped!')", jobName, stepName); return RepeatStatus.FINISHED; } @@ -82,4 +86,5 @@ public class ErrorLogTasklet implements Tasklet, StepExecutionListener { public ExitStatus afterStep(StepExecution stepExecution) { return null; } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/ExceptionThrowingItemReaderProxyTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/ExceptionThrowingItemReaderProxyTests.java index 4f50780d6..63d7a78ce 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/ExceptionThrowingItemReaderProxyTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/ExceptionThrowingItemReaderProxyTests.java @@ -30,42 +30,48 @@ import org.springframework.batch.sample.support.ExceptionThrowingItemReaderProxy public class ExceptionThrowingItemReaderProxyTests { - //expected call count before exception is thrown (exception should be thrown in next iteration) + // expected call count before exception is thrown (exception should be thrown in next + // iteration) private static final int ITER_COUNT = 5; - + @After public void tearDown() throws Exception { RepeatSynchronizationManager.clear(); } - + @SuppressWarnings("serial") @Test public void testProcess() throws Exception { - - //create module and set item processor and iteration count + + // create module and set item processor and iteration count ExceptionThrowingItemReaderProxy itemReader = new ExceptionThrowingItemReaderProxy<>(); - itemReader.setDelegate(new ListItemReader<>(new ArrayList() {{ - add("a"); - add("b"); - add("c"); - add("d"); - add("e"); - add("f"); - }})); + itemReader.setDelegate(new ListItemReader<>(new ArrayList() { + { + add("a"); + add("b"); + add("c"); + add("d"); + add("e"); + add("f"); + } + })); itemReader.setThrowExceptionOnRecordNumber(ITER_COUNT + 1); - + RepeatSynchronizationManager.register(new RepeatContextSupport(null)); - - //call process method multiple times and verify whether exception is thrown when expected + + // call process method multiple times and verify whether exception is thrown when + // expected for (int i = 0; i <= ITER_COUNT; i++) { try { itemReader.read(); assertTrue(i < ITER_COUNT); - } catch (UnexpectedJobExecutionException bce) { - assertEquals(ITER_COUNT,i); + } + catch (UnexpectedJobExecutionException bce) { + assertEquals(ITER_COUNT, i); } } - + } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/OutputFileListenerTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/OutputFileListenerTests.java index a4f95f46c..aabe993c1 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/OutputFileListenerTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/OutputFileListenerTests.java @@ -1,57 +1,60 @@ -/* - * Copyright 2009 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.sample.common; - -import org.junit.Test; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.StepExecution; - -import static org.junit.Assert.assertEquals; - -public class OutputFileListenerTests { - private OutputFileListener listener = new OutputFileListener(); - private StepExecution stepExecution = new StepExecution("foo", new JobExecution(0L), 1L); - - @Test - public void testCreateOutputNameFromInput() { - listener.createOutputNameFromInput(stepExecution); - assertEquals("{outputFile=file:./target/output/foo.csv}", stepExecution.getExecutionContext().toString()); - } - - @Test - public void testSetPath() { - listener.setPath("spam/"); - listener.createOutputNameFromInput(stepExecution); - assertEquals("{outputFile=spam/foo.csv}", stepExecution.getExecutionContext().toString()); - } - - @Test - public void testSetOutputKeyName() { - listener.setPath(""); - listener.setOutputKeyName("spam"); - listener.createOutputNameFromInput(stepExecution); - assertEquals("{spam=foo.csv}", stepExecution.getExecutionContext().toString()); - } - - @Test - public void testSetInputKeyName() { - listener.setPath(""); - listener.setInputKeyName("spam"); - stepExecution.getExecutionContext().putString("spam", "bar"); - listener.createOutputNameFromInput(stepExecution); - assertEquals("bar.csv", stepExecution.getExecutionContext().getString("outputFile")); - } -} +/* + * Copyright 2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.sample.common; + +import org.junit.Test; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.StepExecution; + +import static org.junit.Assert.assertEquals; + +public class OutputFileListenerTests { + + private OutputFileListener listener = new OutputFileListener(); + + private StepExecution stepExecution = new StepExecution("foo", new JobExecution(0L), 1L); + + @Test + public void testCreateOutputNameFromInput() { + listener.createOutputNameFromInput(stepExecution); + assertEquals("{outputFile=file:./target/output/foo.csv}", stepExecution.getExecutionContext().toString()); + } + + @Test + public void testSetPath() { + listener.setPath("spam/"); + listener.createOutputNameFromInput(stepExecution); + assertEquals("{outputFile=spam/foo.csv}", stepExecution.getExecutionContext().toString()); + } + + @Test + public void testSetOutputKeyName() { + listener.setPath(""); + listener.setOutputKeyName("spam"); + listener.createOutputNameFromInput(stepExecution); + assertEquals("{spam=foo.csv}", stepExecution.getExecutionContext().toString()); + } + + @Test + public void testSetInputKeyName() { + listener.setPath(""); + listener.setInputKeyName("spam"); + stepExecution.getExecutionContext().putString("spam", "bar"); + listener.createOutputNameFromInput(stepExecution); + assertEquals("bar.csv", stepExecution.getExecutionContext().getString("outputFile")); + } + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/SkipCheckingDecider.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/SkipCheckingDecider.java index 01f738dd2..55dadc706 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/SkipCheckingDecider.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/SkipCheckingDecider.java @@ -1,37 +1,38 @@ -/* - * Copyright 2008-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.sample.common; - -import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.job.flow.FlowExecutionStatus; -import org.springframework.batch.core.job.flow.JobExecutionDecider; -import org.springframework.lang.Nullable; - -public class SkipCheckingDecider implements JobExecutionDecider { - - @Override - public FlowExecutionStatus decide(JobExecution jobExecution, @Nullable StepExecution stepExecution) { - if (!stepExecution.getExitStatus().getExitCode().equals( - ExitStatus.FAILED.getExitCode()) - && stepExecution.getSkipCount() > 0) { - return new FlowExecutionStatus("COMPLETED WITH SKIPS"); - } else { - return new FlowExecutionStatus(ExitStatus.COMPLETED.getExitCode()); - } - } -} +/* + * Copyright 2008-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.sample.common; + +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.job.flow.FlowExecutionStatus; +import org.springframework.batch.core.job.flow.JobExecutionDecider; +import org.springframework.lang.Nullable; + +public class SkipCheckingDecider implements JobExecutionDecider { + + @Override + public FlowExecutionStatus decide(JobExecution jobExecution, @Nullable StepExecution stepExecution) { + if (!stepExecution.getExitStatus().getExitCode().equals(ExitStatus.FAILED.getExitCode()) + && stepExecution.getSkipCount() > 0) { + return new FlowExecutionStatus("COMPLETED WITH SKIPS"); + } + else { + return new FlowExecutionStatus(ExitStatus.COMPLETED.getExitCode()); + } + } + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/SkipCheckingListener.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/SkipCheckingListener.java index a76553a8c..f71678fad 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/SkipCheckingListener.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/SkipCheckingListener.java @@ -32,6 +32,7 @@ import org.springframework.batch.sample.domain.trade.Trade; public class SkipCheckingListener { private static final Log logger = LogFactory.getLog(SkipCheckingListener.class); + private static int processSkips; @AfterStep @@ -44,7 +45,7 @@ public class SkipCheckingListener { return null; } } - + /** * Convenience method for testing * @return the processSkips @@ -75,4 +76,5 @@ public class SkipCheckingListener { public void saveStepName(StepExecution stepExecution) { stepExecution.getExecutionContext().put("stepName", stepExecution.getStepName()); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/StagingItemReaderTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/StagingItemReaderTests.java index c88f8793e..ec2c45496 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/StagingItemReaderTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/StagingItemReaderTests.java @@ -45,6 +45,7 @@ import org.springframework.transaction.support.TransactionTemplate; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration() public class StagingItemReaderTests { + private JdbcTemplate jdbcTemplate; @Autowired @@ -65,8 +66,8 @@ public class StagingItemReaderTests { @BeforeTransaction public void onSetUpBeforeTransaction() throws Exception { - StepExecution stepExecution = new StepExecution("stepName", new JobExecution(new JobInstance(jobId, - "testJob"), new JobParameters())); + StepExecution stepExecution = new StepExecution("stepName", + new JobExecution(new JobInstance(jobId, "testJob"), new JobParameters())); writer.beforeStep(stepExecution); writer.write(Arrays.asList("FOO", "BAR", "SPAM", "BUCKET")); reader.beforeStep(stepExecution); @@ -82,8 +83,7 @@ public class StagingItemReaderTests { @Test public void testReaderWithProcessorUpdatesProcessIndicator() throws Exception { long id = jdbcTemplate.queryForObject("SELECT MIN(ID) from BATCH_STAGING where JOB_ID=?", Long.class, jobId); - String before = jdbcTemplate.queryForObject("SELECT PROCESSED from BATCH_STAGING where ID=?", - String.class, id); + String before = jdbcTemplate.queryForObject("SELECT PROCESSED from BATCH_STAGING where ID=?", String.class, id); assertEquals(StagingItemWriter.NEW, before); ProcessIndicatorItemWrapper wrapper = reader.read(); @@ -94,8 +94,7 @@ public class StagingItemReaderTests { updater.setJdbcTemplate(jdbcTemplate); updater.process(wrapper); - String after = jdbcTemplate.queryForObject("SELECT PROCESSED from BATCH_STAGING where ID=?", - String.class, id); + String after = jdbcTemplate.queryForObject("SELECT PROCESSED from BATCH_STAGING where ID=?", String.class, id); assertEquals(StagingItemWriter.DONE, after); } @@ -117,8 +116,7 @@ public class StagingItemReaderTests { } }); long id = jdbcTemplate.queryForObject("SELECT MIN(ID) from BATCH_STAGING where JOB_ID=?", Long.class, jobId); - String before = jdbcTemplate.queryForObject("SELECT PROCESSED from BATCH_STAGING where ID=?", - String.class, id); + String before = jdbcTemplate.queryForObject("SELECT PROCESSED from BATCH_STAGING where ID=?", String.class, id); assertEquals(StagingItemWriter.DONE, before); } @@ -132,7 +130,8 @@ public class StagingItemReaderTests { @Override public Long doInTransaction(TransactionStatus transactionStatus) { - long id = jdbcTemplate.queryForObject("SELECT MIN(ID) from BATCH_STAGING where JOB_ID=?", Long.class, jobId); + long id = jdbcTemplate.queryForObject("SELECT MIN(ID) from BATCH_STAGING where JOB_ID=?", Long.class, + jobId); String before = jdbcTemplate.queryForObject("SELECT PROCESSED from BATCH_STAGING where ID=?", String.class, id); assertEquals(StagingItemWriter.NEW, before); @@ -146,8 +145,9 @@ public class StagingItemReaderTests { } }); - String after = jdbcTemplate.queryForObject("SELECT PROCESSED from BATCH_STAGING where ID=?", - String.class, idToUse); + String after = jdbcTemplate.queryForObject("SELECT PROCESSED from BATCH_STAGING where ID=?", String.class, + idToUse); assertEquals(StagingItemWriter.NEW, after); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/StagingItemWriterTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/StagingItemWriterTests.java index 4f9513dac..eb4257e01 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/StagingItemWriterTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/common/StagingItemWriterTests.java @@ -38,6 +38,7 @@ import org.springframework.transaction.annotation.Transactional; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration public class StagingItemWriterTests { + private JdbcTemplate jdbcTemplate; @Autowired @@ -50,8 +51,8 @@ public class StagingItemWriterTests { @Before public void onSetUpBeforeTransaction() throws Exception { - StepExecution stepExecution = new StepExecution("stepName", new JobExecution(new JobInstance(12L, - "testJob"), new JobParameters())); + StepExecution stepExecution = new StepExecution("stepName", + new JobExecution(new JobInstance(12L, "testJob"), new JobParameters())); writer.beforeStep(stepExecution); } @@ -63,4 +64,5 @@ public class StagingItemWriterTests { int after = JdbcTestUtils.countRowsInTable(jdbcTemplate, "BATCH_STAGING"); assertEquals(before + 1, after); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/football/internal/JdbcGameDaoIntegrationTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/football/internal/JdbcGameDaoIntegrationTests.java index 77107e8b3..1f74bfcb9 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/football/internal/JdbcGameDaoIntegrationTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/football/internal/JdbcGameDaoIntegrationTests.java @@ -41,10 +41,13 @@ import org.springframework.transaction.annotation.Transactional; * */ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = {"/data-source-context.xml"}) +@ContextConfiguration(locations = { "/data-source-context.xml" }) public class JdbcGameDaoIntegrationTests { + private JdbcGameDao gameDao; + private Game game = new Game(); + private JdbcOperations jdbcTemplate; @Autowired @@ -74,7 +77,8 @@ public class JdbcGameDaoIntegrationTests { game.setTotalTd(2); } - @Transactional @Test + @Transactional + @Test public void testWrite() { gameDao.write(Collections.singletonList(game)); @@ -84,6 +88,7 @@ public class JdbcGameDaoIntegrationTests { } private static class GameRowMapper implements RowMapper { + @Override public Game mapRow(ResultSet rs, int arg1) throws SQLException { if (rs == null) { @@ -109,5 +114,7 @@ public class JdbcGameDaoIntegrationTests { return game; } + } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/football/internal/JdbcPlayerDaoIntegrationTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/football/internal/JdbcPlayerDaoIntegrationTests.java index abf366832..eb337e9bb 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/football/internal/JdbcPlayerDaoIntegrationTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/football/internal/JdbcPlayerDaoIntegrationTests.java @@ -40,11 +40,15 @@ import org.springframework.transaction.annotation.Transactional; * */ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = {"/data-source-context.xml"}) +@ContextConfiguration(locations = { "/data-source-context.xml" }) public class JdbcPlayerDaoIntegrationTests { + private JdbcPlayerDao playerDao; + private Player player; + private static final String GET_PLAYER = "SELECT * from PLAYERS"; + private JdbcTemplate jdbcTemplate; @Autowired @@ -69,9 +73,9 @@ public class JdbcPlayerDaoIntegrationTests { @Test @Transactional - public void testSavePlayer(){ + public void testSavePlayer() { playerDao.savePlayer(player); - jdbcTemplate.query(GET_PLAYER, new RowCallbackHandler() { + jdbcTemplate.query(GET_PLAYER, new RowCallbackHandler() { @Override public void processRow(ResultSet rs) throws SQLException { assertEquals(rs.getString("PLAYER_ID"), "AKFJDL00"); @@ -83,4 +87,5 @@ public class JdbcPlayerDaoIntegrationTests { } }); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/football/internal/JdbcPlayerSummaryDaoIntegrationTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/football/internal/JdbcPlayerSummaryDaoIntegrationTests.java index 78b116c79..ed522ada9 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/football/internal/JdbcPlayerSummaryDaoIntegrationTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/football/internal/JdbcPlayerSummaryDaoIntegrationTests.java @@ -40,8 +40,11 @@ import org.springframework.transaction.annotation.Transactional; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "/data-source-context.xml" }) public class JdbcPlayerSummaryDaoIntegrationTests { + private JdbcPlayerSummaryDao playerSummaryDao; + private PlayerSummary summary; + private JdbcTemplate jdbcTemplate; @Autowired @@ -80,4 +83,5 @@ public class JdbcPlayerSummaryDaoIntegrationTests { assertEquals(summary, testSummary); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/multiline/AggregateItemFieldSetMapperTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/multiline/AggregateItemFieldSetMapperTests.java index af2ca6c6b..3d88a5c65 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/multiline/AggregateItemFieldSetMapperTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/multiline/AggregateItemFieldSetMapperTests.java @@ -26,6 +26,7 @@ import org.springframework.batch.item.file.transform.DefaultFieldSet; import org.springframework.batch.item.file.transform.FieldSet; public class AggregateItemFieldSetMapperTests { + private AggregateItemFieldSetMapper mapper = new AggregateItemFieldSetMapper<>(); @Test @@ -73,4 +74,5 @@ public class AggregateItemFieldSetMapperTests { }); assertEquals("foo", mapper.mapFieldSet(new DefaultFieldSet(new String[] { "FOO" })).getItem()); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/multiline/AggregateItemReaderTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/multiline/AggregateItemReaderTests.java index 1b427a17d..fa386ede4 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/multiline/AggregateItemReaderTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/multiline/AggregateItemReaderTests.java @@ -24,7 +24,9 @@ import org.springframework.batch.item.ItemReader; import org.springframework.lang.Nullable; public class AggregateItemReaderTests { + private ItemReader> input; + private AggregateItemReader provider; @Before @@ -68,4 +70,5 @@ public class AggregateItemReaderTests { assertNull(provider.read()); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/multiline/AggregateItemTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/multiline/AggregateItemTests.java index 2578818cb..b1dae3588 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/multiline/AggregateItemTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/multiline/AggregateItemTests.java @@ -26,8 +26,10 @@ import org.junit.Test; * */ public class AggregateItemTests { + /** - * Test method for {@link org.springframework.batch.sample.domain.multiline.AggregateItem#getFooter()}. + * Test method for + * {@link org.springframework.batch.sample.domain.multiline.AggregateItem#getFooter()}. */ @Test public void testGetFooter() { @@ -36,7 +38,8 @@ public class AggregateItemTests { } /** - * Test method for {@link org.springframework.batch.sample.domain.multiline.AggregateItem#getHeader()}. + * Test method for + * {@link org.springframework.batch.sample.domain.multiline.AggregateItem#getHeader()}. */ @Test public void testGetHeader() { @@ -49,7 +52,8 @@ public class AggregateItemTests { try { AggregateItem.getHeader().getItem(); fail("Expected IllegalStateException"); - } catch(IllegalStateException e) { + } + catch (IllegalStateException e) { // expected } } @@ -59,8 +63,10 @@ public class AggregateItemTests { try { AggregateItem.getFooter().getItem(); fail("Expected IllegalStateException"); - } catch(IllegalStateException e) { + } + catch (IllegalStateException e) { // expected } } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/AddressFieldSetMapperTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/AddressFieldSetMapperTests.java index a90b2c7bd..500414029 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/AddressFieldSetMapperTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/AddressFieldSetMapperTests.java @@ -22,12 +22,19 @@ import org.springframework.batch.sample.domain.order.internal.mapper.AddressFiel import org.springframework.batch.sample.support.AbstractFieldSetMapperTests; public class AddressFieldSetMapperTests extends AbstractFieldSetMapperTests { + private static final String ADDRESSEE = "Jan Hrach"; + private static final String ADDRESS_LINE_1 = "Plynarenska 7c"; + private static final String ADDRESS_LINE_2 = ""; + private static final String CITY = "Bratislava"; + private static final String STATE = ""; + private static final String COUNTRY = "Slovakia"; + private static final String ZIP_CODE = "80000"; @Override @@ -58,4 +65,5 @@ public class AddressFieldSetMapperTests extends AbstractFieldSetMapperTests { protected FieldSetMapper
      fieldSetMapper() { return new AddressFieldSetMapper(); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/BillingFieldSetMapperTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/BillingFieldSetMapperTests.java index 4b50aeb78..9daec6487 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/BillingFieldSetMapperTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/BillingFieldSetMapperTests.java @@ -22,7 +22,9 @@ import org.springframework.batch.sample.domain.order.internal.mapper.BillingFiel import org.springframework.batch.sample.support.AbstractFieldSetMapperTests; public class BillingFieldSetMapperTests extends AbstractFieldSetMapperTests { + private static final String PAYMENT_ID = "777"; + private static final String PAYMENT_DESC = "My last penny"; @Override @@ -45,4 +47,5 @@ public class BillingFieldSetMapperTests extends AbstractFieldSetMapperTests { protected FieldSetMapper fieldSetMapper() { return new BillingFieldSetMapper(); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/CustomerFieldSetMapperTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/CustomerFieldSetMapperTests.java index 8b8a5514c..6e013d3a2 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/CustomerFieldSetMapperTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/CustomerFieldSetMapperTests.java @@ -22,12 +22,19 @@ import org.springframework.batch.sample.domain.order.internal.mapper.CustomerFie import org.springframework.batch.sample.support.AbstractFieldSetMapperTests; public class CustomerFieldSetMapperTests extends AbstractFieldSetMapperTests { + private static final boolean BUSINESS_CUSTOMER = false; + private static final String FIRST_NAME = "Jan"; + private static final String LAST_NAME = "Hrach"; + private static final String MIDDLE_NAME = ""; + private static final boolean REGISTERED = true; + private static final long REG_ID = 1; + private static final boolean VIP = true; @Override @@ -59,4 +66,5 @@ public class CustomerFieldSetMapperTests extends AbstractFieldSetMapperTests { protected FieldSetMapper fieldSetMapper() { return new CustomerFieldSetMapper(); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/HeaderFieldSetMapperTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/HeaderFieldSetMapperTests.java index a31f536b5..451cdcc8f 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/HeaderFieldSetMapperTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/HeaderFieldSetMapperTests.java @@ -24,7 +24,9 @@ import org.springframework.batch.sample.domain.order.internal.mapper.HeaderField import org.springframework.batch.sample.support.AbstractFieldSetMapperTests; public class HeaderFieldSetMapperTests extends AbstractFieldSetMapperTests { + private static final long ORDER_ID = 1; + private static final String DATE = "2007-01-01"; @Override @@ -50,4 +52,5 @@ public class HeaderFieldSetMapperTests extends AbstractFieldSetMapperTests { protected FieldSetMapper fieldSetMapper() { return new HeaderFieldSetMapper(); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/OrderItemFieldSetMapperTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/OrderItemFieldSetMapperTests.java index 6f1cb16d7..677fcc1e4 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/OrderItemFieldSetMapperTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/OrderItemFieldSetMapperTests.java @@ -24,13 +24,21 @@ import org.springframework.batch.sample.domain.order.internal.mapper.OrderItemFi import org.springframework.batch.sample.support.AbstractFieldSetMapperTests; public class OrderItemFieldSetMapperTests extends AbstractFieldSetMapperTests { + private static final BigDecimal DISCOUNT_AMOUNT = new BigDecimal("1"); + private static final BigDecimal DISCOUNT_PERC = new BigDecimal("2"); + private static final BigDecimal HANDLING_PRICE = new BigDecimal("3"); + private static final long ITEM_ID = 4; + private static final BigDecimal PRICE = new BigDecimal("5"); + private static final int QUANTITY = 6; + private static final BigDecimal SHIPPING_PRICE = new BigDecimal("7"); + private static final BigDecimal TOTAL_PRICE = new BigDecimal("8"); @Override @@ -64,4 +72,5 @@ public class OrderItemFieldSetMapperTests extends AbstractFieldSetMapperTests { protected FieldSetMapper fieldSetMapper() { return new OrderItemFieldSetMapper(); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/OrderItemReaderTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/OrderItemReaderTests.java index aca273d26..d4fdaa764 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/OrderItemReaderTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/OrderItemReaderTests.java @@ -31,7 +31,9 @@ import org.springframework.batch.item.file.transform.FieldSet; import org.springframework.batch.sample.domain.order.internal.OrderItemReader; public class OrderItemReaderTests { + private OrderItemReader provider; + private ItemReader
      input; @Before @@ -44,14 +46,13 @@ public class OrderItemReaderTests { } /* - * OrderItemProvider is responsible for retrieving validated value object - * from input source. OrderItemProvider.next(): - reads lines from the input - * source - returned as fieldsets - pass fieldsets to the mapper - mapper - * will create value object - pass value object to validator - returns - * validated object - * - * In testNext method we are going to test these responsibilities. So we - * need create mock objects for input source, mapper and validator. + * OrderItemProvider is responsible for retrieving validated value object from input + * source. OrderItemProvider.next(): - reads lines from the input source - returned as + * fieldsets - pass fieldsets to the mapper - mapper will create value object - pass + * value object to validator - returns validated object + * + * In testNext method we are going to test these responsibilities. So we need create + * mock objects for input source, mapper and validator. */ @Test @SuppressWarnings("unchecked") @@ -63,11 +64,11 @@ public class OrderItemReaderTests { FieldSet billingInfoFS = new DefaultFieldSet(new String[] { BillingInfo.LINE_ID_BILLING_INFO }); FieldSet shippingInfoFS = new DefaultFieldSet(new String[] { ShippingInfo.LINE_ID_SHIPPING_INFO }); FieldSet itemFS = new DefaultFieldSet(new String[] { LineItem.LINE_ID_ITEM }); - FieldSet footerFS = new DefaultFieldSet(new String[] { Order.LINE_ID_FOOTER, "100", "3", "3" }, new String[] { - "ID", "TOTAL_PRICE", "TOTAL_LINE_ITEMS", "TOTAL_ITEMS" }); + FieldSet footerFS = new DefaultFieldSet(new String[] { Order.LINE_ID_FOOTER, "100", "3", "3" }, + new String[] { "ID", "TOTAL_PRICE", "TOTAL_LINE_ITEMS", "TOTAL_ITEMS" }); - when(input.read()).thenReturn(headerFS, customerFS, billingFS, shippingFS, billingInfoFS, - shippingInfoFS, itemFS, itemFS, itemFS, footerFS, null); + when(input.read()).thenReturn(headerFS, customerFS, billingFS, shippingFS, billingInfoFS, shippingInfoFS, + itemFS, itemFS, itemFS, footerFS, null); Order order = new Order(); Customer customer = new Customer(); @@ -115,4 +116,5 @@ public class OrderItemReaderTests { assertNull(provider.read()); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/ShippingFieldSetMapperTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/ShippingFieldSetMapperTests.java index 2d054dd16..c20add4a6 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/ShippingFieldSetMapperTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/ShippingFieldSetMapperTests.java @@ -22,8 +22,11 @@ import org.springframework.batch.sample.domain.order.internal.mapper.ShippingFie import org.springframework.batch.sample.support.AbstractFieldSetMapperTests; public class ShippingFieldSetMapperTests extends AbstractFieldSetMapperTests { + private static final String SHIPPER_ID = "1"; + private static final String SHIPPING_INFO = "most interesting and informative shipping info ever"; + private static final String SHIPPING_TYPE_ID = "X"; @Override @@ -39,7 +42,8 @@ public class ShippingFieldSetMapperTests extends AbstractFieldSetMapperTests { protected FieldSet fieldSet() { String[] tokens = new String[] { SHIPPER_ID, SHIPPING_INFO, SHIPPING_TYPE_ID }; String[] columnNames = new String[] { ShippingFieldSetMapper.SHIPPER_ID_COLUMN, - ShippingFieldSetMapper.ADDITIONAL_SHIPPING_INFO_COLUMN, ShippingFieldSetMapper.SHIPPING_TYPE_ID_COLUMN }; + ShippingFieldSetMapper.ADDITIONAL_SHIPPING_INFO_COLUMN, + ShippingFieldSetMapper.SHIPPING_TYPE_ID_COLUMN }; return new DefaultFieldSet(tokens, columnNames); } @@ -47,4 +51,5 @@ public class ShippingFieldSetMapperTests extends AbstractFieldSetMapperTests { protected FieldSetMapper fieldSetMapper() { return new ShippingFieldSetMapper(); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/internal/validator/OrderValidatorTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/internal/validator/OrderValidatorTests.java index cc2d88f71..ebafe70fa 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/internal/validator/OrderValidatorTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/internal/validator/OrderValidatorTests.java @@ -283,7 +283,8 @@ public class OrderValidatorTests { info = new ShippingInfo(); info.setShipperId("FEDX"); info.setShippingTypeId("EXP"); - info.setShippingInfo("12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"); + info.setShippingInfo( + "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"); order.setShipping(info); errors = new BeanPropertyBindingResult(order, "validOrder"); @@ -340,7 +341,8 @@ public class OrderValidatorTests { assertEquals("error.lineitems.totalprice", errors.getFieldErrors("lineItems").get(6).getCode()); } - private LineItem buildLineItem(long itemId, double price, int discountPercentage, int discountAmount, long shippingPrice, long handlingPrice, int qty, int totalPrice) { + private LineItem buildLineItem(long itemId, double price, int discountPercentage, int discountAmount, + long shippingPrice, long handlingPrice, int qty, int totalPrice) { LineItem invalidId = new LineItem(); invalidId.setItemId(itemId); invalidId.setPrice(new BigDecimal(price)); @@ -352,4 +354,5 @@ public class OrderValidatorTests { invalidId.setTotalPrice(new BigDecimal(totalPrice)); return invalidId; } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/CompositeCustomerUpdateLineTokenizerTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/CompositeCustomerUpdateLineTokenizerTests.java index 49f2da26a..558d1ea32 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/CompositeCustomerUpdateLineTokenizerTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/CompositeCustomerUpdateLineTokenizerTests.java @@ -29,53 +29,59 @@ import org.springframework.lang.Nullable; * */ public class CompositeCustomerUpdateLineTokenizerTests { + private StubLineTokenizer customerTokenizer; + private FieldSet customerFieldSet = new DefaultFieldSet(null); + private FieldSet footerFieldSet = new DefaultFieldSet(null); + private CompositeCustomerUpdateLineTokenizer compositeTokenizer; - + @Before - public void init(){ + public void init() { customerTokenizer = new StubLineTokenizer(customerFieldSet); compositeTokenizer = new CompositeCustomerUpdateLineTokenizer(); compositeTokenizer.setCustomerTokenizer(customerTokenizer); compositeTokenizer.setFooterTokenizer(new StubLineTokenizer(footerFieldSet)); } - + @Test - public void testCustomerAdd() throws Exception{ + public void testCustomerAdd() throws Exception { String customerAddLine = "AFDASFDASFDFSA"; FieldSet fs = compositeTokenizer.tokenize(customerAddLine); assertEquals(customerFieldSet, fs); assertEquals(customerAddLine, customerTokenizer.getTokenizedLine()); } - + @Test - public void testCustomerDelete() throws Exception{ + public void testCustomerDelete() throws Exception { String customerAddLine = "DFDASFDASFDFSA"; FieldSet fs = compositeTokenizer.tokenize(customerAddLine); assertEquals(customerFieldSet, fs); assertEquals(customerAddLine, customerTokenizer.getTokenizedLine()); } - + @Test - public void testCustomerUpdate() throws Exception{ + public void testCustomerUpdate() throws Exception { String customerAddLine = "UFDASFDASFDFSA"; FieldSet fs = compositeTokenizer.tokenize(customerAddLine); assertEquals(customerFieldSet, fs); assertEquals(customerAddLine, customerTokenizer.getTokenizedLine()); } - - @Test(expected=IllegalArgumentException.class) - public void testInvalidLine() throws Exception{ + + @Test(expected = IllegalArgumentException.class) + public void testInvalidLine() throws Exception { String invalidLine = "INVALID"; compositeTokenizer.tokenize(invalidLine); } - private static class StubLineTokenizer implements LineTokenizer{ + private static class StubLineTokenizer implements LineTokenizer { + private final FieldSet fieldSetToReturn; + private String tokenizedLine; - + public StubLineTokenizer(FieldSet fieldSetToReturn) { this.fieldSetToReturn = fieldSetToReturn; } @@ -85,9 +91,11 @@ public class CompositeCustomerUpdateLineTokenizerTests { this.tokenizedLine = line; return fieldSetToReturn; } - + public String getTokenizedLine() { return tokenizedLine; } + } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/CustomerUpdateProcessorTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/CustomerUpdateProcessorTests.java index 250f24d6c..93178702c 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/CustomerUpdateProcessorTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/CustomerUpdateProcessorTests.java @@ -33,53 +33,57 @@ import org.junit.Test; * */ public class CustomerUpdateProcessorTests { + private CustomerDao customerDao; + private InvalidCustomerLogger logger; + private CustomerUpdateProcessor processor; - + @Before - public void init(){ + public void init() { customerDao = mock(CustomerDao.class); logger = mock(InvalidCustomerLogger.class); processor = new CustomerUpdateProcessor(); processor.setCustomerDao(customerDao); processor.setInvalidCustomerLogger(logger); } - + @Test - public void testSuccessfulAdd() throws Exception{ + public void testSuccessfulAdd() throws Exception { CustomerUpdate customerUpdate = new CustomerUpdate(ADD, "test customer", new BigDecimal("232.2")); when(customerDao.getCustomerByName("test customer")).thenReturn(null); assertEquals(customerUpdate, processor.process(customerUpdate)); } - + @Test - public void testInvalidAdd() throws Exception{ + public void testInvalidAdd() throws Exception { CustomerUpdate customerUpdate = new CustomerUpdate(ADD, "test customer", new BigDecimal("232.2")); when(customerDao.getCustomerByName("test customer")).thenReturn(new CustomerCredit()); logger.log(customerUpdate); assertNull("Processor should return null", processor.process(customerUpdate)); } - + @Test - public void testDelete() throws Exception{ + public void testDelete() throws Exception { CustomerUpdate customerUpdate = new CustomerUpdate(DELETE, "test customer", new BigDecimal("232.2")); logger.log(customerUpdate); assertNull("Processor should return null", processor.process(customerUpdate)); } - + @Test - public void testSuccessfulUpdate() throws Exception{ + public void testSuccessfulUpdate() throws Exception { CustomerUpdate customerUpdate = new CustomerUpdate(UPDATE, "test customer", new BigDecimal("232.2")); when(customerDao.getCustomerByName("test customer")).thenReturn(new CustomerCredit()); assertEquals(customerUpdate, processor.process(customerUpdate)); } - + @Test - public void testInvalidUpdate() throws Exception{ + public void testInvalidUpdate() throws Exception { CustomerUpdate customerUpdate = new CustomerUpdate(UPDATE, "test customer", new BigDecimal("232.2")); when(customerDao.getCustomerByName("test customer")).thenReturn(null); logger.log(customerUpdate); assertNull("Processor should return null", processor.process(customerUpdate)); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/TradeTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/TradeTests.java index aba24b005..e71230f4a 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/TradeTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/TradeTests.java @@ -23,13 +23,15 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; public class TradeTests { + @Test - public void testEquality(){ + public void testEquality() { Trade trade1 = new Trade("isin", 1, new BigDecimal("1.1"), "customer1"); Trade trade1Clone = new Trade("isin", 1, new BigDecimal("1.1"), "customer1"); Trade trade2 = new Trade("isin", 1, new BigDecimal("2.3"), "customer2"); - + assertEquals(trade1, trade1Clone); assertFalse(trade1.equals(trade2)); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/CustomerCreditIncreaseProcessorTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/CustomerCreditIncreaseProcessorTests.java index 1d643c3cf..08fee4f57 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/CustomerCreditIncreaseProcessorTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/CustomerCreditIncreaseProcessorTests.java @@ -24,10 +24,11 @@ import org.springframework.batch.sample.domain.trade.CustomerCredit; /** * Tests for {@link CustomerCreditIncreaseProcessor}. - * + * * @author Robert Kasanicky */ public class CustomerCreditIncreaseProcessorTests { + private CustomerCreditIncreaseProcessor tested = new CustomerCreditIncreaseProcessor(); /* @@ -38,7 +39,9 @@ public class CustomerCreditIncreaseProcessorTests { final BigDecimal oldCredit = new BigDecimal("10.54"); CustomerCredit customerCredit = new CustomerCredit(); customerCredit.setCredit(oldCredit); - - assertEquals(oldCredit.add(CustomerCreditIncreaseProcessor.FIXED_AMOUNT),tested.process(customerCredit).getCredit()); + + assertEquals(oldCredit.add(CustomerCreditIncreaseProcessor.FIXED_AMOUNT), + tested.process(customerCredit).getCredit()); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/CustomerCreditRowMapperTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/CustomerCreditRowMapperTests.java index 70db7ebc0..f8271ab7f 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/CustomerCreditRowMapperTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/CustomerCreditRowMapperTests.java @@ -28,7 +28,9 @@ import org.springframework.jdbc.core.RowMapper; public class CustomerCreditRowMapperTests extends AbstractRowMapperTests { private static final int ID = 12; + private static final String CUSTOMER = "Jozef Mak"; + private static final BigDecimal CREDIT = new BigDecimal("0.1"); @Override @@ -51,4 +53,5 @@ public class CustomerCreditRowMapperTests extends AbstractRowMapperTests, ItemStream { } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/GeneratingItemReaderTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/GeneratingItemReaderTests.java index 24f7778c0..201951728 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/GeneratingItemReaderTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/GeneratingItemReaderTests.java @@ -21,29 +21,29 @@ import org.junit.Test; /** * Tests for {@link GeneratingTradeItemReader}. - * + * * @author Robert Kasanicky */ public class GeneratingItemReaderTests { private GeneratingTradeItemReader reader = new GeneratingTradeItemReader(); - + /* - * Generates a given number of not-null records, - * consecutive calls return null. + * Generates a given number of not-null records, consecutive calls return null. */ @Test public void testRead() throws Exception { int counter = 0; int limit = 10; reader.setLimit(limit); - + while (reader.read() != null) { counter++; } - + assertEquals(null, reader.read()); assertEquals(limit, counter); assertEquals(counter, reader.getCounter()); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/ItemTrackingTradeItemWriter.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/ItemTrackingTradeItemWriter.java index f5c870b7c..2cfd8f486 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/ItemTrackingTradeItemWriter.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/ItemTrackingTradeItemWriter.java @@ -27,8 +27,11 @@ import org.springframework.jdbc.core.JdbcOperations; import org.springframework.jdbc.core.JdbcTemplate; public class ItemTrackingTradeItemWriter implements ItemWriter { + private List items = new ArrayList<>(); + private String writeFailureISIN; + private JdbcOperations jdbcTemplate; public void setDataSource(DataSource dataSource) { @@ -55,11 +58,12 @@ public class ItemTrackingTradeItemWriter implements ItemWriter { newItems.add(t); if (jdbcTemplate != null) { - jdbcTemplate.update("UPDATE TRADE set VERSION=? where ID=? and version=?", t.getVersion() + 1, t - .getId(), t.getVersion()); + jdbcTemplate.update("UPDATE TRADE set VERSION=? where ID=? and version=?", t.getVersion() + 1, + t.getId(), t.getVersion()); } } this.items.addAll(newItems); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/JdbcCustomerDebitDaoTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/JdbcCustomerDebitDaoTests.java index 084a86fdd..071fd1de8 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/JdbcCustomerDebitDaoTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/JdbcCustomerDebitDaoTests.java @@ -37,6 +37,7 @@ import org.springframework.transaction.annotation.Transactional; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration() public class JdbcCustomerDebitDaoTests { + private JdbcOperations jdbcTemplate; @Autowired @@ -50,7 +51,7 @@ public class JdbcCustomerDebitDaoTests { @Test @Transactional public void testWrite() { - jdbcTemplate.execute("INSERT INTO CUSTOMER VALUES (99, 0, 'testName', 100)"); + jdbcTemplate.execute("INSERT INTO CUSTOMER VALUES (99, 0, 'testName', 100)"); CustomerDebit customerDebit = new CustomerDebit(); customerDebit.setName("testName"); @@ -58,12 +59,12 @@ public class JdbcCustomerDebitDaoTests { writer.write(customerDebit); - jdbcTemplate.query("SELECT name, credit FROM CUSTOMER WHERE name = 'testName'", - new RowCallbackHandler() { - @Override - public void processRow(ResultSet rs) throws SQLException { - assertEquals(95, rs.getLong("credit")); - } - }); + jdbcTemplate.query("SELECT name, credit FROM CUSTOMER WHERE name = 'testName'", new RowCallbackHandler() { + @Override + public void processRow(ResultSet rs) throws SQLException { + assertEquals(95, rs.getLong("credit")); + } + }); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/JdbcTradeWriterTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/JdbcTradeWriterTests.java index 7ad44436b..b08ce167d 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/JdbcTradeWriterTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/JdbcTradeWriterTests.java @@ -38,10 +38,13 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.transaction.annotation.Transactional; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = {"/data-source-context.xml"}) +@ContextConfiguration(locations = { "/data-source-context.xml" }) public class JdbcTradeWriterTests implements InitializingBean { + private JdbcOperations jdbcTemplate; + private JdbcTradeDao writer; + private AbstractDataFieldMaxValueIncrementer incrementer; @Autowired @@ -73,7 +76,7 @@ public class JdbcTradeWriterTests implements InitializingBean { public void processRow(ResultSet rs) throws SQLException { assertEquals("testCustomer", rs.getString("CUSTOMER")); assertEquals(new BigDecimal(Double.toString(99.69)), rs.getBigDecimal("PRICE")); - assertEquals(5,rs.getLong("QUANTITY")); + assertEquals(5, rs.getLong("QUANTITY")); } }); } @@ -82,4 +85,5 @@ public class JdbcTradeWriterTests implements InitializingBean { public void afterPropertiesSet() throws Exception { this.writer.setIncrementer(incrementer); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/TradeFieldSetMapperTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/TradeFieldSetMapperTests.java index 7508fd675..76f7b4e93 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/TradeFieldSetMapperTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/TradeFieldSetMapperTests.java @@ -24,9 +24,13 @@ import org.springframework.batch.sample.domain.trade.Trade; import org.springframework.batch.sample.support.AbstractFieldSetMapperTests; public class TradeFieldSetMapperTests extends AbstractFieldSetMapperTests { + private static final String CUSTOMER = "Mike Tomcat"; + private static final BigDecimal PRICE = new BigDecimal(1.3); + private static final long QUANTITY = 7; + private static final String ISIN = "fj893gnsalX"; @Override @@ -54,4 +58,5 @@ public class TradeFieldSetMapperTests extends AbstractFieldSetMapperTests { protected FieldSetMapper fieldSetMapper() { return new TradeFieldSetMapper(); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/TradeProcessorTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/TradeProcessorTests.java index efb82828e..793eced79 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/TradeProcessorTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/TradeProcessorTests.java @@ -25,23 +25,26 @@ import org.springframework.batch.sample.domain.trade.Trade; import org.springframework.batch.sample.domain.trade.TradeDao; public class TradeProcessorTests { + private TradeDao writer; + private TradeWriter processor; - + @Before public void setUp() { writer = mock(TradeDao.class); - + processor = new TradeWriter(); processor.setDao(writer); } - + @Test public void testProcess() { Trade trade = new Trade(); writer.writeTrade(trade); - + processor.write(Collections.singletonList(trade)); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/TradeRowMapperTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/TradeRowMapperTests.java index 05a96f177..194c44dd0 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/TradeRowMapperTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/trade/internal/TradeRowMapperTests.java @@ -28,8 +28,11 @@ import org.springframework.jdbc.core.RowMapper; public class TradeRowMapperTests extends AbstractRowMapperTests { private static final String ISIN = "jsgk342"; + private static final long QUANTITY = 0; + private static final BigDecimal PRICE = new BigDecimal("1.1"); + private static final String CUSTOMER = "Martin Hrancok"; @Override @@ -57,4 +60,5 @@ public class TradeRowMapperTests extends AbstractRowMapperTests { when(rs.getString(TradeRowMapper.CUSTOMER_COLUMN)).thenReturn(CUSTOMER); when(rs.getInt(TradeRowMapper.VERSION_COLUMN)).thenReturn(0); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/AbstractIoSampleTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/AbstractIoSampleTests.java index c5195795c..9dec7260f 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/AbstractIoSampleTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/AbstractIoSampleTests.java @@ -1,147 +1,145 @@ -/* - * Copyright 2008-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.sample.iosample; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.Test; -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.ItemStream; -import org.springframework.batch.sample.domain.trade.CustomerCredit; -import org.springframework.batch.sample.domain.trade.internal.CustomerCreditIncreaseProcessor; -import org.springframework.batch.test.JobLauncherTestUtils; -import org.springframework.batch.test.MetaDataInstanceFactory; -import org.springframework.batch.test.StepScopeTestExecutionListener; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.TestExecutionListeners; -import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; - -/** - * Base class for IoSample tests that increase input customer credit by fixed - * amount. Assumes inputs and outputs are in the same format and uses the job's - * {@link ItemReader} to parse the outputs. - * - * @author Robert Kasanicky - */ -@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/job-runner-context.xml", - "/jobs/ioSampleJob.xml" }) -@TestExecutionListeners( { DependencyInjectionTestExecutionListener.class, StepScopeTestExecutionListener.class }) -public abstract class AbstractIoSampleTests { - - @Autowired - private JobLauncherTestUtils jobLauncherTestUtils; - - @Autowired - private ItemReader reader; - - /** - * Check the resulting credits correspond to inputs increased by fixed - * amount. - */ - @Test - public void testUpdateCredit() throws Exception { - - open(reader); - List inputs = getCredits(reader); - close(reader); - - JobExecution jobExecution = jobLauncherTestUtils.launchJob(getUniqueJobParameters()); - assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); - - pointReaderToOutput(reader); - open(reader); - List outputs = getCredits(reader); - close(reader); - - assertEquals(inputs.size(), outputs.size()); - int itemCount = inputs.size(); - assertTrue(itemCount > 0); - - for (int i = 0; i < itemCount; i++) { - assertEquals(inputs.get(i).getCredit().add(CustomerCreditIncreaseProcessor.FIXED_AMOUNT).intValue(), - outputs.get(i).getCredit().intValue()); - } - - } - - protected JobParameters getUniqueJobParameters() { - return jobLauncherTestUtils.getUniqueJobParameters(); - } - - protected JobParametersBuilder getUniqueJobParametersBuilder() { - return jobLauncherTestUtils.getUniqueJobParametersBuilder(); - } - - /** - * Configure the reader to read outputs (if necessary). Required for - * file-to-file jobs jobs, usually no-op for database jobs where inputs are - * updated (rather than outputs created). - */ - protected abstract void pointReaderToOutput(ItemReader reader); - - /** - * Read all credits using the provided reader. - */ - private List getCredits(ItemReader reader) throws Exception { - CustomerCredit credit; - List result = new ArrayList<>(); - while ((credit = reader.read()) != null) { - result.add(credit); - } - return result; - - } - - /** - * Open the reader if applicable. - */ - private void open(ItemReader reader) { - if (reader instanceof ItemStream) { - ((ItemStream) reader).open(new ExecutionContext()); - } - } - - /** - * Close the reader if applicable. - */ - private void close(ItemReader reader) { - if (reader instanceof ItemStream) { - ((ItemStream) reader).close(); - } - } - - /** - * Create a {@link StepExecution} that can be used to satisfy step scoped - * dependencies in the test itself (not in the job it launches). - * - * @return a {@link StepExecution} - */ - protected StepExecution getStepExecution() { - return MetaDataInstanceFactory.createStepExecution(getUniqueJobParameters()); - } - -} +/* + * Copyright 2008-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.sample.iosample; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.JobParametersBuilder; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemStream; +import org.springframework.batch.sample.domain.trade.CustomerCredit; +import org.springframework.batch.sample.domain.trade.internal.CustomerCreditIncreaseProcessor; +import org.springframework.batch.test.JobLauncherTestUtils; +import org.springframework.batch.test.MetaDataInstanceFactory; +import org.springframework.batch.test.StepScopeTestExecutionListener; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestExecutionListeners; +import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; + +/** + * Base class for IoSample tests that increase input customer credit by fixed amount. + * Assumes inputs and outputs are in the same format and uses the job's {@link ItemReader} + * to parse the outputs. + * + * @author Robert Kasanicky + */ +@ContextConfiguration( + locations = { "/simple-job-launcher-context.xml", "/job-runner-context.xml", "/jobs/ioSampleJob.xml" }) +@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, StepScopeTestExecutionListener.class }) +public abstract class AbstractIoSampleTests { + + @Autowired + private JobLauncherTestUtils jobLauncherTestUtils; + + @Autowired + private ItemReader reader; + + /** + * Check the resulting credits correspond to inputs increased by fixed amount. + */ + @Test + public void testUpdateCredit() throws Exception { + + open(reader); + List inputs = getCredits(reader); + close(reader); + + JobExecution jobExecution = jobLauncherTestUtils.launchJob(getUniqueJobParameters()); + assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); + + pointReaderToOutput(reader); + open(reader); + List outputs = getCredits(reader); + close(reader); + + assertEquals(inputs.size(), outputs.size()); + int itemCount = inputs.size(); + assertTrue(itemCount > 0); + + for (int i = 0; i < itemCount; i++) { + assertEquals(inputs.get(i).getCredit().add(CustomerCreditIncreaseProcessor.FIXED_AMOUNT).intValue(), + outputs.get(i).getCredit().intValue()); + } + + } + + protected JobParameters getUniqueJobParameters() { + return jobLauncherTestUtils.getUniqueJobParameters(); + } + + protected JobParametersBuilder getUniqueJobParametersBuilder() { + return jobLauncherTestUtils.getUniqueJobParametersBuilder(); + } + + /** + * Configure the reader to read outputs (if necessary). Required for file-to-file jobs + * jobs, usually no-op for database jobs where inputs are updated (rather than outputs + * created). + */ + protected abstract void pointReaderToOutput(ItemReader reader); + + /** + * Read all credits using the provided reader. + */ + private List getCredits(ItemReader reader) throws Exception { + CustomerCredit credit; + List result = new ArrayList<>(); + while ((credit = reader.read()) != null) { + result.add(credit); + } + return result; + + } + + /** + * Open the reader if applicable. + */ + private void open(ItemReader reader) { + if (reader instanceof ItemStream) { + ((ItemStream) reader).open(new ExecutionContext()); + } + } + + /** + * Close the reader if applicable. + */ + private void close(ItemReader reader) { + if (reader instanceof ItemStream) { + ((ItemStream) reader).close(); + } + } + + /** + * Create a {@link StepExecution} that can be used to satisfy step scoped dependencies + * in the test itself (not in the job it launches). + * @return a {@link StepExecution} + */ + protected StepExecution getStepExecution() { + return MetaDataInstanceFactory.createStepExecution(getUniqueJobParameters()); + } + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/DelimitedFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/DelimitedFunctionalTests.java index a77f38332..ec2a529d4 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/DelimitedFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/DelimitedFunctionalTests.java @@ -37,8 +37,8 @@ public class DelimitedFunctionalTests extends AbstractIoSampleTests { @Override protected void pointReaderToOutput(ItemReader reader) { - JobParameters jobParameters = super.getUniqueJobParametersBuilder().addString("inputFile", - "file:./target/test-outputs/delimitedOutput.csv").toJobParameters(); + JobParameters jobParameters = super.getUniqueJobParametersBuilder() + .addString("inputFile", "file:./target/test-outputs/delimitedOutput.csv").toJobParameters(); StepExecution stepExecution = MetaDataInstanceFactory.createStepExecution(jobParameters); StepSynchronizationManager.close(); StepSynchronizationManager.register(stepExecution); @@ -46,9 +46,8 @@ public class DelimitedFunctionalTests extends AbstractIoSampleTests { @Override protected JobParameters getUniqueJobParameters() { - return super.getUniqueJobParametersBuilder().addString("inputFile", - "data/iosample/input/delimited.csv").addString("outputFile", - "file:./target/test-outputs/delimitedOutput.csv").toJobParameters(); + return super.getUniqueJobParametersBuilder().addString("inputFile", "data/iosample/input/delimited.csv") + .addString("outputFile", "file:./target/test-outputs/delimitedOutput.csv").toJobParameters(); } } \ No newline at end of file diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/FixedLengthFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/FixedLengthFunctionalTests.java index 2db007f0b..9e61821c4 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/FixedLengthFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/FixedLengthFunctionalTests.java @@ -32,8 +32,8 @@ public class FixedLengthFunctionalTests extends AbstractIoSampleTests { @Override protected void pointReaderToOutput(ItemReader reader) { - JobParameters jobParameters = super.getUniqueJobParametersBuilder().addString("inputFile", - "file:./target/test-outputs/fixedLengthOutput.txt").toJobParameters(); + JobParameters jobParameters = super.getUniqueJobParametersBuilder() + .addString("inputFile", "file:./target/test-outputs/fixedLengthOutput.txt").toJobParameters(); StepExecution stepExecution = MetaDataInstanceFactory.createStepExecution(jobParameters); StepSynchronizationManager.close(); StepSynchronizationManager.register(stepExecution); @@ -41,9 +41,8 @@ public class FixedLengthFunctionalTests extends AbstractIoSampleTests { @Override protected JobParameters getUniqueJobParameters() { - return super.getUniqueJobParametersBuilder().addString("inputFile", - "data/iosample/input/fixedLength.txt").addString("outputFile", - "file:./target/test-outputs/fixedLengthOutput.txt").toJobParameters(); + return super.getUniqueJobParametersBuilder().addString("inputFile", "data/iosample/input/fixedLength.txt") + .addString("outputFile", "file:./target/test-outputs/fixedLengthOutput.txt").toJobParameters(); } } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/HibernateFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/HibernateFunctionalTests.java index 4f0b13be0..cc065d651 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/HibernateFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/HibernateFunctionalTests.java @@ -1,33 +1,33 @@ -/* - * Copyright 2008-2009 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.sample.iosample; - -import org.junit.runner.RunWith; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.sample.domain.trade.CustomerCredit; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = { "/hibernate-context.xml", "/jobs/iosample/hibernate.xml" }) -public class HibernateFunctionalTests extends AbstractIoSampleTests { - - @Override - protected void pointReaderToOutput(ItemReader reader) { - // no-op - } - -} +/* + * Copyright 2008-2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.sample.iosample; + +import org.junit.runner.RunWith; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.sample.domain.trade.CustomerCredit; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = { "/hibernate-context.xml", "/jobs/iosample/hibernate.xml" }) +public class HibernateFunctionalTests extends AbstractIoSampleTests { + + @Override + protected void pointReaderToOutput(ItemReader reader) { + // no-op + } + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/JdbcPagingFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/JdbcPagingFunctionalTests.java index 67fafcb31..68114c3b1 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/JdbcPagingFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/JdbcPagingFunctionalTests.java @@ -37,8 +37,7 @@ public class JdbcPagingFunctionalTests extends AbstractIoSampleTests { @Override protected void pointReaderToOutput(ItemReader reader) { - JobParameters jobParameters = super.getUniqueJobParametersBuilder().addDouble("credit", 0.) - .toJobParameters(); + JobParameters jobParameters = super.getUniqueJobParametersBuilder().addDouble("credit", 0.).toJobParameters(); StepExecution stepExecution = MetaDataInstanceFactory.createStepExecution(jobParameters); StepSynchronizationManager.close(); StepSynchronizationManager.register(stepExecution); diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/JpaFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/JpaFunctionalTests.java index fd87575bc..f5168d6e6 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/JpaFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/JpaFunctionalTests.java @@ -1,33 +1,33 @@ -/* - * Copyright 2008-2009 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.sample.iosample; - -import org.junit.runner.RunWith; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.sample.domain.trade.CustomerCredit; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = "/jobs/iosample/jpa.xml") -public class JpaFunctionalTests extends AbstractIoSampleTests { - - @Override - protected void pointReaderToOutput(ItemReader reader) { - // no-op - } - -} +/* + * Copyright 2008-2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.sample.iosample; + +import org.junit.runner.RunWith; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.sample.domain.trade.CustomerCredit; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = "/jobs/iosample/jpa.xml") +public class JpaFunctionalTests extends AbstractIoSampleTests { + + @Override + protected void pointReaderToOutput(ItemReader reader) { + // no-op + } + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/MultiLineFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/MultiLineFunctionalTests.java index df195fe81..4406443d8 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/MultiLineFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/MultiLineFunctionalTests.java @@ -30,8 +30,8 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; * @since 2.0 */ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/iosample/multiLine.xml", - "/job-runner-context.xml" }) +@ContextConfiguration( + locations = { "/simple-job-launcher-context.xml", "/jobs/iosample/multiLine.xml", "/job-runner-context.xml" }) public class MultiLineFunctionalTests { private static final String OUTPUT_FILE = "target/test-outputs/multiLineOutput.txt"; @@ -49,4 +49,5 @@ public class MultiLineFunctionalTests { jobLauncherTestUtils.launchJob(); AssertFile.assertFileEquals(new FileSystemResource(INPUT_FILE), new FileSystemResource(OUTPUT_FILE)); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/MultiRecordTypeFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/MultiRecordTypeFunctionalTests.java index 34b0f2fef..3e2ae63a0 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/MultiRecordTypeFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/MultiRecordTypeFunctionalTests.java @@ -49,4 +49,5 @@ public class MultiRecordTypeFunctionalTests { jobLauncherTestUtils.launchJob(); AssertFile.assertFileEquals(new FileSystemResource(INPUT_FILE), new FileSystemResource(OUTPUT_FILE)); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/MultiResourceFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/MultiResourceFunctionalTests.java index 8461992a5..22af2be6a 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/MultiResourceFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/MultiResourceFunctionalTests.java @@ -37,8 +37,8 @@ public class MultiResourceFunctionalTests extends AbstractIoSampleTests { @Override protected void pointReaderToOutput(ItemReader reader) { - JobParameters jobParameters = super.getUniqueJobParametersBuilder().addString( - "input.file.path", "file:target/test-outputs/multiResourceOutput.csv.*").toJobParameters(); + JobParameters jobParameters = super.getUniqueJobParametersBuilder() + .addString("input.file.path", "file:target/test-outputs/multiResourceOutput.csv.*").toJobParameters(); StepExecution stepExecution = MetaDataInstanceFactory.createStepExecution(jobParameters); StepSynchronizationManager.close(); StepSynchronizationManager.register(stepExecution); @@ -47,8 +47,8 @@ public class MultiResourceFunctionalTests extends AbstractIoSampleTests { @Override protected JobParameters getUniqueJobParameters() { JobParametersBuilder builder = super.getUniqueJobParametersBuilder(); - return builder.addString("input.file.path", "classpath:data/iosample/input/delimited*.csv").addString( - "output.file.path", "file:target/test-outputs/multiResourceOutput.csv").toJobParameters(); + return builder.addString("input.file.path", "classpath:data/iosample/input/delimited*.csv") + .addString("output.file.path", "file:target/test-outputs/multiResourceOutput.csv").toJobParameters(); } } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/RepositoryFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/RepositoryFunctionalTests.java index c822f9f2f..a8e086aa3 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/RepositoryFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/RepositoryFunctionalTests.java @@ -1,45 +1,45 @@ -/* - * Copyright 2013-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.sample.iosample; - -import org.junit.runner.RunWith; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.scope.context.StepSynchronizationManager; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.sample.domain.trade.CustomerCredit; -import org.springframework.batch.test.MetaDataInstanceFactory; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = "/jobs/iosample/repository.xml") -public class RepositoryFunctionalTests extends AbstractIoSampleTests { - - @Override - protected void pointReaderToOutput(ItemReader reader) { - JobParameters jobParameters = super.getUniqueJobParametersBuilder().addDouble("credit", 0.) - .toJobParameters(); - StepExecution stepExecution = MetaDataInstanceFactory.createStepExecution(jobParameters); - StepSynchronizationManager.close(); - StepSynchronizationManager.register(stepExecution); - } - - @Override - protected JobParameters getUniqueJobParameters() { - return super.getUniqueJobParametersBuilder().addString("credit", "10000").toJobParameters(); - } -} +/* + * Copyright 2013-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.sample.iosample; + +import org.junit.runner.RunWith; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.scope.context.StepSynchronizationManager; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.sample.domain.trade.CustomerCredit; +import org.springframework.batch.test.MetaDataInstanceFactory; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = "/jobs/iosample/repository.xml") +public class RepositoryFunctionalTests extends AbstractIoSampleTests { + + @Override + protected void pointReaderToOutput(ItemReader reader) { + JobParameters jobParameters = super.getUniqueJobParametersBuilder().addDouble("credit", 0.).toJobParameters(); + StepExecution stepExecution = MetaDataInstanceFactory.createStepExecution(jobParameters); + StepSynchronizationManager.close(); + StepSynchronizationManager.register(stepExecution); + } + + @Override + protected JobParameters getUniqueJobParameters() { + return super.getUniqueJobParametersBuilder().addString("credit", "10000").toJobParameters(); + } + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/TwoJobInstancesDelimitedFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/TwoJobInstancesDelimitedFunctionalTests.java index e2fc4d31a..5eeab39c9 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/TwoJobInstancesDelimitedFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/TwoJobInstancesDelimitedFunctionalTests.java @@ -46,9 +46,10 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; * @since 2.0 */ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/ioSampleJob.xml", - "/jobs/iosample/delimited.xml" }) +@ContextConfiguration( + locations = { "/simple-job-launcher-context.xml", "/jobs/ioSampleJob.xml", "/jobs/iosample/delimited.xml" }) public class TwoJobInstancesDelimitedFunctionalTests { + @Autowired private JobLauncher launcher; @@ -73,8 +74,8 @@ public class TwoJobInstancesDelimitedFunctionalTests { } private void verifyOutput(int expected) throws Exception { - JobParameters jobParameters = new JobParametersBuilder().addString("inputFile", - "file:./target/test-outputs/delimitedOutput.csv").toJobParameters(); + JobParameters jobParameters = new JobParametersBuilder() + .addString("inputFile", "file:./target/test-outputs/delimitedOutput.csv").toJobParameters(); StepExecution stepExecution = MetaDataInstanceFactory.createStepExecution(jobParameters); int count = StepScopeTestUtils.doInStepScope(stepExecution, new Callable() { @@ -103,4 +104,5 @@ public class TwoJobInstancesDelimitedFunctionalTests { return new JobParametersBuilder().addLong("timestamp", new Date().getTime()).addString("inputFile", fileName) .addString("outputFile", "file:./target/test-outputs/delimitedOutput.csv").toJobParameters(); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/TwoJobInstancesPagingFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/TwoJobInstancesPagingFunctionalTests.java index a58669d73..379f980d3 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/TwoJobInstancesPagingFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/TwoJobInstancesPagingFunctionalTests.java @@ -43,9 +43,10 @@ import org.springframework.test.jdbc.JdbcTestUtils; * @since 2.0 */ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/ioSampleJob.xml", - "/jobs/iosample/jdbcPaging.xml" }) +@ContextConfiguration( + locations = { "/simple-job-launcher-context.xml", "/jobs/ioSampleJob.xml", "/jobs/iosample/jdbcPaging.xml" }) public class TwoJobInstancesPagingFunctionalTests { + @Autowired private JobLauncher launcher; @@ -76,4 +77,5 @@ public class TwoJobInstancesPagingFunctionalTests { return new JobParametersBuilder().addLong("timestamp", new Date().getTime()).addDouble("credit", amount) .toJobParameters(); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/XmlFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/XmlFunctionalTests.java index 9dbae1350..8baa49eed 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/XmlFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/XmlFunctionalTests.java @@ -30,17 +30,16 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; * @since 2.0 */ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = "/jobs/iosample/xml.xml" ) +@ContextConfiguration(locations = "/jobs/iosample/xml.xml") public class XmlFunctionalTests extends AbstractIoSampleTests { @Autowired private Resource outputResource; - + @Override protected void pointReaderToOutput(ItemReader reader) { StaxEventItemReader xmlReader = (StaxEventItemReader) reader; xmlReader.setResource(outputResource); } - } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/internal/DelegatingTradeLineAggregator.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/internal/DelegatingTradeLineAggregator.java index 422e7158c..b1707b05a 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/internal/DelegatingTradeLineAggregator.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/internal/DelegatingTradeLineAggregator.java @@ -25,7 +25,9 @@ import org.springframework.batch.sample.domain.trade.Trade; * @since 2.0 */ public class DelegatingTradeLineAggregator implements LineAggregator { + private LineAggregator tradeLineAggregator; + private LineAggregator customerLineAggregator; @Override @@ -48,4 +50,5 @@ public class DelegatingTradeLineAggregator implements LineAggregator { public void setCustomerLineAggregator(LineAggregator customerLineAggregator) { this.customerLineAggregator = customerLineAggregator; } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/internal/MultiLineTradeItemReader.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/internal/MultiLineTradeItemReader.java index b040bdf56..f2b6e8dbd 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/internal/MultiLineTradeItemReader.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/internal/MultiLineTradeItemReader.java @@ -31,6 +31,7 @@ import org.springframework.util.Assert; * @since 2.0 */ public class MultiLineTradeItemReader implements ItemReader, ItemStream { + private FlatFileItemReader
      delegate; /** @@ -82,4 +83,5 @@ public class MultiLineTradeItemReader implements ItemReader, ItemStream { public void update(ExecutionContext executionContext) throws ItemStreamException { this.delegate.update(executionContext); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/internal/MultiLineTradeItemWriter.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/internal/MultiLineTradeItemWriter.java index 86ee19219..f60ff4286 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/internal/MultiLineTradeItemWriter.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/internal/MultiLineTradeItemWriter.java @@ -31,6 +31,7 @@ import org.springframework.batch.sample.domain.trade.Trade; * @since 2.0 */ public class MultiLineTradeItemWriter implements ItemWriter, ItemStream { + private FlatFileItemWriter delegate; @Override @@ -65,4 +66,5 @@ public class MultiLineTradeItemWriter implements ItemWriter, ItemStream { public void update(ExecutionContext executionContext) throws ItemStreamException { this.delegate.update(executionContext); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/internal/TradeCustomerItemWriter.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/internal/TradeCustomerItemWriter.java index b363029d8..3815a5a73 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/internal/TradeCustomerItemWriter.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/iosample/internal/TradeCustomerItemWriter.java @@ -29,7 +29,9 @@ import org.springframework.batch.sample.domain.trade.TradeDao; * @since 2.0 */ public class TradeCustomerItemWriter implements ItemWriter { + private TradeDao dao; + private int count; @Override @@ -43,4 +45,5 @@ public class TradeCustomerItemWriter implements ItemWriter { public void setDao(TradeDao dao) { this.dao = dao; } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/jmx/JobExecutionNotificationPublisherTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/jmx/JobExecutionNotificationPublisherTests.java index 4c92dc118..654d3e517 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/jmx/JobExecutionNotificationPublisherTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/jmx/JobExecutionNotificationPublisherTests.java @@ -33,6 +33,7 @@ import org.springframework.jmx.export.notification.UnableToSendNotificationExcep * */ public class JobExecutionNotificationPublisherTests { + JobExecutionNotificationPublisher publisher = new JobExecutionNotificationPublisher(); @Test @@ -51,4 +52,5 @@ public class JobExecutionNotificationPublisherTests { String message = list.get(0).getMessage(); assertTrue("Message does not contain 'foo': ", message.indexOf("foo") > 0); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/launch/RemoteLauncherTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/launch/RemoteLauncherTests.java index 6f366adba..43d98a1fb 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/launch/RemoteLauncherTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/launch/RemoteLauncherTests.java @@ -40,12 +40,16 @@ import org.springframework.jmx.support.MBeanServerConnectionFactoryBean; /** * @author Dave Syer - * + * */ public class RemoteLauncherTests { + private static Log logger = LogFactory.getLog(RemoteLauncherTests.class); + private static List errors = new ArrayList<>(); + private static JobOperator launcher; + private static JobLoader loader; static private Thread thread; @@ -117,7 +121,7 @@ public class RemoteLauncherTests { /* * (non-Javadoc) - * + * * @see junit.framework.TestCase#setUp() */ @BeforeClass @@ -163,7 +167,8 @@ public class RemoteLauncherTests { try { launcher = (JobOperator) getMBean(connectionFactory, "spring:service=batch,bean=jobOperator", JobOperator.class); - loader = (JobLoader) getMBean(connectionFactory, "spring:service=batch,bean=jobLoader", JobLoader.class); + loader = (JobLoader) getMBean(connectionFactory, "spring:service=batch,bean=jobLoader", + JobLoader.class); } catch (MBeanServerNotFoundException e) { return false; @@ -190,4 +195,5 @@ public class RemoteLauncherTests { factory.afterPropertiesSet(); return factory.getObject(); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/quartz/JobLauncherDetailsTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/quartz/JobLauncherDetailsTests.java index d74db4aec..154dbd5a5 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/quartz/JobLauncherDetailsTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/quartz/JobLauncherDetailsTests.java @@ -46,13 +46,16 @@ import org.springframework.lang.Nullable; /** * @author Dave Syer - * + * */ public class JobLauncherDetailsTests { + private JobLauncherDetails details = new JobLauncherDetails(); + private TriggerFiredBundle firedBundle; + private List list = new ArrayList<>(); - + @Before public void setUp() throws Exception { details.setJobLauncher(new JobLauncher() { @@ -74,7 +77,8 @@ public class JobLauncherDetailsTests { } private JobExecutionContext createContext(JobDetail jobDetail) { - firedBundle = new TriggerFiredBundle(jobDetail, new SimpleTriggerImpl(), null, false, new Date(), new Date(), new Date(), new Date()); + firedBundle = new TriggerFiredBundle(jobDetail, new SimpleTriggerImpl(), null, false, new Date(), new Date(), + new Date(), new Date()); return new StubJobExecutionContext(); } @@ -158,12 +162,15 @@ public class JobLauncherDetailsTests { @SuppressWarnings("serial") private final class StubJobExecutionContext extends JobExecutionContextImpl { + private StubJobExecutionContext() { super(mock(Scheduler.class), firedBundle, mock(Job.class)); } + } - + private static class StubJob implements org.springframework.batch.core.Job { + private final String name; public StubJob(String name) { @@ -194,5 +201,7 @@ public class JobLauncherDetailsTests { public boolean isRestartable() { return false; } + } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/support/AbstractFieldSetMapperTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/support/AbstractFieldSetMapperTests.java index 7e5bbe554..d0f1c4ba1 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/support/AbstractFieldSetMapperTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/support/AbstractFieldSetMapperTests.java @@ -24,7 +24,7 @@ import static org.junit.Assert.assertEquals; /** * Encapsulates basic logic for testing custom {@link FieldSetMapper} implementations. - * + * * @author Robert Kasanicky */ public abstract class AbstractFieldSetMapperTests { @@ -33,27 +33,26 @@ public abstract class AbstractFieldSetMapperTests { * @return FieldSet used for mapping */ protected abstract FieldSet fieldSet(); - + /** * @return domain object excepted as a result of mapping the FieldSet * returned by this.fieldSet() */ protected abstract Object expectedDomainObject(); - + /** - * @return mapper which takes this.fieldSet() and maps it to - * domain object. + * @return mapper which takes this.fieldSet() and maps it to domain + * object. */ protected abstract FieldSetMapper fieldSetMapper(); - - + /** - * Regular usage scenario. - * Assumes the domain object implements sensible equals(Object other) + * Regular usage scenario. Assumes the domain object implements sensible + * equals(Object other) */ @Test public void testRegularUse() throws Exception { assertEquals(expectedDomainObject(), fieldSetMapper().mapFieldSet(fieldSet())); } - + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/support/AbstractRowMapperTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/support/AbstractRowMapperTests.java index de4a42ca0..c918a4537 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/support/AbstractRowMapperTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/support/AbstractRowMapperTests.java @@ -26,7 +26,7 @@ import org.springframework.jdbc.core.RowMapper; /** * Encapsulates logic for testing custom {@link RowMapper} implementations. - * + * * @author Robert Kasanicky * @param the item type */ @@ -39,8 +39,8 @@ public abstract class AbstractRowMapperTests { private ResultSet rs = mock(ResultSet.class); /** - * @return Expected result of mapping the mock ResultSet by the - * mapper being tested. + * @return Expected result of mapping the mock ResultSet by the mapper + * being tested. */ abstract protected T expectedDomainObject(); @@ -63,4 +63,5 @@ public abstract class AbstractRowMapperTests { assertEquals(expectedDomainObject(), rowMapper().mapRow(rs, IGNORED_ROW_NUMBER)); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/support/ItemTrackingItemWriterTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/support/ItemTrackingItemWriterTests.java index ce248d47b..86609391a 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/support/ItemTrackingItemWriterTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/support/ItemTrackingItemWriterTests.java @@ -27,7 +27,7 @@ import org.springframework.batch.sample.domain.trade.internal.ItemTrackingTradeI /** * @author Dave Syer - * + * */ public class ItemTrackingItemWriterTests { @@ -36,7 +36,6 @@ public class ItemTrackingItemWriterTests { /** * Test method for * {@link org.springframework.batch.sample.domain.trade.internal.ItemTrackingTradeItemWriter#write(java.util.List)}. - * * @throws Exception */ @Test @@ -71,4 +70,5 @@ public class ItemTrackingItemWriterTests { writer.write(Arrays.asList(e, f, g)); assertEquals(3, writer.getItems().size()); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/support/RetrySampleItemWriterTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/support/RetrySampleItemWriterTests.java index 6af18df00..dce1d27d3 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/support/RetrySampleItemWriterTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/support/RetrySampleItemWriterTests.java @@ -25,7 +25,7 @@ import org.junit.Test; /** * Tests for {@link RetrySampleItemWriter}. - * + * * @author Robert Kasanicky */ public class RetrySampleItemWriterTests { @@ -52,4 +52,5 @@ public class RetrySampleItemWriterTests { assertEquals(5, processor.getCounter()); } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/ValidationSampleFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/ValidationSampleFunctionalTests.java index d7250e030..d2603f846 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/ValidationSampleFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/ValidationSampleFunctionalTests.java @@ -37,7 +37,7 @@ import org.springframework.test.context.junit4.SpringRunner; * @author Mahmoud Ben Hassine */ @RunWith(SpringRunner.class) -@ContextConfiguration(classes = {ValidationSampleConfiguration.class}) +@ContextConfiguration(classes = { ValidationSampleConfiguration.class }) public class ValidationSampleFunctionalTests { @Autowired @@ -63,4 +63,5 @@ public class ValidationSampleFunctionalTests { Assert.assertEquals(1, writtenItems.size()); Assert.assertEquals("foo", writtenItems.get(0).getName()); } + } diff --git a/spring-batch-test/src/main/java/org/springframework/batch/test/AssertFile.java b/spring-batch-test/src/main/java/org/springframework/batch/test/AssertFile.java index 86ae7afce..3197ca49d 100644 --- a/spring-batch-test/src/main/java/org/springframework/batch/test/AssertFile.java +++ b/spring-batch-test/src/main/java/org/springframework/batch/test/AssertFile.java @@ -26,7 +26,7 @@ import org.springframework.core.io.Resource; /** * This class can be used to assert that two files are the same. - * + * * @author Dan Garrette * @since 2.0 */ @@ -73,4 +73,5 @@ public abstract class AssertFile { public static void assertLineCount(int expectedLineCount, Resource resource) throws Exception { assertLineCount(expectedLineCount, resource.getFile()); } + } diff --git a/spring-batch-test/src/main/java/org/springframework/batch/test/DataSourceInitializer.java b/spring-batch-test/src/main/java/org/springframework/batch/test/DataSourceInitializer.java index d6958983c..038758eb5 100755 --- a/spring-batch-test/src/main/java/org/springframework/batch/test/DataSourceInitializer.java +++ b/spring-batch-test/src/main/java/org/springframework/batch/test/DataSourceInitializer.java @@ -45,15 +45,14 @@ import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; /** - * Wrapper for a {@link DataSource} that can run scripts on start up and shut - * down. Use as a bean definition
      - * - * Run this class to initialize a database in a running server process. - * Make sure the server is running first by launching the "hsql-server" from the - * hsql.server project. Then you can right click in Eclipse and - * Run As -> Java Application. Do the same any time you want to wipe the - * database and start again. - * + * Wrapper for a {@link DataSource} that can run scripts on start up and shut down. Use as + * a bean definition
      + * + * Run this class to initialize a database in a running server process. Make sure the + * server is running first by launching the "hsql-server" from the + * hsql.server project. Then you can right click in Eclipse and Run As -> + * Java Application. Do the same any time you want to wipe the database and start again. + * * @author Dave Syer * @author Drummond Dawson * @author Mahmoud Ben Hassine @@ -75,7 +74,6 @@ public class DataSourceInitializer implements InitializingBean, DisposableBean { /** * Main method as convenient entry point. - * * @param args arguments to be passed to main. */ @SuppressWarnings("resource") @@ -126,13 +124,13 @@ public class DataSourceInitializer implements InitializingBean, DisposableBean { if (scriptResource == null || !scriptResource.exists()) { return; } - TransactionTemplate transactionTemplate = new TransactionTemplate(new DataSourceTransactionManager(this.dataSource)); + TransactionTemplate transactionTemplate = new TransactionTemplate( + new DataSourceTransactionManager(this.dataSource)); transactionTemplate.execute((TransactionCallback) status -> { JdbcTemplate jdbcTemplate = new JdbcTemplate(this.dataSource); String[] scripts; try { - scripts = StringUtils - .delimitedListToStringArray(stripComments(getScriptLines(scriptResource)), ";"); + scripts = StringUtils.delimitedListToStringArray(stripComments(getScriptLines(scriptResource)), ";"); } catch (IOException e) { throw new BeanInitializationException("Cannot load script from [" + scriptResource + "]", e); @@ -144,7 +142,8 @@ public class DataSourceInitializer implements InitializingBean, DisposableBean { jdbcTemplate.execute(trimmedScript); } catch (DataAccessException e) { - if (this.ignoreFailedDrop && trimmedScript.toLowerCase().startsWith("drop") && logger.isDebugEnabled()) { + if (this.ignoreFailedDrop && trimmedScript.toLowerCase().startsWith("drop") + && logger.isDebugEnabled()) { logger.debug("DROP script failed (ignoring): " + trimmedScript); } else { diff --git a/spring-batch-test/src/main/java/org/springframework/batch/test/ExecutionContextTestUtils.java b/spring-batch-test/src/main/java/org/springframework/batch/test/ExecutionContextTestUtils.java index 0e0a668a0..315750b7e 100644 --- a/spring-batch-test/src/main/java/org/springframework/batch/test/ExecutionContextTestUtils.java +++ b/spring-batch-test/src/main/java/org/springframework/batch/test/ExecutionContextTestUtils.java @@ -1,70 +1,70 @@ -/* - * Copyright 2006-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.test; - -import java.util.ArrayList; -import java.util.List; - -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.lang.Nullable; - -/** - * Convenience class for accessing {@link ExecutionContext} values from job and - * step executions. - * - * @author Dave Syer - * @author Mahmoud Ben Hassine - * @since 2.1.4 - * - */ -public class ExecutionContextTestUtils { - - @SuppressWarnings("unchecked") - @Nullable - public static T getValueFromJob(JobExecution jobExecution, String key) { - return (T) jobExecution.getExecutionContext().get(key); - } - - @Nullable - public static T getValueFromStepInJob(JobExecution jobExecution, String stepName, String key) { - StepExecution stepExecution = null; - List stepNames = new ArrayList<>(); - for (StepExecution candidate : jobExecution.getStepExecutions()) { - String name = candidate.getStepName(); - stepNames.add(name); - if (name.equals(stepName)) { - stepExecution = candidate; - } - } - if (stepExecution == null) { - throw new IllegalArgumentException("No such step in this job execution: " + stepName + " not in " - + stepNames); - } - @SuppressWarnings("unchecked") - T result = (T) stepExecution.getExecutionContext().get(key); - return result; - } - - @SuppressWarnings("unchecked") - @Nullable - public static T getValueFromStep(StepExecution stepExecution, String key) { - return (T) stepExecution.getExecutionContext().get(key); - } - -} +/* + * Copyright 2006-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.test; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.lang.Nullable; + +/** + * Convenience class for accessing {@link ExecutionContext} values from job and step + * executions. + * + * @author Dave Syer + * @author Mahmoud Ben Hassine + * @since 2.1.4 + * + */ +public class ExecutionContextTestUtils { + + @SuppressWarnings("unchecked") + @Nullable + public static T getValueFromJob(JobExecution jobExecution, String key) { + return (T) jobExecution.getExecutionContext().get(key); + } + + @Nullable + public static T getValueFromStepInJob(JobExecution jobExecution, String stepName, String key) { + StepExecution stepExecution = null; + List stepNames = new ArrayList<>(); + for (StepExecution candidate : jobExecution.getStepExecutions()) { + String name = candidate.getStepName(); + stepNames.add(name); + if (name.equals(stepName)) { + stepExecution = candidate; + } + } + if (stepExecution == null) { + throw new IllegalArgumentException( + "No such step in this job execution: " + stepName + " not in " + stepNames); + } + @SuppressWarnings("unchecked") + T result = (T) stepExecution.getExecutionContext().get(key); + return result; + } + + @SuppressWarnings("unchecked") + @Nullable + public static T getValueFromStep(StepExecution stepExecution, String key) { + return (T) stepExecution.getExecutionContext().get(key); + } + +} diff --git a/spring-batch-test/src/main/java/org/springframework/batch/test/JobLauncherTestUtils.java b/spring-batch-test/src/main/java/org/springframework/batch/test/JobLauncherTestUtils.java index 74070eb9e..c54555ad2 100644 --- a/spring-batch-test/src/main/java/org/springframework/batch/test/JobLauncherTestUtils.java +++ b/spring-batch-test/src/main/java/org/springframework/batch/test/JobLauncherTestUtils.java @@ -1,253 +1,243 @@ -/* - * Copyright 2006-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.test; - -import java.security.SecureRandom; -import java.util.HashMap; -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameter; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.Step; -import org.springframework.batch.core.job.AbstractJob; -import org.springframework.batch.core.job.SimpleJob; -import org.springframework.batch.core.job.flow.FlowJob; -import org.springframework.batch.core.launch.JobLauncher; -import org.springframework.batch.core.repository.JobRepository; -import org.springframework.batch.core.step.StepLocator; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; -import org.springframework.lang.Nullable; - -/** - *

      - * Utility class for testing batch jobs. It provides methods for launching an - * entire {@link AbstractJob}, allowing for end to end testing of individual - * steps, without having to run every step in the job. Any test classes using - * this utility can set up an instance in the {@link ApplicationContext} as part - * of the Spring test framework. - *

      - * - *

      - * This class also provides the ability to run {@link Step}s from a - * {@link FlowJob} or {@link SimpleJob} individually. By launching {@link Step}s - * within a {@link Job} on their own, end to end testing of individual steps can - * be performed without having to run every step in the job. - *

      - * - *

      - * It should be noted that using any of the methods that don't contain - * {@link JobParameters} in their signature, will result in one being created - * with a random number of type {@code long} as a parameter. This will ensure - * restartability when no parameters are provided. - *

      - * - * @author Lucas Ward - * @author Dan Garrette - * @author Dave Syer - * @author Mahmoud Ben Hassine - * @since 2.1 - */ -public class JobLauncherTestUtils { - - private SecureRandom secureRandom = new SecureRandom(); - - /** Logger */ - protected final Log logger = LogFactory.getLog(getClass()); - - private JobLauncher jobLauncher; - - private Job job; - - private JobRepository jobRepository; - - private StepRunner stepRunner; - - /** - * The Job instance that can be manipulated (e.g. launched) in this utility. - * - * @param job the {@link AbstractJob} to use - */ - @Autowired - public void setJob(Job job) { - this.job = job; - } - - /** - * The {@link JobRepository} to use for creating new {@link JobExecution} - * instances. - * - * @param jobRepository a {@link JobRepository} - */ - @Autowired - public void setJobRepository(JobRepository jobRepository) { - this.jobRepository = jobRepository; - } - - /** - * @return the job repository - */ - public JobRepository getJobRepository() { - return jobRepository; - } - - /** - * @return the job - */ - public Job getJob() { - return job; - } - - /** - * A {@link JobLauncher} instance that can be used to launch jobs. - * - * @param jobLauncher a job launcher - */ - @Autowired - public void setJobLauncher(JobLauncher jobLauncher) { - this.jobLauncher = jobLauncher; - } - - /** - * @return the job launcher - */ - public JobLauncher getJobLauncher() { - return jobLauncher; - } - - /** - * Launch the entire job, including all steps. - * - * @return JobExecution, so that the test can validate the exit status - * @throws Exception thrown if error occurs launching the job. - */ - public JobExecution launchJob() throws Exception { - return this.launchJob(this.getUniqueJobParameters()); - } - - /** - * Launch the entire job, including all steps - * - * @param jobParameters instance of {@link JobParameters}. - * @return JobExecution, so that the test can validate the exit status - * @throws Exception thrown if error occurs launching the job. - */ - public JobExecution launchJob(JobParameters jobParameters) throws Exception { - return getJobLauncher().run(this.job, jobParameters); - } - - /** - * @return a new JobParameters object containing only a parameter with a - * random number of type {@code long}, to ensure that the job instance will be unique. - */ - public JobParameters getUniqueJobParameters() { - Map parameters = new HashMap<>(); - parameters.put("random", new JobParameter(this.secureRandom.nextLong())); - return new JobParameters(parameters); - } - - /** - * @return a new JobParametersBuilder object containing only a parameter with a - * random number of type {@code long}, to ensure that the job instance will be unique. - */ - public JobParametersBuilder getUniqueJobParametersBuilder() { - return new JobParametersBuilder(this.getUniqueJobParameters()); - } - - /** - * Convenient method for subclasses to grab a {@link StepRunner} for running - * steps by name. - * - * @return a {@link StepRunner} - */ - protected StepRunner getStepRunner() { - if (this.stepRunner == null) { - this.stepRunner = new StepRunner(getJobLauncher(), getJobRepository()); - } - return this.stepRunner; - } - - /** - * Launch just the specified step in the job. A unique set of JobParameters - * will automatically be generated. An IllegalStateException is thrown if - * there is no Step with the given name. - * - * @param stepName The name of the step to launch - * @return JobExecution - */ - public JobExecution launchStep(String stepName) { - return this.launchStep(stepName, this.getUniqueJobParameters(), null); - } - - /** - * Launch just the specified step in the job. A unique set of JobParameters - * will automatically be generated. An IllegalStateException is thrown if - * there is no Step with the given name. - * - * @param stepName The name of the step to launch - * @param jobExecutionContext An ExecutionContext whose values will be - * loaded into the Job ExecutionContext prior to launching the step. - * @return JobExecution - */ - public JobExecution launchStep(String stepName, ExecutionContext jobExecutionContext) { - return this.launchStep(stepName, this.getUniqueJobParameters(), jobExecutionContext); - } - - /** - * Launch just the specified step in the job. An IllegalStateException is - * thrown if there is no Step with the given name. - * - * @param stepName The name of the step to launch - * @param jobParameters The JobParameters to use during the launch - * @return JobExecution - */ - public JobExecution launchStep(String stepName, JobParameters jobParameters) { - return this.launchStep(stepName, jobParameters, null); - } - - /** - * Launch just the specified step in the job. An IllegalStateException is - * thrown if there is no Step with the given name. - * - * @param stepName The name of the step to launch - * @param jobParameters The JobParameters to use during the launch - * @param jobExecutionContext An ExecutionContext whose values will be - * loaded into the Job ExecutionContext prior to launching the step. - * @return JobExecution - */ - public JobExecution launchStep(String stepName, JobParameters jobParameters, @Nullable ExecutionContext jobExecutionContext) { - if (!(job instanceof StepLocator)) { - throw new UnsupportedOperationException("Cannot locate step from a Job that is not a StepLocator: job=" - + job.getName() + " does not implement StepLocator"); - } - StepLocator locator = (StepLocator) this.job; - Step step = locator.getStep(stepName); - if (step == null) { - step = locator.getStep(this.job.getName() + "." + stepName); - } - if (step == null) { - throw new IllegalStateException("No Step found with name: [" + stepName + "]"); - } - return getStepRunner().launchStep(step, jobParameters, jobExecutionContext); - } -} +/* + * Copyright 2006-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.test; + +import java.security.SecureRandom; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.batch.core.Job; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobParameter; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.JobParametersBuilder; +import org.springframework.batch.core.Step; +import org.springframework.batch.core.job.AbstractJob; +import org.springframework.batch.core.job.SimpleJob; +import org.springframework.batch.core.job.flow.FlowJob; +import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.core.step.StepLocator; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.lang.Nullable; + +/** + *

      + * Utility class for testing batch jobs. It provides methods for launching an entire + * {@link AbstractJob}, allowing for end to end testing of individual steps, without + * having to run every step in the job. Any test classes using this utility can set up an + * instance in the {@link ApplicationContext} as part of the Spring test framework. + *

      + * + *

      + * This class also provides the ability to run {@link Step}s from a {@link FlowJob} or + * {@link SimpleJob} individually. By launching {@link Step}s within a {@link Job} on + * their own, end to end testing of individual steps can be performed without having to + * run every step in the job. + *

      + * + *

      + * It should be noted that using any of the methods that don't contain + * {@link JobParameters} in their signature, will result in one being created with a + * random number of type {@code long} as a parameter. This will ensure restartability when + * no parameters are provided. + *

      + * + * @author Lucas Ward + * @author Dan Garrette + * @author Dave Syer + * @author Mahmoud Ben Hassine + * @since 2.1 + */ +public class JobLauncherTestUtils { + + private SecureRandom secureRandom = new SecureRandom(); + + /** Logger */ + protected final Log logger = LogFactory.getLog(getClass()); + + private JobLauncher jobLauncher; + + private Job job; + + private JobRepository jobRepository; + + private StepRunner stepRunner; + + /** + * The Job instance that can be manipulated (e.g. launched) in this utility. + * @param job the {@link AbstractJob} to use + */ + @Autowired + public void setJob(Job job) { + this.job = job; + } + + /** + * The {@link JobRepository} to use for creating new {@link JobExecution} instances. + * @param jobRepository a {@link JobRepository} + */ + @Autowired + public void setJobRepository(JobRepository jobRepository) { + this.jobRepository = jobRepository; + } + + /** + * @return the job repository + */ + public JobRepository getJobRepository() { + return jobRepository; + } + + /** + * @return the job + */ + public Job getJob() { + return job; + } + + /** + * A {@link JobLauncher} instance that can be used to launch jobs. + * @param jobLauncher a job launcher + */ + @Autowired + public void setJobLauncher(JobLauncher jobLauncher) { + this.jobLauncher = jobLauncher; + } + + /** + * @return the job launcher + */ + public JobLauncher getJobLauncher() { + return jobLauncher; + } + + /** + * Launch the entire job, including all steps. + * @return JobExecution, so that the test can validate the exit status + * @throws Exception thrown if error occurs launching the job. + */ + public JobExecution launchJob() throws Exception { + return this.launchJob(this.getUniqueJobParameters()); + } + + /** + * Launch the entire job, including all steps + * @param jobParameters instance of {@link JobParameters}. + * @return JobExecution, so that the test can validate the exit status + * @throws Exception thrown if error occurs launching the job. + */ + public JobExecution launchJob(JobParameters jobParameters) throws Exception { + return getJobLauncher().run(this.job, jobParameters); + } + + /** + * @return a new JobParameters object containing only a parameter with a random number + * of type {@code long}, to ensure that the job instance will be unique. + */ + public JobParameters getUniqueJobParameters() { + Map parameters = new HashMap<>(); + parameters.put("random", new JobParameter(this.secureRandom.nextLong())); + return new JobParameters(parameters); + } + + /** + * @return a new JobParametersBuilder object containing only a parameter with a random + * number of type {@code long}, to ensure that the job instance will be unique. + */ + public JobParametersBuilder getUniqueJobParametersBuilder() { + return new JobParametersBuilder(this.getUniqueJobParameters()); + } + + /** + * Convenient method for subclasses to grab a {@link StepRunner} for running steps by + * name. + * @return a {@link StepRunner} + */ + protected StepRunner getStepRunner() { + if (this.stepRunner == null) { + this.stepRunner = new StepRunner(getJobLauncher(), getJobRepository()); + } + return this.stepRunner; + } + + /** + * Launch just the specified step in the job. A unique set of JobParameters will + * automatically be generated. An IllegalStateException is thrown if there is no Step + * with the given name. + * @param stepName The name of the step to launch + * @return JobExecution + */ + public JobExecution launchStep(String stepName) { + return this.launchStep(stepName, this.getUniqueJobParameters(), null); + } + + /** + * Launch just the specified step in the job. A unique set of JobParameters will + * automatically be generated. An IllegalStateException is thrown if there is no Step + * with the given name. + * @param stepName The name of the step to launch + * @param jobExecutionContext An ExecutionContext whose values will be loaded into the + * Job ExecutionContext prior to launching the step. + * @return JobExecution + */ + public JobExecution launchStep(String stepName, ExecutionContext jobExecutionContext) { + return this.launchStep(stepName, this.getUniqueJobParameters(), jobExecutionContext); + } + + /** + * Launch just the specified step in the job. An IllegalStateException is thrown if + * there is no Step with the given name. + * @param stepName The name of the step to launch + * @param jobParameters The JobParameters to use during the launch + * @return JobExecution + */ + public JobExecution launchStep(String stepName, JobParameters jobParameters) { + return this.launchStep(stepName, jobParameters, null); + } + + /** + * Launch just the specified step in the job. An IllegalStateException is thrown if + * there is no Step with the given name. + * @param stepName The name of the step to launch + * @param jobParameters The JobParameters to use during the launch + * @param jobExecutionContext An ExecutionContext whose values will be loaded into the + * Job ExecutionContext prior to launching the step. + * @return JobExecution + */ + public JobExecution launchStep(String stepName, JobParameters jobParameters, + @Nullable ExecutionContext jobExecutionContext) { + if (!(job instanceof StepLocator)) { + throw new UnsupportedOperationException("Cannot locate step from a Job that is not a StepLocator: job=" + + job.getName() + " does not implement StepLocator"); + } + StepLocator locator = (StepLocator) this.job; + Step step = locator.getStep(stepName); + if (step == null) { + step = locator.getStep(this.job.getName() + "." + stepName); + } + if (step == null) { + throw new IllegalStateException("No Step found with name: [" + stepName + "]"); + } + return getStepRunner().launchStep(step, jobParameters, jobExecutionContext); + } + +} diff --git a/spring-batch-test/src/main/java/org/springframework/batch/test/JobRepositoryTestUtils.java b/spring-batch-test/src/main/java/org/springframework/batch/test/JobRepositoryTestUtils.java index 6f0584f19..58ef69b69 100644 --- a/spring-batch-test/src/main/java/org/springframework/batch/test/JobRepositoryTestUtils.java +++ b/spring-batch-test/src/main/java/org/springframework/batch/test/JobRepositoryTestUtils.java @@ -1,221 +1,212 @@ -/* - * Copyright 2006-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.test; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -import javax.sql.DataSource; - -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobInstance; -import org.springframework.batch.core.JobParameter; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersIncrementer; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException; -import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException; -import org.springframework.batch.core.repository.JobRepository; -import org.springframework.batch.core.repository.JobRestartException; -import org.springframework.batch.core.repository.dao.AbstractJdbcBatchMetadataDao; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.dao.DataAccessException; -import org.springframework.jdbc.core.JdbcOperations; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.core.RowMapper; -import org.springframework.lang.Nullable; -import org.springframework.util.Assert; - -/** - * Convenience class for creating and removing {@link JobExecution} instances - * from a database. Typical usage in test case would be to create instances - * before a transaction, save the result, and then use it to remove them after - * the transaction. - * - * @author Dave Syer - * @author Mahmoud Ben Hassine - */ -public class JobRepositoryTestUtils extends AbstractJdbcBatchMetadataDao implements InitializingBean { - - private JobRepository jobRepository; - - private JobParametersIncrementer jobParametersIncrementer = new JobParametersIncrementer() { - - Long count = 0L; - - @Override - public JobParameters getNext(@Nullable JobParameters parameters) { - return new JobParameters(Collections.singletonMap("count", new JobParameter(count++))); - } - - }; - - private JdbcOperations jdbcTemplate; - - /** - * @see InitializingBean#afterPropertiesSet() - */ - @Override - public void afterPropertiesSet() throws Exception { - Assert.notNull(jobRepository, "JobRepository must be set"); - Assert.notNull(jdbcTemplate, "DataSource must be set"); - } - - /** - * Default constructor. - */ - public JobRepositoryTestUtils() { - } - - /** - * Create a {@link JobRepositoryTestUtils} with all its mandatory - * properties. - * - * @param jobRepository a {@link JobRepository} backed by a database - * @param dataSource a {@link DataSource} - */ - public JobRepositoryTestUtils(JobRepository jobRepository, DataSource dataSource) { - super(); - this.jobRepository = jobRepository; - setDataSource(dataSource); - } - - @Autowired - public final void setDataSource(DataSource dataSource) { - jdbcTemplate = new JdbcTemplate(dataSource); - } - - /** - * @param jobParametersIncrementer the jobParametersIncrementer to set - */ - public void setJobParametersIncrementer(JobParametersIncrementer jobParametersIncrementer) { - this.jobParametersIncrementer = jobParametersIncrementer; - } - - /** - * @param jobRepository the jobRepository to set - */ - @Autowired - public void setJobRepository(JobRepository jobRepository) { - this.jobRepository = jobRepository; - } - - /** - * Use the {@link JobRepository} to create some {@link JobExecution} - * instances each with the given job name and each having step executions - * with the given step names. - * - * @param jobName the name of the job - * @param stepNames the names of the step executions - * @param count the required number of instances of {@link JobExecution} to - * create - * @return a collection of {@link JobExecution} - * - * @throws JobExecutionAlreadyRunningException thrown if Job is already running. - * @throws JobRestartException thrown if Job is not restartable. - * @throws JobInstanceAlreadyCompleteException thrown if Job Instance is already complete. - */ - public List createJobExecutions(String jobName, String[] stepNames, int count) - throws JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException { - List list = new ArrayList<>(); - JobParameters jobParameters = new JobParameters(); - for (int i = 0; i < count; i++) { - JobExecution jobExecution = jobRepository.createJobExecution(jobName, jobParametersIncrementer - .getNext(jobParameters)); - list.add(jobExecution); - for (String stepName : stepNames) { - jobRepository.add(jobExecution.createStepExecution(stepName)); - } - } - return list; - } - - /** - * Use the {@link JobRepository} to create some {@link JobExecution} - * instances each with a single step execution. - * - * @param count the required number of instances of {@link JobExecution} to - * create - * @return a collection of {@link JobExecution} - * @throws JobExecutionAlreadyRunningException thrown if Job is already running. - * @throws JobRestartException thrown if Job is not restartable. - * @throws JobInstanceAlreadyCompleteException thrown if Job Instance is already complete. - */ - public List createJobExecutions(int count) throws JobExecutionAlreadyRunningException, - JobRestartException, JobInstanceAlreadyCompleteException { - return createJobExecutions("job", new String[] { "step" }, count); - } - - /** - * Remove the {@link JobExecution} instances, and all associated - * {@link JobInstance} and {@link StepExecution} instances from the standard - * RDBMS locations used by Spring Batch. - * - * @param list a list of {@link JobExecution} - * @throws DataAccessException if there is a problem - */ - public void removeJobExecutions(Collection list) throws DataAccessException { - for (JobExecution jobExecution : list) { - List stepExecutionIds = jdbcTemplate.query( - getQuery("select STEP_EXECUTION_ID from %PREFIX%STEP_EXECUTION where JOB_EXECUTION_ID=?"), - new RowMapper() { - @Override - public Long mapRow(ResultSet rs, int rowNum) throws SQLException { - return rs.getLong(1); - } - }, jobExecution.getId()); - for (Long stepExecutionId : stepExecutionIds) { - jdbcTemplate.update(getQuery("delete from %PREFIX%STEP_EXECUTION_CONTEXT where STEP_EXECUTION_ID=?"), - stepExecutionId); - jdbcTemplate.update(getQuery("delete from %PREFIX%STEP_EXECUTION where STEP_EXECUTION_ID=?"), - stepExecutionId); - } - jdbcTemplate.update(getQuery("delete from %PREFIX%JOB_EXECUTION_CONTEXT where JOB_EXECUTION_ID=?"), - jobExecution.getId()); - jdbcTemplate.update(getQuery("delete from %PREFIX%JOB_EXECUTION_PARAMS where JOB_EXECUTION_ID=?"), jobExecution - .getId()); - jdbcTemplate.update(getQuery("delete from %PREFIX%JOB_EXECUTION where JOB_EXECUTION_ID=?"), jobExecution - .getId()); - } - for (JobExecution jobExecution : list) { - jdbcTemplate.update(getQuery("delete from %PREFIX%JOB_INSTANCE where JOB_INSTANCE_ID=?"), jobExecution - .getJobId()); - } - } - - /** - * Remove all the {@link JobExecution} instances, and all associated - * {@link JobInstance} and {@link StepExecution} instances from the standard - * RDBMS locations used by Spring Batch. - * - * @throws DataAccessException if there is a problem - */ - public void removeJobExecutions() throws DataAccessException { - jdbcTemplate.update(getQuery("delete from %PREFIX%STEP_EXECUTION_CONTEXT")); - jdbcTemplate.update(getQuery("delete from %PREFIX%STEP_EXECUTION")); - jdbcTemplate.update(getQuery("delete from %PREFIX%JOB_EXECUTION_CONTEXT")); - jdbcTemplate.update(getQuery("delete from %PREFIX%JOB_EXECUTION_PARAMS")); - jdbcTemplate.update(getQuery("delete from %PREFIX%JOB_EXECUTION")); - jdbcTemplate.update(getQuery("delete from %PREFIX%JOB_INSTANCE")); - - } - -} +/* + * Copyright 2006-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.test; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import javax.sql.DataSource; + +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobInstance; +import org.springframework.batch.core.JobParameter; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.JobParametersIncrementer; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException; +import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.core.repository.JobRestartException; +import org.springframework.batch.core.repository.dao.AbstractJdbcBatchMetadataDao; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.jdbc.core.JdbcOperations; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; + +/** + * Convenience class for creating and removing {@link JobExecution} instances from a + * database. Typical usage in test case would be to create instances before a transaction, + * save the result, and then use it to remove them after the transaction. + * + * @author Dave Syer + * @author Mahmoud Ben Hassine + */ +public class JobRepositoryTestUtils extends AbstractJdbcBatchMetadataDao implements InitializingBean { + + private JobRepository jobRepository; + + private JobParametersIncrementer jobParametersIncrementer = new JobParametersIncrementer() { + + Long count = 0L; + + @Override + public JobParameters getNext(@Nullable JobParameters parameters) { + return new JobParameters(Collections.singletonMap("count", new JobParameter(count++))); + } + + }; + + private JdbcOperations jdbcTemplate; + + /** + * @see InitializingBean#afterPropertiesSet() + */ + @Override + public void afterPropertiesSet() throws Exception { + Assert.notNull(jobRepository, "JobRepository must be set"); + Assert.notNull(jdbcTemplate, "DataSource must be set"); + } + + /** + * Default constructor. + */ + public JobRepositoryTestUtils() { + } + + /** + * Create a {@link JobRepositoryTestUtils} with all its mandatory properties. + * @param jobRepository a {@link JobRepository} backed by a database + * @param dataSource a {@link DataSource} + */ + public JobRepositoryTestUtils(JobRepository jobRepository, DataSource dataSource) { + super(); + this.jobRepository = jobRepository; + setDataSource(dataSource); + } + + @Autowired + public final void setDataSource(DataSource dataSource) { + jdbcTemplate = new JdbcTemplate(dataSource); + } + + /** + * @param jobParametersIncrementer the jobParametersIncrementer to set + */ + public void setJobParametersIncrementer(JobParametersIncrementer jobParametersIncrementer) { + this.jobParametersIncrementer = jobParametersIncrementer; + } + + /** + * @param jobRepository the jobRepository to set + */ + @Autowired + public void setJobRepository(JobRepository jobRepository) { + this.jobRepository = jobRepository; + } + + /** + * Use the {@link JobRepository} to create some {@link JobExecution} instances each + * with the given job name and each having step executions with the given step names. + * @param jobName the name of the job + * @param stepNames the names of the step executions + * @param count the required number of instances of {@link JobExecution} to create + * @return a collection of {@link JobExecution} + * @throws JobExecutionAlreadyRunningException thrown if Job is already running. + * @throws JobRestartException thrown if Job is not restartable. + * @throws JobInstanceAlreadyCompleteException thrown if Job Instance is already + * complete. + */ + public List createJobExecutions(String jobName, String[] stepNames, int count) + throws JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException { + List list = new ArrayList<>(); + JobParameters jobParameters = new JobParameters(); + for (int i = 0; i < count; i++) { + JobExecution jobExecution = jobRepository.createJobExecution(jobName, + jobParametersIncrementer.getNext(jobParameters)); + list.add(jobExecution); + for (String stepName : stepNames) { + jobRepository.add(jobExecution.createStepExecution(stepName)); + } + } + return list; + } + + /** + * Use the {@link JobRepository} to create some {@link JobExecution} instances each + * with a single step execution. + * @param count the required number of instances of {@link JobExecution} to create + * @return a collection of {@link JobExecution} + * @throws JobExecutionAlreadyRunningException thrown if Job is already running. + * @throws JobRestartException thrown if Job is not restartable. + * @throws JobInstanceAlreadyCompleteException thrown if Job Instance is already + * complete. + */ + public List createJobExecutions(int count) + throws JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException { + return createJobExecutions("job", new String[] { "step" }, count); + } + + /** + * Remove the {@link JobExecution} instances, and all associated {@link JobInstance} + * and {@link StepExecution} instances from the standard RDBMS locations used by + * Spring Batch. + * @param list a list of {@link JobExecution} + * @throws DataAccessException if there is a problem + */ + public void removeJobExecutions(Collection list) throws DataAccessException { + for (JobExecution jobExecution : list) { + List stepExecutionIds = jdbcTemplate.query( + getQuery("select STEP_EXECUTION_ID from %PREFIX%STEP_EXECUTION where JOB_EXECUTION_ID=?"), + new RowMapper() { + @Override + public Long mapRow(ResultSet rs, int rowNum) throws SQLException { + return rs.getLong(1); + } + }, jobExecution.getId()); + for (Long stepExecutionId : stepExecutionIds) { + jdbcTemplate.update(getQuery("delete from %PREFIX%STEP_EXECUTION_CONTEXT where STEP_EXECUTION_ID=?"), + stepExecutionId); + jdbcTemplate.update(getQuery("delete from %PREFIX%STEP_EXECUTION where STEP_EXECUTION_ID=?"), + stepExecutionId); + } + jdbcTemplate.update(getQuery("delete from %PREFIX%JOB_EXECUTION_CONTEXT where JOB_EXECUTION_ID=?"), + jobExecution.getId()); + jdbcTemplate.update(getQuery("delete from %PREFIX%JOB_EXECUTION_PARAMS where JOB_EXECUTION_ID=?"), + jobExecution.getId()); + jdbcTemplate.update(getQuery("delete from %PREFIX%JOB_EXECUTION where JOB_EXECUTION_ID=?"), + jobExecution.getId()); + } + for (JobExecution jobExecution : list) { + jdbcTemplate.update(getQuery("delete from %PREFIX%JOB_INSTANCE where JOB_INSTANCE_ID=?"), + jobExecution.getJobId()); + } + } + + /** + * Remove all the {@link JobExecution} instances, and all associated + * {@link JobInstance} and {@link StepExecution} instances from the standard RDBMS + * locations used by Spring Batch. + * @throws DataAccessException if there is a problem + */ + public void removeJobExecutions() throws DataAccessException { + jdbcTemplate.update(getQuery("delete from %PREFIX%STEP_EXECUTION_CONTEXT")); + jdbcTemplate.update(getQuery("delete from %PREFIX%STEP_EXECUTION")); + jdbcTemplate.update(getQuery("delete from %PREFIX%JOB_EXECUTION_CONTEXT")); + jdbcTemplate.update(getQuery("delete from %PREFIX%JOB_EXECUTION_PARAMS")); + jdbcTemplate.update(getQuery("delete from %PREFIX%JOB_EXECUTION")); + jdbcTemplate.update(getQuery("delete from %PREFIX%JOB_INSTANCE")); + + } + +} diff --git a/spring-batch-test/src/main/java/org/springframework/batch/test/JobScopeTestExecutionListener.java b/spring-batch-test/src/main/java/org/springframework/batch/test/JobScopeTestExecutionListener.java index 8a99eb4ee..00c08f895 100644 --- a/spring-batch-test/src/main/java/org/springframework/batch/test/JobScopeTestExecutionListener.java +++ b/spring-batch-test/src/main/java/org/springframework/batch/test/JobScopeTestExecutionListener.java @@ -27,39 +27,38 @@ import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils.MethodCallback; /** - * A {@link TestExecutionListener} that sets up job-scope context for - * dependency injection into unit tests. A {@link JobContext} will be created - * for the duration of a test method and made available to any dependencies that - * are injected. The default behaviour is just to create a {@link JobExecution} with fixed properties. Alternatively it - * can be provided by the test case as a - * factory methods returning the correct type. Example: - * + * A {@link TestExecutionListener} that sets up job-scope context for dependency injection + * into unit tests. A {@link JobContext} will be created for the duration of a test method + * and made available to any dependencies that are injected. The default behaviour is just + * to create a {@link JobExecution} with fixed properties. Alternatively it can be + * provided by the test case as a factory methods returning the correct type. Example: + * *
        * @ContextConfiguration
        * @TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, JobScopeTestExecutionListener.class })
        * @RunWith(SpringJUnit4ClassRunner.class)
        * public class JobScopeTestExecutionListenerIntegrationTests {
      - * 
      + *
        * 	// A job-scoped dependency configured in the ApplicationContext
        * 	@Autowired
        * 	private ItemReader<String> reader;
      - * 
      + *
        * 	public JobExecution getJobExecution() {
        * 		JobExecution execution = MetaDataInstanceFactory.createJobExecution();
        * 		execution.getExecutionContext().putString("foo", "bar");
        * 		return execution;
        * 	}
      - * 
      + *
        * 	@Test
        * 	public void testJobScopedReader() {
        * 		// Job context is active here so the reader can be used,
        * 		// and the job execution context will contain foo=bar...
        * 		assertNotNull(reader.read());
        * 	}
      - * 
      + *
        * }
        * 
      - * + * * @author Dave Syer * @author Jimmy Praet */ @@ -69,7 +68,6 @@ public class JobScopeTestExecutionListener implements TestExecutionListener { /** * Set up a {@link JobExecution} as a test context attribute. - * * @param testContext the current test context * @throws Exception if there is a problem * @see TestExecutionListener#prepareTestInstance(TestContext) @@ -107,11 +105,10 @@ public class JobScopeTestExecutionListener implements TestExecutionListener { JobSynchronizationManager.close(); } } - + /** - * Discover a {@link JobExecution} as a field in the test case or create - * one if none is available. - * + * Discover a {@link JobExecution} as a field in the test case or create one if none + * is available. * @param testContext the current test context * @return a {@link JobExecution} */ @@ -139,10 +136,11 @@ public class JobScopeTestExecutionListener implements TestExecutionListener { } /** - * Look for a method returning the type provided, preferring one with the - * name provided. + * Look for a method returning the type provided, preferring one with the name + * provided. */ private final class ExtractorMethodCallback implements MethodCallback { + private String preferredName; private final Class preferredType; @@ -168,6 +166,7 @@ public class JobScopeTestExecutionListener implements TestExecutionListener { } } } + } } diff --git a/spring-batch-test/src/main/java/org/springframework/batch/test/JobScopeTestUtils.java b/spring-batch-test/src/main/java/org/springframework/batch/test/JobScopeTestUtils.java index 6c54e35da..00e9871fe 100644 --- a/spring-batch-test/src/main/java/org/springframework/batch/test/JobScopeTestUtils.java +++ b/spring-batch-test/src/main/java/org/springframework/batch/test/JobScopeTestUtils.java @@ -22,11 +22,10 @@ import org.springframework.batch.core.scope.JobScope; import org.springframework.batch.core.scope.context.JobSynchronizationManager; /** - * Utility class for creating and manipulating {@link JobScope} in unit tests. - * This is useful when you want to use the Spring test support and inject - * dependencies into your test case that happen to be job scoped in the - * application context. - * + * Utility class for creating and manipulating {@link JobScope} in unit tests. This is + * useful when you want to use the Spring test support and inject dependencies into your + * test case that happen to be job scoped in the application context. + * * @author Dave Syer * @author Jimmy Praet */ diff --git a/spring-batch-test/src/main/java/org/springframework/batch/test/MetaDataInstanceFactory.java b/spring-batch-test/src/main/java/org/springframework/batch/test/MetaDataInstanceFactory.java index 698d779ef..94c2c5e4d 100644 --- a/spring-batch-test/src/main/java/org/springframework/batch/test/MetaDataInstanceFactory.java +++ b/spring-batch-test/src/main/java/org/springframework/batch/test/MetaDataInstanceFactory.java @@ -1,242 +1,226 @@ -/* - * Copyright 2006-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.test; - -import java.util.Collection; - -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobInstance; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.converter.DefaultJobParametersConverter; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.support.PropertiesConverter; - -/** - * Convenience methods for creating test instances of {@link JobExecution}, - * {@link JobInstance} and {@link StepExecution}. - * - * @author Dave Syer - * @author Mahmoud Ben Hassine - * - */ -public class MetaDataInstanceFactory { - - /** - * The default name for a job ("job") - */ - public static final String DEFAULT_JOB_NAME = "job"; - - /** - * The default id for a job instance (12L) - */ - public static final long DEFAULT_JOB_INSTANCE_ID = 12L; - - /** - * The default id for a job execution (123L) - */ - public static final long DEFAULT_JOB_EXECUTION_ID = 123L; - - /** - * The default name for a step ("step") - */ - public static final String DEFAULT_STEP_NAME = "step"; - - /** - * The default id for a step execution (1234L) - */ - public static final long DEFAULT_STEP_EXECUTION_ID = 1234L; - - /** - * Create a {@link JobInstance} with the parameters provided. - * - * @param jobName the name of the job - * @param instanceId the Id of the {@link JobInstance} - * @return a {@link JobInstance} with empty {@link JobParameters} - */ - public static JobInstance createJobInstance(String jobName, Long instanceId) { - return new JobInstance(instanceId, jobName); - } - - /** - * Create a {@link JobInstance} with default parameters. - * - * @return a {@link JobInstance} with name=DEFAULT_JOB_NAME, - * id=DEFAULT_JOB_INSTANCE_ID and empty parameters - */ - public static JobInstance createJobInstance() { - return new JobInstance(DEFAULT_JOB_INSTANCE_ID, DEFAULT_JOB_NAME); - } - - /** - * Create a {@link JobExecution} with default parameters. - * - * @return a {@link JobExecution} with id=DEFAULT_JOB_EXECUTION_ID - */ - public static JobExecution createJobExecution() { - return createJobExecution(DEFAULT_JOB_EXECUTION_ID); - } - - /** - * Create a {@link JobExecution} with the parameters provided. - * - * @param executionId the id for the {@link JobExecution} - * @return a {@link JobExecution} with valid {@link JobInstance} - */ - public static JobExecution createJobExecution(Long executionId) { - return createJobExecution(DEFAULT_JOB_NAME, DEFAULT_JOB_INSTANCE_ID, executionId); - } - - /** - * Create a {@link JobExecution} with the parameters provided. - * - * @param jobName the name of the job - * @param instanceId the id for the {@link JobInstance} - * @param executionId the id for the {@link JobExecution} - * @return a {@link JobExecution} with empty {@link JobParameters} - */ - public static JobExecution createJobExecution(String jobName, Long instanceId, Long executionId) { - return createJobExecution(jobName, instanceId, executionId, new JobParameters()); - } - - /** - * Create a {@link JobExecution} with the parameters provided. - * - * @param jobName the name of the job - * @param instanceId the Id of the {@link JobInstance} - * @param executionId the id for the {@link JobExecution} - * @param jobParameters comma or new line separated name=value pairs - * @return a {@link JobExecution} - */ - public static JobExecution createJobExecution(String jobName, Long instanceId, Long executionId, - String jobParameters) { - JobParameters params = new DefaultJobParametersConverter().getJobParameters(PropertiesConverter - .stringToProperties(jobParameters)); - return createJobExecution(jobName, instanceId, executionId, params); - } - - /** - * Create a {@link JobExecution} with the parameters provided. - * - * @param jobName the name of the job - * @param instanceId the Id of the {@link JobInstance} - * @param executionId the id for the {@link JobExecution} - * @param jobParameters an instance of {@link JobParameters} - * @return a {@link JobExecution} - */ - public static JobExecution createJobExecution(String jobName, Long instanceId, Long executionId, - JobParameters jobParameters) { - return new JobExecution(createJobInstance(jobName, instanceId), executionId, jobParameters); - } - - /** - * Create a {@link StepExecution} with default parameters. - * - * @return a {@link StepExecution} with stepName="step" and - * id=DEFAULT_STEP_EXECUTION_ID - */ - public static StepExecution createStepExecution() { - return createStepExecution(DEFAULT_STEP_NAME, DEFAULT_STEP_EXECUTION_ID); - } - - /** - * Create a {@link StepExecution} with the parameters provided. - * - * @param stepName the stepName for the {@link StepExecution} - * @param executionId the id for the {@link StepExecution} - * @return a {@link StepExecution} with a {@link JobExecution} having - * default properties - */ - public static StepExecution createStepExecution(String stepName, Long executionId) { - return createStepExecution(createJobExecution(), stepName, executionId); - } - - /** - * Create a {@link StepExecution} with the parameters provided. - * - * @param jobExecution instance of {@link JobExecution}. - * @param stepName the name for the {@link StepExecution}. - * @param executionId the id for the {@link StepExecution}. - * @return a {@link StepExecution} with the given {@link JobExecution}. - */ - public static StepExecution createStepExecution(JobExecution jobExecution, String stepName, Long executionId) { - StepExecution stepExecution = jobExecution.createStepExecution(stepName); - stepExecution.setId(executionId); - return stepExecution; - } - - /** - * Create a {@link JobExecution} with the parameters provided with attached - * step executions. - * - * @param executionId the {@link JobExecution} id - * @param stepNames the names of the step executions - * @return a {@link JobExecution} with step executions as specified, each - * with a unique id - */ - public static JobExecution createJobExecutionWithStepExecutions(Long executionId, Collection stepNames) { - JobExecution jobExecution = createJobExecution(DEFAULT_JOB_NAME, DEFAULT_JOB_INSTANCE_ID, executionId); - Long stepExecutionId = DEFAULT_STEP_EXECUTION_ID; - for (String stepName : stepNames) { - createStepExecution(jobExecution, stepName, stepExecutionId); - stepExecutionId++; - } - return jobExecution; - } - - /** - * Create a {@link StepExecution} and all its parent entities with default - * values, but using the {@link ExecutionContext} and {@link JobParameters} - * provided. - * - * @param jobParameters come {@link JobParameters} - * @param executionContext some {@link ExecutionContext} - * - * @return a {@link StepExecution} with the execution context provided - */ - public static StepExecution createStepExecution(JobParameters jobParameters, ExecutionContext executionContext) { - StepExecution stepExecution = createStepExecution(jobParameters); - stepExecution.setExecutionContext(executionContext); - return stepExecution; - } - - /** - * Create a {@link StepExecution} and all its parent entities with default - * values, but using the {@link JobParameters} provided. - * - * @param jobParameters some {@link JobParameters} - * @return a {@link StepExecution} with the job parameters provided - */ - public static StepExecution createStepExecution(JobParameters jobParameters) { - JobExecution jobExecution = createJobExecution(DEFAULT_JOB_NAME, DEFAULT_JOB_INSTANCE_ID, - DEFAULT_JOB_EXECUTION_ID, jobParameters); - return jobExecution.createStepExecution(DEFAULT_STEP_NAME); - } - - /** - * Create a {@link StepExecution} and all its parent entities with default - * values, but using the {@link ExecutionContext} provided. - * - * @param executionContext some {@link ExecutionContext} - * @return a {@link StepExecution} with the execution context provided - */ - public static StepExecution createStepExecution(ExecutionContext executionContext) { - StepExecution stepExecution = createStepExecution(); - stepExecution.setExecutionContext(executionContext); - return stepExecution; - } - -} +/* + * Copyright 2006-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.test; + +import java.util.Collection; + +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobInstance; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.converter.DefaultJobParametersConverter; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.support.PropertiesConverter; + +/** + * Convenience methods for creating test instances of {@link JobExecution}, + * {@link JobInstance} and {@link StepExecution}. + * + * @author Dave Syer + * @author Mahmoud Ben Hassine + * + */ +public class MetaDataInstanceFactory { + + /** + * The default name for a job ("job") + */ + public static final String DEFAULT_JOB_NAME = "job"; + + /** + * The default id for a job instance (12L) + */ + public static final long DEFAULT_JOB_INSTANCE_ID = 12L; + + /** + * The default id for a job execution (123L) + */ + public static final long DEFAULT_JOB_EXECUTION_ID = 123L; + + /** + * The default name for a step ("step") + */ + public static final String DEFAULT_STEP_NAME = "step"; + + /** + * The default id for a step execution (1234L) + */ + public static final long DEFAULT_STEP_EXECUTION_ID = 1234L; + + /** + * Create a {@link JobInstance} with the parameters provided. + * @param jobName the name of the job + * @param instanceId the Id of the {@link JobInstance} + * @return a {@link JobInstance} with empty {@link JobParameters} + */ + public static JobInstance createJobInstance(String jobName, Long instanceId) { + return new JobInstance(instanceId, jobName); + } + + /** + * Create a {@link JobInstance} with default parameters. + * @return a {@link JobInstance} with name=DEFAULT_JOB_NAME, + * id=DEFAULT_JOB_INSTANCE_ID and empty parameters + */ + public static JobInstance createJobInstance() { + return new JobInstance(DEFAULT_JOB_INSTANCE_ID, DEFAULT_JOB_NAME); + } + + /** + * Create a {@link JobExecution} with default parameters. + * @return a {@link JobExecution} with id=DEFAULT_JOB_EXECUTION_ID + */ + public static JobExecution createJobExecution() { + return createJobExecution(DEFAULT_JOB_EXECUTION_ID); + } + + /** + * Create a {@link JobExecution} with the parameters provided. + * @param executionId the id for the {@link JobExecution} + * @return a {@link JobExecution} with valid {@link JobInstance} + */ + public static JobExecution createJobExecution(Long executionId) { + return createJobExecution(DEFAULT_JOB_NAME, DEFAULT_JOB_INSTANCE_ID, executionId); + } + + /** + * Create a {@link JobExecution} with the parameters provided. + * @param jobName the name of the job + * @param instanceId the id for the {@link JobInstance} + * @param executionId the id for the {@link JobExecution} + * @return a {@link JobExecution} with empty {@link JobParameters} + */ + public static JobExecution createJobExecution(String jobName, Long instanceId, Long executionId) { + return createJobExecution(jobName, instanceId, executionId, new JobParameters()); + } + + /** + * Create a {@link JobExecution} with the parameters provided. + * @param jobName the name of the job + * @param instanceId the Id of the {@link JobInstance} + * @param executionId the id for the {@link JobExecution} + * @param jobParameters comma or new line separated name=value pairs + * @return a {@link JobExecution} + */ + public static JobExecution createJobExecution(String jobName, Long instanceId, Long executionId, + String jobParameters) { + JobParameters params = new DefaultJobParametersConverter() + .getJobParameters(PropertiesConverter.stringToProperties(jobParameters)); + return createJobExecution(jobName, instanceId, executionId, params); + } + + /** + * Create a {@link JobExecution} with the parameters provided. + * @param jobName the name of the job + * @param instanceId the Id of the {@link JobInstance} + * @param executionId the id for the {@link JobExecution} + * @param jobParameters an instance of {@link JobParameters} + * @return a {@link JobExecution} + */ + public static JobExecution createJobExecution(String jobName, Long instanceId, Long executionId, + JobParameters jobParameters) { + return new JobExecution(createJobInstance(jobName, instanceId), executionId, jobParameters); + } + + /** + * Create a {@link StepExecution} with default parameters. + * @return a {@link StepExecution} with stepName="step" and + * id=DEFAULT_STEP_EXECUTION_ID + */ + public static StepExecution createStepExecution() { + return createStepExecution(DEFAULT_STEP_NAME, DEFAULT_STEP_EXECUTION_ID); + } + + /** + * Create a {@link StepExecution} with the parameters provided. + * @param stepName the stepName for the {@link StepExecution} + * @param executionId the id for the {@link StepExecution} + * @return a {@link StepExecution} with a {@link JobExecution} having default + * properties + */ + public static StepExecution createStepExecution(String stepName, Long executionId) { + return createStepExecution(createJobExecution(), stepName, executionId); + } + + /** + * Create a {@link StepExecution} with the parameters provided. + * @param jobExecution instance of {@link JobExecution}. + * @param stepName the name for the {@link StepExecution}. + * @param executionId the id for the {@link StepExecution}. + * @return a {@link StepExecution} with the given {@link JobExecution}. + */ + public static StepExecution createStepExecution(JobExecution jobExecution, String stepName, Long executionId) { + StepExecution stepExecution = jobExecution.createStepExecution(stepName); + stepExecution.setId(executionId); + return stepExecution; + } + + /** + * Create a {@link JobExecution} with the parameters provided with attached step + * executions. + * @param executionId the {@link JobExecution} id + * @param stepNames the names of the step executions + * @return a {@link JobExecution} with step executions as specified, each with a + * unique id + */ + public static JobExecution createJobExecutionWithStepExecutions(Long executionId, Collection stepNames) { + JobExecution jobExecution = createJobExecution(DEFAULT_JOB_NAME, DEFAULT_JOB_INSTANCE_ID, executionId); + Long stepExecutionId = DEFAULT_STEP_EXECUTION_ID; + for (String stepName : stepNames) { + createStepExecution(jobExecution, stepName, stepExecutionId); + stepExecutionId++; + } + return jobExecution; + } + + /** + * Create a {@link StepExecution} and all its parent entities with default values, but + * using the {@link ExecutionContext} and {@link JobParameters} provided. + * @param jobParameters come {@link JobParameters} + * @param executionContext some {@link ExecutionContext} + * @return a {@link StepExecution} with the execution context provided + */ + public static StepExecution createStepExecution(JobParameters jobParameters, ExecutionContext executionContext) { + StepExecution stepExecution = createStepExecution(jobParameters); + stepExecution.setExecutionContext(executionContext); + return stepExecution; + } + + /** + * Create a {@link StepExecution} and all its parent entities with default values, but + * using the {@link JobParameters} provided. + * @param jobParameters some {@link JobParameters} + * @return a {@link StepExecution} with the job parameters provided + */ + public static StepExecution createStepExecution(JobParameters jobParameters) { + JobExecution jobExecution = createJobExecution(DEFAULT_JOB_NAME, DEFAULT_JOB_INSTANCE_ID, + DEFAULT_JOB_EXECUTION_ID, jobParameters); + return jobExecution.createStepExecution(DEFAULT_STEP_NAME); + } + + /** + * Create a {@link StepExecution} and all its parent entities with default values, but + * using the {@link ExecutionContext} provided. + * @param executionContext some {@link ExecutionContext} + * @return a {@link StepExecution} with the execution context provided + */ + public static StepExecution createStepExecution(ExecutionContext executionContext) { + StepExecution stepExecution = createStepExecution(); + stepExecution.setExecutionContext(executionContext); + return stepExecution; + } + +} diff --git a/spring-batch-test/src/main/java/org/springframework/batch/test/StepRunner.java b/spring-batch-test/src/main/java/org/springframework/batch/test/StepRunner.java index 79ccfa8e3..26d805959 100755 --- a/spring-batch-test/src/main/java/org/springframework/batch/test/StepRunner.java +++ b/spring-batch-test/src/main/java/org/springframework/batch/test/StepRunner.java @@ -42,22 +42,22 @@ import org.springframework.batch.item.ExecutionContext; import org.springframework.lang.Nullable; /** - * Utility class for executing steps outside of a {@link Job}. This is useful in - * end to end testing in order to allow for the testing of a step individually - * without running every Step in a job. + * Utility class for executing steps outside of a {@link Job}. This is useful in end to + * end testing in order to allow for the testing of a step individually without running + * every Step in a job. * *
        - *
      • launchStep(Step step): Launch the step with new parameters each - * time. (The current system time will be used) - *
      • launchStep(Step step, JobParameters jobParameters): Launch the - * specified step with the provided JobParameters. This may be useful if your - * step requires a certain parameter during runtime. + *
      • launchStep(Step step): Launch the step with new parameters each time. (The + * current system time will be used) + *
      • launchStep(Step step, JobParameters jobParameters): Launch the specified + * step with the provided JobParameters. This may be useful if your step requires a + * certain parameter during runtime. *
      * - * It should be noted that any checked exceptions encountered while running the - * Step will wrapped with RuntimeException. Any checked exception thrown will be - * due to a framework error, not the logic of the step, and thus requiring a - * throws declaration in clients of this class is unnecessary. + * It should be noted that any checked exceptions encountered while running the Step will + * wrapped with RuntimeException. Any checked exception thrown will be due to a framework + * error, not the logic of the step, and thus requiring a throws declaration in clients of + * this class is unnecessary. * * @author Dan Garrette * @author Lucas Ward @@ -80,10 +80,9 @@ public class StepRunner { } /** - * Launch just the specified step as its own job. A unique set of - * JobParameters will automatically be generated. An IllegalStateException - * is thrown if there is no Step with the given name. - * + * Launch just the specified step as its own job. A unique set of JobParameters will + * automatically be generated. An IllegalStateException is thrown if there is no Step + * with the given name. * @param step The step to launch * @return JobExecution */ @@ -92,13 +91,12 @@ public class StepRunner { } /** - * Launch just the specified step as its own job. A unique set of - * JobParameters will automatically be generated. An IllegalStateException - * is thrown if there is no Step with the given name. - * + * Launch just the specified step as its own job. A unique set of JobParameters will + * automatically be generated. An IllegalStateException is thrown if there is no Step + * with the given name. * @param step The step to launch - * @param jobExecutionContext An ExecutionContext whose values will be - * loaded into the Job ExecutionContext prior to launching the step. + * @param jobExecutionContext An ExecutionContext whose values will be loaded into the + * Job ExecutionContext prior to launching the step. * @return JobExecution */ public JobExecution launchStep(Step step, @Nullable ExecutionContext jobExecutionContext) { @@ -106,9 +104,8 @@ public class StepRunner { } /** - * Launch just the specified step as its own job. An IllegalStateException - * is thrown if there is no Step with the given name. - * + * Launch just the specified step as its own job. An IllegalStateException is thrown + * if there is no Step with the given name. * @param step The step to launch * @param jobParameters The JobParameters to use during the launch * @return JobExecution @@ -118,16 +115,16 @@ public class StepRunner { } /** - * Launch just the specified step as its own job. An IllegalStateException - * is thrown if there is no Step with the given name. - * + * Launch just the specified step as its own job. An IllegalStateException is thrown + * if there is no Step with the given name. * @param step The step to launch * @param jobParameters The JobParameters to use during the launch - * @param jobExecutionContext An ExecutionContext whose values will be - * loaded into the Job ExecutionContext prior to launching the step. + * @param jobExecutionContext An ExecutionContext whose values will be loaded into the + * Job ExecutionContext prior to launching the step. * @return JobExecution */ - public JobExecution launchStep(Step step, JobParameters jobParameters, @Nullable final ExecutionContext jobExecutionContext) { + public JobExecution launchStep(Step step, JobParameters jobParameters, + @Nullable final ExecutionContext jobExecutionContext) { // // Create a fake job // @@ -162,7 +159,6 @@ public class StepRunner { /** * Launch the given job - * * @param job * @param jobParameters */ @@ -185,12 +181,13 @@ public class StepRunner { } /** - * @return a new JobParameters object containing only a parameter for the - * current timestamp, to ensure that the job instance will be unique + * @return a new JobParameters object containing only a parameter for the current + * timestamp, to ensure that the job instance will be unique */ private JobParameters makeUniqueJobParameters() { Map parameters = new HashMap<>(); parameters.put("timestamp", new JobParameter(new Date().getTime())); return new JobParameters(parameters); } + } diff --git a/spring-batch-test/src/main/java/org/springframework/batch/test/StepScopeTestExecutionListener.java b/spring-batch-test/src/main/java/org/springframework/batch/test/StepScopeTestExecutionListener.java index d41fefcc5..3aa675fbf 100644 --- a/spring-batch-test/src/main/java/org/springframework/batch/test/StepScopeTestExecutionListener.java +++ b/spring-batch-test/src/main/java/org/springframework/batch/test/StepScopeTestExecutionListener.java @@ -27,48 +27,48 @@ import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils.MethodCallback; /** - * A {@link TestExecutionListener} that sets up step-scope context for - * dependency injection into unit tests. A {@link StepContext} will be created - * for the duration of a test method and made available to any dependencies that - * are injected. The default behaviour is just to create a {@link StepExecution} - * with fixed properties. Alternatively it can be provided by the test case as a - * factory methods returning the correct type. Example: - * + * A {@link TestExecutionListener} that sets up step-scope context for dependency + * injection into unit tests. A {@link StepContext} will be created for the duration of a + * test method and made available to any dependencies that are injected. The default + * behaviour is just to create a {@link StepExecution} with fixed properties. + * Alternatively it can be provided by the test case as a factory methods returning the + * correct type. Example: + * *
        * @ContextConfiguration
        * @TestExecutionListeners( { DependencyInjectionTestExecutionListener.class, StepScopeTestExecutionListener.class })
        * @RunWith(SpringJUnit4ClassRunner.class)
        * public class StepScopeTestExecutionListenerIntegrationTests {
      - * 
      + *
        * 	// A step-scoped dependency configured in the ApplicationContext
        * 	@Autowired
        * 	private ItemReader<String> reader;
      - * 
      + *
        *  public StepExecution getStepExecution() {
        *    StepExecution execution = MetaDataInstanceFactory.createStepExecution();
        *    execution.getExecutionContext().putString("foo", "bar");
        *    return execution;
        *  }
      - * 
      + *
        * 	@Test
        * 	public void testStepScopedReader() {
        * 		// Step context is active here so the reader can be used,
        *      // and the step execution context will contain foo=bar...
        * 		assertNotNull(reader.read());
        * 	}
      - * 
      + *
        * }
        * 
      - * + * * @author Dave Syer * @author Chris Schaefer */ public class StepScopeTestExecutionListener implements TestExecutionListener { + private static final String STEP_EXECUTION = StepScopeTestExecutionListener.class.getName() + ".STEP_EXECUTION"; /** * Set up a {@link StepExecution} as a test context attribute. - * * @param testContext the current test context * @throws Exception if there is a problem * @see TestExecutionListener#prepareTestInstance(TestContext) @@ -109,11 +109,10 @@ public class StepScopeTestExecutionListener implements TestExecutionListener { StepSynchronizationManager.close(); } } - + /** - * Discover a {@link StepExecution} as a field in the test case or create - * one if none is available. - * + * Discover a {@link StepExecution} as a field in the test case or create one if none + * is available. * @param testContext the current test context * @return a {@link StepExecution} */ @@ -140,10 +139,11 @@ public class StepScopeTestExecutionListener implements TestExecutionListener { } /** - * Look for a method returning the type provided, preferring one with the - * name provided. + * Look for a method returning the type provided, preferring one with the name + * provided. */ private final class ExtractorMethodCallback implements MethodCallback { + private String preferredName; private final Class preferredType; @@ -169,5 +169,7 @@ public class StepScopeTestExecutionListener implements TestExecutionListener { } } } + } + } diff --git a/spring-batch-test/src/main/java/org/springframework/batch/test/StepScopeTestUtils.java b/spring-batch-test/src/main/java/org/springframework/batch/test/StepScopeTestUtils.java index 23656940d..1365d5c0e 100644 --- a/spring-batch-test/src/main/java/org/springframework/batch/test/StepScopeTestUtils.java +++ b/spring-batch-test/src/main/java/org/springframework/batch/test/StepScopeTestUtils.java @@ -22,13 +22,12 @@ import org.springframework.batch.core.scope.StepScope; import org.springframework.batch.core.scope.context.StepSynchronizationManager; /** - * Utility class for creating and manipulating {@link StepScope} in unit tests. - * This is useful when you want to use the Spring test support and inject - * dependencies into your test case that happen to be step scoped in the - * application context. - * + * Utility class for creating and manipulating {@link StepScope} in unit tests. This is + * useful when you want to use the Spring test support and inject dependencies into your + * test case that happen to be step scoped in the application context. + * * @author Dave Syer - * + * */ public class StepScopeTestUtils { diff --git a/spring-batch-test/src/main/java/org/springframework/batch/test/context/BatchTestContextCustomizer.java b/spring-batch-test/src/main/java/org/springframework/batch/test/context/BatchTestContextCustomizer.java index 95e290d67..2285b2fe5 100644 --- a/spring-batch-test/src/main/java/org/springframework/batch/test/context/BatchTestContextCustomizer.java +++ b/spring-batch-test/src/main/java/org/springframework/batch/test/context/BatchTestContextCustomizer.java @@ -27,8 +27,8 @@ import org.springframework.util.Assert; /** * {@link ContextCustomizer} implementation that adds batch test utility classes - * ({@link JobLauncherTestUtils} and {@link JobRepositoryTestUtils}) as beans in - * the test context. + * ({@link JobLauncherTestUtils} and {@link JobRepositoryTestUtils}) as beans in the test + * context. * * @author Mahmoud Ben Hassine * @since 4.1 @@ -36,6 +36,7 @@ import org.springframework.util.Assert; public class BatchTestContextCustomizer implements ContextCustomizer { private static final String JOB_LAUNCHER_TEST_UTILS_BEAN_NAME = "jobLauncherTestUtils"; + private static final String JOB_REPOSITORY_TEST_UTILS_BEAN_NAME = "jobRepositoryTestUtils"; @Override diff --git a/spring-batch-test/src/main/java/org/springframework/batch/test/context/BatchTestContextCustomizerFactory.java b/spring-batch-test/src/main/java/org/springframework/batch/test/context/BatchTestContextCustomizerFactory.java index dbedc8895..12625b0de 100644 --- a/spring-batch-test/src/main/java/org/springframework/batch/test/context/BatchTestContextCustomizerFactory.java +++ b/spring-batch-test/src/main/java/org/springframework/batch/test/context/BatchTestContextCustomizerFactory.java @@ -31,7 +31,8 @@ import org.springframework.test.context.ContextCustomizerFactory; public class BatchTestContextCustomizerFactory implements ContextCustomizerFactory { @Override - public ContextCustomizer createContextCustomizer(Class testClass, List configAttributes) { + public ContextCustomizer createContextCustomizer(Class testClass, + List configAttributes) { if (AnnotatedElementUtils.hasAnnotation(testClass, SpringBatchTest.class)) { return new BatchTestContextCustomizer(); } diff --git a/spring-batch-test/src/main/java/org/springframework/batch/test/context/SpringBatchTest.java b/spring-batch-test/src/main/java/org/springframework/batch/test/context/SpringBatchTest.java index 231de41e1..f77ca4ac7 100644 --- a/spring-batch-test/src/main/java/org/springframework/batch/test/context/SpringBatchTest.java +++ b/spring-batch-test/src/main/java/org/springframework/batch/test/context/SpringBatchTest.java @@ -37,15 +37,13 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; *
        *
      • Registers a {@link JobLauncherTestUtils} bean with the * {@link BatchTestContextCustomizer#JOB_LAUNCHER_TEST_UTILS_BEAN_NAME} which can be used - * in tests for launching jobs and steps. - *
      • - *
      • Registers a {@link JobRepositoryTestUtils} bean - * with the {@link BatchTestContextCustomizer#JOB_REPOSITORY_TEST_UTILS_BEAN_NAME} - * which can be used in tests setup to create or remove job executions. - *
      • - *
      • Registers the {@link StepScopeTestExecutionListener} and {@link JobScopeTestExecutionListener} - * as test execution listeners which are required to test step/job scoped beans. - *
      • + * in tests for launching jobs and steps. + *
      • Registers a {@link JobRepositoryTestUtils} bean with the + * {@link BatchTestContextCustomizer#JOB_REPOSITORY_TEST_UTILS_BEAN_NAME} which can be + * used in tests setup to create or remove job executions.
      • + *
      • Registers the {@link StepScopeTestExecutionListener} and + * {@link JobScopeTestExecutionListener} as test execution listeners which are required to + * test step/job scoped beans.
      • *
      *

      * A typical usage of this annotation with JUnit 4 is like: @@ -113,22 +111,21 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; * // then * Assertions.assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus()); * } - * + * * } * - * - *

      - * It should be noted that {@link JobLauncherTestUtils} requires a - * {@link org.springframework.batch.core.Job} bean and that - * {@link JobRepositoryTestUtils} requires a {@link javax.sql.DataSource} bean. - * Since this annotation registers a {@link JobLauncherTestUtils} and a - * {@link JobRepositoryTestUtils} in the test context, it is expected that the - * test context contains a single autowire candidate for a - * {@link org.springframework.batch.core.Job} and a {@link javax.sql.DataSource} - * (either a single bean definition or one that is - * annotated with {@link org.springframework.context.annotation.Primary}). - *

      - * + * + *

      + * It should be noted that {@link JobLauncherTestUtils} requires a + * {@link org.springframework.batch.core.Job} bean and that {@link JobRepositoryTestUtils} + * requires a {@link javax.sql.DataSource} bean. Since this annotation registers a + * {@link JobLauncherTestUtils} and a {@link JobRepositoryTestUtils} in the test context, + * it is expected that the test context contains a single autowire candidate for a + * {@link org.springframework.batch.core.Job} and a {@link javax.sql.DataSource} (either a + * single bean definition or one that is annotated with + * {@link org.springframework.context.annotation.Primary}). + *

      + * * @author Mahmoud Ben Hassine * @since 4.1 * @see JobLauncherTestUtils @@ -140,10 +137,9 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited -@TestExecutionListeners( - listeners = {StepScopeTestExecutionListener.class, JobScopeTestExecutionListener.class}, - mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS -) +@TestExecutionListeners(listeners = { StepScopeTestExecutionListener.class, JobScopeTestExecutionListener.class }, + mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS) @ExtendWith(SpringExtension.class) public @interface SpringBatchTest { + } diff --git a/spring-batch-test/src/test/java/org/springframework/batch/test/AbstractSampleJobTests.java b/spring-batch-test/src/test/java/org/springframework/batch/test/AbstractSampleJobTests.java index 80a04910b..da3f95f8f 100644 --- a/spring-batch-test/src/test/java/org/springframework/batch/test/AbstractSampleJobTests.java +++ b/spring-batch-test/src/test/java/org/springframework/batch/test/AbstractSampleJobTests.java @@ -1,112 +1,116 @@ -/* - * Copyright 2009-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.test.sample.SampleTasklet; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.test.annotation.Repeat; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.jdbc.JdbcTestUtils; - -/** - * This is an abstract test class. - * - * @author Dan Garrette - * @since 2.0 - */ -@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/job-runner-context.xml" }) -public abstract class AbstractSampleJobTests { - - private JdbcTemplate jdbcTemplate; - - @Autowired - private JobLauncherTestUtils jobLauncherTestUtils; - - @Autowired - @Qualifier("tasklet2") - private SampleTasklet tasklet2; - - @Autowired - public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; - } - - @Before - public void setUp() { - this.jdbcTemplate.update("create table TESTS (ID integer, NAME varchar(40))"); - tasklet2.jobContextEntryFound = false; - } - - @After - public void tearDown() { - JdbcTestUtils.dropTables(this.jdbcTemplate, "TESTS"); - } - - @Test - public void testJob() throws Exception { - assertEquals(BatchStatus.COMPLETED, jobLauncherTestUtils.launchJob().getStatus()); - this.verifyTasklet(1); - this.verifyTasklet(2); - } - - @Test(expected = IllegalStateException.class) - public void testNonExistentStep() { - jobLauncherTestUtils.launchStep("nonExistent"); - } - - @Test - public void testStep1Execution() { - assertEquals(BatchStatus.COMPLETED, jobLauncherTestUtils.launchStep("step1").getStatus()); - this.verifyTasklet(1); - } - - @Test - public void testStep2Execution() { - assertEquals(BatchStatus.COMPLETED, jobLauncherTestUtils.launchStep("step2").getStatus()); - this.verifyTasklet(2); - } - - @Test - @Repeat(10) - public void testStep3Execution() throws Exception { - // logging only, may complete in < 1ms (repeat so that it's likely to for at least one of those times) - assertEquals(BatchStatus.COMPLETED, jobLauncherTestUtils.launchStep("step3").getStatus()); - } - - @Test - public void testStepLaunchJobContextEntry() { - ExecutionContext jobContext = new ExecutionContext(); - jobContext.put("key1", "value1"); - assertEquals(BatchStatus.COMPLETED, jobLauncherTestUtils.launchStep("step2", jobContext).getStatus()); - this.verifyTasklet(2); - assertTrue(tasklet2.jobContextEntryFound); - } - - private void verifyTasklet(int id) { - assertEquals(id, jdbcTemplate.queryForObject("SELECT ID from TESTS where NAME = 'SampleTasklet" + id + "'", Integer.class).intValue()); - } - -} +/* + * Copyright 2009-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.test.sample.SampleTasklet; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.test.annotation.Repeat; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.jdbc.JdbcTestUtils; + +/** + * This is an abstract test class. + * + * @author Dan Garrette + * @since 2.0 + */ +@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/job-runner-context.xml" }) +public abstract class AbstractSampleJobTests { + + private JdbcTemplate jdbcTemplate; + + @Autowired + private JobLauncherTestUtils jobLauncherTestUtils; + + @Autowired + @Qualifier("tasklet2") + private SampleTasklet tasklet2; + + @Autowired + public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + @Before + public void setUp() { + this.jdbcTemplate.update("create table TESTS (ID integer, NAME varchar(40))"); + tasklet2.jobContextEntryFound = false; + } + + @After + public void tearDown() { + JdbcTestUtils.dropTables(this.jdbcTemplate, "TESTS"); + } + + @Test + public void testJob() throws Exception { + assertEquals(BatchStatus.COMPLETED, jobLauncherTestUtils.launchJob().getStatus()); + this.verifyTasklet(1); + this.verifyTasklet(2); + } + + @Test(expected = IllegalStateException.class) + public void testNonExistentStep() { + jobLauncherTestUtils.launchStep("nonExistent"); + } + + @Test + public void testStep1Execution() { + assertEquals(BatchStatus.COMPLETED, jobLauncherTestUtils.launchStep("step1").getStatus()); + this.verifyTasklet(1); + } + + @Test + public void testStep2Execution() { + assertEquals(BatchStatus.COMPLETED, jobLauncherTestUtils.launchStep("step2").getStatus()); + this.verifyTasklet(2); + } + + @Test + @Repeat(10) + public void testStep3Execution() throws Exception { + // logging only, may complete in < 1ms (repeat so that it's likely to for at least + // one of those times) + assertEquals(BatchStatus.COMPLETED, jobLauncherTestUtils.launchStep("step3").getStatus()); + } + + @Test + public void testStepLaunchJobContextEntry() { + ExecutionContext jobContext = new ExecutionContext(); + jobContext.put("key1", "value1"); + assertEquals(BatchStatus.COMPLETED, jobLauncherTestUtils.launchStep("step2", jobContext).getStatus()); + this.verifyTasklet(2); + assertTrue(tasklet2.jobContextEntryFound); + } + + private void verifyTasklet(int id) { + assertEquals(id, + jdbcTemplate + .queryForObject("SELECT ID from TESTS where NAME = 'SampleTasklet" + id + "'", Integer.class) + .intValue()); + } + +} diff --git a/spring-batch-test/src/test/java/org/springframework/batch/test/AssertFileTests.java b/spring-batch-test/src/test/java/org/springframework/batch/test/AssertFileTests.java index 4078f51b4..de05efae1 100644 --- a/spring-batch-test/src/test/java/org/springframework/batch/test/AssertFileTests.java +++ b/spring-batch-test/src/test/java/org/springframework/batch/test/AssertFileTests.java @@ -24,11 +24,12 @@ import org.springframework.core.io.FileSystemResource; /** * This class can be used to assert that two files are the same. - * + * * @author Dan Garrette * @since 2.0 */ public class AssertFileTests { + private static final String DIRECTORY = "src/test/resources/data/input/"; @Test @@ -97,12 +98,13 @@ public class AssertFileTests { } private void executeAssertEquals(String expected, String actual) throws Exception { - AssertFile.assertFileEquals(new FileSystemResource(DIRECTORY + expected), new FileSystemResource(DIRECTORY - + actual)); + AssertFile.assertFileEquals(new FileSystemResource(DIRECTORY + expected), + new FileSystemResource(DIRECTORY + actual)); } @Test public void testAssertLineCount() throws Exception { AssertFile.assertLineCount(5, new FileSystemResource(DIRECTORY + "input1.txt")); } + } diff --git a/spring-batch-test/src/test/java/org/springframework/batch/test/ExecutionContextTestUtilsTests.java b/spring-batch-test/src/test/java/org/springframework/batch/test/ExecutionContextTestUtilsTests.java index a5a5edb9f..8eafe873f 100644 --- a/spring-batch-test/src/test/java/org/springframework/batch/test/ExecutionContextTestUtilsTests.java +++ b/spring-batch-test/src/test/java/org/springframework/batch/test/ExecutionContextTestUtilsTests.java @@ -1,66 +1,68 @@ -/* - * Copyright 2006-2009 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.test; - -import static org.junit.Assert.assertEquals; - -import java.util.Arrays; -import java.util.Date; - -import org.junit.Test; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.StepExecution; - -public class ExecutionContextTestUtilsTests { - - @Test - public void testFromJob() throws Exception { - Date date = new Date(); - JobExecution jobExecution = MetaDataInstanceFactory.createJobExecution(); - jobExecution.getExecutionContext().put("foo", date); - Date result = ExecutionContextTestUtils.getValueFromJob(jobExecution, "foo"); - assertEquals(date, result); - } - - @Test - public void testFromStepInJob() throws Exception { - Date date = new Date(); - JobExecution jobExecution = MetaDataInstanceFactory.createJobExecutionWithStepExecutions(123L, Arrays.asList("foo", "bar")); - StepExecution stepExecution = jobExecution.createStepExecution("spam"); - stepExecution.getExecutionContext().put("foo", date); - Date result = ExecutionContextTestUtils.getValueFromStepInJob(jobExecution, "spam", "foo"); - assertEquals(date, result); - } - - @Test(expected=IllegalArgumentException.class) - public void testFromStepInJobNoSuchStep() throws Exception { - Date date = new Date(); - JobExecution jobExecution = MetaDataInstanceFactory.createJobExecutionWithStepExecutions(123L, Arrays.asList("foo", "bar")); - Date result = ExecutionContextTestUtils.getValueFromStepInJob(jobExecution, "spam", "foo"); - assertEquals(date, result); - } - - @Test - public void testFromStep() throws Exception { - Date date = new Date(); - StepExecution stepExecution = MetaDataInstanceFactory.createStepExecution(); - stepExecution.getExecutionContext().put("foo", date); - Date result = ExecutionContextTestUtils.getValueFromStep(stepExecution, "foo"); - assertEquals(date, result); - } - -} +/* + * Copyright 2006-2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.test; + +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; +import java.util.Date; + +import org.junit.Test; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.StepExecution; + +public class ExecutionContextTestUtilsTests { + + @Test + public void testFromJob() throws Exception { + Date date = new Date(); + JobExecution jobExecution = MetaDataInstanceFactory.createJobExecution(); + jobExecution.getExecutionContext().put("foo", date); + Date result = ExecutionContextTestUtils.getValueFromJob(jobExecution, "foo"); + assertEquals(date, result); + } + + @Test + public void testFromStepInJob() throws Exception { + Date date = new Date(); + JobExecution jobExecution = MetaDataInstanceFactory.createJobExecutionWithStepExecutions(123L, + Arrays.asList("foo", "bar")); + StepExecution stepExecution = jobExecution.createStepExecution("spam"); + stepExecution.getExecutionContext().put("foo", date); + Date result = ExecutionContextTestUtils.getValueFromStepInJob(jobExecution, "spam", "foo"); + assertEquals(date, result); + } + + @Test(expected = IllegalArgumentException.class) + public void testFromStepInJobNoSuchStep() throws Exception { + Date date = new Date(); + JobExecution jobExecution = MetaDataInstanceFactory.createJobExecutionWithStepExecutions(123L, + Arrays.asList("foo", "bar")); + Date result = ExecutionContextTestUtils.getValueFromStepInJob(jobExecution, "spam", "foo"); + assertEquals(date, result); + } + + @Test + public void testFromStep() throws Exception { + Date date = new Date(); + StepExecution stepExecution = MetaDataInstanceFactory.createStepExecution(); + stepExecution.getExecutionContext().put("foo", date); + Date result = ExecutionContextTestUtils.getValueFromStep(stepExecution, "foo"); + assertEquals(date, result); + } + +} diff --git a/spring-batch-test/src/test/java/org/springframework/batch/test/JobLauncherTestUtilsTests.java b/spring-batch-test/src/test/java/org/springframework/batch/test/JobLauncherTestUtilsTests.java index 573fc71d3..461454285 100644 --- a/spring-batch-test/src/test/java/org/springframework/batch/test/JobLauncherTestUtilsTests.java +++ b/spring-batch-test/src/test/java/org/springframework/batch/test/JobLauncherTestUtilsTests.java @@ -110,12 +110,10 @@ public class JobLauncherTestUtilsTests { @Bean public DataSource dataSource() { - return new EmbeddedDatabaseBuilder() - .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("/org/springframework/batch/core/schema-hsqldb.sql") - .generateUniqueName(true) - .build(); + return new EmbeddedDatabaseBuilder().addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") + .addScript("/org/springframework/batch/core/schema-hsqldb.sql").generateUniqueName(true).build(); } + } } diff --git a/spring-batch-test/src/test/java/org/springframework/batch/test/JobRepositoryTestUtilsTests.java b/spring-batch-test/src/test/java/org/springframework/batch/test/JobRepositoryTestUtilsTests.java index a915f9147..16ad48d4d 100644 --- a/spring-batch-test/src/test/java/org/springframework/batch/test/JobRepositoryTestUtilsTests.java +++ b/spring-batch-test/src/test/java/org/springframework/batch/test/JobRepositoryTestUtilsTests.java @@ -1,149 +1,150 @@ -/* - * Copyright 2006-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.test; - -import static org.junit.Assert.assertEquals; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import javax.sql.DataSource; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.JobParametersIncrementer; -import org.springframework.batch.core.repository.JobRepository; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.lang.Nullable; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.jdbc.JdbcTestUtils; - -/** - * @author Dave Syer - * - */ -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = "/simple-job-launcher-context.xml") -public class JobRepositoryTestUtilsTests { - - private JobRepositoryTestUtils utils; - - @Autowired - private JobRepository jobRepository; - - @Autowired - private DataSource dataSource; - - private JdbcTemplate jdbcTemplate; - - private int beforeJobs; - - private int beforeSteps; - - @Before - public void init() { - jdbcTemplate = new JdbcTemplate(dataSource); - beforeJobs = JdbcTestUtils.countRowsInTable(jdbcTemplate, "BATCH_JOB_EXECUTION"); - beforeSteps = JdbcTestUtils.countRowsInTable(jdbcTemplate, "BATCH_STEP_EXECUTION"); - } - - @Test(expected=IllegalArgumentException.class) - public void testMandatoryProperties() throws Exception { - utils = new JobRepositoryTestUtils(); - utils.afterPropertiesSet(); - } - - @Test(expected=IllegalArgumentException.class) - public void testMandatoryDataSource() throws Exception { - utils = new JobRepositoryTestUtils(); - utils.setJobRepository(jobRepository); - utils.afterPropertiesSet(); - } - - @Test - public void testCreateJobExecutions() throws Exception { - utils = new JobRepositoryTestUtils(jobRepository, dataSource); - List list = utils.createJobExecutions(3); - assertEquals(3, list.size()); - assertEquals(beforeJobs + 3, JdbcTestUtils.countRowsInTable(jdbcTemplate, "BATCH_JOB_EXECUTION")); - assertEquals(beforeSteps + 3, JdbcTestUtils.countRowsInTable(jdbcTemplate, "BATCH_STEP_EXECUTION")); - utils.removeJobExecutions(list); - assertEquals(beforeJobs, JdbcTestUtils.countRowsInTable(jdbcTemplate, "BATCH_JOB_EXECUTION")); - assertEquals(beforeSteps, JdbcTestUtils.countRowsInTable(jdbcTemplate, "BATCH_STEP_EXECUTION")); - } - - @Test - public void testRemoveJobExecutionsWithSameJobInstance() throws Exception { - utils = new JobRepositoryTestUtils(jobRepository, dataSource); - List list = new ArrayList<>(); - JobExecution jobExecution = jobRepository.createJobExecution("job", new JobParameters()); - jobExecution.setEndTime(new Date()); - list.add(jobExecution); - jobRepository.update(jobExecution); - jobExecution = jobRepository.createJobExecution("job", new JobParameters()); - list.add(jobExecution); - assertEquals(beforeJobs + 2, JdbcTestUtils.countRowsInTable(jdbcTemplate, "BATCH_JOB_EXECUTION")); - utils.removeJobExecutions(list); - assertEquals(beforeJobs, JdbcTestUtils.countRowsInTable(jdbcTemplate, "BATCH_JOB_EXECUTION")); - } - - @Test - public void testCreateJobExecutionsByName() throws Exception { - utils = new JobRepositoryTestUtils(jobRepository, dataSource); - List list = utils.createJobExecutions("foo",new String[] {"bar", "spam"}, 3); - assertEquals(3, list.size()); - assertEquals(beforeJobs + 3, JdbcTestUtils.countRowsInTable(jdbcTemplate, "BATCH_JOB_EXECUTION")); - assertEquals(beforeSteps + 6, JdbcTestUtils.countRowsInTable(jdbcTemplate, "BATCH_STEP_EXECUTION")); - utils.removeJobExecutions(list); - assertEquals(beforeJobs, JdbcTestUtils.countRowsInTable(jdbcTemplate, "BATCH_JOB_EXECUTION")); - assertEquals(beforeSteps, JdbcTestUtils.countRowsInTable(jdbcTemplate, "BATCH_STEP_EXECUTION")); - } - - @Test - public void testRemoveJobExecutionsIncrementally() throws Exception { - utils = new JobRepositoryTestUtils(jobRepository, dataSource); - List list1 = utils.createJobExecutions(3); - List list2 = utils.createJobExecutions(2); - assertEquals(beforeJobs + 5, JdbcTestUtils.countRowsInTable(jdbcTemplate, "BATCH_JOB_EXECUTION")); - utils.removeJobExecutions(list2); - assertEquals(beforeJobs + 3, JdbcTestUtils.countRowsInTable(jdbcTemplate, "BATCH_JOB_EXECUTION")); - utils.removeJobExecutions(list1); - assertEquals(beforeJobs, JdbcTestUtils.countRowsInTable(jdbcTemplate, "BATCH_JOB_EXECUTION")); - } - - @Test - public void testCreateJobExecutionsWithIncrementer() throws Exception { - utils = new JobRepositoryTestUtils(jobRepository, dataSource); - utils.setJobParametersIncrementer(new JobParametersIncrementer() { - @Override - public JobParameters getNext(@Nullable JobParameters parameters) { - return new JobParametersBuilder().addString("foo","bar").toJobParameters(); - } - }); - List list = utils.createJobExecutions(1); - assertEquals(1, list.size()); - assertEquals("bar", list.get(0).getJobParameters().getString("foo")); - utils.removeJobExecutions(list); - assertEquals(beforeJobs, JdbcTestUtils.countRowsInTable(jdbcTemplate, "BATCH_JOB_EXECUTION")); - } -} +/* + * Copyright 2006-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.test; + +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import javax.sql.DataSource; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.JobParametersBuilder; +import org.springframework.batch.core.JobParametersIncrementer; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.lang.Nullable; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.jdbc.JdbcTestUtils; + +/** + * @author Dave Syer + * + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = "/simple-job-launcher-context.xml") +public class JobRepositoryTestUtilsTests { + + private JobRepositoryTestUtils utils; + + @Autowired + private JobRepository jobRepository; + + @Autowired + private DataSource dataSource; + + private JdbcTemplate jdbcTemplate; + + private int beforeJobs; + + private int beforeSteps; + + @Before + public void init() { + jdbcTemplate = new JdbcTemplate(dataSource); + beforeJobs = JdbcTestUtils.countRowsInTable(jdbcTemplate, "BATCH_JOB_EXECUTION"); + beforeSteps = JdbcTestUtils.countRowsInTable(jdbcTemplate, "BATCH_STEP_EXECUTION"); + } + + @Test(expected = IllegalArgumentException.class) + public void testMandatoryProperties() throws Exception { + utils = new JobRepositoryTestUtils(); + utils.afterPropertiesSet(); + } + + @Test(expected = IllegalArgumentException.class) + public void testMandatoryDataSource() throws Exception { + utils = new JobRepositoryTestUtils(); + utils.setJobRepository(jobRepository); + utils.afterPropertiesSet(); + } + + @Test + public void testCreateJobExecutions() throws Exception { + utils = new JobRepositoryTestUtils(jobRepository, dataSource); + List list = utils.createJobExecutions(3); + assertEquals(3, list.size()); + assertEquals(beforeJobs + 3, JdbcTestUtils.countRowsInTable(jdbcTemplate, "BATCH_JOB_EXECUTION")); + assertEquals(beforeSteps + 3, JdbcTestUtils.countRowsInTable(jdbcTemplate, "BATCH_STEP_EXECUTION")); + utils.removeJobExecutions(list); + assertEquals(beforeJobs, JdbcTestUtils.countRowsInTable(jdbcTemplate, "BATCH_JOB_EXECUTION")); + assertEquals(beforeSteps, JdbcTestUtils.countRowsInTable(jdbcTemplate, "BATCH_STEP_EXECUTION")); + } + + @Test + public void testRemoveJobExecutionsWithSameJobInstance() throws Exception { + utils = new JobRepositoryTestUtils(jobRepository, dataSource); + List list = new ArrayList<>(); + JobExecution jobExecution = jobRepository.createJobExecution("job", new JobParameters()); + jobExecution.setEndTime(new Date()); + list.add(jobExecution); + jobRepository.update(jobExecution); + jobExecution = jobRepository.createJobExecution("job", new JobParameters()); + list.add(jobExecution); + assertEquals(beforeJobs + 2, JdbcTestUtils.countRowsInTable(jdbcTemplate, "BATCH_JOB_EXECUTION")); + utils.removeJobExecutions(list); + assertEquals(beforeJobs, JdbcTestUtils.countRowsInTable(jdbcTemplate, "BATCH_JOB_EXECUTION")); + } + + @Test + public void testCreateJobExecutionsByName() throws Exception { + utils = new JobRepositoryTestUtils(jobRepository, dataSource); + List list = utils.createJobExecutions("foo", new String[] { "bar", "spam" }, 3); + assertEquals(3, list.size()); + assertEquals(beforeJobs + 3, JdbcTestUtils.countRowsInTable(jdbcTemplate, "BATCH_JOB_EXECUTION")); + assertEquals(beforeSteps + 6, JdbcTestUtils.countRowsInTable(jdbcTemplate, "BATCH_STEP_EXECUTION")); + utils.removeJobExecutions(list); + assertEquals(beforeJobs, JdbcTestUtils.countRowsInTable(jdbcTemplate, "BATCH_JOB_EXECUTION")); + assertEquals(beforeSteps, JdbcTestUtils.countRowsInTable(jdbcTemplate, "BATCH_STEP_EXECUTION")); + } + + @Test + public void testRemoveJobExecutionsIncrementally() throws Exception { + utils = new JobRepositoryTestUtils(jobRepository, dataSource); + List list1 = utils.createJobExecutions(3); + List list2 = utils.createJobExecutions(2); + assertEquals(beforeJobs + 5, JdbcTestUtils.countRowsInTable(jdbcTemplate, "BATCH_JOB_EXECUTION")); + utils.removeJobExecutions(list2); + assertEquals(beforeJobs + 3, JdbcTestUtils.countRowsInTable(jdbcTemplate, "BATCH_JOB_EXECUTION")); + utils.removeJobExecutions(list1); + assertEquals(beforeJobs, JdbcTestUtils.countRowsInTable(jdbcTemplate, "BATCH_JOB_EXECUTION")); + } + + @Test + public void testCreateJobExecutionsWithIncrementer() throws Exception { + utils = new JobRepositoryTestUtils(jobRepository, dataSource); + utils.setJobParametersIncrementer(new JobParametersIncrementer() { + @Override + public JobParameters getNext(@Nullable JobParameters parameters) { + return new JobParametersBuilder().addString("foo", "bar").toJobParameters(); + } + }); + List list = utils.createJobExecutions(1); + assertEquals(1, list.size()); + assertEquals("bar", list.get(0).getJobParameters().getString("foo")); + utils.removeJobExecutions(list); + assertEquals(beforeJobs, JdbcTestUtils.countRowsInTable(jdbcTemplate, "BATCH_JOB_EXECUTION")); + } + +} diff --git a/spring-batch-test/src/test/java/org/springframework/batch/test/JobScopeTestExecutionListenerIntegrationTests.java b/spring-batch-test/src/test/java/org/springframework/batch/test/JobScopeTestExecutionListenerIntegrationTests.java index 2eea7c3c9..25b71a4b5 100644 --- a/spring-batch-test/src/test/java/org/springframework/batch/test/JobScopeTestExecutionListenerIntegrationTests.java +++ b/spring-batch-test/src/test/java/org/springframework/batch/test/JobScopeTestExecutionListenerIntegrationTests.java @@ -1,64 +1,64 @@ -/* - * Copyright 2013-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.ItemStream; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.TestExecutionListeners; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; - -/** - * @author Dave Syer - * @author Mahmoud Ben Hassine - * @since 2.1 - */ -@ContextConfiguration -@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, JobScopeTestExecutionListener.class }) -@RunWith(SpringJUnit4ClassRunner.class) -public class JobScopeTestExecutionListenerIntegrationTests { - - @Autowired - private ItemReader reader; - - @Autowired - private ItemStream stream; - - public JobExecution getJobExecution() { - // Assert that dependencies are already injected... - assertNotNull(reader); - // Then create the execution for the job scope... - JobExecution execution = MetaDataInstanceFactory.createJobExecution(); - execution.getExecutionContext().putString("input.file", "classpath:/org/springframework/batch/test/simple.txt"); - return execution; - } - - @Test - public void testJob() throws Exception { - stream.open(new ExecutionContext()); - assertEquals("foo", reader.read()); - } - -} +/* + * Copyright 2013-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemStream; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestExecutionListeners; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; + +/** + * @author Dave Syer + * @author Mahmoud Ben Hassine + * @since 2.1 + */ +@ContextConfiguration +@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, JobScopeTestExecutionListener.class }) +@RunWith(SpringJUnit4ClassRunner.class) +public class JobScopeTestExecutionListenerIntegrationTests { + + @Autowired + private ItemReader reader; + + @Autowired + private ItemStream stream; + + public JobExecution getJobExecution() { + // Assert that dependencies are already injected... + assertNotNull(reader); + // Then create the execution for the job scope... + JobExecution execution = MetaDataInstanceFactory.createJobExecution(); + execution.getExecutionContext().putString("input.file", "classpath:/org/springframework/batch/test/simple.txt"); + return execution; + } + + @Test + public void testJob() throws Exception { + stream.open(new ExecutionContext()); + assertEquals("foo", reader.read()); + } + +} diff --git a/spring-batch-test/src/test/java/org/springframework/batch/test/JobScopeTestExecutionListenerTests.java b/spring-batch-test/src/test/java/org/springframework/batch/test/JobScopeTestExecutionListenerTests.java index 6db1ea975..df63c4cb6 100644 --- a/spring-batch-test/src/test/java/org/springframework/batch/test/JobScopeTestExecutionListenerTests.java +++ b/spring-batch-test/src/test/java/org/springframework/batch/test/JobScopeTestExecutionListenerTests.java @@ -1,118 +1,120 @@ -/* - * Copyright 2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -import org.junit.Test; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.scope.context.JobContext; -import org.springframework.batch.core.scope.context.JobSynchronizationManager; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.TestContext; -import org.springframework.test.context.TestContextManager; - -/** - * @author Dave Syer - * @since 2.1 - */ -@ContextConfiguration -public class JobScopeTestExecutionListenerTests { - - private JobScopeTestExecutionListener listener = new JobScopeTestExecutionListener(); - - @Test - public void testDefaultJobContext() throws Exception { - TestContext testContext = getTestContext(new Object()); - listener.prepareTestInstance(testContext); - listener.beforeTestMethod(testContext); - JobContext context = JobSynchronizationManager.getContext(); - assertNotNull(context); - listener.afterTestMethod(testContext); - assertNull(JobSynchronizationManager.getContext()); - } - - @Test - public void testWithJobExecutionFactory() throws Exception { - testExecutionContext(new WithJobExecutionFactory()); - } - - @Test - public void testWithParameters() throws Exception { - testJobParameters(new WithJobExecutionFactory()); - } - - private void testExecutionContext(Object target) throws Exception { - TestContext testContext = getTestContext(target); - listener.prepareTestInstance(testContext); - try { - listener.beforeTestMethod(testContext); - JobContext context = JobSynchronizationManager.getContext(); - assertNotNull(context); - assertEquals("bar", context.getJobExecutionContext().get("foo")); - } - finally { - listener.afterTestMethod(testContext); - } - assertNull(JobSynchronizationManager.getContext()); - } - - private void testJobParameters(Object target) throws Exception { - TestContext testContext = getTestContext(target); - listener.prepareTestInstance(testContext); - try { - listener.beforeTestMethod(testContext); - JobContext context = JobSynchronizationManager.getContext(); - assertNotNull(context); - assertEquals("spam", context.getJobParameters().get("foo")); - } - finally { - listener.afterTestMethod(testContext); - } - assertNull(JobSynchronizationManager.getContext()); - } - - @SuppressWarnings("unused") - private static class WithJobExecutionFactory { - public JobExecution getJobExecution() { - JobExecution jobExecution = MetaDataInstanceFactory.createJobExecution("job", 11L, 123L, - new JobParametersBuilder().addString("foo", "spam").toJobParameters()); - jobExecution.getExecutionContext().putString("foo", "bar"); - return jobExecution; - } - } - - private TestContext getTestContext(Object target) throws Exception { - return new MockTestContextManager(target, getClass()).getContext(); - } - - private final class MockTestContextManager extends TestContextManager { - - private MockTestContextManager(Object target, Class testClass) throws Exception { - super(testClass); - prepareTestInstance(target); - } - - public TestContext getContext() { - return getTestContext(); - } - - } - -} +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import org.junit.Test; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobParametersBuilder; +import org.springframework.batch.core.scope.context.JobContext; +import org.springframework.batch.core.scope.context.JobSynchronizationManager; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestContext; +import org.springframework.test.context.TestContextManager; + +/** + * @author Dave Syer + * @since 2.1 + */ +@ContextConfiguration +public class JobScopeTestExecutionListenerTests { + + private JobScopeTestExecutionListener listener = new JobScopeTestExecutionListener(); + + @Test + public void testDefaultJobContext() throws Exception { + TestContext testContext = getTestContext(new Object()); + listener.prepareTestInstance(testContext); + listener.beforeTestMethod(testContext); + JobContext context = JobSynchronizationManager.getContext(); + assertNotNull(context); + listener.afterTestMethod(testContext); + assertNull(JobSynchronizationManager.getContext()); + } + + @Test + public void testWithJobExecutionFactory() throws Exception { + testExecutionContext(new WithJobExecutionFactory()); + } + + @Test + public void testWithParameters() throws Exception { + testJobParameters(new WithJobExecutionFactory()); + } + + private void testExecutionContext(Object target) throws Exception { + TestContext testContext = getTestContext(target); + listener.prepareTestInstance(testContext); + try { + listener.beforeTestMethod(testContext); + JobContext context = JobSynchronizationManager.getContext(); + assertNotNull(context); + assertEquals("bar", context.getJobExecutionContext().get("foo")); + } + finally { + listener.afterTestMethod(testContext); + } + assertNull(JobSynchronizationManager.getContext()); + } + + private void testJobParameters(Object target) throws Exception { + TestContext testContext = getTestContext(target); + listener.prepareTestInstance(testContext); + try { + listener.beforeTestMethod(testContext); + JobContext context = JobSynchronizationManager.getContext(); + assertNotNull(context); + assertEquals("spam", context.getJobParameters().get("foo")); + } + finally { + listener.afterTestMethod(testContext); + } + assertNull(JobSynchronizationManager.getContext()); + } + + @SuppressWarnings("unused") + private static class WithJobExecutionFactory { + + public JobExecution getJobExecution() { + JobExecution jobExecution = MetaDataInstanceFactory.createJobExecution("job", 11L, 123L, + new JobParametersBuilder().addString("foo", "spam").toJobParameters()); + jobExecution.getExecutionContext().putString("foo", "bar"); + return jobExecution; + } + + } + + private TestContext getTestContext(Object target) throws Exception { + return new MockTestContextManager(target, getClass()).getContext(); + } + + private final class MockTestContextManager extends TestContextManager { + + private MockTestContextManager(Object target, Class testClass) throws Exception { + super(testClass); + prepareTestInstance(target); + } + + public TestContext getContext() { + return getTestContext(); + } + + } + +} diff --git a/spring-batch-test/src/test/java/org/springframework/batch/test/MetaDataInstanceFactoryTests.java b/spring-batch-test/src/test/java/org/springframework/batch/test/MetaDataInstanceFactoryTests.java index 6c505c608..91c876be6 100644 --- a/spring-batch-test/src/test/java/org/springframework/batch/test/MetaDataInstanceFactoryTests.java +++ b/spring-batch-test/src/test/java/org/springframework/batch/test/MetaDataInstanceFactoryTests.java @@ -1,149 +1,146 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.test; - -import static org.junit.Assert.assertNotNull; - -import java.util.Arrays; - -import org.junit.Test; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.converter.DefaultJobParametersConverter; -import org.springframework.batch.support.PropertiesConverter; - -/** - * @author Dave Syer - * - */ -public class MetaDataInstanceFactoryTests { - - private String jobName = "JOB"; - - private Long instanceId = 321L; - - private String jobParametersString = "foo=bar"; - - private JobParameters jobParameters = new DefaultJobParametersConverter().getJobParameters(PropertiesConverter - .stringToProperties(jobParametersString)); - - private Long executionId = 4321L; - - private String stepName = "step"; - - private Long stepExecutionId = 11L; - - /** - * Test method for - * {@link MetaDataInstanceFactory#createJobInstance(String, Long)} . - */ - @Test - public void testCreateJobInstanceStringLong() { - assertNotNull(MetaDataInstanceFactory.createJobInstance(jobName, instanceId)); - } - - /** - * Test method for {@link MetaDataInstanceFactory#createJobInstance()} . - */ - @Test - public void testCreateJobInstance() { - assertNotNull(MetaDataInstanceFactory.createJobInstance()); - } - - /** - * Test method for {@link MetaDataInstanceFactory#createJobExecution()} . - */ - @Test - public void testCreateJobExecution() { - assertNotNull(MetaDataInstanceFactory.createJobExecution()); - } - - /** - * Test method for {@link MetaDataInstanceFactory#createJobExecution(Long)} - * . - */ - @Test - public void testCreateJobExecutionLong() { - assertNotNull(MetaDataInstanceFactory.createJobExecution(instanceId)); - } - - /** - * Test method for - * {@link MetaDataInstanceFactory#createJobExecution(String, Long, Long)} . - */ - @Test - public void testCreateJobExecutionStringLongLong() { - assertNotNull(MetaDataInstanceFactory.createJobExecution(jobName, instanceId, executionId)); - } - - /** - * Test method for - * {@link MetaDataInstanceFactory#createJobExecution(String, Long, Long, String)} - * . - */ - @Test - public void testCreateJobExecutionStringLongLongString() { - assertNotNull(MetaDataInstanceFactory.createJobExecution(jobName, instanceId, executionId, jobParametersString)); - } - - /** - * Test method for - * {@link MetaDataInstanceFactory#createJobExecution(String, Long, Long, JobParameters)} - * . - */ - @Test - public void testCreateJobExecutionStringLongLongJobParameters() { - assertNotNull(MetaDataInstanceFactory.createJobExecution(jobName, instanceId, executionId, jobParameters)); - } - - /** - * Test method for {@link MetaDataInstanceFactory#createStepExecution()} . - */ - @Test - public void testCreateStepExecution() { - assertNotNull(MetaDataInstanceFactory.createStepExecution()); - } - - /** - * Test method for - * {@link MetaDataInstanceFactory#createStepExecution(String, Long)} . - */ - @Test - public void testCreateStepExecutionStringLong() { - assertNotNull(MetaDataInstanceFactory.createStepExecution(stepName, stepExecutionId)); - } - - /** - * Test method for - * {@link MetaDataInstanceFactory#createStepExecution(JobExecution, String, Long)} - * . - */ - @Test - public void testCreateStepExecutionJobExecutionStringLong() { - assertNotNull(MetaDataInstanceFactory.createStepExecution(stepName, stepExecutionId)); - } - - /** - * Test method for - * {@link MetaDataInstanceFactory#createJobExecutionWithStepExecutions(Long, java.util.Collection)} - * . - */ - @Test - public void testCreateJobExecutionWithStepExecutions() { - assertNotNull(MetaDataInstanceFactory.createJobExecutionWithStepExecutions(executionId, Arrays.asList(stepName))); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.test; + +import static org.junit.Assert.assertNotNull; + +import java.util.Arrays; + +import org.junit.Test; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.converter.DefaultJobParametersConverter; +import org.springframework.batch.support.PropertiesConverter; + +/** + * @author Dave Syer + * + */ +public class MetaDataInstanceFactoryTests { + + private String jobName = "JOB"; + + private Long instanceId = 321L; + + private String jobParametersString = "foo=bar"; + + private JobParameters jobParameters = new DefaultJobParametersConverter() + .getJobParameters(PropertiesConverter.stringToProperties(jobParametersString)); + + private Long executionId = 4321L; + + private String stepName = "step"; + + private Long stepExecutionId = 11L; + + /** + * Test method for {@link MetaDataInstanceFactory#createJobInstance(String, Long)} . + */ + @Test + public void testCreateJobInstanceStringLong() { + assertNotNull(MetaDataInstanceFactory.createJobInstance(jobName, instanceId)); + } + + /** + * Test method for {@link MetaDataInstanceFactory#createJobInstance()} . + */ + @Test + public void testCreateJobInstance() { + assertNotNull(MetaDataInstanceFactory.createJobInstance()); + } + + /** + * Test method for {@link MetaDataInstanceFactory#createJobExecution()} . + */ + @Test + public void testCreateJobExecution() { + assertNotNull(MetaDataInstanceFactory.createJobExecution()); + } + + /** + * Test method for {@link MetaDataInstanceFactory#createJobExecution(Long)} . + */ + @Test + public void testCreateJobExecutionLong() { + assertNotNull(MetaDataInstanceFactory.createJobExecution(instanceId)); + } + + /** + * Test method for + * {@link MetaDataInstanceFactory#createJobExecution(String, Long, Long)} . + */ + @Test + public void testCreateJobExecutionStringLongLong() { + assertNotNull(MetaDataInstanceFactory.createJobExecution(jobName, instanceId, executionId)); + } + + /** + * Test method for + * {@link MetaDataInstanceFactory#createJobExecution(String, Long, Long, String)} . + */ + @Test + public void testCreateJobExecutionStringLongLongString() { + assertNotNull( + MetaDataInstanceFactory.createJobExecution(jobName, instanceId, executionId, jobParametersString)); + } + + /** + * Test method for + * {@link MetaDataInstanceFactory#createJobExecution(String, Long, Long, JobParameters)} + * . + */ + @Test + public void testCreateJobExecutionStringLongLongJobParameters() { + assertNotNull(MetaDataInstanceFactory.createJobExecution(jobName, instanceId, executionId, jobParameters)); + } + + /** + * Test method for {@link MetaDataInstanceFactory#createStepExecution()} . + */ + @Test + public void testCreateStepExecution() { + assertNotNull(MetaDataInstanceFactory.createStepExecution()); + } + + /** + * Test method for {@link MetaDataInstanceFactory#createStepExecution(String, Long)} . + */ + @Test + public void testCreateStepExecutionStringLong() { + assertNotNull(MetaDataInstanceFactory.createStepExecution(stepName, stepExecutionId)); + } + + /** + * Test method for + * {@link MetaDataInstanceFactory#createStepExecution(JobExecution, String, Long)} . + */ + @Test + public void testCreateStepExecutionJobExecutionStringLong() { + assertNotNull(MetaDataInstanceFactory.createStepExecution(stepName, stepExecutionId)); + } + + /** + * Test method for + * {@link MetaDataInstanceFactory#createJobExecutionWithStepExecutions(Long, java.util.Collection)} + * . + */ + @Test + public void testCreateJobExecutionWithStepExecutions() { + assertNotNull( + MetaDataInstanceFactory.createJobExecutionWithStepExecutions(executionId, Arrays.asList(stepName))); + } + +} diff --git a/spring-batch-test/src/test/java/org/springframework/batch/test/SampleFlowJobTests.java b/spring-batch-test/src/test/java/org/springframework/batch/test/SampleFlowJobTests.java index 1ab97987c..03e59a818 100644 --- a/spring-batch-test/src/test/java/org/springframework/batch/test/SampleFlowJobTests.java +++ b/spring-batch-test/src/test/java/org/springframework/batch/test/SampleFlowJobTests.java @@ -1,34 +1,34 @@ -/* - * Copyright 2009 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.test; - -import org.junit.runner.RunWith; -import org.springframework.batch.core.job.flow.FlowJob; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -/** - * This class will specifically test the capabilities of - * {@link JobRepositoryTestUtils} to test {@link FlowJob}s. - * - * @author Dan Garrette - * @since 2.0 - */ -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = "/jobs/sampleFlowJob.xml") -public class SampleFlowJobTests extends AbstractSampleJobTests { - -} +/* + * Copyright 2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.test; + +import org.junit.runner.RunWith; +import org.springframework.batch.core.job.flow.FlowJob; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * This class will specifically test the capabilities of {@link JobRepositoryTestUtils} to + * test {@link FlowJob}s. + * + * @author Dan Garrette + * @since 2.0 + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = "/jobs/sampleFlowJob.xml") +public class SampleFlowJobTests extends AbstractSampleJobTests { + +} diff --git a/spring-batch-test/src/test/java/org/springframework/batch/test/SampleSimpleJobTests.java b/spring-batch-test/src/test/java/org/springframework/batch/test/SampleSimpleJobTests.java index 916cab60e..1a1f67f9a 100644 --- a/spring-batch-test/src/test/java/org/springframework/batch/test/SampleSimpleJobTests.java +++ b/spring-batch-test/src/test/java/org/springframework/batch/test/SampleSimpleJobTests.java @@ -1,34 +1,34 @@ -/* - * Copyright 2009 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.test; - -import org.junit.runner.RunWith; -import org.springframework.batch.core.job.SimpleJob; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -/** - * This class will specifically test the capabilities of - * {@link JobRepositoryTestUtils} to test {@link SimpleJob}s. - * - * @author Dan Garrette - * @since 2.0 - */ -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = "/jobs/sampleSimpleJob.xml") -public class SampleSimpleJobTests extends AbstractSampleJobTests { - -} +/* + * Copyright 2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.test; + +import org.junit.runner.RunWith; +import org.springframework.batch.core.job.SimpleJob; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * This class will specifically test the capabilities of {@link JobRepositoryTestUtils} to + * test {@link SimpleJob}s. + * + * @author Dan Garrette + * @since 2.0 + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = "/jobs/sampleSimpleJob.xml") +public class SampleSimpleJobTests extends AbstractSampleJobTests { + +} diff --git a/spring-batch-test/src/test/java/org/springframework/batch/test/SampleStepTests.java b/spring-batch-test/src/test/java/org/springframework/batch/test/SampleStepTests.java index 087caa7e2..aec81fedc 100755 --- a/spring-batch-test/src/test/java/org/springframework/batch/test/SampleStepTests.java +++ b/spring-batch-test/src/test/java/org/springframework/batch/test/SampleStepTests.java @@ -1,77 +1,78 @@ -/* - * Copyright 2008-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.test; - -import static org.junit.Assert.*; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Step; -import org.springframework.batch.core.launch.JobLauncher; -import org.springframework.batch.core.repository.JobRepository; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.jdbc.JdbcTestUtils; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/sample-steps.xml" }) -public class SampleStepTests implements ApplicationContextAware { - - @Autowired - private JdbcTemplate jdbcTemplate; - - private StepRunner stepRunner; - - private ApplicationContext context; - - @Autowired - private JobLauncher jobLauncher; - - @Autowired - private JobRepository jobRepository; - - @Before - public void setUp() { - jdbcTemplate.update("create table TESTS (ID integer, NAME varchar(40))"); - stepRunner = new StepRunner(jobLauncher, jobRepository); - } - - @After - public void tearDown() { - JdbcTestUtils.dropTables(this.jdbcTemplate, "TESTS"); - } - - @Test - public void testTasklet() { - Step step = (Step) context.getBean("s2"); - assertEquals(BatchStatus.COMPLETED, stepRunner.launchStep(step).getStatus()); - assertEquals(2, jdbcTemplate.queryForObject("SELECT ID from TESTS where NAME = 'SampleTasklet2'", Integer.class).intValue()); - } - - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.context = applicationContext; - } - -} +/* + * Copyright 2008-2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.test; + +import static org.junit.Assert.*; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.Step; +import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.jdbc.JdbcTestUtils; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/sample-steps.xml" }) +public class SampleStepTests implements ApplicationContextAware { + + @Autowired + private JdbcTemplate jdbcTemplate; + + private StepRunner stepRunner; + + private ApplicationContext context; + + @Autowired + private JobLauncher jobLauncher; + + @Autowired + private JobRepository jobRepository; + + @Before + public void setUp() { + jdbcTemplate.update("create table TESTS (ID integer, NAME varchar(40))"); + stepRunner = new StepRunner(jobLauncher, jobRepository); + } + + @After + public void tearDown() { + JdbcTestUtils.dropTables(this.jdbcTemplate, "TESTS"); + } + + @Test + public void testTasklet() { + Step step = (Step) context.getBean("s2"); + assertEquals(BatchStatus.COMPLETED, stepRunner.launchStep(step).getStatus()); + assertEquals(2, jdbcTemplate.queryForObject("SELECT ID from TESTS where NAME = 'SampleTasklet2'", Integer.class) + .intValue()); + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.context = applicationContext; + } + +} diff --git a/spring-batch-test/src/test/java/org/springframework/batch/test/SpringBatchTestJUnit4Tests.java b/spring-batch-test/src/test/java/org/springframework/batch/test/SpringBatchTestJUnit4Tests.java index 57d0ef23a..83088d2fd 100644 --- a/spring-batch-test/src/test/java/org/springframework/batch/test/SpringBatchTestJUnit4Tests.java +++ b/spring-batch-test/src/test/java/org/springframework/batch/test/SpringBatchTestJUnit4Tests.java @@ -119,11 +119,9 @@ public class SpringBatchTestJUnit4Tests { @Bean public DataSource dataSource() { - return new EmbeddedDatabaseBuilder() - .setType(EmbeddedDatabaseType.HSQL) + return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL) .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("/org/springframework/batch/core/schema-hsqldb.sql") - .build(); + .addScript("/org/springframework/batch/core/schema-hsqldb.sql").build(); } @Bean @@ -140,11 +138,10 @@ public class SpringBatchTestJUnit4Tests { @Bean public Job job() { - return this.jobBuilderFactory.get("job") - .start(this.stepBuilderFactory.get("step") - .tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED) - .build()) - .build(); + return this.jobBuilderFactory.get("job").start(this.stepBuilderFactory.get("step") + .tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED).build()).build(); } + } + } diff --git a/spring-batch-test/src/test/java/org/springframework/batch/test/SpringBatchTestJUnit5Tests.java b/spring-batch-test/src/test/java/org/springframework/batch/test/SpringBatchTestJUnit5Tests.java index 8390d18e4..bc397643f 100644 --- a/spring-batch-test/src/test/java/org/springframework/batch/test/SpringBatchTestJUnit5Tests.java +++ b/spring-batch-test/src/test/java/org/springframework/batch/test/SpringBatchTestJUnit5Tests.java @@ -89,7 +89,7 @@ public class SpringBatchTestJUnit5Tests { public void testJob() throws Exception { // given JobParameters jobParameters = this.jobLauncherTestUtils.getUniqueJobParameters(); - + // when JobExecution jobExecution = this.jobLauncherTestUtils.launchJob(jobParameters); @@ -115,11 +115,9 @@ public class SpringBatchTestJUnit5Tests { @Bean public DataSource dataSource() { - return new EmbeddedDatabaseBuilder() - .setType(EmbeddedDatabaseType.HSQL) + return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL) .addScript("/org/springframework/batch/core/schema-drop-hsqldb.sql") - .addScript("/org/springframework/batch/core/schema-hsqldb.sql") - .build(); + .addScript("/org/springframework/batch/core/schema-hsqldb.sql").build(); } @Bean @@ -136,11 +134,10 @@ public class SpringBatchTestJUnit5Tests { @Bean public Job job(JobBuilderFactory jobBuilderFactory, StepBuilderFactory stepBuilderFactory) { - return jobBuilderFactory.get("job") - .start(stepBuilderFactory.get("step") - .tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED) - .build()) - .build(); + return jobBuilderFactory.get("job").start(stepBuilderFactory.get("step") + .tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED).build()).build(); } + } + } diff --git a/spring-batch-test/src/test/java/org/springframework/batch/test/StepScopeAnnotatedListenerIntegrationTests.java b/spring-batch-test/src/test/java/org/springframework/batch/test/StepScopeAnnotatedListenerIntegrationTests.java index f84aeeebd..b568b4531 100644 --- a/spring-batch-test/src/test/java/org/springframework/batch/test/StepScopeAnnotatedListenerIntegrationTests.java +++ b/spring-batch-test/src/test/java/org/springframework/batch/test/StepScopeAnnotatedListenerIntegrationTests.java @@ -87,13 +87,16 @@ public class StepScopeAnnotatedListenerIntegrationTests { } return null; } + } @Configuration @EnableBatchProcessing public static class TestConfig { + @Autowired private JobBuilderFactory jobBuilder; + @Autowired private StepBuilderFactory stepBuilder; @@ -107,25 +110,18 @@ public class StepScopeAnnotatedListenerIntegrationTests { EmbeddedDatabaseBuilder embeddedDatabaseBuilder = new EmbeddedDatabaseBuilder(); return embeddedDatabaseBuilder.addScript("classpath:org/springframework/batch/core/schema-drop-hsqldb.sql") .addScript("classpath:org/springframework/batch/core/schema-hsqldb.sql") - .setType(EmbeddedDatabaseType.HSQL) - .build(); + .setType(EmbeddedDatabaseType.HSQL).build(); } @Bean public Job jobUnderTest() { - return jobBuilder.get("job-under-test") - .start(stepUnderTest()) - .build(); + return jobBuilder.get("job-under-test").start(stepUnderTest()).build(); } @Bean public Step stepUnderTest() { - return stepBuilder.get("step-under-test") - .chunk(1) - .reader(reader()) - .processor(processor()) - .writer(writer()) - .build(); + return stepBuilder.get("step-under-test").chunk(1).reader(reader()).processor(processor()) + .writer(writer()).build(); } @Bean @@ -151,10 +147,11 @@ public class StepScopeAnnotatedListenerIntegrationTests { return new ItemWriter() { @Override - public void write(List items) - throws Exception { + public void write(List items) throws Exception { } }; } + } + } diff --git a/spring-batch-test/src/test/java/org/springframework/batch/test/StepScopeTestExecutionListenerIntegrationTests.java b/spring-batch-test/src/test/java/org/springframework/batch/test/StepScopeTestExecutionListenerIntegrationTests.java index a39f161fb..0b228bce0 100644 --- a/spring-batch-test/src/test/java/org/springframework/batch/test/StepScopeTestExecutionListenerIntegrationTests.java +++ b/spring-batch-test/src/test/java/org/springframework/batch/test/StepScopeTestExecutionListenerIntegrationTests.java @@ -1,64 +1,64 @@ -/* - * Copyright 2010-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.ItemStream; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.TestExecutionListeners; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; - -/** - * @author Dave Syer - * @author Mahmoud Ben Hassine - * @since 2.1 - */ -@ContextConfiguration -@TestExecutionListeners( { DependencyInjectionTestExecutionListener.class, StepScopeTestExecutionListener.class }) -@RunWith(SpringJUnit4ClassRunner.class) -public class StepScopeTestExecutionListenerIntegrationTests { - - @Autowired - private ItemReader reader; - - @Autowired - private ItemStream stream; - - public StepExecution getStepExecution() { - // Assert that dependencies are already injected... - assertNotNull(reader); - // Then create the execution for the step scope... - StepExecution execution = MetaDataInstanceFactory.createStepExecution(); - execution.getExecutionContext().putString("input.file", "classpath:/org/springframework/batch/test/simple.txt"); - return execution; - } - - @Test - public void testJob() throws Exception { - stream.open(new ExecutionContext()); - assertEquals("foo", reader.read()); - } - -} +/* + * Copyright 2010-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemStream; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestExecutionListeners; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; + +/** + * @author Dave Syer + * @author Mahmoud Ben Hassine + * @since 2.1 + */ +@ContextConfiguration +@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, StepScopeTestExecutionListener.class }) +@RunWith(SpringJUnit4ClassRunner.class) +public class StepScopeTestExecutionListenerIntegrationTests { + + @Autowired + private ItemReader reader; + + @Autowired + private ItemStream stream; + + public StepExecution getStepExecution() { + // Assert that dependencies are already injected... + assertNotNull(reader); + // Then create the execution for the step scope... + StepExecution execution = MetaDataInstanceFactory.createStepExecution(); + execution.getExecutionContext().putString("input.file", "classpath:/org/springframework/batch/test/simple.txt"); + return execution; + } + + @Test + public void testJob() throws Exception { + stream.open(new ExecutionContext()); + assertEquals("foo", reader.read()); + } + +} diff --git a/spring-batch-test/src/test/java/org/springframework/batch/test/StepScopeTestExecutionListenerTests.java b/spring-batch-test/src/test/java/org/springframework/batch/test/StepScopeTestExecutionListenerTests.java index acf8898d5..b72ab6fc6 100644 --- a/spring-batch-test/src/test/java/org/springframework/batch/test/StepScopeTestExecutionListenerTests.java +++ b/spring-batch-test/src/test/java/org/springframework/batch/test/StepScopeTestExecutionListenerTests.java @@ -1,120 +1,122 @@ -/* - * Copyright 2010 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -import org.junit.Test; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.scope.context.StepContext; -import org.springframework.batch.core.scope.context.StepSynchronizationManager; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.TestContext; -import org.springframework.test.context.TestContextManager; - -/** - * @author Dave Syer - * @since 2.1 - */ -@ContextConfiguration -public class StepScopeTestExecutionListenerTests { - - private StepScopeTestExecutionListener listener = new StepScopeTestExecutionListener(); - - @Test - public void testDefaultStepContext() throws Exception { - TestContext testContext = getTestContext(new Object()); - listener.prepareTestInstance(testContext); - listener.beforeTestMethod(testContext); - StepContext context = StepSynchronizationManager.getContext(); - assertNotNull(context); - listener.afterTestMethod(testContext); - assertNull(StepSynchronizationManager.getContext()); - } - - @Test - public void testWithStepExecutionFactory() throws Exception { - testExecutionContext(new WithStepExecutionFactory()); - } - - @Test - public void testWithParameters() throws Exception { - testJobParameters(new WithStepExecutionFactory()); - } - - private void testExecutionContext(Object target) throws Exception { - TestContext testContext = getTestContext(target); - listener.prepareTestInstance(testContext); - try { - listener.beforeTestMethod(testContext); - StepContext context = StepSynchronizationManager.getContext(); - assertNotNull(context); - assertEquals("bar", context.getStepExecutionContext().get("foo")); - } - finally { - listener.afterTestMethod(testContext); - } - assertNull(StepSynchronizationManager.getContext()); - } - - private void testJobParameters(Object target) throws Exception { - TestContext testContext = getTestContext(target); - listener.prepareTestInstance(testContext); - try { - listener.beforeTestMethod(testContext); - StepContext context = StepSynchronizationManager.getContext(); - assertNotNull(context); - assertEquals("spam", context.getJobParameters().get("foo")); - } - finally { - listener.afterTestMethod(testContext); - } - assertNull(StepSynchronizationManager.getContext()); - } - - @SuppressWarnings("unused") - private static class WithStepExecutionFactory { - public StepExecution getStepExecution() { - JobExecution jobExecution = MetaDataInstanceFactory.createJobExecution("job", 11L, 123L, - new JobParametersBuilder().addString("foo", "spam").toJobParameters()); - StepExecution stepExecution = jobExecution.createStepExecution("step"); - stepExecution.getExecutionContext().putString("foo", "bar"); - return stepExecution; - } - } - - private TestContext getTestContext(Object target) throws Exception { - return new MockTestContextManager(target, getClass()).getContext(); - } - - private final class MockTestContextManager extends TestContextManager { - - private MockTestContextManager(Object target, Class testClass) throws Exception { - super(testClass); - prepareTestInstance(target); - } - - public TestContext getContext() { - return getTestContext(); - } - - } - -} +/* + * Copyright 2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import org.junit.Test; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobParametersBuilder; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.scope.context.StepContext; +import org.springframework.batch.core.scope.context.StepSynchronizationManager; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestContext; +import org.springframework.test.context.TestContextManager; + +/** + * @author Dave Syer + * @since 2.1 + */ +@ContextConfiguration +public class StepScopeTestExecutionListenerTests { + + private StepScopeTestExecutionListener listener = new StepScopeTestExecutionListener(); + + @Test + public void testDefaultStepContext() throws Exception { + TestContext testContext = getTestContext(new Object()); + listener.prepareTestInstance(testContext); + listener.beforeTestMethod(testContext); + StepContext context = StepSynchronizationManager.getContext(); + assertNotNull(context); + listener.afterTestMethod(testContext); + assertNull(StepSynchronizationManager.getContext()); + } + + @Test + public void testWithStepExecutionFactory() throws Exception { + testExecutionContext(new WithStepExecutionFactory()); + } + + @Test + public void testWithParameters() throws Exception { + testJobParameters(new WithStepExecutionFactory()); + } + + private void testExecutionContext(Object target) throws Exception { + TestContext testContext = getTestContext(target); + listener.prepareTestInstance(testContext); + try { + listener.beforeTestMethod(testContext); + StepContext context = StepSynchronizationManager.getContext(); + assertNotNull(context); + assertEquals("bar", context.getStepExecutionContext().get("foo")); + } + finally { + listener.afterTestMethod(testContext); + } + assertNull(StepSynchronizationManager.getContext()); + } + + private void testJobParameters(Object target) throws Exception { + TestContext testContext = getTestContext(target); + listener.prepareTestInstance(testContext); + try { + listener.beforeTestMethod(testContext); + StepContext context = StepSynchronizationManager.getContext(); + assertNotNull(context); + assertEquals("spam", context.getJobParameters().get("foo")); + } + finally { + listener.afterTestMethod(testContext); + } + assertNull(StepSynchronizationManager.getContext()); + } + + @SuppressWarnings("unused") + private static class WithStepExecutionFactory { + + public StepExecution getStepExecution() { + JobExecution jobExecution = MetaDataInstanceFactory.createJobExecution("job", 11L, 123L, + new JobParametersBuilder().addString("foo", "spam").toJobParameters()); + StepExecution stepExecution = jobExecution.createStepExecution("step"); + stepExecution.getExecutionContext().putString("foo", "bar"); + return stepExecution; + } + + } + + private TestContext getTestContext(Object target) throws Exception { + return new MockTestContextManager(target, getClass()).getContext(); + } + + private final class MockTestContextManager extends TestContextManager { + + private MockTestContextManager(Object target, Class testClass) throws Exception { + super(testClass); + prepareTestInstance(target); + } + + public TestContext getContext() { + return getTestContext(); + } + + } + +} diff --git a/spring-batch-test/src/test/java/org/springframework/batch/test/common/LogAdvice.java b/spring-batch-test/src/test/java/org/springframework/batch/test/common/LogAdvice.java index 75bd8be74..6a3e37277 100755 --- a/spring-batch-test/src/test/java/org/springframework/batch/test/common/LogAdvice.java +++ b/spring-batch-test/src/test/java/org/springframework/batch/test/common/LogAdvice.java @@ -20,23 +20,22 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.aspectj.lang.JoinPoint; - /** - * Wraps calls for 'Processing' methods which output a single Object to write - * the string representation of the object to the log. - * + * Wraps calls for 'Processing' methods which output a single Object to write the string + * representation of the object to the log. + * * @author Lucas Ward */ public class LogAdvice { - - private static Log log = LogFactory.getLog(LogAdvice.class); - /* - * Wraps original method and adds logging both before and after method - */ - public void doBasicLogging(JoinPoint pjp) throws Throwable { - Object[] args = pjp.getArgs(); - StringBuilder output = new StringBuilder(); + private static Log log = LogFactory.getLog(LogAdvice.class); + + /* + * Wraps original method and adds logging both before and after method + */ + public void doBasicLogging(JoinPoint pjp) throws Throwable { + Object[] args = pjp.getArgs(); + StringBuilder output = new StringBuilder(); output.append(pjp.getTarget().getClass().getName()).append(": "); output.append(pjp.toShortString()).append(": "); @@ -45,12 +44,11 @@ public class LogAdvice { output.append(arg).append(" "); } - log.info("Basic: " + output.toString()); - } - - public void doStronglyTypedLogging(Object item){ - log.info("Processed: " + item); - } + } + + public void doStronglyTypedLogging(Object item) { + log.info("Processed: " + item); + } } diff --git a/spring-batch-test/src/test/java/org/springframework/batch/test/context/BatchTestContextCustomizerFactoryTests.java b/spring-batch-test/src/test/java/org/springframework/batch/test/context/BatchTestContextCustomizerFactoryTests.java index e903ed577..04632345b 100644 --- a/spring-batch-test/src/test/java/org/springframework/batch/test/context/BatchTestContextCustomizerFactoryTests.java +++ b/spring-batch-test/src/test/java/org/springframework/batch/test/context/BatchTestContextCustomizerFactoryTests.java @@ -65,4 +65,5 @@ public class BatchTestContextCustomizerFactoryTests { private static class MyOtherJobTest { } + } diff --git a/spring-batch-test/src/test/java/org/springframework/batch/test/context/BatchTestContextCustomizerTests.java b/spring-batch-test/src/test/java/org/springframework/batch/test/context/BatchTestContextCustomizerTests.java index 35f03b1c3..ab6433376 100644 --- a/spring-batch-test/src/test/java/org/springframework/batch/test/context/BatchTestContextCustomizerTests.java +++ b/spring-batch-test/src/test/java/org/springframework/batch/test/context/BatchTestContextCustomizerTests.java @@ -58,6 +58,8 @@ public class BatchTestContextCustomizerTests { () -> this.contextCustomizer.customizeContext(context, mergedConfig)); // then - assertThat(expectedException.getMessage(), containsString("The bean factory must be an instance of BeanDefinitionRegistry")); + assertThat(expectedException.getMessage(), + containsString("The bean factory must be an instance of BeanDefinitionRegistry")); } + } diff --git a/spring-batch-test/src/test/java/org/springframework/batch/test/jmx/JobExecutionNotificationPublisher.java b/spring-batch-test/src/test/java/org/springframework/batch/test/jmx/JobExecutionNotificationPublisher.java index 48750e1de..20df81953 100755 --- a/spring-batch-test/src/test/java/org/springframework/batch/test/jmx/JobExecutionNotificationPublisher.java +++ b/spring-batch-test/src/test/java/org/springframework/batch/test/jmx/JobExecutionNotificationPublisher.java @@ -27,11 +27,12 @@ import org.springframework.jmx.export.notification.NotificationPublisherAware; /** * JMX notification broadcaster - * + * * @author Dave Syer * @since 1.0 */ -public class JobExecutionNotificationPublisher implements ApplicationListener, NotificationPublisherAware { +public class JobExecutionNotificationPublisher + implements ApplicationListener, NotificationPublisherAware { protected static final Log logger = LogFactory.getLog(JobExecutionNotificationPublisher.class); @@ -41,22 +42,21 @@ public class JobExecutionNotificationPublisher implements ApplicationListener