Apply spring-javaformat style for consistency with other projects
Resolves #4118
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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. <em>As a result, you should use {@code PROPAGATION_REQUIRES_NEW} for any
|
||||
* transactional operation that is called from here.</em>
|
||||
*
|
||||
* @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. <em>As a result, you should use
|
||||
* {@code PROPAGATION_REQUIRES_NEW} for any transactional operation that is called
|
||||
* from here.</em>
|
||||
* @param context the chunk context containing the exception that caused the
|
||||
* underlying rollback.
|
||||
*/
|
||||
default void afterChunkError(ChunkContext context) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<JobParameters> {
|
||||
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).");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
*/
|
||||
|
||||
@@ -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<ExitStatus> {
|
||||
|
||||
/**
|
||||
* 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<ExitStatus> {
|
||||
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<ExitStatus> {
|
||||
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<ExitStatus> {
|
||||
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<ExitStatus> {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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<ExitStatus> {
|
||||
|
||||
/**
|
||||
* 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<ExitStatus> {
|
||||
|
||||
/**
|
||||
* 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<ExitStatus> {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.<br>
|
||||
* 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.<br>
|
||||
* <br>
|
||||
*
|
||||
* Severity is defined by the exit code:
|
||||
@@ -133,10 +127,9 @@ public class ExitStatus implements Serializable, Comparable<ExitStatus> {
|
||||
* Others have severity 7, so custom exit codes always win.<br>
|
||||
*
|
||||
* 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<ExitStatus> {
|
||||
|
||||
/**
|
||||
* @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<ExitStatus> {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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<ExitStatus> {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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<ExitStatus> {
|
||||
|
||||
/**
|
||||
* 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<ExitStatus> {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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<ExitStatus> {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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<ExitStatus> {
|
||||
}
|
||||
|
||||
/**
|
||||
* @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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<T, S> 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<T, S> 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) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -33,10 +33,8 @@ public interface ItemReadListener<T> 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<T> extends StepListener {
|
||||
|
||||
/**
|
||||
* Called if an error occurs while trying to read.
|
||||
*
|
||||
* @param ex thrown from {@link ItemReader}
|
||||
*/
|
||||
default void onReadError(Exception ex) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,20 +22,18 @@ import org.springframework.batch.item.ItemWriter;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 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.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* <em>Note: </em> 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.
|
||||
*</p>
|
||||
* <em>Note: </em> 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.
|
||||
* </p>
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @author Mahmoud Ben Hassine
|
||||
@@ -45,31 +43,28 @@ public interface ItemWriteListener<S> extends StepListener {
|
||||
|
||||
/**
|
||||
* Called before {@link ItemWriter#write(java.util.List)}
|
||||
*
|
||||
* @param items to be written
|
||||
*/
|
||||
default void beforeWrite(List<? extends S> 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<? extends S> 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<? extends S> items) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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}.
|
||||
*/
|
||||
|
||||
@@ -67,8 +67,8 @@ public class JobExecution extends Entity {
|
||||
private transient volatile List<Throwable> 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<StepExecution> 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<Throwable>} 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<StepExecution> stepExecutions) {
|
||||
if (stepExecutions!=null) {
|
||||
if (stepExecutions != null) {
|
||||
this.stepExecutions.removeAll(stepExecutions);
|
||||
this.stepExecutions.addAll(stepExecutions);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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 <T> The type of the source data used to calculate the key.
|
||||
* @since 2.2
|
||||
*/
|
||||
@@ -29,11 +28,10 @@ public interface JobKeyGenerator<T> {
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<String,JobParameter> parameters;
|
||||
private final Map<String, JobParameter> 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<String,JobParameter> parameters) {
|
||||
public JobParameters(Map<String, JobParameter> 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<String, JobParameter> getParameters(){
|
||||
public Map<String, JobParameter> 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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.<br>
|
||||
* {@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.<br>
|
||||
* <br>
|
||||
* 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<Object, Object> 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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})
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
@@ -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<T,S> extends StepListener {
|
||||
public interface SkipListener<T, S> 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<T,S> 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
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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.<br>
|
||||
*
|
||||
* 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.<br>
|
||||
*
|
||||
* 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;
|
||||
|
||||
@@ -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 <code>StepContribution</code>.
|
||||
* @return the sum of skips accumulated in the parent {@link StepExecution} and this
|
||||
* <code>StepContribution</code>.
|
||||
*/
|
||||
public long getStepSkipCount() {
|
||||
return readSkipCount + writeSkipCount + processSkipCount + parentSkipCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of skips collected in this
|
||||
* <code>StepContribution</code> (not including skips accumulated in the
|
||||
* parent {@link StepExecution}).
|
||||
* @return the number of skips collected in this <code>StepContribution</code> (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() {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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 {
|
||||
|
||||
}
|
||||
|
||||
@@ -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.<br>
|
||||
* Marks a method to be called after a chunk has failed and been marked for rollback.<br>
|
||||
* <br>
|
||||
* 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 {
|
||||
|
||||
}
|
||||
|
||||
@@ -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}. <br>
|
||||
* Marks a method to be called after a {@link Job} has completed. Annotated methods are
|
||||
* called regardless of the status of the {@link JobExecution}. <br>
|
||||
* <br>
|
||||
* 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 {
|
||||
|
||||
}
|
||||
|
||||
@@ -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.<br>
|
||||
* 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.<br>
|
||||
* <br>
|
||||
* 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 {
|
||||
|
||||
}
|
||||
|
||||
@@ -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} <br>
|
||||
* <br>
|
||||
* 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 {
|
||||
|
||||
}
|
||||
|
||||
@@ -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}. <br>
|
||||
* Marks a method to be called after a {@link Step} has completed. Annotated methods are
|
||||
* called regardless of the status of the {@link StepExecution}. <br>
|
||||
* <br>
|
||||
* 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 {
|
||||
|
||||
}
|
||||
|
||||
@@ -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).<br>
|
||||
* 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).<br>
|
||||
* <br>
|
||||
* 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 {
|
||||
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
}
|
||||
|
||||
@@ -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. <br>
|
||||
* 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. <br>
|
||||
* <br>
|
||||
* 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 {
|
||||
|
||||
|
||||
@@ -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} <br>
|
||||
* Marks a method to be called before an item is passed to an {@link ItemProcessor} <br>
|
||||
* <br>
|
||||
* 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 {
|
||||
|
||||
}
|
||||
|
||||
@@ -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} <br>
|
||||
* <br>
|
||||
* Expected signature: void beforeRead()
|
||||
*
|
||||
*
|
||||
* @author Lucas Ward
|
||||
* @since 2.0
|
||||
* @see ItemReadListener
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.METHOD})
|
||||
@Target({ ElementType.METHOD })
|
||||
public @interface BeforeRead {
|
||||
|
||||
}
|
||||
|
||||
@@ -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. <br>
|
||||
* 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. <br>
|
||||
* <br>
|
||||
* 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 {
|
||||
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ import org.springframework.batch.item.ItemWriter;
|
||||
* @see ItemWriteListener
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.METHOD})
|
||||
@Target({ ElementType.METHOD })
|
||||
public @interface BeforeWrite {
|
||||
|
||||
}
|
||||
|
||||
@@ -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}. <br>
|
||||
* Marks a method to be called if an exception is thrown by an {@link ItemProcessor}. <br>
|
||||
* <br>
|
||||
* 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 {
|
||||
|
||||
}
|
||||
|
||||
@@ -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}. <br>
|
||||
* Marks a method to be called if an exception is thrown by an {@link ItemReader}. <br>
|
||||
* <br>
|
||||
* 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 {
|
||||
|
||||
}
|
||||
|
||||
@@ -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}.<br>
|
||||
* Marks a method to be called when an item is skipped due to an exception thrown in the
|
||||
* {@link ItemProcessor}.<br>
|
||||
* <br>
|
||||
* 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 {
|
||||
|
||||
}
|
||||
|
||||
@@ -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}. <br>
|
||||
* Marks a method to be called when an item is skipped due to an exception thrown in the
|
||||
* {@link ItemReader}. <br>
|
||||
* <br>
|
||||
* 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 {
|
||||
|
||||
}
|
||||
|
||||
@@ -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}.<br>
|
||||
* Marks a method to be called when an item is skipped due to an exception thrown in the
|
||||
* {@link ItemWriter}.<br>
|
||||
* <br>
|
||||
* 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 {
|
||||
|
||||
}
|
||||
|
||||
@@ -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).<br>
|
||||
* 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).<br>
|
||||
* <br>
|
||||
* 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 {
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -22,22 +22,19 @@ import org.springframework.lang.Nullable;
|
||||
/**
|
||||
* A runtime service locator interface for retrieving job configurations by
|
||||
* <code>name</code>.
|
||||
*
|
||||
*
|
||||
* @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;
|
||||
|
||||
}
|
||||
|
||||
@@ -20,27 +20,25 @@ import org.springframework.batch.core.Job;
|
||||
/**
|
||||
* A runtime service registry interface for registering job configurations by
|
||||
* <code>name</code>.
|
||||
*
|
||||
*
|
||||
* @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);
|
||||
|
||||
}
|
||||
|
||||
@@ -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<String> getJobNames();
|
||||
|
||||
}
|
||||
|
||||
@@ -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<Step> 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<Step> 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;
|
||||
|
||||
}
|
||||
|
||||
@@ -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<String, Object> annotationAttributes =
|
||||
importMetadata.getAnnotationAttributes(EnableBatchProcessing.class.getName(), false);
|
||||
Map<String, Object> 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<BatchConfigurer> 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);
|
||||
|
||||
@@ -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()));
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -33,8 +33,10 @@ import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Enable Spring Batch features and provide a base configuration for setting up batch jobs in an @Configuration
|
||||
* class, roughly equivalent to using the {@code <batch:*>} XML namespace.</p>
|
||||
* Enable Spring Batch features and provide a base configuration for setting up batch jobs
|
||||
* in an @Configuration class, roughly equivalent to using the {@code <batch:*>} XML
|
||||
* namespace.
|
||||
* </p>
|
||||
*
|
||||
* <pre class="code">
|
||||
* @Configuration
|
||||
@@ -62,8 +64,8 @@ import org.springframework.transaction.PlatformTransactionManager;
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* <pre class="code">
|
||||
* @Configuration
|
||||
@@ -85,30 +87,41 @@ import org.springframework.transaction.PlatformTransactionManager;
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* 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 <code>@EnableBatchProcessing</code>
|
||||
* annotation. Once you have an <code>@EnableBatchProcessing</code> 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 <code>@Scope("step")</code> and <code>@Scope("job")</code> respectively. You will also be
|
||||
* able to <code>@Autowired</code> some useful stuff into your context:
|
||||
* Note that only one of your configuration classes needs to have the
|
||||
* <code>@EnableBatchProcessing</code> annotation. Once you have an
|
||||
* <code>@EnableBatchProcessing</code> 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 <code>@Scope("step")</code> and
|
||||
* <code>@Scope("job")</code> respectively. You will also be able to
|
||||
* <code>@Autowired</code> some useful stuff into your context:
|
||||
*
|
||||
* <ul>
|
||||
* <li>a {@link JobRepository} (bean name "jobRepository" of type {@link org.springframework.batch.core.repository.support.SimpleJobRepository})</li>
|
||||
* <li>a {@link JobLauncher} (bean name "jobLauncher" of type {@link org.springframework.batch.core.launch.support.SimpleJobLauncher})</li>
|
||||
* <li>a {@link JobRegistry} (bean name "jobRegistry" of type {@link org.springframework.batch.core.configuration.support.MapJobRegistry})</li>
|
||||
* <li>a {@link org.springframework.batch.core.explore.JobExplorer} (bean name "jobExplorer" of type {@link org.springframework.batch.core.explore.support.SimpleJobExplorer})</li>
|
||||
* <li>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</li>
|
||||
* <li>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</li>
|
||||
* <li>a {@link JobRepository} (bean name "jobRepository" of type
|
||||
* {@link org.springframework.batch.core.repository.support.SimpleJobRepository})</li>
|
||||
* <li>a {@link JobLauncher} (bean name "jobLauncher" of type
|
||||
* {@link org.springframework.batch.core.launch.support.SimpleJobLauncher})</li>
|
||||
* <li>a {@link JobRegistry} (bean name "jobRegistry" of type
|
||||
* {@link org.springframework.batch.core.configuration.support.MapJobRegistry})</li>
|
||||
* <li>a {@link org.springframework.batch.core.explore.JobExplorer} (bean name
|
||||
* "jobExplorer" of type
|
||||
* {@link org.springframework.batch.core.explore.support.SimpleJobExplorer})</li>
|
||||
* <li>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</li>
|
||||
* <li>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</li>
|
||||
* </ul>
|
||||
*
|
||||
* 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:
|
||||
*
|
||||
* <pre class="code">
|
||||
* @Configuration
|
||||
@@ -130,11 +143,13 @@ import org.springframework.transaction.PlatformTransactionManager;
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* If the configuration is specified as <code>modular=true</code> 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 <code>modular=true</code> 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:
|
||||
*
|
||||
* <pre class="code">
|
||||
@@ -157,12 +172,13 @@ import org.springframework.transaction.PlatformTransactionManager;
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* Note that a modular parent context in general should <em>not</em> 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 <em>not</em> itself contain
|
||||
* @Bean definitions for job, especially if a {@link BatchConfigurer} is provided,
|
||||
* because cyclic configuration dependencies are otherwise likely to develop.
|
||||
*
|
||||
* <p>
|
||||
* 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:
|
||||
*
|
||||
* <pre class="code">
|
||||
* {@code
|
||||
@@ -173,7 +189,8 @@ import org.springframework.transaction.PlatformTransactionManager;
|
||||
* <step id="step2" .../>
|
||||
* </job>
|
||||
* <beans:bean id="transactionManager" .../>
|
||||
* <beans:bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
|
||||
* <beans:bean id="jobLauncher" class=
|
||||
"org.springframework.batch.core.launch.support.SimpleJobLauncher">
|
||||
* <beans:property name="jobRepository" ref="jobRepository" />
|
||||
* </beans:bean>
|
||||
* </batch>
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -24,9 +24,10 @@ import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 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.
|
||||
* </p>
|
||||
*
|
||||
* <pre class="code">
|
||||
@@ -38,7 +39,10 @@ import java.lang.annotation.RetentionPolicy;
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>Marking a @Bean as @JobScope is equivalent to marking it as <code>@Scope(value="job", proxyMode=TARGET_CLASS)</code></p>
|
||||
* <p>
|
||||
* Marking a @Bean as @JobScope is equivalent to marking it as
|
||||
* <code>@Scope(value="job", proxyMode=TARGET_CLASS)</code>
|
||||
* </p>
|
||||
*
|
||||
* @author Michael Minella
|
||||
*
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -55,4 +55,5 @@ public class ScopeConfiguration {
|
||||
public static JobScope jobScope() {
|
||||
return jobScope;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,9 +24,10 @@ import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 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.
|
||||
* </p>
|
||||
*
|
||||
* <pre class="code">
|
||||
@@ -38,7 +39,10 @@ import java.lang.annotation.RetentionPolicy;
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>Marking a @Bean as @StepScope is equivalent to marking it as <code>@Scope(value="step", proxyMode=TARGET_CLASS)</code></p>
|
||||
* <p>
|
||||
* Marking a @Bean as @StepScope is equivalent to marking it as
|
||||
* <code>@Scope(value="step", proxyMode=TARGET_CLASS)</code>
|
||||
* </p>
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
|
||||
@@ -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<Class<?>> 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<Class<? extends BeanFactoryPostProcessor>> 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<BeanPostProcessor> parentPostProcessors = new ArrayList<>();
|
||||
List<BeanPostProcessor> 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<BeanPostProcessor> beanPostProcessors = beanFactory instanceof AbstractBeanFactory ? ((AbstractBeanFactory) beanFactory)
|
||||
.getBeanPostProcessors() : new ArrayList<>();
|
||||
List<BeanPostProcessor> beanPostProcessors = beanFactory instanceof AbstractBeanFactory
|
||||
? ((AbstractBeanFactory) beanFactory).getBeanPostProcessors() : new ArrayList<>();
|
||||
|
||||
beanPostProcessors.clear();
|
||||
beanPostProcessors.addAll(aggregatedPostProcessors);
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
*/
|
||||
|
||||
@@ -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<ApplicationContextFactory> 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()
|
||||
*/
|
||||
|
||||
@@ -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<ApplicationContextFactory[]>, ApplicationContextAware {
|
||||
public class ClasspathXmlApplicationContextsFactoryBean
|
||||
implements FactoryBean<ApplicationContextFactory[]>, ApplicationContextAware {
|
||||
|
||||
private List<Resource> resources = new ArrayList<>();
|
||||
|
||||
@@ -50,13 +51,10 @@ public class ClasspathXmlApplicationContextsFactoryBean implements FactoryBean<A
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* <code>classpath*:/config/*-context.xml</code>).
|
||||
*
|
||||
* 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. <code>classpath*:/config/*-context.xml</code>).
|
||||
* @param resources array of resources to use
|
||||
*/
|
||||
public void setResources(Resource[] resources) {
|
||||
@@ -64,10 +62,8 @@ public class ClasspathXmlApplicationContextsFactoryBean implements FactoryBean<A
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
@@ -75,10 +71,9 @@ public class ClasspathXmlApplicationContextsFactoryBean implements FactoryBean<A
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines which bean factory post processors (like property
|
||||
* placeholders) should be copied from the parent context. Defaults to
|
||||
* 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 post processor types to be copied
|
||||
*/
|
||||
|
||||
@@ -88,12 +83,11 @@ public class ClasspathXmlApplicationContextsFactoryBean implements FactoryBean<A
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
@@ -101,9 +95,8 @@ public class ClasspathXmlApplicationContextsFactoryBean implements FactoryBean<A
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an {@link ApplicationContextFactory} from each resource provided
|
||||
* in {@link #setResources(Resource[])}.
|
||||
*
|
||||
* Create an {@link ApplicationContextFactory} from each resource provided in
|
||||
* {@link #setResources(Resource[])}.
|
||||
* @return an array of {@link ApplicationContextFactory}
|
||||
* @see org.springframework.beans.factory.FactoryBean#getObject()
|
||||
*/
|
||||
@@ -133,7 +126,6 @@ public class ClasspathXmlApplicationContextsFactoryBean implements FactoryBean<A
|
||||
/**
|
||||
* The type of object returned by this factory - an array of
|
||||
* {@link ApplicationContextFactory}.
|
||||
*
|
||||
* @return array of {@link ApplicationContextFactory}
|
||||
* @see FactoryBean#getObjectType()
|
||||
*/
|
||||
@@ -153,9 +145,7 @@ public class ClasspathXmlApplicationContextsFactoryBean implements FactoryBean<A
|
||||
}
|
||||
|
||||
/**
|
||||
* An application context that can be used as a parent context for all the
|
||||
* factories.
|
||||
*
|
||||
* An application context that can be used as a parent context for all the factories.
|
||||
* @param applicationContext the {@link ApplicationContext} to set
|
||||
* @see ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
|
||||
*/
|
||||
|
||||
@@ -39,10 +39,10 @@ import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link JobLoader}. Uses a {@link JobRegistry} to
|
||||
* manage a population of loaded jobs and clears them up when asked. An optional
|
||||
* {@link StepRegistry} might also be set to register the step(s) available for
|
||||
* each registered job.
|
||||
* Default implementation of {@link JobLoader}. Uses a {@link JobRegistry} to manage a
|
||||
* population of loaded jobs and clears them up when asked. An optional
|
||||
* {@link StepRegistry} might also be set to register the step(s) available for each
|
||||
* registered job.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Stephane Nicoll
|
||||
@@ -53,6 +53,7 @@ public class DefaultJobLoader implements JobLoader, InitializingBean {
|
||||
private static Log logger = LogFactory.getLog(DefaultJobLoader.class);
|
||||
|
||||
private JobRegistry jobRegistry;
|
||||
|
||||
private StepRegistry stepRegistry;
|
||||
|
||||
private Map<ApplicationContextFactory, ConfigurableApplicationContext> 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}.
|
||||
* <br>
|
||||
* The specified <tt>jobApplicationContext</tt> 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}. <br>
|
||||
* The specified <tt>jobApplicationContext</tt> 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<String, Step> allSteps = jobApplicationContext.getBeansOfType(Step.class);
|
||||
for (Map.Entry<String, Step> entry : allSteps.entrySet()) {
|
||||
@@ -247,10 +244,9 @@ public class DefaultJobLoader implements JobLoader, InitializingBean {
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the specified {@link Job} defined in the specified {@link ConfigurableApplicationContext}.
|
||||
* <br>
|
||||
* Registers the specified {@link Job} defined in the specified
|
||||
* {@link ConfigurableApplicationContext}. <br>
|
||||
* 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 <tt>jobName</tt>.
|
||||
*
|
||||
* @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.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<Class<?>> 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<String> 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<String> 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();
|
||||
|
||||
@@ -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 <code>overnightJob</code> and the group
|
||||
* <code>financeDepartment</code>, which would result in a {@link Job} with
|
||||
* identical functionality but named <code>financeDepartment.overnightJob</code>
|
||||
* . The use of a "." separator for elements is deliberate, since it is a "safe"
|
||||
* character in a <a href="https://www.w3.org/Addressing/URL">URL</a>.
|
||||
*
|
||||
* 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
|
||||
* <code>overnightJob</code> and the group <code>financeDepartment</code>, which would
|
||||
* result in a {@link Job} with identical functionality but named
|
||||
* <code>financeDepartment.overnightJob</code> . The use of a "." separator for elements
|
||||
* is deliberate, since it is a "safe" character in a
|
||||
* <a href="https://www.w3.org/Addressing/URL">URL</a>.
|
||||
*
|
||||
* @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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<Job> 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<Job> 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();
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<String, JobFactory> 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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<String, Step> 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<String, Step> 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 + "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
@@ -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<String, Set<String>> 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<BeanDefinition> 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<BeanDefinition> 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<BeanDefinition> 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<BeanDefinition> 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<String, String> 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<Element> beanElements = DomUtils.getChildElementsByTagName(element, BEAN_ELE);
|
||||
List<Element> 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<? extends AbstractListenerFactoryBean<?>> getBeanClass();
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<TypedStringValue, Boolean> skippableExceptions =
|
||||
new ExceptionElementParser().parse(element, parserContext, "skippable-exception-classes");
|
||||
ManagedMap<TypedStringValue, Boolean> 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<Element> exceptionClassElements = DomUtils.getChildElementsByTagName(element, "skippable-exception-classes");
|
||||
List<Element> 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<TypedStringValue, Boolean> retryableExceptions =
|
||||
new ExceptionElementParser().parse(element, parserContext, "retryable-exception-classes");
|
||||
ManagedMap<TypedStringValue, Boolean> 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<Element> exceptionClassElements = DomUtils.getChildElementsByTagName(element, "retryable-exception-classes");
|
||||
List<Element> 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<Element> 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<Element> beanElements = DomUtils.getChildElementsByTagName(element, BEAN_ELE);
|
||||
List<Element> 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<BeanMetadataElement> beans,
|
||||
BeanDefinition enclosing) {
|
||||
private void handleRetryListenerElements(ParserContext parserContext, Element element,
|
||||
ManagedList<BeanMetadataElement> beans, BeanDefinition enclosing) {
|
||||
List<Element> 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<RuntimeBeanReference> streamBeans = new ManagedList<>();
|
||||
|
||||
@@ -19,8 +19,6 @@ import org.springframework.beans.factory.xml.NamespaceHandler;
|
||||
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -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.
|
||||
* <ul>
|
||||
* <li>Inject "jobRepository" into any {@link JobParserJobFactoryBean}
|
||||
* without a jobRepository.
|
||||
* <li>Inject "transactionManager" into any
|
||||
* {@link StepParserStepFactoryBean} without a transactionManager.
|
||||
* </ul>
|
||||
*
|
||||
* @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.
|
||||
* <ul>
|
||||
* <li>Inject "jobRepository" into any {@link JobParserJobFactoryBean} without a
|
||||
* jobRepository.
|
||||
* <li>Inject "transactionManager" into any {@link StepParserStepFactoryBean} without
|
||||
* a transactionManager.
|
||||
* </ul>
|
||||
* @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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<String, String> 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
|
||||
*/
|
||||
|
||||
@@ -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<BeanDefinition> 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);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,7 +26,8 @@ import org.w3c.dom.Element;
|
||||
|
||||
public class ExceptionElementParser {
|
||||
|
||||
public ManagedMap<TypedStringValue, Boolean> parse(Element element, ParserContext parserContext, String exceptionListName) {
|
||||
public ManagedMap<TypedStringValue, Boolean> parse(Element element, ParserContext parserContext,
|
||||
String exceptionListName) {
|
||||
List<Element> children = DomUtils.getChildElementsByTagName(element, exceptionListName);
|
||||
if (children.size() == 1) {
|
||||
ManagedMap<TypedStringValue, Boolean> 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<BeanDefinition> parse(Element element, ParserContext parserContext) {
|
||||
|
||||
@@ -65,4 +63,5 @@ public class FlowElementParser {
|
||||
return InlineFlowParser.getNextElements(parserContext, stateBuilder.getBeanDefinition(), element);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<BeanDefinition> parse(Element element, ParserContext parserContext, String jobFactoryRef) {
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 <job/> with abstract=\"true\" ["
|
||||
+ jobName + "]", element);
|
||||
parserContext.getReaderContext().error("The <" + tagName
|
||||
+ "/> element may not appear on a <job/> 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 '<listeners/>' element may not appear more than once in a single <job/>.", element);
|
||||
parserContext.getReaderContext()
|
||||
.error("The '<listeners/>' element may not appear more than once in a single <job/>.", 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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<FlowJob> {
|
||||
|
||||
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<FlowJob> 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<FlowJob> {
|
||||
|
||||
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<FlowJob> getObjectType() {
|
||||
return FlowJob.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEagerInit() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrototype() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<SimpleFlow>, 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<SimpleFlow>, 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<StateTransition> stateTransitions) {
|
||||
@@ -93,19 +90,20 @@ public class SimpleFlowFactoryBean implements FactoryBean<SimpleFlow>, 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<SimpleFlow>, 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<SimpleFlow>, 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<SimpleFlow>, 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<SimpleFlow>, Initializ
|
||||
|
||||
@Override
|
||||
public Collection<Flow> getFlows() {
|
||||
return (state instanceof FlowHolder) ? ((FlowHolder)state).getFlows() : Collections.<Flow>emptyList();
|
||||
return (state instanceof FlowHolder) ? ((FlowHolder) state).getFlows() : Collections.<Flow>emptyList();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<BeanDefinition> parse(Element element, ParserContext parserContext) {
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user