Add support to use any type as a job parameter
This commit also changes the way job parameters are parsed and persisted. NB: This commit should ideally have been split into two change sets. But the changes are tightly related that is was not possible to separate them. Related to: * https://github.com/spring-projects/spring-batch/issues/3960 * https://github.com/spring-projects/spring-batch/issues/2122 * https://github.com/spring-projects/spring-batch/issues/1035 * https://github.com/spring-projects/spring-batch/issues/1983
This commit is contained in:
@@ -44,14 +44,14 @@ public class DefaultJobKeyGenerator implements JobKeyGenerator<JobParameters> {
|
||||
public String generateKey(JobParameters source) {
|
||||
|
||||
Assert.notNull(source, "source must not be null");
|
||||
Map<String, JobParameter> props = source.getParameters();
|
||||
Map<String, JobParameter<?>> props = source.getParameters();
|
||||
StringBuilder stringBuffer = new StringBuilder();
|
||||
List<String> keys = new ArrayList<>(props.keySet());
|
||||
Collections.sort(keys);
|
||||
for (String key : keys) {
|
||||
JobParameter jobParameter = props.get(key);
|
||||
JobParameter<?> jobParameter = props.get(key);
|
||||
if (jobParameter.isIdentifying()) {
|
||||
String value = jobParameter.getValue() == null ? "" : jobParameter.toString();
|
||||
String value = jobParameter.toString();
|
||||
stringBuffer.append(key).append("=").append(value).append(";");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,15 +17,14 @@
|
||||
package org.springframework.batch.core;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
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. 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
|
||||
@@ -34,87 +33,35 @@ import org.springframework.util.Assert;
|
||||
* @since 2.0
|
||||
*
|
||||
*/
|
||||
public class JobParameter implements Serializable {
|
||||
public class JobParameter<T> implements Serializable {
|
||||
|
||||
private final Object parameter;
|
||||
private T value;
|
||||
|
||||
private final ParameterType parameterType;
|
||||
private Class<T> type;
|
||||
|
||||
private final boolean identifying;
|
||||
private boolean identifying;
|
||||
|
||||
/**
|
||||
* Construct a new {@code JobParameter} from a {@link String}.
|
||||
* @param parameter {@link String} instance. Must not be {@code null}.
|
||||
* @param identifying {@code true} if the {@code JobParameter} should be identifying.
|
||||
* reate a new {@link JobParameter}.
|
||||
* @param value the value of the parameter. Must not be {@code null}.
|
||||
* @param type the type of the parameter. Must not be {@code null}.
|
||||
* @param identifying true if the parameter is identifying. false otherwise.
|
||||
*/
|
||||
public JobParameter(@NonNull String parameter, boolean identifying) {
|
||||
this(parameter, identifying, ParameterType.STRING);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public JobParameter(@NonNull Long parameter, boolean identifying) {
|
||||
this(parameter, identifying, ParameterType.LONG);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public JobParameter(@NonNull Date parameter, boolean identifying) {
|
||||
this(parameter, identifying, ParameterType.DATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public JobParameter(@NonNull Double parameter, boolean identifying) {
|
||||
this(parameter, identifying, ParameterType.DOUBLE);
|
||||
}
|
||||
|
||||
private JobParameter(Object parameter, boolean identifying, ParameterType parameterType) {
|
||||
Assert.notNull(parameter, "parameter must not be null");
|
||||
this.parameter = parameter;
|
||||
this.parameterType = parameterType;
|
||||
public JobParameter(@NonNull T value, @NonNull Class<T> type, boolean identifying) {
|
||||
Assert.notNull(value, "value must not be null");
|
||||
Assert.notNull(value, "type must not be null");
|
||||
this.value = value;
|
||||
this.type = type;
|
||||
this.identifying = identifying;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new {@code JobParameter} from a {@link String}.
|
||||
* @param parameter A {@link String} instance.
|
||||
* Create a new identifying {@link JobParameter}.
|
||||
* @param value the value of the parameter. Must not be {@code null}.
|
||||
* @param type the type of the parameter. Must not be {@code null}.
|
||||
*/
|
||||
public JobParameter(String parameter) {
|
||||
this(parameter, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new {@code JobParameter} from a {@link Long}.
|
||||
* @param parameter A {@link Long} instance.
|
||||
*/
|
||||
public JobParameter(Long parameter) {
|
||||
this(parameter, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new {@code JobParameter} as a {@link Date}.
|
||||
* @param parameter A {@link Date} instance.
|
||||
*/
|
||||
public JobParameter(Date parameter) {
|
||||
this(parameter, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new {@code JobParameter} from a {@link Double}.
|
||||
* @param parameter A {@link Double} instance.
|
||||
*/
|
||||
public JobParameter(Double parameter) {
|
||||
this(parameter, true);
|
||||
public JobParameter(@NonNull T value, @NonNull Class<T> type) {
|
||||
this(value, type, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,15 +75,16 @@ public class JobParameter implements Serializable {
|
||||
/**
|
||||
* @return the value contained within this {@code JobParameter}.
|
||||
*/
|
||||
public Object getValue() {
|
||||
return parameter;
|
||||
public T getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a {@link ParameterType} representing the type of this parameter.
|
||||
* Return the type of the parameter.
|
||||
* @return the type of the parameter
|
||||
*/
|
||||
public ParameterType getType() {
|
||||
return parameterType;
|
||||
public Class<T> getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -150,41 +98,17 @@ public class JobParameter implements Serializable {
|
||||
}
|
||||
|
||||
JobParameter rhs = (JobParameter) obj;
|
||||
return parameterType == rhs.parameterType && parameter.equals(rhs.parameter);
|
||||
return type == rhs.type && value.equals(rhs.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return parameterType == ParameterType.DATE ? "" + ((Date) parameter).getTime() : parameter.toString();
|
||||
return "{" + "value=" + value + ", type=" + type + ", identifying=" + identifying + '}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 7 + 21 * parameter.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enumeration representing the type of {@link JobParameter}.
|
||||
*/
|
||||
public enum ParameterType {
|
||||
|
||||
/**
|
||||
* String parameter type.
|
||||
*/
|
||||
STRING,
|
||||
/**
|
||||
* Date parameter type.
|
||||
*/
|
||||
DATE,
|
||||
/**
|
||||
* Long parameter type.
|
||||
*/
|
||||
LONG,
|
||||
/**
|
||||
* Double parameter type.
|
||||
*/
|
||||
DOUBLE;
|
||||
|
||||
return 7 + 21 * value.hashCode();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,14 +17,17 @@
|
||||
package org.springframework.batch.core;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Value object representing runtime parameters to a batch job. Because the parameters
|
||||
@@ -46,7 +49,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.
|
||||
@@ -61,7 +64,7 @@ public class JobParameters implements Serializable {
|
||||
* @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);
|
||||
}
|
||||
|
||||
@@ -75,8 +78,11 @@ public class JobParameters implements Serializable {
|
||||
if (!parameters.containsKey(key)) {
|
||||
return null;
|
||||
}
|
||||
Object value = parameters.get(key).getValue();
|
||||
return value == null ? null : ((Long) value).longValue();
|
||||
JobParameter<?> jobParameter = parameters.get(key);
|
||||
if (!jobParameter.getType().equals(Long.class)) {
|
||||
throw new IllegalArgumentException("Key " + key + " is not of type Long");
|
||||
}
|
||||
return (Long) jobParameter.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -104,8 +110,14 @@ public class JobParameters implements Serializable {
|
||||
*/
|
||||
@Nullable
|
||||
public String getString(String key) {
|
||||
JobParameter value = parameters.get(key);
|
||||
return value == null ? null : value.toString();
|
||||
if (!parameters.containsKey(key)) {
|
||||
return null;
|
||||
}
|
||||
JobParameter<?> jobParameter = parameters.get(key);
|
||||
if (!jobParameter.getType().equals(String.class)) {
|
||||
throw new IllegalArgumentException("Key " + key + " is not of type String");
|
||||
}
|
||||
return (String) jobParameter.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -136,8 +148,11 @@ public class JobParameters implements Serializable {
|
||||
if (!parameters.containsKey(key)) {
|
||||
return null;
|
||||
}
|
||||
Double value = (Double) parameters.get(key).getValue();
|
||||
return value == null ? null : value.doubleValue();
|
||||
JobParameter<?> jobParameter = parameters.get(key);
|
||||
if (!jobParameter.getType().equals(Double.class)) {
|
||||
throw new IllegalArgumentException("Key " + key + " is not of type Double");
|
||||
}
|
||||
return (Double) jobParameter.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -165,7 +180,14 @@ public class JobParameters implements Serializable {
|
||||
*/
|
||||
@Nullable
|
||||
public Date getDate(String key) {
|
||||
return this.getDate(key, null);
|
||||
if (!parameters.containsKey(key)) {
|
||||
return null;
|
||||
}
|
||||
JobParameter<?> jobParameter = parameters.get(key);
|
||||
if (!jobParameter.getType().equals(Date.class)) {
|
||||
throw new IllegalArgumentException("Key " + key + " is not of type java.util.Date");
|
||||
}
|
||||
return (Date) jobParameter.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -179,19 +201,24 @@ public class JobParameters implements Serializable {
|
||||
@Nullable
|
||||
public Date getDate(String key, @Nullable Date defaultValue) {
|
||||
if (parameters.containsKey(key)) {
|
||||
return (Date) parameters.get(key).getValue();
|
||||
return getDate(key);
|
||||
}
|
||||
else {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public JobParameter<?> getParameter(String key) {
|
||||
Assert.notNull(key, "key must not be null");
|
||||
return parameters.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a map of all parameters, including {@link String}, {@link Long}, and
|
||||
* {@link Date} types.
|
||||
* Get a map of all parameters.
|
||||
* @return an unmodifiable map containing all parameters.
|
||||
*/
|
||||
public Map<String, JobParameter> getParameters() {
|
||||
public Map<String, JobParameter<?>> getParameters() {
|
||||
return Collections.unmodifiableMap(parameters);
|
||||
}
|
||||
|
||||
@@ -223,17 +250,25 @@ public class JobParameters implements Serializable {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return parameters.toString();
|
||||
List<String> parameters = new ArrayList<>();
|
||||
for (Map.Entry<String, JobParameter<?>> entry : this.parameters.entrySet()) {
|
||||
parameters.add(String.format("'%s':'%s'", entry.getKey(), entry.getValue()));
|
||||
}
|
||||
return new StringBuilder("{").append(String.join(",", parameters)).append("}").toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The {@link Properties} that contain the key and values for the
|
||||
* {@link JobParameter} objects.
|
||||
* @deprecated since 5.0, scheduled for removal in 5.2. Use
|
||||
* {@link org.springframework.batch.core.converter.JobParametersConverter#getProperties(JobParameters)}
|
||||
*
|
||||
*/
|
||||
@Deprecated(since = "5.0", forRemoval = true)
|
||||
public Properties toProperties() {
|
||||
Properties props = new Properties();
|
||||
|
||||
for (Map.Entry<String, JobParameter> param : parameters.entrySet()) {
|
||||
for (Map.Entry<String, JobParameter<?>> param : parameters.entrySet()) {
|
||||
if (param.getValue() != null) {
|
||||
props.put(param.getKey(), Objects.toString(param.getValue().toString(), ""));
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class JobParametersBuilder {
|
||||
|
||||
private Map<String, JobParameter> parameterMap;
|
||||
private Map<String, JobParameter<?>> parameterMap;
|
||||
|
||||
private JobExplorer jobExplorer;
|
||||
|
||||
@@ -74,23 +74,6 @@ public class JobParametersBuilder {
|
||||
this(jobParameters, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
for (Map.Entry<Object, Object> curProperty : properties.entrySet()) {
|
||||
this.parameterMap.put((String) curProperty.getKey(),
|
||||
new JobParameter((String) curProperty.getValue(), false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy constructor. Initializes the builder with the supplied parameters.
|
||||
* @param jobParameters {@link JobParameters} instance used to initialize the builder.
|
||||
@@ -109,8 +92,7 @@ public class JobParametersBuilder {
|
||||
* @return a reference to this object.
|
||||
*/
|
||||
public JobParametersBuilder addString(String key, @NonNull String parameter) {
|
||||
this.parameterMap.put(key, new JobParameter(parameter, true));
|
||||
return this;
|
||||
return addString(key, parameter, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -122,7 +104,7 @@ public class JobParametersBuilder {
|
||||
* @return a reference to this object.
|
||||
*/
|
||||
public JobParametersBuilder addString(String key, @NonNull String parameter, boolean identifying) {
|
||||
this.parameterMap.put(key, new JobParameter(parameter, identifying));
|
||||
this.parameterMap.put(key, new JobParameter(parameter, String.class, identifying));
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -133,8 +115,7 @@ public class JobParametersBuilder {
|
||||
* @return a reference to this object.
|
||||
*/
|
||||
public JobParametersBuilder addDate(String key, @NonNull Date parameter) {
|
||||
this.parameterMap.put(key, new JobParameter(parameter, true));
|
||||
return this;
|
||||
return addDate(key, parameter, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,7 +127,7 @@ public class JobParametersBuilder {
|
||||
* @return a reference to this object.
|
||||
*/
|
||||
public JobParametersBuilder addDate(String key, @NonNull Date parameter, boolean identifying) {
|
||||
this.parameterMap.put(key, new JobParameter(parameter, identifying));
|
||||
this.parameterMap.put(key, new JobParameter(parameter, Date.class, identifying));
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -157,8 +138,7 @@ public class JobParametersBuilder {
|
||||
* @return a reference to this object.
|
||||
*/
|
||||
public JobParametersBuilder addLong(String key, @NonNull Long parameter) {
|
||||
this.parameterMap.put(key, new JobParameter(parameter, true));
|
||||
return this;
|
||||
return addLong(key, parameter, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -170,7 +150,7 @@ public class JobParametersBuilder {
|
||||
* @return a reference to this object.
|
||||
*/
|
||||
public JobParametersBuilder addLong(String key, @NonNull Long parameter, boolean identifying) {
|
||||
this.parameterMap.put(key, new JobParameter(parameter, identifying));
|
||||
this.parameterMap.put(key, new JobParameter(parameter, Long.class, identifying));
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -181,8 +161,7 @@ public class JobParametersBuilder {
|
||||
* @return a reference to this object.
|
||||
*/
|
||||
public JobParametersBuilder addDouble(String key, @NonNull Double parameter) {
|
||||
this.parameterMap.put(key, new JobParameter(parameter, true));
|
||||
return this;
|
||||
return addDouble(key, parameter, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -194,7 +173,7 @@ public class JobParametersBuilder {
|
||||
* @return a reference to this object.
|
||||
*/
|
||||
public JobParametersBuilder addDouble(String key, @NonNull Double parameter, boolean identifying) {
|
||||
this.parameterMap.put(key, new JobParameter(parameter, identifying));
|
||||
this.parameterMap.put(key, new JobParameter(parameter, Double.class, identifying));
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -212,13 +191,54 @@ public class JobParametersBuilder {
|
||||
* @param key The parameter accessor.
|
||||
* @param jobParameter The runtime parameter.
|
||||
* @return a reference to this object.
|
||||
* @deprecated since 5.0, scheduled for removal in 5.2. Use {@link #addJobParameter}.
|
||||
*/
|
||||
public JobParametersBuilder addParameter(String key, JobParameter jobParameter) {
|
||||
@Deprecated(since = "5.0", forRemoval = true)
|
||||
public JobParametersBuilder addParameter(String key, JobParameter<?> jobParameter) {
|
||||
Assert.notNull(jobParameter, "JobParameter must not be null");
|
||||
this.parameterMap.put(key, jobParameter);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public JobParametersBuilder addJobParameter(String key, JobParameter<?> jobParameter) {
|
||||
Assert.notNull(jobParameter, "JobParameter must not be null");
|
||||
this.parameterMap.put(key, jobParameter);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a job parameter.
|
||||
* @param name the name of the parameter
|
||||
* @param value the value of the parameter
|
||||
* @param type the type of the parameter
|
||||
* @param identifying true if the parameter is identifying. false otherwise
|
||||
* @return a reference to this object.
|
||||
* @param <T> the type of the parameter
|
||||
* @since 5.0
|
||||
*/
|
||||
public <T> JobParametersBuilder addJobParameter(String name, T value, Class<T> type, boolean identifying) {
|
||||
return addJobParameter(name, new JobParameter(value, type, identifying));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an identifying job parameter.
|
||||
* @param name the name of the parameter
|
||||
* @param value the value of the parameter
|
||||
* @param type the type of the parameter
|
||||
* @return a reference to this object.
|
||||
* @param <T> the type of the parameter
|
||||
* @since 5.0
|
||||
*/
|
||||
public <T> JobParametersBuilder addJobParameter(String name, T value, Class<T> type) {
|
||||
return addJobParameter(name, value, type, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy job parameters into the current state.
|
||||
* @param jobParameters The parameters to copy in.
|
||||
@@ -272,7 +292,7 @@ public class JobParametersBuilder {
|
||||
}
|
||||
|
||||
// start with parameters from the incrementer
|
||||
Map<String, JobParameter> nextParametersMap = new HashMap<>(nextParameters.getParameters());
|
||||
Map<String, JobParameter<?>> nextParametersMap = new HashMap<>(nextParameters.getParameters());
|
||||
// append new parameters (overriding those with the same key)
|
||||
nextParametersMap.putAll(this.parameterMap);
|
||||
this.parameterMap = nextParametersMap;
|
||||
|
||||
@@ -102,6 +102,11 @@ class BatchRegistrar implements ImportBeanDefinitionRegistrar {
|
||||
beanDefinitionBuilder.addPropertyReference("lobHandler", lobHandlerRef);
|
||||
}
|
||||
|
||||
String conversionServiceRef = batchAnnotation.conversionServiceRef();
|
||||
if (registry.containsBeanDefinition(conversionServiceRef)) {
|
||||
beanDefinitionBuilder.addPropertyReference("conversionService", conversionServiceRef);
|
||||
}
|
||||
|
||||
String incrementerFactoryRef = batchAnnotation.incrementerFactoryRef();
|
||||
if (registry.containsBeanDefinition(incrementerFactoryRef)) {
|
||||
beanDefinitionBuilder.addPropertyReference("incrementerFactory", incrementerFactoryRef);
|
||||
@@ -155,6 +160,11 @@ class BatchRegistrar implements ImportBeanDefinitionRegistrar {
|
||||
beanDefinitionBuilder.addPropertyReference("lobHandler", lobHandlerRef);
|
||||
}
|
||||
|
||||
String conversionServiceRef = batchAnnotation.conversionServiceRef();
|
||||
if (registry.containsBeanDefinition(conversionServiceRef)) {
|
||||
beanDefinitionBuilder.addPropertyReference("conversionService", conversionServiceRef);
|
||||
}
|
||||
|
||||
String charset = batchAnnotation.charset();
|
||||
if (charset != null) {
|
||||
beanDefinitionBuilder.addPropertyValue("charset", Charset.forName(charset));
|
||||
|
||||
@@ -235,4 +235,13 @@ public @interface EnableBatchProcessing {
|
||||
*/
|
||||
String taskExecutorRef() default "taskExecutor";
|
||||
|
||||
/**
|
||||
* Set the conversion service to use in the job repository and job explorer. This
|
||||
* service is used to convert job parameters from String literal to typed values and
|
||||
* vice versa.
|
||||
* @return the bean name of the conversion service to use. Defauls to
|
||||
* {@literal conversionService}
|
||||
*/
|
||||
String conversionServiceRef() default "conversionService";
|
||||
|
||||
}
|
||||
|
||||
@@ -48,6 +48,8 @@ import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.convert.support.ConfigurableConversionService;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.core.task.SyncTaskExecutor;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.jdbc.core.JdbcOperations;
|
||||
@@ -125,6 +127,7 @@ public class DefaultBatchConfiguration implements ApplicationContextAware {
|
||||
jobRepositoryFactoryBean.setClobType(getClobType());
|
||||
jobRepositoryFactoryBean.setTablePrefix(getTablePrefix());
|
||||
jobRepositoryFactoryBean.setSerializer(getExecutionContextSerializer());
|
||||
jobRepositoryFactoryBean.setConversionService(getConversionService());
|
||||
jobRepositoryFactoryBean.setJdbcOperations(getJdbcOperations());
|
||||
jobRepositoryFactoryBean.setLobHandler(getLobHandler());
|
||||
jobRepositoryFactoryBean.setCharset(getCharset());
|
||||
@@ -162,6 +165,7 @@ public class DefaultBatchConfiguration implements ApplicationContextAware {
|
||||
jobExplorerFactoryBean.setCharset(getCharset());
|
||||
jobExplorerFactoryBean.setTablePrefix(getTablePrefix());
|
||||
jobExplorerFactoryBean.setLobHandler(getLobHandler());
|
||||
jobExplorerFactoryBean.setConversionService(getConversionService());
|
||||
jobExplorerFactoryBean.setSerializer(getExecutionContextSerializer());
|
||||
try {
|
||||
jobExplorerFactoryBean.afterPropertiesSet();
|
||||
@@ -343,4 +347,14 @@ public class DefaultBatchConfiguration implements ApplicationContextAware {
|
||||
return new SyncTaskExecutor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the conversion service to use in the job repository and job explorer. This
|
||||
* service is used to convert job parameters from String literal to typed values and
|
||||
* vice versa.
|
||||
* @return the {@link ConfigurableConversionService} to use.
|
||||
*/
|
||||
protected ConfigurableConversionService getConversionService() {
|
||||
return new DefaultConversionService();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2006-2008 the original author or authors.
|
||||
* 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.
|
||||
@@ -31,6 +31,7 @@ import org.w3c.dom.Element;
|
||||
* returns a JobRepositoryFactoryBean.
|
||||
*
|
||||
* @author Thomas Risberg
|
||||
* @author Mahmoud Ben Hassine
|
||||
* @since 2.0
|
||||
*
|
||||
*/
|
||||
@@ -80,6 +81,8 @@ public class JobRepositoryParser extends AbstractSingleBeanDefinitionParser {
|
||||
|
||||
String serializer = element.getAttribute("serializer");
|
||||
|
||||
String conversionService = element.getAttribute("conversion-service");
|
||||
|
||||
RuntimeBeanReference ds = new RuntimeBeanReference(dataSource);
|
||||
builder.addPropertyValue("dataSource", ds);
|
||||
RuntimeBeanReference tx = new RuntimeBeanReference(transactionManager);
|
||||
@@ -103,6 +106,9 @@ public class JobRepositoryParser extends AbstractSingleBeanDefinitionParser {
|
||||
if (StringUtils.hasText(serializer)) {
|
||||
builder.addPropertyReference("serializer", serializer);
|
||||
}
|
||||
if (StringUtils.hasText(conversionService)) {
|
||||
builder.addPropertyReference("conversionService", conversionService);
|
||||
}
|
||||
|
||||
builder.setRole(BeanDefinition.ROLE_SUPPORT);
|
||||
|
||||
|
||||
@@ -15,47 +15,43 @@
|
||||
*/
|
||||
package org.springframework.batch.core.converter;
|
||||
|
||||
import org.springframework.batch.core.JobInstance;
|
||||
import org.springframework.batch.core.JobParameter;
|
||||
import org.springframework.batch.core.JobParameter.ParameterType;
|
||||
import org.springframework.batch.core.JobParameters;
|
||||
import org.springframework.batch.core.JobParametersBuilder;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.NumberFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.springframework.batch.core.JobParameter;
|
||||
import org.springframework.batch.core.JobParameters;
|
||||
import org.springframework.batch.core.JobParametersBuilder;
|
||||
import org.springframework.core.convert.support.ConfigurableConversionService;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Converter for {@link JobParameters} instances that uses a simple naming convention for
|
||||
* property keys. Key names that are prefixed with a {@code -} are considered
|
||||
* non-identifying and do not contribute to the identity of a {@link JobInstance}. Key
|
||||
* names ending with "(<type>)" (where type is one of string, date, long) are
|
||||
* converted to the corresponding type. The default type is string. Consider the following
|
||||
* example:
|
||||
* converting job parameters. The expected notation is the following:
|
||||
*
|
||||
* <pre>
|
||||
* schedule.date(date)=2007/12/11
|
||||
* department.id(long)=2345
|
||||
* </pre>
|
||||
* key=value,type,identifying
|
||||
*
|
||||
* The literal values are converted to the correct type by using the default Spring
|
||||
* strategies, augmented if necessary by any custom editors that have been provided.
|
||||
* where:
|
||||
*
|
||||
* <br>
|
||||
* <ul>
|
||||
* <li>value: string literal repesenting the value</li>
|
||||
* <li>type (optional): fully qualified name of the type of the value. Defaults to
|
||||
* String.</li>
|
||||
* <li>identifying (optional): boolean to flag the job parameter as identifying or not.
|
||||
* Defaults to true</li>
|
||||
* </ul>
|
||||
*
|
||||
* If you need to be able to parse and format local-specific dates and numbers, you can
|
||||
* inject formatters ({@link #setDateFormat(DateFormat)} and
|
||||
* {@link #setNumberFormat(NumberFormat)}).
|
||||
* For example, schedule.date=2022-12-12,java.time.LocalDate will be converted to an
|
||||
* identifying job parameter of type {@link java.time.LocalDate} with value "2022-12-12".
|
||||
*
|
||||
* The literal values are converted to the target type by using the default Spring
|
||||
* conversion service, augmented if necessary by any custom converters. The conversion
|
||||
* service should be configured with a converter to and from string literals to job
|
||||
* parameter types.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Michael Minella
|
||||
@@ -64,208 +60,110 @@ import java.util.Properties;
|
||||
*/
|
||||
public class DefaultJobParametersConverter implements JobParametersConverter {
|
||||
|
||||
/**
|
||||
* Parameter key suffix representing the date type.
|
||||
*/
|
||||
public static final String DATE_TYPE = "(date)";
|
||||
protected ConfigurableConversionService conversionService = new DefaultConversionService();
|
||||
|
||||
/**
|
||||
* Parameter key suffix representing the string type.
|
||||
*/
|
||||
public static final String STRING_TYPE = "(string)";
|
||||
|
||||
/**
|
||||
* Parameter key suffix representing the long type.
|
||||
*/
|
||||
public static final String LONG_TYPE = "(long)";
|
||||
|
||||
/**
|
||||
* Parameter key suffix representing the double type.
|
||||
*/
|
||||
public static final String DOUBLE_TYPE = "(double)";
|
||||
|
||||
private static final String NON_IDENTIFYING_FLAG = "-";
|
||||
|
||||
private static final String IDENTIFYING_FLAG = "+";
|
||||
|
||||
private static NumberFormat DEFAULT_NUMBER_FORMAT = NumberFormat.getInstance(Locale.US);
|
||||
|
||||
private DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
|
||||
|
||||
private NumberFormat numberFormat = DEFAULT_NUMBER_FORMAT;
|
||||
|
||||
private final NumberFormat longNumberFormat = new DecimalFormat("#");
|
||||
|
||||
/**
|
||||
* Check for a suffix on keys and use those to decide how to convert the value.
|
||||
* @throws IllegalArgumentException if a number or date is passed in that cannot be
|
||||
* parsed or cast to the correct type.
|
||||
*
|
||||
* @see org.springframework.batch.core.converter.JobParametersConverter#getJobParameters(java.util.Properties)
|
||||
*/
|
||||
@Override
|
||||
public JobParameters getJobParameters(@Nullable Properties props) {
|
||||
|
||||
if (props == null || props.isEmpty()) {
|
||||
public JobParameters getJobParameters(@Nullable Properties properties) {
|
||||
if (properties == null || properties.isEmpty()) {
|
||||
return new JobParameters();
|
||||
}
|
||||
|
||||
JobParametersBuilder propertiesBuilder = new JobParametersBuilder();
|
||||
|
||||
for (Iterator<Entry<Object, Object>> it = props.entrySet().iterator(); it.hasNext();) {
|
||||
Entry<Object, Object> entry = it.next();
|
||||
String key = (String) entry.getKey();
|
||||
String value = (String) entry.getValue();
|
||||
|
||||
boolean identifying = isIdentifyingKey(key);
|
||||
if (!identifying) {
|
||||
key = key.replaceFirst(NON_IDENTIFYING_FLAG, "");
|
||||
}
|
||||
else if (identifying && key.startsWith(IDENTIFYING_FLAG)) {
|
||||
key = key.replaceFirst("\\" + IDENTIFYING_FLAG, "");
|
||||
}
|
||||
|
||||
if (key.endsWith(DATE_TYPE)) {
|
||||
Date date;
|
||||
synchronized (dateFormat) {
|
||||
try {
|
||||
date = dateFormat.parse(value);
|
||||
}
|
||||
catch (ParseException ex) {
|
||||
String suffix = (dateFormat instanceof SimpleDateFormat)
|
||||
? ", use " + ((SimpleDateFormat) dateFormat).toPattern() : "";
|
||||
throw new IllegalArgumentException("Date format is invalid: [" + value + "]" + suffix);
|
||||
}
|
||||
}
|
||||
propertiesBuilder.addDate(StringUtils.replace(key, DATE_TYPE, ""), date, identifying);
|
||||
}
|
||||
else if (key.endsWith(LONG_TYPE)) {
|
||||
Long result;
|
||||
try {
|
||||
result = (Long) parseNumber(value);
|
||||
}
|
||||
catch (ClassCastException ex) {
|
||||
throw new IllegalArgumentException("Number format is invalid for long value: [" + value
|
||||
+ "], use a format with no decimal places");
|
||||
}
|
||||
propertiesBuilder.addLong(StringUtils.replace(key, LONG_TYPE, ""), result, identifying);
|
||||
}
|
||||
else if (key.endsWith(DOUBLE_TYPE)) {
|
||||
Double result = parseNumber(value).doubleValue();
|
||||
propertiesBuilder.addDouble(StringUtils.replace(key, DOUBLE_TYPE, ""), result, identifying);
|
||||
}
|
||||
else if (StringUtils.endsWithIgnoreCase(key, STRING_TYPE)) {
|
||||
propertiesBuilder.addString(StringUtils.replace(key, STRING_TYPE, ""), value, identifying);
|
||||
}
|
||||
else {
|
||||
propertiesBuilder.addString(key, value, identifying);
|
||||
}
|
||||
JobParametersBuilder jobParametersBuilder = new JobParametersBuilder();
|
||||
for (Entry<Object, Object> entry : properties.entrySet()) {
|
||||
String parameterName = (String) entry.getKey();
|
||||
String encodedJobParameter = (String) entry.getValue();
|
||||
JobParameter<?> jobParameter = decode(encodedJobParameter);
|
||||
jobParametersBuilder.addJobParameter(parameterName, jobParameter);
|
||||
}
|
||||
|
||||
return propertiesBuilder.toJobParameters();
|
||||
}
|
||||
|
||||
private boolean isIdentifyingKey(String key) {
|
||||
boolean identifying = true;
|
||||
|
||||
if (key.startsWith(NON_IDENTIFYING_FLAG)) {
|
||||
identifying = false;
|
||||
}
|
||||
|
||||
return identifying;
|
||||
return jobParametersBuilder.toJobParameters();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegate to {@link NumberFormat} to parse the value.
|
||||
*/
|
||||
private Number parseNumber(String value) {
|
||||
synchronized (numberFormat) {
|
||||
try {
|
||||
return numberFormat.parse(value);
|
||||
}
|
||||
catch (ParseException ex) {
|
||||
String suffix = (numberFormat instanceof DecimalFormat)
|
||||
? ", use " + ((DecimalFormat) numberFormat).toPattern() : "";
|
||||
throw new IllegalArgumentException("Number format is invalid: [" + value + "], use " + suffix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the same suffixes to create properties (omitting the string suffix because it
|
||||
* is the default). Non-identifying parameters are prefixed with the
|
||||
* {@link #NON_IDENTIFYING_FLAG}. However, since parameters are identifying by
|
||||
* default, they are <em>not</em> prefixed with the {@link #IDENTIFYING_FLAG}.
|
||||
*
|
||||
* @see org.springframework.batch.core.converter.JobParametersConverter#getProperties(org.springframework.batch.core.JobParameters)
|
||||
*/
|
||||
@Override
|
||||
public Properties getProperties(@Nullable JobParameters params) {
|
||||
|
||||
if (params == null || params.isEmpty()) {
|
||||
public Properties getProperties(@Nullable JobParameters jobParameters) {
|
||||
if (jobParameters == null || jobParameters.isEmpty()) {
|
||||
return new Properties();
|
||||
}
|
||||
|
||||
Map<String, JobParameter> parameters = params.getParameters();
|
||||
Properties result = new Properties();
|
||||
for (Entry<String, JobParameter> entry : parameters.entrySet()) {
|
||||
|
||||
String key = entry.getKey();
|
||||
JobParameter jobParameter = entry.getValue();
|
||||
Object value = jobParameter.getValue();
|
||||
if (value != null) {
|
||||
key = (!jobParameter.isIdentifying() ? NON_IDENTIFYING_FLAG : "") + key;
|
||||
if (jobParameter.getType() == ParameterType.DATE) {
|
||||
synchronized (dateFormat) {
|
||||
result.setProperty(key + DATE_TYPE, dateFormat.format(value));
|
||||
}
|
||||
}
|
||||
else if (jobParameter.getType() == ParameterType.LONG) {
|
||||
synchronized (longNumberFormat) {
|
||||
result.setProperty(key + LONG_TYPE, longNumberFormat.format(value));
|
||||
}
|
||||
}
|
||||
else if (jobParameter.getType() == ParameterType.DOUBLE) {
|
||||
result.setProperty(key + DOUBLE_TYPE, decimalFormat((Double) value));
|
||||
}
|
||||
else {
|
||||
result.setProperty(key, "" + value);
|
||||
}
|
||||
}
|
||||
Map<String, JobParameter<?>> parameters = jobParameters.getParameters();
|
||||
Properties properties = new Properties();
|
||||
for (Entry<String, JobParameter<?>> entry : parameters.entrySet()) {
|
||||
String parameterName = entry.getKey();
|
||||
JobParameter<?> jobParameter = entry.getValue();
|
||||
properties.setProperty(parameterName, encode(jobParameter));
|
||||
}
|
||||
return result;
|
||||
return properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a best guess at converting a double to a string representation of a decimal
|
||||
* format.
|
||||
* @param value A decimal value.
|
||||
* @return a best guess at the desired format.
|
||||
* Set the conversion service to use.
|
||||
* @param conversionService the conversion service to use. Must not be {@code null}.
|
||||
* @since 5.0
|
||||
*/
|
||||
private String decimalFormat(double value) {
|
||||
if (numberFormat != DEFAULT_NUMBER_FORMAT) {
|
||||
synchronized (numberFormat) {
|
||||
return numberFormat.format(value);
|
||||
}
|
||||
public void setConversionService(@NonNull ConfigurableConversionService conversionService) {
|
||||
Assert.notNull(conversionService, "The conversionService must not be null");
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a job parameter to a string.
|
||||
* @param jobParameter the parameter to encode
|
||||
* @return the encoded job parameter
|
||||
*/
|
||||
protected String encode(JobParameter<?> jobParameter) {
|
||||
Class<?> parameterType = jobParameter.getType();
|
||||
boolean parameterIdentifying = jobParameter.isIdentifying();
|
||||
Object parameterTypedValue = jobParameter.getValue();
|
||||
String parameterStringValue = this.conversionService.convert(parameterTypedValue, String.class);
|
||||
return String.join(",", parameterStringValue, parameterType.getName(), Boolean.toString(parameterIdentifying));
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a job parameter from a string.
|
||||
* @param encodedJobParameter the encoded job parameter
|
||||
* @return the decoded job parameter
|
||||
*/
|
||||
protected JobParameter<?> decode(String encodedJobParameter) {
|
||||
String parameterStringValue = parseValue(encodedJobParameter);
|
||||
Class<?> parameterType = parseType(encodedJobParameter);
|
||||
boolean parameterIdentifying = parseIdentifying(encodedJobParameter);
|
||||
try {
|
||||
Object typedValue = this.conversionService.convert(parameterStringValue, parameterType);
|
||||
return new JobParameter(typedValue, parameterType, parameterIdentifying);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new JobParametersConversionException(
|
||||
"Unable to convert job parameter " + parameterStringValue + " to type " + parameterType, e);
|
||||
}
|
||||
return Double.toString(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter for injecting a date format.
|
||||
* @param dateFormat A {@link DateFormat}, defaults to "yyyy/MM/dd".
|
||||
*/
|
||||
public void setDateFormat(DateFormat dateFormat) {
|
||||
this.dateFormat = dateFormat;
|
||||
private String parseValue(String encodedJobParameter) {
|
||||
return StringUtils.commaDelimitedListToStringArray(encodedJobParameter)[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Public setter for the {@link NumberFormat}. Used to parse longs and doubles, so
|
||||
* must not contain decimal place (for example, use "#" or "#,###" but not "#.##").
|
||||
* @param numberFormat the {@link NumberFormat} to set
|
||||
*/
|
||||
public void setNumberFormat(NumberFormat numberFormat) {
|
||||
this.numberFormat = numberFormat;
|
||||
private Class<?> parseType(String encodedJobParameter) {
|
||||
String[] tokens = StringUtils.commaDelimitedListToStringArray(encodedJobParameter);
|
||||
if (tokens.length <= 1) {
|
||||
return String.class;
|
||||
}
|
||||
try {
|
||||
Class<?> type = Class.forName(tokens[1]);
|
||||
return type;
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
throw new JobParametersConversionException("Unable to parse job parameter " + encodedJobParameter, e);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean parseIdentifying(String encodedJobParameter) {
|
||||
String[] tokens = StringUtils.commaDelimitedListToStringArray(encodedJobParameter);
|
||||
if (tokens.length <= 2) {
|
||||
return true;
|
||||
}
|
||||
return Boolean.valueOf(tokens[2]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Exception to report an error when converting job parameters.
|
||||
*
|
||||
* @author Mahmoud Ben Hassine
|
||||
* @since 5.0
|
||||
*/
|
||||
package org.springframework.batch.core.converter;
|
||||
|
||||
public class JobParametersConversionException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* Create a new {@link JobParametersConversionException}.
|
||||
* @param message the message of the exception
|
||||
*/
|
||||
public JobParametersConversionException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link JobParametersConversionException}.
|
||||
* @param message the message of the exception
|
||||
* @param cause the cause of the exception
|
||||
*/
|
||||
public JobParametersConversionException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright 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.converter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.MappingJsonFactory;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import org.springframework.batch.core.JobParameter;
|
||||
import org.springframework.batch.core.JobParameters;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Converter for {@link JobParameters} instances that uses a JSON naming convention for
|
||||
* converting job parameters. The expected notation is the following:
|
||||
*
|
||||
* key='{"value": "parameterStringLiteralValue",
|
||||
* "type":"fully.qualified.name.of.the.parameter.Type", "identifying": "booleanValue"}'
|
||||
*
|
||||
* where:
|
||||
*
|
||||
* <ul>
|
||||
* <li>value: string literal repesenting the value</li>
|
||||
* <li>type (optional): fully qualified name of the type of the value. Defaults to
|
||||
* String.</li>
|
||||
* <li>identifying (optional): boolean to flag the job parameter as identifying or not.
|
||||
* Defaults to true</li>
|
||||
* </ul>
|
||||
*
|
||||
* For example, schedule.date={"value": "2022-12-12", "type":"java.time.LocalDate",
|
||||
* "identifying": "false"} will be converted to a non identifying job parameter of type
|
||||
* {@link java.time.LocalDate} with value "2022-12-12".
|
||||
*
|
||||
* The literal values are converted to the correct type by using the default Spring
|
||||
* conversion service, augmented if necessary by any custom converters. The conversion
|
||||
* service should be configured with a converter to and from string literals to job
|
||||
* parameter types.
|
||||
*
|
||||
* @author Mahmoud Ben Hassine
|
||||
* @since 5.0
|
||||
*
|
||||
*/
|
||||
public class JsonJobParametersConverter extends DefaultJobParametersConverter {
|
||||
|
||||
private ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
/**
|
||||
* Create a new {@link JsonJobParametersConverter} with a default
|
||||
* {@link ObjectMapper}.
|
||||
*/
|
||||
public JsonJobParametersConverter() {
|
||||
this(new ObjectMapper());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link JsonJobParametersConverter} with a custom {@link ObjectMapper}.
|
||||
* @param objectMapper the object mapper to use
|
||||
*/
|
||||
public JsonJobParametersConverter(ObjectMapper objectMapper) {
|
||||
this.objectMapper = objectMapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String encode(JobParameter<?> jobParameter) {
|
||||
Class<?> parameterType = jobParameter.getType();
|
||||
Object parameterTypedValue = jobParameter.getValue();
|
||||
boolean parameterIdentifying = jobParameter.isIdentifying();
|
||||
String parameterStringValue = this.conversionService.convert(parameterTypedValue, String.class);
|
||||
try {
|
||||
return this.objectMapper.writeValueAsString(new JobParameterDefinition(parameterStringValue,
|
||||
parameterType.getName(), Boolean.toString(parameterIdentifying)));
|
||||
}
|
||||
catch (JsonProcessingException e) {
|
||||
throw new JobParametersConversionException("Unable to encode job parameter " + jobParameter, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JobParameter decode(String encodedJobParameter) {
|
||||
try {
|
||||
JobParameterDefinition jobParameterDefinition = this.objectMapper.readValue(encodedJobParameter,
|
||||
JobParameterDefinition.class);
|
||||
Class<?> parameterType = Class.forName(jobParameterDefinition.type());
|
||||
boolean parameterIdentifying = true;
|
||||
if (jobParameterDefinition.identifying() != null && !jobParameterDefinition.identifying().isEmpty()) {
|
||||
parameterIdentifying = Boolean.valueOf(jobParameterDefinition.identifying());
|
||||
}
|
||||
Object parameterTypedValue = this.conversionService.convert(jobParameterDefinition.value(), parameterType);
|
||||
return new JobParameter(parameterTypedValue, parameterType, parameterIdentifying);
|
||||
}
|
||||
catch (JsonProcessingException | ClassNotFoundException e) {
|
||||
throw new JobParametersConversionException("Unable to decode job parameter " + encodedJobParameter, e);
|
||||
}
|
||||
}
|
||||
|
||||
public record JobParameterDefinition(String value, String type, String identifying) {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -36,6 +36,8 @@ import org.springframework.batch.core.repository.dao.StepExecutionDao;
|
||||
import org.springframework.batch.item.ExecutionContext;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.core.convert.support.ConfigurableConversionService;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.jdbc.core.JdbcOperations;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.support.incrementer.AbstractDataFieldMaxValueIncrementer;
|
||||
@@ -74,6 +76,8 @@ public class JobExplorerFactoryBean extends AbstractJobExplorerFactoryBean imple
|
||||
|
||||
private Charset charset = StandardCharsets.UTF_8;
|
||||
|
||||
private ConfigurableConversionService conversionService;
|
||||
|
||||
/**
|
||||
* A custom implementation of {@link ExecutionContextSerializer}. The default, if not
|
||||
* injected, is the {@link Jackson2ExecutionContextStringSerializer}.
|
||||
@@ -135,6 +139,17 @@ public class JobExplorerFactoryBean extends AbstractJobExplorerFactoryBean imple
|
||||
this.charset = charset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the conversion service to use in the job explorer. This service is used to
|
||||
* convert job parameters from String literal to typed values and vice versa.
|
||||
* @param conversionService the conversion service to use
|
||||
* @since 5.0
|
||||
*/
|
||||
public void setConversionService(@NonNull ConfigurableConversionService conversionService) {
|
||||
Assert.notNull(conversionService, "ConversionService must not be null");
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
|
||||
@@ -148,6 +163,10 @@ public class JobExplorerFactoryBean extends AbstractJobExplorerFactoryBean imple
|
||||
serializer = new Jackson2ExecutionContextStringSerializer();
|
||||
}
|
||||
|
||||
if (this.conversionService == null) {
|
||||
this.conversionService = new DefaultConversionService();
|
||||
}
|
||||
|
||||
super.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@@ -179,6 +198,7 @@ public class JobExplorerFactoryBean extends AbstractJobExplorerFactoryBean imple
|
||||
dao.setJdbcTemplate(jdbcOperations);
|
||||
dao.setJobExecutionIncrementer(incrementer);
|
||||
dao.setTablePrefix(tablePrefix);
|
||||
dao.setConversionService(this.conversionService);
|
||||
dao.afterPropertiesSet();
|
||||
return dao;
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ import org.springframework.util.StringUtils;
|
||||
* <p>
|
||||
* <code>
|
||||
* java org.springframework.batch.core.launch.support.CommandLineJobRunner testJob.xml
|
||||
* testJob schedule.date=2008/01/24 vendor.id=3902483920
|
||||
* testJob schedule.date=2008-01-24,java.time.LocalDate vendor.id=3902483920,java.lang.Long
|
||||
* </code>
|
||||
* </p>
|
||||
*
|
||||
@@ -139,14 +139,15 @@ import org.springframework.util.StringUtils;
|
||||
* By default, the `CommandLineJobRunner` uses a {@link DefaultJobParametersConverter}
|
||||
* which implicitly converts key/value pairs to identifying job parameters. However, it is
|
||||
* possible to explicitly specify which job parameters are identifying and which are not
|
||||
* by prefixing them with `+` or `-` respectively. In the following example,
|
||||
* by suffixing them with `true` or `false` respectively. In the following example,
|
||||
* `schedule.date` is an identifying job parameter while `vendor.id` is not:
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* <code>
|
||||
* java org.springframework.batch.core.launch.support.CommandLineJobRunner testJob.xml
|
||||
* testJob +schedule.date=2008/01/24 -vendor.id=3902483920
|
||||
* testJob schedule.date=2008-01-24,java.time.LocalDate,true \
|
||||
* vendor.id=3902483920,java.lang.Long,false
|
||||
* </code>
|
||||
* </p>
|
||||
*
|
||||
|
||||
@@ -21,11 +21,13 @@ import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.batch.core.BatchStatus;
|
||||
import org.springframework.batch.core.Job;
|
||||
import org.springframework.batch.core.JobExecution;
|
||||
@@ -58,7 +60,6 @@ import org.springframework.batch.core.step.StepLocator;
|
||||
import org.springframework.batch.core.step.tasklet.StoppableTasklet;
|
||||
import org.springframework.batch.core.step.tasklet.Tasklet;
|
||||
import org.springframework.batch.core.step.tasklet.TaskletStep;
|
||||
import org.springframework.batch.support.PropertiesConverter;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -207,8 +208,13 @@ public class SimpleJobOperator implements JobOperator, InitializingBean {
|
||||
public String getParameters(long executionId) throws NoSuchJobExecutionException {
|
||||
JobExecution jobExecution = findExecutionById(executionId);
|
||||
|
||||
return PropertiesConverter
|
||||
.propertiesToString(jobParametersConverter.getProperties(jobExecution.getJobParameters()));
|
||||
Properties properties = this.jobParametersConverter.getProperties(jobExecution.getJobParameters());
|
||||
|
||||
List<String> keyValuePairs = new ArrayList<>();
|
||||
for (Map.Entry<Object, Object> entry : properties.entrySet()) {
|
||||
keyValuePairs.add(entry.getKey() + "=" + entry.getValue());
|
||||
}
|
||||
return String.join(" ", keyValuePairs);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -301,18 +307,26 @@ public class SimpleJobOperator implements JobOperator, InitializingBean {
|
||||
logger.info("Checking status of job with name=" + jobName);
|
||||
}
|
||||
|
||||
JobParameters jobParameters = jobParametersConverter
|
||||
.getJobParameters(PropertiesConverter.stringToProperties(parameters));
|
||||
Properties properties = new Properties();
|
||||
if (!parameters.isEmpty()) {
|
||||
String[] keyValuePairs = parameters.split(" ");
|
||||
for (String string : keyValuePairs) {
|
||||
String[] keyValuePair = string.split("=");
|
||||
properties.setProperty(keyValuePair[0], keyValuePair[1]);
|
||||
}
|
||||
}
|
||||
JobParameters jobParameters = jobParametersConverter.getJobParameters(properties);
|
||||
|
||||
if (jobRepository.isJobInstanceExists(jobName, jobParameters)) {
|
||||
throw new JobInstanceAlreadyExistsException(
|
||||
String.format("Cannot start a job instance that already exists with name=%s and parameters=%s",
|
||||
String.format("Cannot start a job instance that already exists with name=%s and parameters={%s}",
|
||||
jobName, parameters));
|
||||
}
|
||||
|
||||
Job job = jobRegistry.getJob(jobName);
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info(String.format("Attempting to launch job with name=%s and parameters=%s", jobName, parameters));
|
||||
logger.info(
|
||||
String.format("Attempting to launch job with name=%s and parameters={%s}", jobName, parameters));
|
||||
}
|
||||
try {
|
||||
return jobLauncher.run(job, jobParameters).getId();
|
||||
|
||||
@@ -21,7 +21,6 @@ import java.io.OutputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
@@ -31,8 +30,10 @@ import java.util.Set;
|
||||
import com.fasterxml.jackson.annotation.JacksonAnnotation;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.core.type.WritableTypeId;
|
||||
import com.fasterxml.jackson.databind.DatabindContext;
|
||||
import com.fasterxml.jackson.databind.DeserializationConfig;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
@@ -41,6 +42,7 @@ import com.fasterxml.jackson.databind.JavaType;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.MapperFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import com.fasterxml.jackson.databind.cfg.MapperConfig;
|
||||
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
|
||||
import com.fasterxml.jackson.databind.json.JsonMapper;
|
||||
@@ -49,8 +51,10 @@ import com.fasterxml.jackson.databind.jsontype.NamedType;
|
||||
import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
|
||||
import com.fasterxml.jackson.databind.jsontype.TypeIdResolver;
|
||||
import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder;
|
||||
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
|
||||
import com.fasterxml.jackson.databind.jsontype.impl.StdTypeResolverBuilder;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
|
||||
|
||||
import org.springframework.batch.core.JobParameter;
|
||||
import org.springframework.batch.core.JobParameters;
|
||||
@@ -58,6 +62,8 @@ import org.springframework.batch.core.repository.ExecutionContextSerializer;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import static com.fasterxml.jackson.core.JsonToken.START_OBJECT;
|
||||
|
||||
/**
|
||||
* Implementation that uses Jackson2 to provide (de)serialization.
|
||||
*
|
||||
@@ -104,6 +110,12 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class Jackson2ExecutionContextStringSerializer implements ExecutionContextSerializer {
|
||||
|
||||
private static final String IDENTIFYING_KEY_NAME = "identifying";
|
||||
|
||||
private static final String TYPE_KEY_NAME = "type";
|
||||
|
||||
private static final String VALUE_KEY_NAME = "value";
|
||||
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
/**
|
||||
@@ -144,7 +156,7 @@ public class Jackson2ExecutionContextStringSerializer implements ExecutionContex
|
||||
// BATCH-2680
|
||||
/**
|
||||
* Custom Jackson module to support {@link JobParameter} and {@link JobParameters}
|
||||
* deserialization.
|
||||
* serialization and deserialization.
|
||||
*/
|
||||
private class JobParametersModule extends SimpleModule {
|
||||
|
||||
@@ -154,6 +166,7 @@ public class Jackson2ExecutionContextStringSerializer implements ExecutionContex
|
||||
super("Job parameters module");
|
||||
setMixInAnnotation(JobParameters.class, JobParametersMixIn.class);
|
||||
addDeserializer(JobParameter.class, new JobParameterDeserializer());
|
||||
addSerializer(JobParameter.class, new JobParameterSerializer(JobParameter.class));
|
||||
}
|
||||
|
||||
private abstract class JobParametersMixIn {
|
||||
@@ -163,16 +176,38 @@ public class Jackson2ExecutionContextStringSerializer implements ExecutionContex
|
||||
|
||||
}
|
||||
|
||||
private class JobParameterSerializer extends StdSerializer<JobParameter> {
|
||||
|
||||
protected JobParameterSerializer(Class<JobParameter> type) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWithType(JobParameter value, JsonGenerator gen, SerializerProvider provider,
|
||||
TypeSerializer typeSer) throws IOException {
|
||||
WritableTypeId typeId = typeSer.typeId(value, START_OBJECT);
|
||||
typeSer.writeTypePrefix(gen, typeId);
|
||||
serialize(value, gen, provider);
|
||||
typeSer.writeTypeSuffix(gen, typeId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(JobParameter jobParameter, JsonGenerator jsonGenerator,
|
||||
SerializerProvider serializerProvider) throws IOException {
|
||||
jsonGenerator.writeFieldName(VALUE_KEY_NAME);
|
||||
jsonGenerator.writeObject(jobParameter.getValue());
|
||||
jsonGenerator.writeFieldName(TYPE_KEY_NAME);
|
||||
jsonGenerator.writeString(jobParameter.getType().getName());
|
||||
jsonGenerator.writeFieldName(IDENTIFYING_KEY_NAME);
|
||||
jsonGenerator.writeObject(jobParameter.isIdentifying());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class JobParameterDeserializer extends StdDeserializer<JobParameter> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final String IDENTIFYING_KEY_NAME = "identifying";
|
||||
|
||||
private static final String TYPE_KEY_NAME = "type";
|
||||
|
||||
private static final String VALUE_KEY_NAME = "value";
|
||||
|
||||
JobParameterDeserializer() {
|
||||
super(JobParameter.class);
|
||||
}
|
||||
@@ -183,26 +218,14 @@ public class Jackson2ExecutionContextStringSerializer implements ExecutionContex
|
||||
boolean identifying = node.get(IDENTIFYING_KEY_NAME).asBoolean();
|
||||
String type = node.get(TYPE_KEY_NAME).asText();
|
||||
JsonNode value = node.get(VALUE_KEY_NAME);
|
||||
Object parameterValue;
|
||||
switch (JobParameter.ParameterType.valueOf(type)) {
|
||||
case STRING: {
|
||||
parameterValue = value.asText();
|
||||
return new JobParameter((String) parameterValue, identifying);
|
||||
}
|
||||
case DATE: {
|
||||
parameterValue = new Date(value.get(1).asLong());
|
||||
return new JobParameter((Date) parameterValue, identifying);
|
||||
}
|
||||
case LONG: {
|
||||
parameterValue = value.get(1).asLong();
|
||||
return new JobParameter((Long) parameterValue, identifying);
|
||||
}
|
||||
case DOUBLE: {
|
||||
parameterValue = value.asDouble();
|
||||
return new JobParameter((Double) parameterValue, identifying);
|
||||
}
|
||||
try {
|
||||
Class<?> parameterType = Class.forName(type);
|
||||
Object typedValue = objectMapper.convertValue(value, parameterType);
|
||||
return new JobParameter(typedValue, parameterType, identifying);
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException("Unable to deserialize job parameter " + value.asText(), e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -34,14 +34,16 @@ import org.springframework.batch.core.ExitStatus;
|
||||
import org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.batch.core.JobInstance;
|
||||
import org.springframework.batch.core.JobParameter;
|
||||
import org.springframework.batch.core.JobParameter.ParameterType;
|
||||
import org.springframework.batch.core.JobParameters;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.core.convert.support.ConfigurableConversionService;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.dao.OptimisticLockingFailureException;
|
||||
import org.springframework.jdbc.core.RowCallbackHandler;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -88,11 +90,11 @@ public class JdbcJobExecutionDao extends AbstractJdbcBatchMetadataDao implements
|
||||
|
||||
private static final String CURRENT_VERSION_JOB_EXECUTION = "SELECT VERSION FROM %PREFIX%JOB_EXECUTION WHERE JOB_EXECUTION_ID=?";
|
||||
|
||||
private static final String FIND_PARAMS_FROM_ID = "SELECT JOB_EXECUTION_ID, KEY_NAME, TYPE_CD, "
|
||||
+ "STRING_VAL, DATE_VAL, LONG_VAL, DOUBLE_VAL, IDENTIFYING from %PREFIX%JOB_EXECUTION_PARAMS where JOB_EXECUTION_ID = ?";
|
||||
private static final String FIND_PARAMS_FROM_ID = "SELECT JOB_EXECUTION_ID, NAME, TYPE, "
|
||||
+ "VALUE, IDENTIFYING from %PREFIX%JOB_EXECUTION_PARAMS where JOB_EXECUTION_ID = ?";
|
||||
|
||||
private static final String CREATE_JOB_PARAMETERS = "INSERT into %PREFIX%JOB_EXECUTION_PARAMS(JOB_EXECUTION_ID, KEY_NAME, TYPE_CD, "
|
||||
+ "STRING_VAL, DATE_VAL, LONG_VAL, DOUBLE_VAL, IDENTIFYING) values (?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
private static final String CREATE_JOB_PARAMETERS = "INSERT into %PREFIX%JOB_EXECUTION_PARAMS(JOB_EXECUTION_ID, NAME, TYPE, "
|
||||
+ "VALUE, IDENTIFYING) values (?, ?, ?, ?, ?)";
|
||||
|
||||
private static final String DELETE_JOB_EXECUTION = "DELETE FROM %PREFIX%JOB_EXECUTION WHERE JOB_EXECUTION_ID = ?";
|
||||
|
||||
@@ -102,6 +104,8 @@ public class JdbcJobExecutionDao extends AbstractJdbcBatchMetadataDao implements
|
||||
|
||||
private DataFieldMaxValueIncrementer jobExecutionIncrementer;
|
||||
|
||||
private ConfigurableConversionService conversionService = new DefaultConversionService();
|
||||
|
||||
/**
|
||||
* Public setter for the exit message length in database. Do not set this if you
|
||||
* haven't modified the schema.
|
||||
@@ -120,6 +124,15 @@ public class JdbcJobExecutionDao extends AbstractJdbcBatchMetadataDao implements
|
||||
this.jobExecutionIncrementer = jobExecutionIncrementer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the conversion service to use to convert job parameters from String literal to
|
||||
* typed values and vice versa.
|
||||
*/
|
||||
public void setConversionService(@NonNull ConfigurableConversionService conversionService) {
|
||||
Assert.notNull(conversionService, "conversionService must not be null");
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
super.afterPropertiesSet();
|
||||
@@ -329,7 +342,7 @@ public class JdbcJobExecutionDao extends AbstractJdbcBatchMetadataDao implements
|
||||
*/
|
||||
private void insertJobParameters(Long executionId, JobParameters jobParameters) {
|
||||
|
||||
for (Entry<String, JobParameter> entry : jobParameters.getParameters().entrySet()) {
|
||||
for (Entry<String, JobParameter<?>> entry : jobParameters.getParameters().entrySet()) {
|
||||
JobParameter jobParameter = entry.getValue();
|
||||
insertParameter(executionId, jobParameter.getType(), entry.getKey(), jobParameter.getValue(),
|
||||
jobParameter.isIdentifying());
|
||||
@@ -339,26 +352,15 @@ public class JdbcJobExecutionDao extends AbstractJdbcBatchMetadataDao implements
|
||||
/**
|
||||
* Convenience method that inserts an individual records into the JobParameters table.
|
||||
*/
|
||||
private void insertParameter(Long executionId, ParameterType type, String key, Object value, boolean identifying) {
|
||||
private <T> void insertParameter(Long executionId, Class<T> type, String key, T value, boolean identifying) {
|
||||
|
||||
Object[] args = new Object[0];
|
||||
int[] argTypes = new int[] { Types.BIGINT, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.TIMESTAMP,
|
||||
Types.BIGINT, Types.DOUBLE, Types.CHAR };
|
||||
int[] argTypes = new int[] { Types.BIGINT, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.CHAR };
|
||||
|
||||
String identifyingFlag = identifying ? "Y" : "N";
|
||||
|
||||
if (type == ParameterType.STRING) {
|
||||
args = new Object[] { executionId, key, type, value, null, 0L, 0D, identifyingFlag };
|
||||
}
|
||||
else if (type == ParameterType.LONG) {
|
||||
args = new Object[] { executionId, key, type, "", null, value, 0.0d, identifyingFlag };
|
||||
}
|
||||
else if (type == ParameterType.DOUBLE) {
|
||||
args = new Object[] { executionId, key, type, "", null, 0L, value, identifyingFlag };
|
||||
}
|
||||
else if (type == ParameterType.DATE) {
|
||||
args = new Object[] { executionId, key, type, "", value, 0L, 0D, identifyingFlag };
|
||||
}
|
||||
String stringValue = this.conversionService.convert(value, String.class);
|
||||
args = new Object[] { executionId, key, type.getName(), stringValue, identifyingFlag };
|
||||
|
||||
getJdbcTemplate().update(getQuery(CREATE_JOB_PARAMETERS), args, argTypes);
|
||||
}
|
||||
@@ -368,28 +370,27 @@ public class JdbcJobExecutionDao extends AbstractJdbcBatchMetadataDao implements
|
||||
* @return job parameters for the requested execution id
|
||||
*/
|
||||
protected JobParameters getJobParameters(Long executionId) {
|
||||
final Map<String, JobParameter> map = new HashMap<>();
|
||||
final Map<String, JobParameter<?>> map = new HashMap<>();
|
||||
RowCallbackHandler handler = new RowCallbackHandler() {
|
||||
@Override
|
||||
public void processRow(ResultSet rs) throws SQLException {
|
||||
ParameterType type = ParameterType.valueOf(rs.getString(3));
|
||||
JobParameter value = null;
|
||||
String parameterName = rs.getString("NAME");
|
||||
|
||||
if (type == ParameterType.STRING) {
|
||||
value = new JobParameter(rs.getString(4), rs.getString(8).equalsIgnoreCase("Y"));
|
||||
Class<?> parameterType = null;
|
||||
try {
|
||||
parameterType = Class.forName(rs.getString("TYPE"));
|
||||
}
|
||||
else if (type == ParameterType.LONG) {
|
||||
value = new JobParameter(rs.getLong(6), rs.getString(8).equalsIgnoreCase("Y"));
|
||||
}
|
||||
else if (type == ParameterType.DOUBLE) {
|
||||
value = new JobParameter(rs.getDouble(7), rs.getString(8).equalsIgnoreCase("Y"));
|
||||
}
|
||||
else if (type == ParameterType.DATE) {
|
||||
value = new JobParameter(rs.getTimestamp(5), rs.getString(8).equalsIgnoreCase("Y"));
|
||||
catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
String stringValue = rs.getString("VALUE");
|
||||
Object typedValue = conversionService.convert(stringValue, parameterType);
|
||||
|
||||
// No need to assert that value is not null because it's an enum
|
||||
map.put(rs.getString(2), value);
|
||||
boolean identifying = rs.getString("IDENTIFYING").equalsIgnoreCase("Y");
|
||||
|
||||
JobParameter<?> jobParameter = new JobParameter(typedValue, parameterType, identifying);
|
||||
|
||||
map.put(parameterName, jobParameter);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -41,6 +41,8 @@ import org.springframework.batch.item.database.support.DefaultDataFieldMaxValueI
|
||||
import org.springframework.batch.support.DatabaseType;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.core.convert.support.ConfigurableConversionService;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.jdbc.core.JdbcOperations;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.support.lob.DefaultLobHandler;
|
||||
@@ -86,6 +88,8 @@ public class JobRepositoryFactoryBean extends AbstractJobRepositoryFactoryBean i
|
||||
|
||||
private Charset charset = StandardCharsets.UTF_8;
|
||||
|
||||
private ConfigurableConversionService conversionService;
|
||||
|
||||
/**
|
||||
* @param type a value from the {@link java.sql.Types} class to indicate the type to
|
||||
* use for a CLOB
|
||||
@@ -181,6 +185,17 @@ public class JobRepositoryFactoryBean extends AbstractJobRepositoryFactoryBean i
|
||||
this.charset = charset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the conversion service to use in the job repository. This service is used to
|
||||
* convert job parameters from String literal to typed values and vice versa.
|
||||
* @param conversionService the conversion service to use
|
||||
* @since 5.0
|
||||
*/
|
||||
public void setConversionService(@NonNull ConfigurableConversionService conversionService) {
|
||||
Assert.notNull(conversionService, "ConversionService must not be null");
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
|
||||
@@ -219,6 +234,10 @@ public class JobRepositoryFactoryBean extends AbstractJobRepositoryFactoryBean i
|
||||
Assert.isTrue(isValidTypes(clobType), "lobType must be a value from the java.sql.Types class");
|
||||
}
|
||||
|
||||
if (this.conversionService == null) {
|
||||
this.conversionService = new DefaultConversionService();
|
||||
}
|
||||
|
||||
super.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@@ -241,6 +260,7 @@ public class JobRepositoryFactoryBean extends AbstractJobRepositoryFactoryBean i
|
||||
dao.setTablePrefix(tablePrefix);
|
||||
dao.setClobTypeToUse(determineClobTypeToUse(this.databaseType));
|
||||
dao.setExitMessageLength(maxVarCharLength);
|
||||
dao.setConversionService(this.conversionService);
|
||||
dao.afterPropertiesSet();
|
||||
return dao;
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ public class SimpleJobRepository implements JobRepository {
|
||||
+ "The last execution ended with a failure that could not be rolled back, "
|
||||
+ "so it may be dangerous to proceed. Manual intervention is probably necessary.");
|
||||
}
|
||||
Collection<JobParameter> allJobParameters = execution.getJobParameters().getParameters().values();
|
||||
Collection<JobParameter<?>> allJobParameters = execution.getJobParameters().getParameters().values();
|
||||
long identifyingJobParametersCount = allJobParameters.stream().filter(JobParameter::isIdentifying)
|
||||
.count();
|
||||
if (identifyingJobParametersCount > 0
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2006-2018 the original author or authors.
|
||||
* 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.
|
||||
@@ -94,7 +94,7 @@ public class JobContext extends SynchronizedAttributeAccessor {
|
||||
*/
|
||||
public Map<String, Object> getJobParameters() {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
for (Entry<String, JobParameter> entry : jobExecution.getJobParameters().getParameters().entrySet()) {
|
||||
for (Entry<String, JobParameter<?>> entry : jobExecution.getJobParameters().getParameters().entrySet()) {
|
||||
result.put(entry.getKey(), entry.getValue().getValue());
|
||||
}
|
||||
return Collections.unmodifiableMap(result);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2006-2021 the original author or authors.
|
||||
* 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.
|
||||
@@ -134,7 +134,7 @@ public class StepContext extends SynchronizedAttributeAccessor {
|
||||
*/
|
||||
public Map<String, Object> getJobParameters() {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
for (Entry<String, JobParameter> entry : stepExecution.getJobParameters().getParameters().entrySet()) {
|
||||
for (Entry<String, JobParameter<?>> entry : stepExecution.getJobParameters().getParameters().entrySet()) {
|
||||
result.put(entry.getKey(), entry.getValue().getValue());
|
||||
}
|
||||
return Collections.unmodifiableMap(result);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2006-2013 the original author or authors.
|
||||
* 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.
|
||||
@@ -19,6 +19,7 @@ import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.batch.core.Job;
|
||||
@@ -26,7 +27,11 @@ import org.springframework.batch.core.JobParameter;
|
||||
import org.springframework.batch.core.JobParameters;
|
||||
import org.springframework.batch.core.JobParametersBuilder;
|
||||
import org.springframework.batch.core.StepExecution;
|
||||
import org.springframework.batch.core.converter.DefaultJobParametersConverter;
|
||||
import org.springframework.batch.core.converter.JobParametersConverter;
|
||||
import org.springframework.batch.item.ExecutionContext;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Simple implementation of {@link JobParametersExtractor} which pulls parameters with
|
||||
@@ -35,6 +40,7 @@ import org.springframework.batch.item.ExecutionContext;
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Will Schipp
|
||||
* @author Mahmoud Ben Hassine
|
||||
*
|
||||
*/
|
||||
public class DefaultJobParametersExtractor implements JobParametersExtractor {
|
||||
@@ -43,16 +49,13 @@ public class DefaultJobParametersExtractor implements JobParametersExtractor {
|
||||
|
||||
private boolean useAllParentParameters = true;
|
||||
|
||||
private JobParametersConverter jobParametersConverter = new DefaultJobParametersConverter();
|
||||
|
||||
/**
|
||||
* The key names to pull out of the execution context or job parameters, if they
|
||||
* exist. If a key doesn't exist in the execution context then the job parameters from
|
||||
* the enclosing job execution are tried, and if there is nothing there either then no
|
||||
* parameter is extracted. Key names ending with <code>(long)</code>,
|
||||
* <code>(int)</code>, <code>(double)</code>, <code>(date)</code> or
|
||||
* <code>(string)</code> will be assumed to refer to values of the respective type and
|
||||
* assigned to job parameters accordingly (there will be an error if they are not of
|
||||
* the right type). Without a special suffix in that form a parameter is assumed to be
|
||||
* of type String.
|
||||
* parameter is extracted.
|
||||
* @param keys the keys to set
|
||||
*/
|
||||
public void setKeys(String[] keys) {
|
||||
@@ -65,68 +68,20 @@ public class DefaultJobParametersExtractor implements JobParametersExtractor {
|
||||
@Override
|
||||
public JobParameters getJobParameters(Job job, StepExecution stepExecution) {
|
||||
JobParametersBuilder builder = new JobParametersBuilder();
|
||||
Map<String, JobParameter> jobParameters = stepExecution.getJobParameters().getParameters();
|
||||
Map<String, JobParameter<?>> jobParameters = stepExecution.getJobParameters().getParameters();
|
||||
ExecutionContext executionContext = stepExecution.getExecutionContext();
|
||||
if (useAllParentParameters) {
|
||||
for (String key : jobParameters.keySet()) {
|
||||
builder.addParameter(key, jobParameters.get(key));
|
||||
}
|
||||
}
|
||||
Properties properties = new Properties();
|
||||
for (String key : keys) {
|
||||
if (key.endsWith("(long)")) {
|
||||
key = key.replace("(long)", "");
|
||||
if (executionContext.containsKey(key)) {
|
||||
builder.addLong(key, executionContext.getLong(key));
|
||||
}
|
||||
else if (jobParameters.containsKey(key)) {
|
||||
builder.addLong(key, (Long) jobParameters.get(key).getValue());
|
||||
}
|
||||
}
|
||||
else if (key.endsWith("(int)")) {
|
||||
key = key.replace("(int)", "");
|
||||
if (executionContext.containsKey(key)) {
|
||||
builder.addLong(key, (long) executionContext.getInt(key));
|
||||
}
|
||||
else if (jobParameters.containsKey(key)) {
|
||||
builder.addLong(key, (Long) jobParameters.get(key).getValue());
|
||||
}
|
||||
}
|
||||
else if (key.endsWith("(double)")) {
|
||||
key = key.replace("(double)", "");
|
||||
if (executionContext.containsKey(key)) {
|
||||
builder.addDouble(key, executionContext.getDouble(key));
|
||||
}
|
||||
else if (jobParameters.containsKey(key)) {
|
||||
builder.addDouble(key, (Double) jobParameters.get(key).getValue());
|
||||
}
|
||||
}
|
||||
else if (key.endsWith("(string)")) {
|
||||
key = key.replace("(string)", "");
|
||||
if (executionContext.containsKey(key)) {
|
||||
builder.addString(key, executionContext.getString(key));
|
||||
}
|
||||
else if (jobParameters.containsKey(key)) {
|
||||
builder.addString(key, (String) jobParameters.get(key).getValue());
|
||||
}
|
||||
}
|
||||
else if (key.endsWith("(date)")) {
|
||||
key = key.replace("(date)", "");
|
||||
if (executionContext.containsKey(key)) {
|
||||
builder.addDate(key, (Date) executionContext.get(key));
|
||||
}
|
||||
else if (jobParameters.containsKey(key)) {
|
||||
builder.addDate(key, (Date) jobParameters.get(key).getValue());
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (executionContext.containsKey(key)) {
|
||||
builder.addString(key, executionContext.get(key).toString());
|
||||
}
|
||||
else if (jobParameters.containsKey(key)) {
|
||||
builder.addString(key, jobParameters.get(key).getValue().toString());
|
||||
}
|
||||
if (executionContext.containsKey(key)) {
|
||||
properties.setProperty(key, executionContext.getString(key));
|
||||
}
|
||||
}
|
||||
builder.addJobParameters(this.jobParametersConverter.getJobParameters(properties));
|
||||
return builder.toJobParameters();
|
||||
}
|
||||
|
||||
@@ -139,4 +94,13 @@ public class DefaultJobParametersExtractor implements JobParametersExtractor {
|
||||
this.useAllParentParameters = useAllParentParameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link JobParametersConverter} to use.
|
||||
* @param jobParametersConverter the converter to use. Must not be {@code null}.
|
||||
*/
|
||||
public void setJobParametersConverter(@NonNull JobParametersConverter jobParametersConverter) {
|
||||
Assert.notNull(jobParametersConverter, "jobParametersConverter must not be null");
|
||||
this.jobParametersConverter = jobParametersConverter;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,2 +1,10 @@
|
||||
ALTER TABLE BATCH_STEP_EXECUTION ADD CREATE_TIME TIMESTAMP NOT NULL DEFAULT '1970-01-01 00:00:00';
|
||||
ALTER TABLE BATCH_STEP_EXECUTION ALTER COLUMN START_TIME DROP NOT NULL;
|
||||
ALTER TABLE BATCH_STEP_EXECUTION ALTER COLUMN START_TIME DROP NOT NULL;
|
||||
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN DATE_VAL;
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN LONG_VAL;
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN DOUBLE_VAL;
|
||||
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS MODIFY COLUMN TYPE_CD TYPE VARCHAR(100);
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS MODIFY COLUMN KEY_NAME NAME VARCHAR(100);
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS MODIFY COLUMN STRING_VAL VALUE VARCHAR(2500);
|
||||
@@ -1,2 +1,10 @@
|
||||
ALTER TABLE BATCH_STEP_EXECUTION ADD CREATE_TIME TIMESTAMP NOT NULL DEFAULT '1970-01-01 00:00:00';
|
||||
ALTER TABLE BATCH_STEP_EXECUTION ALTER COLUMN START_TIME DROP NOT NULL;
|
||||
ALTER TABLE BATCH_STEP_EXECUTION ALTER COLUMN START_TIME DROP NOT NULL;
|
||||
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN DATE_VAL;
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN LONG_VAL;
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN DOUBLE_VAL;
|
||||
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS MODIFY COLUMN TYPE_CD TYPE VARCHAR(100);
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS MODIFY COLUMN KEY_NAME NAME VARCHAR(100);
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS MODIFY COLUMN STRING_VAL VALUE VARCHAR(2500);
|
||||
@@ -1,2 +1,10 @@
|
||||
ALTER TABLE BATCH_STEP_EXECUTION ADD CREATE_TIME TIMESTAMP NOT NULL DEFAULT '1970-01-01 00:00:00';
|
||||
ALTER TABLE BATCH_STEP_EXECUTION ALTER COLUMN START_TIME DROP NOT NULL;
|
||||
ALTER TABLE BATCH_STEP_EXECUTION ALTER COLUMN START_TIME DROP NOT NULL;
|
||||
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN DATE_VAL;
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN LONG_VAL;
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN DOUBLE_VAL;
|
||||
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS MODIFY COLUMN TYPE_CD TYPE VARCHAR(100);
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS MODIFY COLUMN KEY_NAME NAME VARCHAR(100);
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS MODIFY COLUMN STRING_VAL VALUE VARCHAR(2500);
|
||||
@@ -1,2 +1,10 @@
|
||||
ALTER TABLE BATCH_STEP_EXECUTION ADD CREATE_TIME TIMESTAMP DEFAULT '1970-01-01 00:00:00' NOT NULL;
|
||||
ALTER TABLE BATCH_STEP_EXECUTION ALTER COLUMN START_TIME DROP NOT NULL;
|
||||
ALTER TABLE BATCH_STEP_EXECUTION ALTER COLUMN START_TIME DROP NOT NULL;
|
||||
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN DATE_VAL;
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN LONG_VAL;
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN DOUBLE_VAL;
|
||||
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS MODIFY COLUMN TYPE_CD TYPE VARCHAR(100);
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS MODIFY COLUMN KEY_NAME NAME VARCHAR(100);
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS MODIFY COLUMN STRING_VAL VALUE VARCHAR(2500);
|
||||
@@ -1,2 +1,10 @@
|
||||
ALTER TABLE BATCH_STEP_EXECUTION ADD CREATE_TIME DATETIME(6) NOT NULL DEFAULT '1970-01-01 00:00:00';
|
||||
ALTER TABLE BATCH_STEP_EXECUTION MODIFY START_TIME DATETIME(6) NULL;
|
||||
ALTER TABLE BATCH_STEP_EXECUTION MODIFY START_TIME DATETIME(6) NULL;
|
||||
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN DATE_VAL;
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN LONG_VAL;
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN DOUBLE_VAL;
|
||||
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS CHANGE COLUMN TYPE_CD TYPE VARCHAR(100);
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS CHANGE COLUMN KEY_NAME NAME VARCHAR(100);
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS CHANGE COLUMN STRING_VAL VALUE VARCHAR(2500);
|
||||
@@ -3,4 +3,12 @@ ALTER SEQUENCE BATCH_JOB_EXECUTION_SEQ ORDER;
|
||||
ALTER SEQUENCE BATCH_JOB_SEQ ORDER;
|
||||
|
||||
ALTER TABLE BATCH_STEP_EXECUTION ADD CREATE_TIME TIMESTAMP DEFAULT TO_TIMESTAMP('1970-01-01 00:00:00', 'yyyy-MM-dd HH24:mi:ss') NOT NULL;
|
||||
ALTER TABLE BATCH_STEP_EXECUTION MODIFY START_TIME TIMESTAMP NULL;
|
||||
ALTER TABLE BATCH_STEP_EXECUTION MODIFY START_TIME TIMESTAMP NULL;
|
||||
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN DATE_VAL;
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN LONG_VAL;
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN DOUBLE_VAL;
|
||||
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS MODIFY COLUMN TYPE_CD TYPE VARCHAR(100);
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS MODIFY COLUMN KEY_NAME NAME VARCHAR(100);
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS MODIFY COLUMN STRING_VAL VALUE VARCHAR(2500);
|
||||
@@ -1,2 +1,10 @@
|
||||
ALTER TABLE BATCH_STEP_EXECUTION ADD CREATE_TIME TIMESTAMP NOT NULL DEFAULT '1970-01-01 00:00:00';
|
||||
ALTER TABLE BATCH_STEP_EXECUTION ALTER COLUMN START_TIME DROP NOT NULL;
|
||||
ALTER TABLE BATCH_STEP_EXECUTION ALTER COLUMN START_TIME DROP NOT NULL;
|
||||
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN DATE_VAL;
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN LONG_VAL;
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN DOUBLE_VAL;
|
||||
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS MODIFY COLUMN TYPE_CD TYPE VARCHAR(100);
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS MODIFY COLUMN KEY_NAME NAME VARCHAR(100);
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS MODIFY COLUMN STRING_VAL VALUE VARCHAR(2500);
|
||||
@@ -1,4 +1,12 @@
|
||||
ALTER TABLE BATCH_STEP_EXECUTION ADD CREATE_TIME TIMESTAMP NOT NULL DEFAULT '1970-01-01 00:00:00';
|
||||
-- ALTER TABLE BATCH_STEP_EXECUTION ALTER COLUMN START_TIME DROP NOT NULL;
|
||||
-- ALTER COLUMN is not supported in SQLITE: https://www.sqlite.org/lang_altertable.html
|
||||
-- There are several ways to drop the 'NOT NULL' constraint on START_TIME, this is left to the user.
|
||||
-- There are several ways to drop the 'NOT NULL' constraint on START_TIME, this is left to the user.
|
||||
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN DATE_VAL;
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN LONG_VAL;
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN DOUBLE_VAL;
|
||||
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS MODIFY COLUMN TYPE_CD TYPE VARCHAR(100);
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS MODIFY COLUMN KEY_NAME NAME VARCHAR(100);
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS MODIFY COLUMN STRING_VAL VALUE VARCHAR(2500);
|
||||
@@ -2,4 +2,12 @@ ALTER TABLE BATCH_STEP_EXECUTION_CONTEXT ALTER COLUMN SERIALIZED_CONTEXT VARCHAR
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_CONTEXT ALTER COLUMN SERIALIZED_CONTEXT VARCHAR(MAX) NULL;
|
||||
|
||||
ALTER TABLE BATCH_STEP_EXECUTION ADD CREATE_TIME DATETIME NOT NULL DEFAULT '1970-01-01 00:00:00';
|
||||
ALTER TABLE BATCH_STEP_EXECUTION ALTER COLUMN START_TIME DATETIME NULL;
|
||||
ALTER TABLE BATCH_STEP_EXECUTION ALTER COLUMN START_TIME DATETIME NULL;
|
||||
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN DATE_VAL;
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN LONG_VAL;
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN DOUBLE_VAL;
|
||||
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS MODIFY COLUMN TYPE_CD TYPE VARCHAR(100);
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS MODIFY COLUMN KEY_NAME NAME VARCHAR(100);
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS MODIFY COLUMN STRING_VAL VALUE VARCHAR(2500);
|
||||
@@ -1,2 +1,10 @@
|
||||
ALTER TABLE BATCH_STEP_EXECUTION ADD CREATE_TIME DATETIME DEFAULT '1970-01-01 00:00:00' NOT NULL;
|
||||
ALTER TABLE BATCH_STEP_EXECUTION MODIFY START_TIME DATETIME NULL;
|
||||
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN DATE_VAL;
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN LONG_VAL;
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN DOUBLE_VAL;
|
||||
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS MODIFY COLUMN TYPE_CD TYPE VARCHAR(100);
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS MODIFY COLUMN KEY_NAME NAME VARCHAR(100);
|
||||
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS MODIFY COLUMN STRING_VAL VALUE VARCHAR(2500);
|
||||
|
||||
@@ -25,12 +25,9 @@ CREATE TABLE BATCH_JOB_EXECUTION (
|
||||
|
||||
CREATE TABLE BATCH_JOB_EXECUTION_PARAMS (
|
||||
JOB_EXECUTION_ID BIGINT NOT NULL ,
|
||||
TYPE_CD VARCHAR(6) NOT NULL ,
|
||||
KEY_NAME VARCHAR(100) NOT NULL ,
|
||||
STRING_VAL VARCHAR(250) ,
|
||||
DATE_VAL TIMESTAMP DEFAULT NULL ,
|
||||
LONG_VAL BIGINT ,
|
||||
DOUBLE_VAL DOUBLE PRECISION ,
|
||||
NAME VARCHAR(100) NOT NULL ,
|
||||
TYPE VARCHAR(100) NOT NULL ,
|
||||
VALUE VARCHAR(2500) ,
|
||||
IDENTIFYING CHAR(1) NOT NULL ,
|
||||
constraint JOB_EXEC_PARAMS_FK foreign key (JOB_EXECUTION_ID)
|
||||
references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
|
||||
|
||||
@@ -25,12 +25,9 @@ CREATE TABLE BATCH_JOB_EXECUTION (
|
||||
|
||||
CREATE TABLE BATCH_JOB_EXECUTION_PARAMS (
|
||||
JOB_EXECUTION_ID BIGINT NOT NULL ,
|
||||
TYPE_CD VARCHAR(6) NOT NULL ,
|
||||
KEY_NAME VARCHAR(100) NOT NULL ,
|
||||
STRING_VAL VARCHAR(250) ,
|
||||
DATE_VAL TIMESTAMP DEFAULT NULL ,
|
||||
LONG_VAL BIGINT ,
|
||||
DOUBLE_VAL DOUBLE PRECISION ,
|
||||
NAME VARCHAR(100) NOT NULL ,
|
||||
TYPE VARCHAR(100) NOT NULL ,
|
||||
VALUE VARCHAR(2500) ,
|
||||
IDENTIFYING CHAR(1) NOT NULL ,
|
||||
constraint JOB_EXEC_PARAMS_FK foreign key (JOB_EXECUTION_ID)
|
||||
references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
|
||||
|
||||
@@ -25,12 +25,9 @@ CREATE TABLE BATCH_JOB_EXECUTION (
|
||||
|
||||
CREATE TABLE BATCH_JOB_EXECUTION_PARAMS (
|
||||
JOB_EXECUTION_ID BIGINT NOT NULL ,
|
||||
TYPE_CD VARCHAR(6) NOT NULL ,
|
||||
KEY_NAME VARCHAR(100) NOT NULL ,
|
||||
STRING_VAL VARCHAR(250) ,
|
||||
DATE_VAL TIMESTAMP DEFAULT NULL ,
|
||||
LONG_VAL BIGINT ,
|
||||
DOUBLE_VAL DOUBLE PRECISION ,
|
||||
NAME VARCHAR(100) NOT NULL ,
|
||||
TYPE VARCHAR(100) NOT NULL ,
|
||||
VALUE VARCHAR(2500) ,
|
||||
IDENTIFYING CHAR(1) NOT NULL ,
|
||||
constraint JOB_EXEC_PARAMS_FK foreign key (JOB_EXECUTION_ID)
|
||||
references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
|
||||
|
||||
@@ -25,12 +25,9 @@ CREATE TABLE BATCH_JOB_EXECUTION (
|
||||
|
||||
CREATE TABLE BATCH_JOB_EXECUTION_PARAMS (
|
||||
JOB_EXECUTION_ID BIGINT NOT NULL ,
|
||||
TYPE_CD VARCHAR(6) NOT NULL ,
|
||||
KEY_NAME VARCHAR(100) NOT NULL ,
|
||||
STRING_VAL VARCHAR(250) ,
|
||||
DATE_VAL TIMESTAMP DEFAULT NULL ,
|
||||
LONG_VAL BIGINT ,
|
||||
DOUBLE_VAL DOUBLE ,
|
||||
NAME VARCHAR(100) NOT NULL ,
|
||||
TYPE VARCHAR(100) NOT NULL ,
|
||||
VALUE VARCHAR(2500) ,
|
||||
IDENTIFYING VARCHAR(1) NOT NULL ,
|
||||
constraint JOB_EXEC_PARAMS_FK foreign key (JOB_EXECUTION_ID)
|
||||
references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
|
||||
|
||||
@@ -25,12 +25,9 @@ CREATE TABLE BATCH_JOB_EXECUTION (
|
||||
|
||||
CREATE TABLE BATCH_JOB_EXECUTION_PARAMS (
|
||||
JOB_EXECUTION_ID BIGINT NOT NULL ,
|
||||
TYPE_CD VARCHAR(6) NOT NULL ,
|
||||
KEY_NAME VARCHAR(100) NOT NULL ,
|
||||
STRING_VAL VARCHAR(250) ,
|
||||
DATE_VAL TIMESTAMP DEFAULT NULL ,
|
||||
LONG_VAL BIGINT ,
|
||||
DOUBLE_VAL DOUBLE PRECISION ,
|
||||
NAME VARCHAR(100) NOT NULL ,
|
||||
TYPE VARCHAR(100) NOT NULL ,
|
||||
VALUE VARCHAR(2500) ,
|
||||
IDENTIFYING CHAR(1) NOT NULL ,
|
||||
constraint JOB_EXEC_PARAMS_FK foreign key (JOB_EXECUTION_ID)
|
||||
references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
|
||||
|
||||
@@ -25,12 +25,9 @@ CREATE TABLE BATCH_JOB_EXECUTION (
|
||||
|
||||
CREATE TABLE BATCH_JOB_EXECUTION_PARAMS (
|
||||
JOB_EXECUTION_ID BIGINT NOT NULL ,
|
||||
TYPE_CD VARCHAR(6) NOT NULL ,
|
||||
KEY_NAME VARCHAR(100) NOT NULL ,
|
||||
STRING_VAL VARCHAR(250) ,
|
||||
DATE_VAL DATETIME(6) DEFAULT NULL ,
|
||||
LONG_VAL BIGINT ,
|
||||
DOUBLE_VAL DOUBLE PRECISION ,
|
||||
NAME VARCHAR(100) NOT NULL ,
|
||||
TYPE VARCHAR(100) NOT NULL ,
|
||||
VALUE VARCHAR(2500) ,
|
||||
IDENTIFYING CHAR(1) NOT NULL ,
|
||||
constraint JOB_EXEC_PARAMS_FK foreign key (JOB_EXECUTION_ID)
|
||||
references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
|
||||
|
||||
@@ -25,12 +25,9 @@ CREATE TABLE BATCH_JOB_EXECUTION (
|
||||
|
||||
CREATE TABLE BATCH_JOB_EXECUTION_PARAMS (
|
||||
JOB_EXECUTION_ID NUMBER(19,0) NOT NULL ,
|
||||
TYPE_CD VARCHAR2(6 char) NOT NULL ,
|
||||
KEY_NAME VARCHAR2(100 char) NOT NULL ,
|
||||
STRING_VAL VARCHAR2(250 char) ,
|
||||
DATE_VAL TIMESTAMP DEFAULT NULL ,
|
||||
LONG_VAL NUMBER(19,0) ,
|
||||
DOUBLE_VAL NUMBER ,
|
||||
NAME VARCHAR(100 char) NOT NULL ,
|
||||
TYPE VARCHAR(100 char) NOT NULL ,
|
||||
VALUE VARCHAR(2500 char) ,
|
||||
IDENTIFYING CHAR(1) NOT NULL ,
|
||||
constraint JOB_EXEC_PARAMS_FK foreign key (JOB_EXECUTION_ID)
|
||||
references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
|
||||
|
||||
@@ -25,12 +25,9 @@ CREATE TABLE BATCH_JOB_EXECUTION (
|
||||
|
||||
CREATE TABLE BATCH_JOB_EXECUTION_PARAMS (
|
||||
JOB_EXECUTION_ID BIGINT NOT NULL ,
|
||||
TYPE_CD VARCHAR(6) NOT NULL ,
|
||||
KEY_NAME VARCHAR(100) NOT NULL ,
|
||||
STRING_VAL VARCHAR(250) ,
|
||||
DATE_VAL TIMESTAMP DEFAULT NULL ,
|
||||
LONG_VAL BIGINT ,
|
||||
DOUBLE_VAL DOUBLE PRECISION ,
|
||||
NAME VARCHAR(100) NOT NULL ,
|
||||
TYPE VARCHAR(100) NOT NULL ,
|
||||
VALUE VARCHAR(2500) ,
|
||||
IDENTIFYING CHAR(1) NOT NULL ,
|
||||
constraint JOB_EXEC_PARAMS_FK foreign key (JOB_EXECUTION_ID)
|
||||
references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
|
||||
|
||||
@@ -25,12 +25,9 @@ CREATE TABLE BATCH_JOB_EXECUTION (
|
||||
|
||||
CREATE TABLE BATCH_JOB_EXECUTION_PARAMS (
|
||||
JOB_EXECUTION_ID INTEGER NOT NULL ,
|
||||
TYPE_CD VARCHAR(6) NOT NULL ,
|
||||
KEY_NAME VARCHAR(100) NOT NULL ,
|
||||
STRING_VAL VARCHAR(250) ,
|
||||
DATE_VAL TIMESTAMP DEFAULT NULL ,
|
||||
LONG_VAL INTEGER ,
|
||||
DOUBLE_VAL DOUBLE PRECISION ,
|
||||
NAME VARCHAR(100) NOT NULL ,
|
||||
TYPE VARCHAR(100) NOT NULL ,
|
||||
VALUE VARCHAR(2500) ,
|
||||
IDENTIFYING CHAR(1) NOT NULL ,
|
||||
constraint JOB_EXEC_PARAMS_FK foreign key (JOB_EXECUTION_ID)
|
||||
references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
|
||||
|
||||
@@ -25,12 +25,9 @@ CREATE TABLE BATCH_JOB_EXECUTION (
|
||||
|
||||
CREATE TABLE BATCH_JOB_EXECUTION_PARAMS (
|
||||
JOB_EXECUTION_ID BIGINT NOT NULL ,
|
||||
TYPE_CD VARCHAR(6) NOT NULL ,
|
||||
KEY_NAME VARCHAR(100) NOT NULL ,
|
||||
STRING_VAL VARCHAR(250) NULL,
|
||||
DATE_VAL DATETIME DEFAULT NULL ,
|
||||
LONG_VAL BIGINT NULL,
|
||||
DOUBLE_VAL DOUBLE PRECISION NULL,
|
||||
NAME VARCHAR(100) NOT NULL ,
|
||||
TYPE VARCHAR(100) NOT NULL ,
|
||||
VALUE VARCHAR(2500) ,
|
||||
IDENTIFYING CHAR(1) NOT NULL ,
|
||||
constraint JOB_EXEC_PARAMS_FK foreign key (JOB_EXECUTION_ID)
|
||||
references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
|
||||
|
||||
@@ -25,12 +25,9 @@ CREATE TABLE BATCH_JOB_EXECUTION (
|
||||
|
||||
CREATE TABLE BATCH_JOB_EXECUTION_PARAMS (
|
||||
JOB_EXECUTION_ID BIGINT NOT NULL ,
|
||||
TYPE_CD VARCHAR(6) NOT NULL ,
|
||||
KEY_NAME VARCHAR(100) NOT NULL ,
|
||||
STRING_VAL VARCHAR(250) NULL,
|
||||
DATE_VAL DATETIME DEFAULT NULL NULL,
|
||||
LONG_VAL BIGINT NULL,
|
||||
DOUBLE_VAL DOUBLE PRECISION NULL,
|
||||
NAME VARCHAR(100) NOT NULL ,
|
||||
TYPE VARCHAR(100) NOT NULL ,
|
||||
VALUE VARCHAR(2500) ,
|
||||
IDENTIFYING CHAR(1) NOT NULL ,
|
||||
constraint JOB_EXEC_PARAMS_FK foreign key (JOB_EXECUTION_ID)
|
||||
references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
|
||||
|
||||
@@ -17,6 +17,7 @@ package org.springframework.batch.core;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@@ -24,6 +25,7 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* @author Lucas Ward
|
||||
* @author Mahmoud Ben Hassine
|
||||
*
|
||||
*/
|
||||
class JobParameterTests {
|
||||
@@ -32,57 +34,58 @@ class JobParameterTests {
|
||||
|
||||
@Test
|
||||
void testStringParameter() {
|
||||
jobParameter = new JobParameter("test", true);
|
||||
jobParameter = new JobParameter("test", String.class, true);
|
||||
assertEquals("test", jobParameter.getValue());
|
||||
assertEquals(String.class, jobParameter.getType());
|
||||
assertTrue(jobParameter.isIdentifying());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNullStringParameter() {
|
||||
assertThrows(IllegalArgumentException.class, () -> new JobParameter((String) null, true));
|
||||
assertThrows(IllegalArgumentException.class, () -> new JobParameter((String) null, String.class, true));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLongParameter() {
|
||||
jobParameter = new JobParameter(1L, true);
|
||||
jobParameter = new JobParameter(1L, Long.class, true);
|
||||
assertEquals(1L, jobParameter.getValue());
|
||||
assertEquals(Long.class, jobParameter.getType());
|
||||
assertTrue(jobParameter.isIdentifying());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDoubleParameter() {
|
||||
jobParameter = new JobParameter(1.1, true);
|
||||
jobParameter = new JobParameter(1.1, Double.class, true);
|
||||
assertEquals(1.1, jobParameter.getValue());
|
||||
assertEquals(Double.class, jobParameter.getType());
|
||||
assertTrue(jobParameter.isIdentifying());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDateParameter() {
|
||||
Date epoch = new Date(0L);
|
||||
jobParameter = new JobParameter(epoch, true);
|
||||
jobParameter = new JobParameter(epoch, Date.class, true);
|
||||
assertEquals(new Date(0L), jobParameter.getValue());
|
||||
assertEquals(Date.class, jobParameter.getType());
|
||||
assertTrue(jobParameter.isIdentifying());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNullDateParameter() {
|
||||
assertThrows(IllegalArgumentException.class, () -> new JobParameter((Date) null, true));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDateParameterToString() {
|
||||
Date epoch = new Date(0L);
|
||||
jobParameter = new JobParameter(epoch, true);
|
||||
assertEquals("0", jobParameter.toString());
|
||||
assertThrows(IllegalArgumentException.class, () -> new JobParameter((Date) null, Date.class, true));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEquals() {
|
||||
jobParameter = new JobParameter("test", true);
|
||||
JobParameter testParameter = new JobParameter("test", true);
|
||||
jobParameter = new JobParameter("test", String.class, true);
|
||||
JobParameter testParameter = new JobParameter("test", String.class, true);
|
||||
assertEquals(jobParameter, testParameter);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHashcode() {
|
||||
jobParameter = new JobParameter("test", true);
|
||||
JobParameter testParameter = new JobParameter("test", true);
|
||||
jobParameter = new JobParameter("test", String.class, true);
|
||||
JobParameter testParameter = new JobParameter("test", String.class, true);
|
||||
assertEquals(testParameter.hashCode(), jobParameter.hashCode());
|
||||
}
|
||||
|
||||
|
||||
@@ -144,29 +144,13 @@ class JobParametersBuilderTests {
|
||||
|
||||
@Test
|
||||
void testAddJobParameter() {
|
||||
JobParameter jobParameter = new JobParameter("bar");
|
||||
JobParameter jobParameter = new JobParameter("bar", String.class);
|
||||
this.parametersBuilder.addParameter("foo", jobParameter);
|
||||
Map<String, JobParameter> parameters = this.parametersBuilder.toJobParameters().getParameters();
|
||||
Map<String, JobParameter<?>> parameters = this.parametersBuilder.toJobParameters().getParameters();
|
||||
assertEquals(1, parameters.size());
|
||||
assertEquals("bar", parameters.get("foo").getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testProperties() {
|
||||
Properties props = new Properties();
|
||||
props.setProperty("SCHEDULE_DATE", "A DATE");
|
||||
props.setProperty("LONG", "1");
|
||||
props.setProperty("STRING", "string value");
|
||||
this.parametersBuilder = new JobParametersBuilder(props);
|
||||
JobParameters parameters = this.parametersBuilder.toJobParameters();
|
||||
assertEquals("A DATE", parameters.getString("SCHEDULE_DATE"));
|
||||
assertEquals("1", parameters.getString("LONG"));
|
||||
assertEquals("string value", parameters.getString("STRING"));
|
||||
assertFalse(parameters.getParameters().get("SCHEDULE_DATE").isIdentifying());
|
||||
assertFalse(parameters.getParameters().get("LONG").isIdentifying());
|
||||
assertFalse(parameters.getParameters().get("STRING").isIdentifying());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetNextJobParametersFirstRun() {
|
||||
job.setJobParametersIncrementer(new RunIdIncrementer());
|
||||
@@ -234,7 +218,7 @@ class JobParametersBuilderTests {
|
||||
|
||||
private void defaultNextJobParametersVerify(JobParameters parameters, int paramCount) {
|
||||
baseJobParametersVerify(parameters, paramCount);
|
||||
assertEquals("1", parameters.getString("run.id"));
|
||||
assertEquals(1, parameters.getLong("run.id"));
|
||||
}
|
||||
|
||||
private void baseJobParametersVerify(JobParameters parameters, int paramCount) {
|
||||
|
||||
@@ -52,15 +52,15 @@ class JobParametersTests {
|
||||
|
||||
private JobParameters getNewParameters() {
|
||||
|
||||
Map<String, JobParameter> parameterMap = new HashMap<>();
|
||||
parameterMap.put("string.key1", new JobParameter("value1", true));
|
||||
parameterMap.put("string.key2", new JobParameter("value2", true));
|
||||
parameterMap.put("long.key1", new JobParameter(1L, true));
|
||||
parameterMap.put("long.key2", new JobParameter(2L, true));
|
||||
parameterMap.put("double.key1", new JobParameter(1.1, true));
|
||||
parameterMap.put("double.key2", new JobParameter(2.2, true));
|
||||
parameterMap.put("date.key1", new JobParameter(date1, true));
|
||||
parameterMap.put("date.key2", new JobParameter(date2, true));
|
||||
Map<String, JobParameter<?>> parameterMap = new HashMap<>();
|
||||
parameterMap.put("string.key1", new JobParameter("value1", String.class, true));
|
||||
parameterMap.put("string.key2", new JobParameter("value2", String.class, true));
|
||||
parameterMap.put("long.key1", new JobParameter(1L, Long.class, true));
|
||||
parameterMap.put("long.key2", new JobParameter(2L, Long.class, true));
|
||||
parameterMap.put("double.key1", new JobParameter(1.1, Double.class, true));
|
||||
parameterMap.put("double.key2", new JobParameter(2.2, Double.class, true));
|
||||
parameterMap.put("date.key1", new JobParameter(date1, Date.class, true));
|
||||
parameterMap.put("date.key2", new JobParameter(date2, Date.class, true));
|
||||
|
||||
return new JobParameters(parameterMap);
|
||||
}
|
||||
@@ -138,29 +138,29 @@ class JobParametersTests {
|
||||
@Test
|
||||
void testToStringOrder() {
|
||||
|
||||
Map<String, JobParameter> props = parameters.getParameters();
|
||||
Map<String, JobParameter<?>> props = parameters.getParameters();
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
for (Entry<String, JobParameter> entry : props.entrySet()) {
|
||||
for (Entry<String, JobParameter<?>> entry : props.entrySet()) {
|
||||
stringBuilder.append(entry.toString()).append(";");
|
||||
}
|
||||
|
||||
String string1 = stringBuilder.toString();
|
||||
|
||||
Map<String, JobParameter> parameterMap = new HashMap<>();
|
||||
parameterMap.put("string.key2", new JobParameter("value2", true));
|
||||
parameterMap.put("string.key1", new JobParameter("value1", true));
|
||||
parameterMap.put("long.key2", new JobParameter(2L, true));
|
||||
parameterMap.put("long.key1", new JobParameter(1L, true));
|
||||
parameterMap.put("double.key2", new JobParameter(2.2, true));
|
||||
parameterMap.put("double.key1", new JobParameter(1.1, true));
|
||||
parameterMap.put("date.key2", new JobParameter(date2, true));
|
||||
parameterMap.put("date.key1", new JobParameter(date1, true));
|
||||
Map<String, JobParameter<?>> parameterMap = new HashMap<>();
|
||||
parameterMap.put("string.key2", new JobParameter("value2", String.class, true));
|
||||
parameterMap.put("string.key1", new JobParameter("value1", String.class, true));
|
||||
parameterMap.put("long.key2", new JobParameter(2L, Long.class, true));
|
||||
parameterMap.put("long.key1", new JobParameter(1L, Long.class, true));
|
||||
parameterMap.put("double.key2", new JobParameter(2.2, Double.class, true));
|
||||
parameterMap.put("double.key1", new JobParameter(1.1, Double.class, true));
|
||||
parameterMap.put("date.key2", new JobParameter(date2, Date.class, true));
|
||||
parameterMap.put("date.key1", new JobParameter(date1, Date.class, true));
|
||||
|
||||
JobParameters testProps = new JobParameters(parameterMap);
|
||||
|
||||
props = testProps.getParameters();
|
||||
stringBuilder = new StringBuilder();
|
||||
for (Entry<String, JobParameter> entry : props.entrySet()) {
|
||||
for (Entry<String, JobParameter<?>> entry : props.entrySet()) {
|
||||
stringBuilder.append(entry.toString()).append(";");
|
||||
}
|
||||
String string2 = stringBuilder.toString();
|
||||
|
||||
@@ -15,14 +15,10 @@
|
||||
*/
|
||||
package org.springframework.batch.core.configuration.xml;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.batch.core.Job;
|
||||
import org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.batch.core.JobParametersBuilder;
|
||||
@@ -32,6 +28,9 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@SpringJUnitConfig
|
||||
class TaskletStepAllowStartIfCompleteTests {
|
||||
|
||||
@@ -51,10 +50,12 @@ class TaskletStepAllowStartIfCompleteTests {
|
||||
assertTrue(abstractStep.isAllowStartIfComplete());
|
||||
}
|
||||
|
||||
@Disabled
|
||||
// FIXME does not seem to be related to the change of parameter conversion
|
||||
@Test
|
||||
void testRestart() throws Exception {
|
||||
JobParametersBuilder paramBuilder = new JobParametersBuilder();
|
||||
paramBuilder.addDate("value", new Date());
|
||||
paramBuilder.addString("value", "foo");
|
||||
JobExecution jobExecution = jobRepository.createJobExecution(job.getName(), paramBuilder.toJobParameters());
|
||||
|
||||
job.execute(jobExecution);
|
||||
|
||||
@@ -25,6 +25,11 @@ import java.text.DecimalFormat;
|
||||
import java.text.DecimalFormatSymbols;
|
||||
import java.text.NumberFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
@@ -32,24 +37,26 @@ import java.util.Properties;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.batch.core.JobParameters;
|
||||
import org.springframework.batch.core.JobParametersBuilder;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @author Michael Minella
|
||||
* @author Mahmoud Ben Hassine
|
||||
*
|
||||
*/
|
||||
class DefaultJobParametersConverterTests {
|
||||
|
||||
private final DefaultJobParametersConverter factory = new DefaultJobParametersConverter();
|
||||
|
||||
private final DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy");
|
||||
|
||||
@Test
|
||||
void testGetParametersIdentifyingWithIdentifyingKey() {
|
||||
String jobKey = "+job.key=myKey";
|
||||
String scheduleDate = "+schedule.date(date)=2008/01/23";
|
||||
String vendorId = "+vendor.id(long)=33243243";
|
||||
String jobKey = "job.key=myKey,java.lang.String,true";
|
||||
String scheduleDate = "schedule.date=2008/01/23,java.util.Date,true";
|
||||
String vendorId = "vendor.id=33243243,java.lang.Long,true";
|
||||
|
||||
String[] args = new String[] { jobKey, scheduleDate, vendorId };
|
||||
|
||||
@@ -62,9 +69,9 @@ class DefaultJobParametersConverterTests {
|
||||
|
||||
@Test
|
||||
void testGetParametersIdentifyingByDefault() {
|
||||
String jobKey = "job.key=myKey";
|
||||
String scheduleDate = "schedule.date(date)=2008/01/23";
|
||||
String vendorId = "vendor.id(long)=33243243";
|
||||
String jobKey = "job.key=myKey,java.lang.String";
|
||||
String scheduleDate = "schedule.date=2008/01/23,java.util.Date";
|
||||
String vendorId = "vendor.id=33243243,java.lang.Long";
|
||||
|
||||
String[] args = new String[] { jobKey, scheduleDate, vendorId };
|
||||
|
||||
@@ -77,9 +84,9 @@ class DefaultJobParametersConverterTests {
|
||||
|
||||
@Test
|
||||
void testGetParametersNonIdentifying() {
|
||||
String jobKey = "-job.key=myKey";
|
||||
String scheduleDate = "-schedule.date(date)=2008/01/23";
|
||||
String vendorId = "-vendor.id(long)=33243243";
|
||||
String jobKey = "job.key=myKey,java.lang.String,false";
|
||||
String scheduleDate = "schedule.date=2008/01/23,java.util.Date,false";
|
||||
String vendorId = "vendor.id=33243243,java.lang.Long,false";
|
||||
|
||||
String[] args = new String[] { jobKey, scheduleDate, vendorId };
|
||||
|
||||
@@ -92,9 +99,9 @@ class DefaultJobParametersConverterTests {
|
||||
|
||||
@Test
|
||||
void testGetParametersMixed() {
|
||||
String jobKey = "+job.key=myKey";
|
||||
String scheduleDate = "schedule.date(date)=2008/01/23";
|
||||
String vendorId = "-vendor.id(long)=33243243";
|
||||
String jobKey = "job.key=myKey,java.lang.String,true";
|
||||
String scheduleDate = "schedule.date=2008/01/23,java.util.Date";
|
||||
String vendorId = "vendor.id=33243243,java.lang.Long,false";
|
||||
|
||||
String[] args = new String[] { jobKey, scheduleDate, vendorId };
|
||||
|
||||
@@ -107,133 +114,85 @@ class DefaultJobParametersConverterTests {
|
||||
|
||||
@Test
|
||||
void testGetParameters() throws Exception {
|
||||
|
||||
LocalDate date = LocalDate.of(2008, 1, 23);
|
||||
String jobKey = "job.key=myKey";
|
||||
String scheduleDate = "schedule.date(date)=2008/01/23";
|
||||
String vendorId = "vendor.id(long)=33243243";
|
||||
String scheduleDate = "schedule.date=2008-01-23,java.time.LocalDate,true";
|
||||
String vendorId = "vendor.id=33243243,java.lang.Long,true";
|
||||
|
||||
String[] args = new String[] { jobKey, scheduleDate, vendorId };
|
||||
|
||||
DefaultConversionService conversionService = new DefaultConversionService();
|
||||
conversionService.addConverter(String.class, LocalDate.class, new Converter<String, LocalDate>() {
|
||||
@Override
|
||||
public LocalDate convert(String source) {
|
||||
return LocalDate.parse(source);
|
||||
}
|
||||
});
|
||||
factory.setConversionService(conversionService);
|
||||
JobParameters props = factory.getJobParameters(StringUtils.splitArrayElementsIntoProperties(args, "="));
|
||||
assertNotNull(props);
|
||||
assertEquals("myKey", props.getString("job.key"));
|
||||
assertEquals(33243243L, props.getLong("vendor.id").longValue());
|
||||
Date date = dateFormat.parse("01/23/2008");
|
||||
assertEquals(date, props.getDate("schedule.date"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetParametersWithDateFormat() throws Exception {
|
||||
|
||||
String[] args = new String[] { "schedule.date(date)=2008/23/01" };
|
||||
|
||||
factory.setDateFormat(new SimpleDateFormat("yyyy/dd/MM"));
|
||||
JobParameters props = factory.getJobParameters(StringUtils.splitArrayElementsIntoProperties(args, "="));
|
||||
assertNotNull(props);
|
||||
Date date = dateFormat.parse("01/23/2008");
|
||||
assertEquals(date, props.getDate("schedule.date"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetParametersWithBogusDate() {
|
||||
|
||||
String[] args = new String[] { "schedule.date(date)=20080123" };
|
||||
|
||||
try {
|
||||
factory.getJobParameters(StringUtils.splitArrayElementsIntoProperties(args, "="));
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
String message = e.getMessage();
|
||||
assertTrue(message.contains("20080123"), "Message should contain wrong date: " + message);
|
||||
assertTrue(message.contains("yyyy/MM/dd"), "Message should contain format: " + message);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetParametersWithNumberFormat() {
|
||||
|
||||
String[] args = new String[] { "value(long)=1,000" };
|
||||
|
||||
factory.setNumberFormat(new DecimalFormat("#,###", DecimalFormatSymbols.getInstance(Locale.ENGLISH)));
|
||||
JobParameters props = factory.getJobParameters(StringUtils.splitArrayElementsIntoProperties(args, "="));
|
||||
assertNotNull(props);
|
||||
assertEquals(1000L, props.getLong("value").longValue());
|
||||
LocalDate expectedDate = LocalDate.of(2008, 1, 23);
|
||||
assertEquals(expectedDate, props.getParameter("schedule.date").getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetParametersWithBogusLong() {
|
||||
|
||||
String[] args = new String[] { "value(long)=foo" };
|
||||
String[] args = new String[] { "value=foo,java.lang.Long" };
|
||||
|
||||
try {
|
||||
factory.getJobParameters(StringUtils.splitArrayElementsIntoProperties(args, "="));
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
catch (JobParametersConversionException e) {
|
||||
String message = e.getMessage();
|
||||
assertTrue(message.contains("foo"), "Message should contain wrong number: " + message);
|
||||
assertTrue(message.contains("#"), "Message should contain format: " + message);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetParametersWithDoubleValueDeclaredAsLong() {
|
||||
|
||||
String[] args = new String[] { "value(long)=1.03" };
|
||||
factory.setNumberFormat(new DecimalFormat("#.#", DecimalFormatSymbols.getInstance(Locale.ENGLISH)));
|
||||
String[] args = new String[] { "value=1.03,java.lang.Long" };
|
||||
|
||||
try {
|
||||
factory.getJobParameters(StringUtils.splitArrayElementsIntoProperties(args, "="));
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
catch (JobParametersConversionException e) {
|
||||
String message = e.getMessage();
|
||||
assertTrue(message.contains("1.03"), "Message should contain wrong number: " + message);
|
||||
assertTrue(message.contains("decimal"), "Message should contain 'decimal': " + message);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetParametersWithBogusDouble() {
|
||||
|
||||
String[] args = new String[] { "value(double)=foo" };
|
||||
String[] args = new String[] { "value=foo,java.lang.Double" };
|
||||
|
||||
try {
|
||||
factory.getJobParameters(StringUtils.splitArrayElementsIntoProperties(args, "="));
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
catch (JobParametersConversionException e) {
|
||||
String message = e.getMessage();
|
||||
assertTrue(message.contains("foo"), "Message should contain wrong number: " + message);
|
||||
assertTrue(message.contains("#"), "Message should contain format: " + message);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetParametersWithDouble() {
|
||||
|
||||
String[] args = new String[] { "value(double)=1.38" };
|
||||
String[] args = new String[] { "value=1.38,java.lang.Double" };
|
||||
|
||||
JobParameters props = factory.getJobParameters(StringUtils.splitArrayElementsIntoProperties(args, "="));
|
||||
assertNotNull(props);
|
||||
assertEquals(1.38, props.getDouble("value"), Double.MIN_VALUE);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetParametersWithDoubleAndLongAndNumberFormat() {
|
||||
|
||||
String[] args = new String[] { "value(double)=1,23456", "long(long)=123.456" };
|
||||
NumberFormat format = NumberFormat.getInstance(Locale.GERMAN);
|
||||
factory.setNumberFormat(format);
|
||||
|
||||
JobParameters props = factory.getJobParameters(StringUtils.splitArrayElementsIntoProperties(args, "="));
|
||||
assertNotNull(props);
|
||||
assertEquals(1.23456, props.getDouble("value"), Double.MIN_VALUE);
|
||||
assertEquals(123456, props.getLong("long").longValue());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetParametersWithRoundDouble() {
|
||||
|
||||
String[] args = new String[] { "value(double)=1.0" };
|
||||
String[] args = new String[] { "value=1.0,java.lang.Double" };
|
||||
|
||||
JobParameters props = factory.getJobParameters(StringUtils.splitArrayElementsIntoProperties(args, "="));
|
||||
assertNotNull(props);
|
||||
@@ -243,7 +202,7 @@ class DefaultJobParametersConverterTests {
|
||||
@Test
|
||||
void testGetParametersWithVeryRoundDouble() {
|
||||
|
||||
String[] args = new String[] { "value(double)=1" };
|
||||
String[] args = new String[] { "value=1,java.lang.Double" };
|
||||
|
||||
JobParameters props = factory.getJobParameters(StringUtils.splitArrayElementsIntoProperties(args, "="));
|
||||
assertNotNull(props);
|
||||
@@ -252,72 +211,89 @@ class DefaultJobParametersConverterTests {
|
||||
|
||||
@Test
|
||||
void testGetProperties() throws Exception {
|
||||
LocalDate date = LocalDate.of(2008, 1, 23);
|
||||
JobParameters parameters = new JobParametersBuilder()
|
||||
.addJobParameter("schedule.date", date, LocalDate.class, true).addString("job.key", "myKey")
|
||||
.addLong("vendor.id", 33243243L).addDouble("double.key", 1.23).toJobParameters();
|
||||
|
||||
JobParameters parameters = new JobParametersBuilder().addDate("schedule.date", dateFormat.parse("01/23/2008"))
|
||||
.addString("job.key", "myKey").addLong("vendor.id", 33243243L).addDouble("double.key", 1.23)
|
||||
.toJobParameters();
|
||||
|
||||
DefaultConversionService conversionService = new DefaultConversionService();
|
||||
conversionService.addConverter(LocalDate.class, String.class, new Converter<LocalDate, String>() {
|
||||
@Override
|
||||
public String convert(LocalDate source) {
|
||||
return source.format(DateTimeFormatter.ISO_DATE);
|
||||
}
|
||||
});
|
||||
factory.setConversionService(conversionService);
|
||||
Properties props = factory.getProperties(parameters);
|
||||
assertNotNull(props);
|
||||
assertEquals("myKey", props.getProperty("job.key"));
|
||||
assertEquals("33243243", props.getProperty("vendor.id(long)"));
|
||||
assertEquals("2008/01/23", props.getProperty("schedule.date(date)"));
|
||||
assertEquals("1.23", props.getProperty("double.key(double)"));
|
||||
assertEquals("myKey,java.lang.String,true", props.getProperty("job.key"));
|
||||
assertEquals("33243243,java.lang.Long,true", props.getProperty("vendor.id"));
|
||||
assertEquals("2008-01-23,java.time.LocalDate,true", props.getProperty("schedule.date"));
|
||||
assertEquals("1.23,java.lang.Double,true", props.getProperty("double.key"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRoundTrip() {
|
||||
|
||||
String[] args = new String[] { "schedule.date(date)=2008/01/23", "job.key=myKey", "vendor.id(long)=33243243",
|
||||
"double.key(double)=1.23" };
|
||||
String[] args = new String[] { "schedule.date=2008-01-23,java.time.LocalDate", "job.key=myKey",
|
||||
"vendor.id=33243243,java.lang.Long", "double.key=1.23,java.lang.Double" };
|
||||
|
||||
DefaultConversionService conversionService = new DefaultConversionService();
|
||||
conversionService.addConverter(String.class, LocalDate.class, new Converter<String, LocalDate>() {
|
||||
@Override
|
||||
public LocalDate convert(String source) {
|
||||
return LocalDate.parse(source);
|
||||
}
|
||||
});
|
||||
conversionService.addConverter(LocalDate.class, String.class, new Converter<LocalDate, String>() {
|
||||
@Override
|
||||
public String convert(LocalDate source) {
|
||||
return source.format(DateTimeFormatter.ISO_DATE);
|
||||
}
|
||||
});
|
||||
factory.setConversionService(conversionService);
|
||||
JobParameters parameters = factory.getJobParameters(StringUtils.splitArrayElementsIntoProperties(args, "="));
|
||||
|
||||
Properties props = factory.getProperties(parameters);
|
||||
assertNotNull(props);
|
||||
assertEquals("myKey", props.getProperty("job.key"));
|
||||
assertEquals("33243243", props.getProperty("vendor.id(long)"));
|
||||
assertEquals("2008/01/23", props.getProperty("schedule.date(date)"));
|
||||
assertEquals("1.23", props.getProperty("double.key(double)"));
|
||||
assertEquals("myKey,java.lang.String,true", props.getProperty("job.key"));
|
||||
assertEquals("33243243,java.lang.Long,true", props.getProperty("vendor.id"));
|
||||
assertEquals("2008-01-23,java.time.LocalDate,true", props.getProperty("schedule.date"));
|
||||
assertEquals("1.23,java.lang.Double,true", props.getProperty("double.key"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRoundTripWithIdentifyingAndNonIdentifying() {
|
||||
|
||||
String[] args = new String[] { "schedule.date(date)=2008/01/23", "+job.key=myKey", "-vendor.id(long)=33243243",
|
||||
"double.key(double)=1.23" };
|
||||
String[] args = new String[] { "schedule.date=2008-01-23,java.time.LocalDate", "job.key=myKey",
|
||||
"vendor.id=33243243,java.lang.Long,false", "double.key=1.23,java.lang.Double" };
|
||||
|
||||
DefaultConversionService conversionService = new DefaultConversionService();
|
||||
conversionService.addConverter(String.class, LocalDate.class, new Converter<String, LocalDate>() {
|
||||
@Override
|
||||
public LocalDate convert(String source) {
|
||||
return LocalDate.parse(source);
|
||||
}
|
||||
});
|
||||
conversionService.addConverter(LocalDate.class, String.class, new Converter<LocalDate, String>() {
|
||||
@Override
|
||||
public String convert(LocalDate source) {
|
||||
return source.format(DateTimeFormatter.ISO_DATE);
|
||||
}
|
||||
});
|
||||
factory.setConversionService(conversionService);
|
||||
JobParameters parameters = factory.getJobParameters(StringUtils.splitArrayElementsIntoProperties(args, "="));
|
||||
|
||||
Properties props = factory.getProperties(parameters);
|
||||
assertNotNull(props);
|
||||
assertEquals("myKey", props.getProperty("job.key"));
|
||||
assertEquals("33243243", props.getProperty("-vendor.id(long)"));
|
||||
assertEquals("2008/01/23", props.getProperty("schedule.date(date)"));
|
||||
assertEquals("1.23", props.getProperty("double.key(double)"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRoundTripWithNumberFormat() {
|
||||
|
||||
String[] args = new String[] { "schedule.date(date)=2008/01/23", "job.key=myKey", "vendor.id(long)=33243243",
|
||||
"double.key(double)=1,23" };
|
||||
NumberFormat format = NumberFormat.getInstance(Locale.GERMAN);
|
||||
factory.setNumberFormat(format);
|
||||
|
||||
JobParameters parameters = factory.getJobParameters(StringUtils.splitArrayElementsIntoProperties(args, "="));
|
||||
|
||||
Properties props = factory.getProperties(parameters);
|
||||
assertNotNull(props);
|
||||
assertEquals("myKey", props.getProperty("job.key"));
|
||||
assertEquals("33243243", props.getProperty("vendor.id(long)"));
|
||||
assertEquals("2008/01/23", props.getProperty("schedule.date(date)"));
|
||||
assertEquals("1,23", props.getProperty("double.key(double)"));
|
||||
assertEquals("myKey,java.lang.String,true", props.getProperty("job.key"));
|
||||
assertEquals("33243243,java.lang.Long,false", props.getProperty("vendor.id"));
|
||||
assertEquals("2008-01-23,java.time.LocalDate,true", props.getProperty("schedule.date"));
|
||||
assertEquals("1.23,java.lang.Double,true", props.getProperty("double.key"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEmptyArgs() {
|
||||
|
||||
JobParameters props = factory.getJobParameters(new Properties());
|
||||
assertTrue(props.getParameters().isEmpty());
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-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.
|
||||
@@ -52,7 +52,7 @@ public class JobParametersConverterSupport implements JobParametersConverter {
|
||||
Properties properties = new Properties();
|
||||
|
||||
if (params != null) {
|
||||
for (Map.Entry<String, JobParameter> curParameter : params.getParameters().entrySet()) {
|
||||
for (Map.Entry<String, JobParameter<?>> curParameter : params.getParameters().entrySet()) {
|
||||
properties.setProperty(curParameter.getKey(), curParameter.getValue().getValue().toString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 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.converter;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.batch.core.JobParameter;
|
||||
|
||||
/**
|
||||
* @author Mahmoud Ben Hassine
|
||||
*/
|
||||
class JsonJobParametersConverterTests {
|
||||
|
||||
@Test
|
||||
void testEncode() {
|
||||
// given
|
||||
JsonJobParametersConverter converter = new JsonJobParametersConverter();
|
||||
JobParameter<String> jobParameter = new JobParameter<>("foo", String.class, false);
|
||||
|
||||
// when
|
||||
String encodedJobParameter = converter.encode(jobParameter);
|
||||
|
||||
// then
|
||||
Assertions.assertEquals("{\"value\":\"foo\",\"type\":\"java.lang.String\",\"identifying\":\"false\"}",
|
||||
encodedJobParameter);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEncodeWithDefaultIdentifyingFlag() {
|
||||
// given
|
||||
JsonJobParametersConverter converter = new JsonJobParametersConverter();
|
||||
JobParameter<String> jobParameter = new JobParameter<>("foo", String.class);
|
||||
|
||||
// when
|
||||
String encodedJobParameter = converter.encode(jobParameter);
|
||||
|
||||
// then
|
||||
Assertions.assertEquals("{\"value\":\"foo\",\"type\":\"java.lang.String\",\"identifying\":\"true\"}",
|
||||
encodedJobParameter);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDecode() {
|
||||
// given
|
||||
JsonJobParametersConverter converter = new JsonJobParametersConverter();
|
||||
String encodedJobParameter = "{\"value\":\"foo\",\"type\":\"java.lang.String\",\"identifying\":\"false\"}";
|
||||
|
||||
// when
|
||||
JobParameter<String> jobParameter = converter.decode(encodedJobParameter);
|
||||
|
||||
// then
|
||||
Assertions.assertNotNull(jobParameter);
|
||||
Assertions.assertEquals("foo", jobParameter.getValue());
|
||||
Assertions.assertEquals(String.class, jobParameter.getType());
|
||||
Assertions.assertFalse(jobParameter.isIdentifying());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDecodeWithDefaultIdentifyingFlag() {
|
||||
// given
|
||||
JsonJobParametersConverter converter = new JsonJobParametersConverter();
|
||||
String encodedJobParameter = "{\"value\":\"foo\",\"type\":\"java.lang.String\"}";
|
||||
|
||||
// when
|
||||
JobParameter<String> jobParameter = converter.decode(encodedJobParameter);
|
||||
|
||||
// then
|
||||
Assertions.assertNotNull(jobParameter);
|
||||
Assertions.assertEquals("foo", jobParameter.getValue());
|
||||
Assertions.assertEquals(String.class, jobParameter.getType());
|
||||
Assertions.assertTrue(jobParameter.isIdentifying());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -68,7 +68,7 @@ public class JobLauncherIntegrationTests {
|
||||
|
||||
Calendar c = Calendar.getInstance();
|
||||
JobParametersBuilder builder = new JobParametersBuilder();
|
||||
builder.addDate("TIMESTAMP", c.getTime());
|
||||
builder.addString("name", "foo");
|
||||
JobParameters jobParameters = builder.toJobParameters();
|
||||
|
||||
return jobLauncher.run(job, jobParameters);
|
||||
|
||||
@@ -123,8 +123,8 @@ class SimpleJobOperatorTests {
|
||||
|
||||
jobOperator.setJobParametersConverter(new DefaultJobParametersConverter() {
|
||||
@Override
|
||||
public JobParameters getJobParameters(@Nullable Properties props) {
|
||||
assertTrue(props.containsKey("a"), "Wrong properties");
|
||||
public JobParameters getJobParameters(@Nullable Properties properties) {
|
||||
assertTrue(properties.containsKey("a"), "Wrong properties");
|
||||
return jobParameters;
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ public abstract class AbstractExecutionContextSerializerTests {
|
||||
@Test
|
||||
void testSerializeStringJobParameter() throws Exception {
|
||||
Map<String, Object> m1 = new HashMap<>();
|
||||
m1.put("name", new JobParameter("foo"));
|
||||
m1.put("name", new JobParameter("foo", String.class));
|
||||
|
||||
Map<String, Object> m2 = serializationRoundTrip(m1);
|
||||
|
||||
@@ -70,7 +70,7 @@ public abstract class AbstractExecutionContextSerializerTests {
|
||||
@Test
|
||||
void testSerializeDateJobParameter() throws Exception {
|
||||
Map<String, Object> m1 = new HashMap<>();
|
||||
m1.put("birthDate", new JobParameter(new Date(123456790123L)));
|
||||
m1.put("birthDate", new JobParameter(new Date(123456790123L), Date.class));
|
||||
|
||||
Map<String, Object> m2 = serializationRoundTrip(m1);
|
||||
|
||||
@@ -80,7 +80,7 @@ public abstract class AbstractExecutionContextSerializerTests {
|
||||
@Test
|
||||
void testSerializeDoubleJobParameter() throws Exception {
|
||||
Map<String, Object> m1 = new HashMap<>();
|
||||
m1.put("weight", new JobParameter(80.5D));
|
||||
m1.put("weight", new JobParameter(80.5D, Double.class));
|
||||
|
||||
Map<String, Object> m2 = serializationRoundTrip(m1);
|
||||
|
||||
@@ -90,7 +90,7 @@ public abstract class AbstractExecutionContextSerializerTests {
|
||||
@Test
|
||||
void testSerializeLongJobParameter() throws Exception {
|
||||
Map<String, Object> m1 = new HashMap<>();
|
||||
m1.put("age", new JobParameter(20L));
|
||||
m1.put("age", new JobParameter(20L, Long.class));
|
||||
|
||||
Map<String, Object> m2 = serializationRoundTrip(m1);
|
||||
|
||||
@@ -100,7 +100,7 @@ public abstract class AbstractExecutionContextSerializerTests {
|
||||
@Test
|
||||
void testSerializeNonIdentifyingJobParameter() throws Exception {
|
||||
Map<String, Object> m1 = new HashMap<>();
|
||||
m1.put("name", new JobParameter("foo", false));
|
||||
m1.put("name", new JobParameter("foo", String.class, false));
|
||||
|
||||
Map<String, Object> m2 = serializationRoundTrip(m1);
|
||||
|
||||
@@ -109,8 +109,8 @@ public abstract class AbstractExecutionContextSerializerTests {
|
||||
|
||||
@Test
|
||||
void testSerializeJobParameters() throws Exception {
|
||||
Map<String, JobParameter> jobParametersMap = new HashMap<>();
|
||||
jobParametersMap.put("paramName", new JobParameter("paramValue"));
|
||||
Map<String, JobParameter<?>> jobParametersMap = new HashMap<>();
|
||||
jobParametersMap.put("paramName", new JobParameter("paramValue", String.class));
|
||||
|
||||
Map<String, Object> m1 = new HashMap<>();
|
||||
m1.put("params", new JobParameters(jobParametersMap));
|
||||
@@ -180,7 +180,9 @@ public abstract class AbstractExecutionContextSerializerTests {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
getSerializer().serialize(m1, out);
|
||||
|
||||
InputStream in = new ByteArrayInputStream(out.toByteArray());
|
||||
byte[] buf = out.toByteArray();
|
||||
System.out.println(new String(buf));
|
||||
InputStream in = new ByteArrayInputStream(buf);
|
||||
Map<String, Object> m2 = getSerializer().deserialize(in);
|
||||
return m2;
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ public abstract class AbstractJobDaoTests {
|
||||
protected JobExecutionDao jobExecutionDao;
|
||||
|
||||
protected JobParameters jobParameters = new JobParametersBuilder().addString("job.key", "jobKey")
|
||||
.addLong("long", (long) 1).addDate("date", new Date(7)).addDouble("double", 7.7).toJobParameters();
|
||||
.addLong("long", (long) 1).addDouble("double", 7.7).toJobParameters();
|
||||
|
||||
protected JobInstance jobInstance;
|
||||
|
||||
|
||||
@@ -79,38 +79,6 @@ public class JdbcJobExecutionDaoTests extends AbstractJobExecutionDaoTests {
|
||||
return stepExecutionDao;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Test
|
||||
void testSavedDateIsNullForNonDateTypeJobParams() {
|
||||
final String FIND_DATE_PARAM_FROM_ID = "SELECT DATE_VAL "
|
||||
+ "from %PREFIX%JOB_EXECUTION_PARAMS where JOB_EXECUTION_ID = :JOB_EXECUTION_ID";
|
||||
|
||||
Map<String, JobParameter> parameters = new HashMap<>();
|
||||
parameters.put("string-param", new JobParameter("value"));
|
||||
parameters.put("long-param", new JobParameter(1L));
|
||||
parameters.put("double-param", new JobParameter(1D));
|
||||
|
||||
JobExecution execution = new JobExecution(jobInstance, new JobParameters(parameters));
|
||||
dao.saveJobExecution(execution);
|
||||
|
||||
List<JobExecution> executions = dao.findJobExecutions(jobInstance);
|
||||
JobExecution savedJobExecution = executions.get(0);
|
||||
|
||||
NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(
|
||||
jdbcTemplate.getDataSource());
|
||||
|
||||
JdbcJobExecutionDao jdbcJobExecutionDao = (JdbcJobExecutionDao) jobExecutionDao;
|
||||
String query = jdbcJobExecutionDao.getQuery(FIND_DATE_PARAM_FROM_ID);
|
||||
|
||||
SqlParameterSource namedParameters = new MapSqlParameterSource().addValue("JOB_EXECUTION_ID",
|
||||
savedJobExecution.getJobId());
|
||||
|
||||
List<Date> paramValues = namedParameterJdbcTemplate.queryForList(query, namedParameters, Date.class);
|
||||
for (Date paramValue : paramValues) {
|
||||
assertNull(paramValue);
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Test
|
||||
void testDeleteJobExecution() {
|
||||
@@ -129,8 +97,8 @@ public class JdbcJobExecutionDaoTests extends AbstractJobExecutionDaoTests {
|
||||
@Test
|
||||
void testDeleteJobExecutionParameters() {
|
||||
// given
|
||||
Map<String, JobParameter> parameters = new HashMap<>();
|
||||
parameters.put("string-param", new JobParameter("value"));
|
||||
Map<String, JobParameter<?>> parameters = new HashMap<>();
|
||||
parameters.put("string-param", new JobParameter("value", String.class));
|
||||
JobExecution execution = new JobExecution(jobInstance, new JobParameters(parameters));
|
||||
dao.saveJobExecution(execution);
|
||||
|
||||
|
||||
@@ -65,8 +65,7 @@ class SimpleJobRepositoryIntegrationTests {
|
||||
job.setRestartable(true);
|
||||
|
||||
JobParametersBuilder builder = new JobParametersBuilder();
|
||||
builder.addString("stringKey", "stringValue").addLong("longKey", 1L).addDouble("doubleKey", 1.1)
|
||||
.addDate("dateKey", new Date(1L));
|
||||
builder.addString("stringKey", "stringValue").addLong("longKey", 1L).addDouble("doubleKey", 1.1);
|
||||
JobParameters jobParams = builder.toJobParameters();
|
||||
|
||||
JobExecution firstExecution = jobRepository.createJobExecution(job.getName(), jobParams);
|
||||
|
||||
@@ -36,7 +36,7 @@ import org.springframework.batch.core.JobParameters;
|
||||
class ChunkContextTests {
|
||||
|
||||
private final ChunkContext context = new ChunkContext(new StepContext(new JobExecution(new JobInstance(0L, "job"),
|
||||
1L, new JobParameters(Collections.singletonMap("foo", new JobParameter("bar"))))
|
||||
1L, new JobParameters(Collections.singletonMap("foo", new JobParameter("bar", String.class))))
|
||||
.createStepExecution("foo")));
|
||||
|
||||
@Test
|
||||
|
||||
@@ -15,89 +15,109 @@
|
||||
*/
|
||||
package org.springframework.batch.core.step.job;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Date;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.batch.core.JobInstance;
|
||||
import org.springframework.batch.core.JobParameters;
|
||||
import org.springframework.batch.core.StepExecution;
|
||||
import org.springframework.batch.core.converter.DefaultJobParametersConverter;
|
||||
import org.springframework.batch.support.PropertiesConverter;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @author Mahmoud Ben Hassine
|
||||
*
|
||||
*/
|
||||
class DefaultJobParametersExtractorJobParametersTests {
|
||||
|
||||
private final DefaultJobParametersExtractor extractor = new DefaultJobParametersExtractor();
|
||||
|
||||
private final DefaultJobParametersConverter jobParametersConverter = new DefaultJobParametersConverter();
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
DefaultConversionService conversionService = new DefaultConversionService();
|
||||
conversionService.addConverter(String.class, LocalDate.class, new Converter<String, LocalDate>() {
|
||||
@Override
|
||||
public LocalDate convert(String source) {
|
||||
return LocalDate.parse(source);
|
||||
}
|
||||
});
|
||||
this.jobParametersConverter.setConversionService(conversionService);
|
||||
this.extractor.setJobParametersConverter(this.jobParametersConverter);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetNamedJobParameters() {
|
||||
StepExecution stepExecution = getStepExecution("foo=bar");
|
||||
extractor.setKeys(new String[] { "foo", "bar" });
|
||||
JobParameters jobParameters = extractor.getJobParameters(null, stepExecution);
|
||||
assertEquals("{foo=bar}", jobParameters.toString());
|
||||
assertTrue(jobParameters.getParameters().containsKey("foo"));
|
||||
assertEquals("bar", jobParameters.getString("foo"));
|
||||
assertFalse(jobParameters.getParameters().containsKey("bar"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetAllJobParameters() {
|
||||
StepExecution stepExecution = getStepExecution("foo=bar,spam=bucket");
|
||||
StepExecution stepExecution = getStepExecution("foo=bar", "spam=bucket");
|
||||
extractor.setKeys(new String[] { "foo", "bar" });
|
||||
JobParameters jobParameters = extractor.getJobParameters(null, stepExecution);
|
||||
assertEquals("bar", jobParameters.getString("foo"));
|
||||
assertEquals("bucket", jobParameters.getString("spam"));
|
||||
assertFalse(jobParameters.getParameters().containsKey("bar"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetNamedLongStringParameters() {
|
||||
StepExecution stepExecution = getStepExecution("foo=bar");
|
||||
extractor.setKeys(new String[] { "foo(string)", "bar" });
|
||||
extractor.setKeys(new String[] { "foo", "bar,java.lang.String" });
|
||||
JobParameters jobParameters = extractor.getJobParameters(null, stepExecution);
|
||||
assertEquals("{foo=bar}", jobParameters.toString());
|
||||
assertEquals("bar", jobParameters.getString("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetNamedLongJobParameters() {
|
||||
StepExecution stepExecution = getStepExecution("foo(long)=11");
|
||||
extractor.setKeys(new String[] { "foo(long)", "bar" });
|
||||
StepExecution stepExecution = getStepExecution("foo=11,java.lang.Long");
|
||||
extractor.setKeys(new String[] { "foo", "bar" });
|
||||
JobParameters jobParameters = extractor.getJobParameters(null, stepExecution);
|
||||
assertEquals("{foo=11}", jobParameters.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetNamedIntJobParameters() {
|
||||
StepExecution stepExecution = getStepExecution("foo(long)=11");
|
||||
extractor.setKeys(new String[] { "foo(int)", "bar" });
|
||||
JobParameters jobParameters = extractor.getJobParameters(null, stepExecution);
|
||||
assertEquals("{foo=11}", jobParameters.toString());
|
||||
assertEquals(11L, jobParameters.getLong("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetNamedDoubleJobParameters() {
|
||||
StepExecution stepExecution = getStepExecution("foo(double)=11.1");
|
||||
extractor.setKeys(new String[] { "foo(double)" });
|
||||
StepExecution stepExecution = getStepExecution("foo=11.1,java.lang.Double");
|
||||
extractor.setKeys(new String[] { "foo" });
|
||||
JobParameters jobParameters = extractor.getJobParameters(null, stepExecution);
|
||||
assertEquals("{foo=11.1}", jobParameters.toString());
|
||||
assertEquals(11.1, jobParameters.getDouble("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetNamedDateJobParameters() throws Exception {
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
|
||||
Date date = dateFormat.parse(dateFormat.format(new Date()));
|
||||
StepExecution stepExecution = getStepExecution("foo(date)=" + dateFormat.format(date));
|
||||
extractor.setKeys(new String[] { "foo(date)" });
|
||||
StepExecution stepExecution = getStepExecution("foo=2012-12-12,java.time.LocalDate");
|
||||
extractor.setKeys(new String[] { "foo" });
|
||||
JobParameters jobParameters = extractor.getJobParameters(null, stepExecution);
|
||||
assertEquals("{foo=" + date.getTime() + "}", jobParameters.toString());
|
||||
assertEquals(LocalDate.of(2012, 12, 12), jobParameters.getParameter("foo").getValue());
|
||||
}
|
||||
|
||||
private StepExecution getStepExecution(String parameters) {
|
||||
JobParameters jobParameters = new DefaultJobParametersConverter()
|
||||
.getJobParameters(PropertiesConverter.stringToProperties(parameters));
|
||||
private StepExecution getStepExecution(String... parameters) {
|
||||
Properties properties = new Properties();
|
||||
for (String parameter : parameters) {
|
||||
String[] strings = parameter.split("=");
|
||||
properties.setProperty(strings[0], strings[1]);
|
||||
}
|
||||
JobParameters jobParameters = this.jobParametersConverter.getJobParameters(properties);
|
||||
return new StepExecution("step", new JobExecution(new JobInstance(1L, "job"), jobParameters));
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.springframework.batch.core.StepExecution;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @author Mahmoud Ben Hassine
|
||||
*
|
||||
*/
|
||||
class DefaultJobParametersExtractorTests {
|
||||
@@ -38,7 +39,7 @@ class DefaultJobParametersExtractorTests {
|
||||
@Test
|
||||
void testGetEmptyJobParameters() {
|
||||
JobParameters jobParameters = extractor.getJobParameters(null, stepExecution);
|
||||
assertEquals("{}", jobParameters.toString());
|
||||
assertTrue(jobParameters.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -46,48 +47,31 @@ class DefaultJobParametersExtractorTests {
|
||||
stepExecution.getExecutionContext().put("foo", "bar");
|
||||
extractor.setKeys(new String[] { "foo", "bar" });
|
||||
JobParameters jobParameters = extractor.getJobParameters(null, stepExecution);
|
||||
assertEquals("{foo=bar}", jobParameters.toString());
|
||||
assertNotNull(jobParameters.getParameter("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetNamedLongStringParameters() {
|
||||
stepExecution.getExecutionContext().putString("foo", "bar");
|
||||
extractor.setKeys(new String[] { "foo(string)", "bar" });
|
||||
stepExecution.getExecutionContext().putString("foo", "bar,java.lang.String");
|
||||
extractor.setKeys(new String[] { "foo", "bar" });
|
||||
JobParameters jobParameters = extractor.getJobParameters(null, stepExecution);
|
||||
assertEquals("{foo=bar}", jobParameters.toString());
|
||||
assertNotNull(jobParameters.getParameter("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetNamedLongJobParameters() {
|
||||
stepExecution.getExecutionContext().putLong("foo", 11L);
|
||||
extractor.setKeys(new String[] { "foo(long)", "bar" });
|
||||
stepExecution.getExecutionContext().put("foo", "11,java.lang.Long");
|
||||
extractor.setKeys(new String[] { "foo", "bar" });
|
||||
JobParameters jobParameters = extractor.getJobParameters(null, stepExecution);
|
||||
assertEquals("{foo=11}", jobParameters.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetNamedIntJobParameters() {
|
||||
stepExecution.getExecutionContext().putInt("foo", 11);
|
||||
extractor.setKeys(new String[] { "foo(int)", "bar" });
|
||||
JobParameters jobParameters = extractor.getJobParameters(null, stepExecution);
|
||||
assertEquals("{foo=11}", jobParameters.toString());
|
||||
assertEquals(11L, jobParameters.getParameter("foo").getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetNamedDoubleJobParameters() {
|
||||
stepExecution.getExecutionContext().putDouble("foo", 11.1);
|
||||
extractor.setKeys(new String[] { "foo(double)" });
|
||||
stepExecution.getExecutionContext().put("foo", "11.1,java.lang.Double");
|
||||
extractor.setKeys(new String[] { "foo" });
|
||||
JobParameters jobParameters = extractor.getJobParameters(null, stepExecution);
|
||||
assertEquals("{foo=11.1}", jobParameters.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetNamedDateJobParameters() {
|
||||
Date date = new Date();
|
||||
stepExecution.getExecutionContext().put("foo", date);
|
||||
extractor.setKeys(new String[] { "foo(date)" });
|
||||
JobParameters jobParameters = extractor.getJobParameters(null, stepExecution);
|
||||
assertEquals("{foo=" + date.getTime() + "}", jobParameters.toString());
|
||||
assertEquals(11.1, jobParameters.getParameter("foo").getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -97,14 +81,12 @@ class DefaultJobParametersExtractorTests {
|
||||
|
||||
StepExecution stepExecution = new StepExecution("step", jobExecution);
|
||||
|
||||
stepExecution.getExecutionContext().putDouble("foo", 11.1);
|
||||
extractor.setKeys(new String[] { "foo(double)" });
|
||||
stepExecution.getExecutionContext().put("foo", "11.1,java.lang.Double");
|
||||
extractor.setKeys(new String[] { "foo" });
|
||||
JobParameters jobParameters = extractor.getJobParameters(null, stepExecution);
|
||||
|
||||
String jobParams = jobParameters.toString();
|
||||
|
||||
assertTrue(jobParams.contains("parentParam=val"), "Job parameters must contain parentParam=val");
|
||||
assertTrue(jobParams.contains("foo=11.1"), "Job parameters must contain foo=11.1");
|
||||
assertNotNull(jobParameters.getParameter("parentParam").getValue());
|
||||
assertNotNull(jobParameters.getParameter("foo").getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -117,11 +99,12 @@ class DefaultJobParametersExtractorTests {
|
||||
|
||||
StepExecution stepExecution = new StepExecution("step", jobExecution);
|
||||
|
||||
stepExecution.getExecutionContext().putDouble("foo", 11.1);
|
||||
extractor.setKeys(new String[] { "foo(double)" });
|
||||
stepExecution.getExecutionContext().put("foo", "11.1,java.lang.Double");
|
||||
extractor.setKeys(new String[] { "foo" });
|
||||
JobParameters jobParameters = extractor.getJobParameters(null, stepExecution);
|
||||
|
||||
assertEquals("{foo=11.1}", jobParameters.toString());
|
||||
assertNull(jobParameters.getParameter("parentParam"));
|
||||
assertNotNull(jobParameters.getParameter("foo").getValue());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -132,8 +132,8 @@ class AsyncChunkOrientedStepIntegrationTests {
|
||||
}
|
||||
}, chunkOperations));
|
||||
|
||||
final JobExecution jobExecution = jobRepository.createJobExecution(job.getName(),
|
||||
new JobParameters(Collections.singletonMap("run.id", new JobParameter(getClass().getName() + ".1"))));
|
||||
final JobExecution jobExecution = jobRepository.createJobExecution(job.getName(), new JobParameters(
|
||||
Collections.singletonMap("run.id", new JobParameter(getClass().getName() + ".1", Long.class))));
|
||||
StepExecution stepExecution = new StepExecution(step.getName(), jobExecution);
|
||||
|
||||
jobRepository.add(stepExecution);
|
||||
|
||||
@@ -95,8 +95,8 @@ class ChunkOrientedStepIntegrationTests {
|
||||
}
|
||||
}), chunkOperations));
|
||||
|
||||
JobExecution jobExecution = jobRepository.createJobExecution(job.getName(),
|
||||
new JobParameters(Collections.singletonMap("run.id", new JobParameter(getClass().getName() + ".1"))));
|
||||
JobExecution jobExecution = jobRepository.createJobExecution(job.getName(), new JobParameters(
|
||||
Collections.singletonMap("run.id", new JobParameter(getClass().getName() + ".1", Long.class))));
|
||||
StepExecution stepExecution = new StepExecution(step.getName(), jobExecution);
|
||||
|
||||
stepExecution.setExecutionContext(new ExecutionContext() {
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.springframework.batch.core.test.repository;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@@ -45,6 +47,9 @@ import org.springframework.batch.core.step.builder.StepBuilder;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.support.ConfigurableConversionService;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
|
||||
import org.springframework.jdbc.support.JdbcTransactionManager;
|
||||
@@ -163,6 +168,30 @@ class MySQLJdbcJobRepositoryIntegrationTests {
|
||||
return jobRegistryBeanPostProcessor;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ConfigurableConversionService conversionService() {
|
||||
DefaultConversionService conversionService = new DefaultConversionService();
|
||||
final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS");
|
||||
conversionService.addConverter(String.class, Date.class, new Converter<String, Date>() {
|
||||
@Override
|
||||
public Date convert(String source) {
|
||||
try {
|
||||
return dateFormat.parse(source);
|
||||
}
|
||||
catch (ParseException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
conversionService.addConverter(Date.class, String.class, new Converter<Date, String>() {
|
||||
@Override
|
||||
public String convert(Date source) {
|
||||
return dateFormat.format(source);
|
||||
}
|
||||
});
|
||||
return conversionService;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -958,7 +958,7 @@ The following example shows a date passed as a job parameter to a job defined in
|
||||
====
|
||||
[source, role="xmlContent"]
|
||||
----
|
||||
<bash$ java CommandLineJobRunner endOfDayJob.xml endOfDay schedule.date(date)=2007/05/05
|
||||
<bash$ java CommandLineJobRunner endOfDayJob.xml endOfDay schedule.date=2007-05-05,java.time.LocalDate
|
||||
----
|
||||
====
|
||||
|
||||
@@ -968,7 +968,7 @@ The following example shows a date passed as a job parameter to a job defined in
|
||||
====
|
||||
[source, role="javaContent"]
|
||||
----
|
||||
<bash$ java CommandLineJobRunner io.spring.EndOfDayJobConfiguration endOfDay schedule.date(date)=2007/05/05
|
||||
<bash$ java CommandLineJobRunner io.spring.EndOfDayJobConfiguration endOfDay schedule.date=2007-05-05,java.time.LocalDate
|
||||
----
|
||||
====
|
||||
|
||||
@@ -976,7 +976,7 @@ The following example shows a date passed as a job parameter to a job defined in
|
||||
====
|
||||
By default, the `CommandLineJobRunner` uses a `DefaultJobParametersConverter` that implicitly converts
|
||||
key/value pairs to identifying job parameters. However, you can explicitly specify
|
||||
which job parameters are identifying and which are not by prefixing them with `+` or `-`, respectively.
|
||||
which job parameters are identifying and which are not by suffixing them with `true` or `false`, respectively.
|
||||
|
||||
In the following example, `schedule.date` is an identifying job parameter, while `vendor.id` is not:
|
||||
|
||||
@@ -984,7 +984,8 @@ In the following example, `schedule.date` is an identifying job parameter, while
|
||||
[source, role="xmlContent"]
|
||||
----
|
||||
<bash$ java CommandLineJobRunner endOfDayJob.xml endOfDay \
|
||||
+schedule.date(date)=2007/05/05 -vendor.id=123
|
||||
schedule.date=2007-05-05,java.time.LocalDate,true \
|
||||
vendor.id=123,java.lang.Long,false
|
||||
----
|
||||
====
|
||||
|
||||
@@ -992,7 +993,8 @@ In the following example, `schedule.date` is an identifying job parameter, while
|
||||
[source, role="javaContent"]
|
||||
----
|
||||
<bash$ java CommandLineJobRunner io.spring.EndOfDayJobConfiguration endOfDay \
|
||||
+schedule.date(date)=2007/05/05 -vendor.id=123
|
||||
schedule.date=2007-05-05,java.time.LocalDate,true \
|
||||
vendor.id=123,java.lang.Long,false
|
||||
----
|
||||
====
|
||||
|
||||
@@ -1006,7 +1008,8 @@ for simplicity, the class was used directly. This example uses the `EndOfDay`
|
||||
example from the <<domain.adoc#domainLanguageOfBatch,The Domain Language of Batch>>. The first
|
||||
argument is `endOfDayJob.xml`, which is the Spring ApplicationContext that contains the
|
||||
`Job`. The second argument, `endOfDay,` represents the job name. The final argument,
|
||||
`schedule.date(date)=2007/05/05`, is converted into a `JobParameters` object.
|
||||
`schedule.date=2007-05-05,java.time.LocalDate`, is converted into a `JobParameter` object of type
|
||||
`java.time.LocalDate`.
|
||||
|
||||
[role="xmlContent"]
|
||||
The following example shows a sample configuration for `endOfDay` in XML:
|
||||
@@ -1030,8 +1033,8 @@ for simplicity, the class was used directly. This example uses the `EndOfDay`
|
||||
example from the <<domain.adoc#domainLanguageOfBatch,The Domain Language of Batch>>. The first
|
||||
argument is `io.spring.EndOfDayJobConfiguration`, which is the fully qualified class name
|
||||
to the configuration class that contains the Job. The second argument, `endOfDay`, represents
|
||||
the job name. The final argument, `schedule.date(date)=2007/05/05`, is converted into a
|
||||
`JobParameters` object.
|
||||
the job name. The final argument, `schedule.date=2007-05-05,java.time.LocalDate`, is converted
|
||||
into a `JobParameter` object of type `java.time.LocalDate`.
|
||||
|
||||
[role="javaContent"]
|
||||
The following example shows a sample configuration for `endOfDay` in Java:
|
||||
@@ -1067,7 +1070,8 @@ for simplicity, the class was used directly. This example uses the `EndOfDay`
|
||||
example from the <<domain.adoc#domainLanguageOfBatch,The Domain Language of Batch>>. The first
|
||||
argument is where your job is configured (either an XML file or a fully qualified class
|
||||
name). The second argument, `endOfDay`, represents the job name. The final argument,
|
||||
`schedule.date(date)=2007/05/05`, is converted into a `JobParameters` object.
|
||||
schedule.date=2007-05-05,java.time.LocalDate`, is converted into a `JobParameter` object of type
|
||||
`java.time.LocalDate`.
|
||||
|
||||
// TODO Given that this block is for PDF output, should it have the xmlContent and
|
||||
// javaContent markers?
|
||||
|
||||
@@ -138,12 +138,9 @@ listing shows:
|
||||
----
|
||||
CREATE TABLE BATCH_JOB_EXECUTION_PARAMS (
|
||||
JOB_EXECUTION_ID BIGINT NOT NULL ,
|
||||
TYPE_CD VARCHAR(6) NOT NULL ,
|
||||
KEY_NAME VARCHAR(100) NOT NULL ,
|
||||
STRING_VAL VARCHAR(250) ,
|
||||
DATE_VAL DATETIME DEFAULT NULL ,
|
||||
LONG_VAL BIGINT ,
|
||||
DOUBLE_VAL DOUBLE PRECISION ,
|
||||
NAME VARCHAR(100) NOT NULL ,
|
||||
TYPE VARCHAR(100) NOT NULL ,
|
||||
VALUE VARCHAR(2500) ,
|
||||
IDENTIFYING CHAR(1) NOT NULL ,
|
||||
constraint JOB_EXEC_PARAMS_FK foreign key (JOB_EXECUTION_ID)
|
||||
references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
|
||||
@@ -157,11 +154,9 @@ job execution to which the parameter entry belongs. Note that multiple rows (tha
|
||||
key/value pairs) may exist for each execution.
|
||||
* TYPE_CD: String representation of the type of value stored, which can be a string, a
|
||||
date, a long, or a double. Because the type must be known, it cannot be null.
|
||||
* KEY_NAME: The parameter key.
|
||||
* STRING_VAL: Parameter value if the type is string.
|
||||
* DATE_VAL: Parameter value if the type is date.
|
||||
* LONG_VAL: Parameter value if the type is long.
|
||||
* DOUBLE_VAL: Parameter value if the type is double.
|
||||
* NAME: The parameter name.
|
||||
* TYPE: The fully qualified name of the type of the parameter.
|
||||
* VALUE: Parameter value
|
||||
* IDENTIFYING: Flag indicating whether the parameter contributed to the identity of the
|
||||
related `JobInstance`.
|
||||
|
||||
|
||||
@@ -57,8 +57,8 @@ class RemoteChunkFaultTolerantStepIntegrationTests {
|
||||
|
||||
@Test
|
||||
void testFailedStep() throws Exception {
|
||||
JobExecution jobExecution = jobLauncher.run(job,
|
||||
new JobParameters(Collections.singletonMap("item.three", new JobParameter("unsupported"))));
|
||||
JobExecution jobExecution = jobLauncher.run(job, new JobParameters(
|
||||
Collections.singletonMap("item.three", new JobParameter("unsupported", String.class))));
|
||||
assertEquals(BatchStatus.FAILED, jobExecution.getStatus());
|
||||
StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next();
|
||||
assertEquals(9, stepExecution.getReadCount());
|
||||
@@ -69,7 +69,7 @@ class RemoteChunkFaultTolerantStepIntegrationTests {
|
||||
@Test
|
||||
void testFailedStepOnError() throws Exception {
|
||||
JobExecution jobExecution = jobLauncher.run(job,
|
||||
new JobParameters(Collections.singletonMap("item.three", new JobParameter("error"))));
|
||||
new JobParameters(Collections.singletonMap("item.three", new JobParameter("error", String.class))));
|
||||
assertEquals(BatchStatus.FAILED, jobExecution.getStatus());
|
||||
StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next();
|
||||
assertEquals(9, stepExecution.getReadCount());
|
||||
@@ -80,7 +80,7 @@ class RemoteChunkFaultTolerantStepIntegrationTests {
|
||||
@Test
|
||||
void testSunnyDayFaultTolerant() throws Exception {
|
||||
JobExecution jobExecution = jobLauncher.run(job,
|
||||
new JobParameters(Collections.singletonMap("item.three", new JobParameter("3"))));
|
||||
new JobParameters(Collections.singletonMap("item.three", new JobParameter("3", Integer.class))));
|
||||
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
|
||||
StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next();
|
||||
assertEquals(9, stepExecution.getReadCount());
|
||||
|
||||
@@ -58,8 +58,8 @@ class RemoteChunkFaultTolerantStepJdbcIntegrationTests {
|
||||
@Test
|
||||
@DirtiesContext
|
||||
void testFailedStep() throws Exception {
|
||||
JobExecution jobExecution = jobLauncher.run(job,
|
||||
new JobParameters(Collections.singletonMap("item.three", new JobParameter("unsupported"))));
|
||||
JobExecution jobExecution = jobLauncher.run(job, new JobParameters(
|
||||
Collections.singletonMap("item.three", new JobParameter("unsupported", String.class))));
|
||||
assertEquals(BatchStatus.FAILED, jobExecution.getStatus());
|
||||
StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next();
|
||||
assertEquals(9, stepExecution.getReadCount());
|
||||
@@ -71,7 +71,7 @@ class RemoteChunkFaultTolerantStepJdbcIntegrationTests {
|
||||
@DirtiesContext
|
||||
void testFailedStepOnError() throws Exception {
|
||||
JobExecution jobExecution = jobLauncher.run(job,
|
||||
new JobParameters(Collections.singletonMap("item.three", new JobParameter("error"))));
|
||||
new JobParameters(Collections.singletonMap("item.three", new JobParameter("error", String.class))));
|
||||
assertEquals(BatchStatus.FAILED, jobExecution.getStatus());
|
||||
StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next();
|
||||
assertEquals(9, stepExecution.getReadCount());
|
||||
@@ -83,7 +83,7 @@ class RemoteChunkFaultTolerantStepJdbcIntegrationTests {
|
||||
@DirtiesContext
|
||||
void testSunnyDayFaultTolerant() throws Exception {
|
||||
JobExecution jobExecution = jobLauncher.run(job,
|
||||
new JobParameters(Collections.singletonMap("item.three", new JobParameter("3"))));
|
||||
new JobParameters(Collections.singletonMap("item.three", new JobParameter("3", Integer.class))));
|
||||
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
|
||||
StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next();
|
||||
assertEquals(9, stepExecution.getReadCount());
|
||||
|
||||
@@ -52,8 +52,8 @@ class RemoteChunkFaultTolerantStepJmsIntegrationTests {
|
||||
|
||||
@Test
|
||||
void testFailedStep() throws Exception {
|
||||
JobExecution jobExecution = jobLauncher.run(job,
|
||||
new JobParameters(Collections.singletonMap("item.three", new JobParameter("unsupported"))));
|
||||
JobExecution jobExecution = jobLauncher.run(job, new JobParameters(
|
||||
Collections.singletonMap("item.three", new JobParameter("unsupported", String.class))));
|
||||
assertEquals(BatchStatus.FAILED, jobExecution.getStatus());
|
||||
StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next();
|
||||
assertEquals(9, stepExecution.getReadCount());
|
||||
@@ -64,7 +64,7 @@ class RemoteChunkFaultTolerantStepJmsIntegrationTests {
|
||||
@Test
|
||||
void testFailedStepOnError() throws Exception {
|
||||
JobExecution jobExecution = jobLauncher.run(job,
|
||||
new JobParameters(Collections.singletonMap("item.three", new JobParameter("error"))));
|
||||
new JobParameters(Collections.singletonMap("item.three", new JobParameter("error", String.class))));
|
||||
assertEquals(BatchStatus.FAILED, jobExecution.getStatus());
|
||||
StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next();
|
||||
assertEquals(9, stepExecution.getReadCount());
|
||||
@@ -75,7 +75,7 @@ class RemoteChunkFaultTolerantStepJmsIntegrationTests {
|
||||
@Test
|
||||
void testSunnyDayFaultTolerant() throws Exception {
|
||||
JobExecution jobExecution = jobLauncher.run(job,
|
||||
new JobParameters(Collections.singletonMap("item.three", new JobParameter("3"))));
|
||||
new JobParameters(Collections.singletonMap("item.three", new JobParameter("3", Integer.class))));
|
||||
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
|
||||
StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next();
|
||||
assertEquals(9, stepExecution.getReadCount());
|
||||
|
||||
@@ -42,7 +42,7 @@ class RemoteChunkStepIntegrationTests {
|
||||
@Test
|
||||
void testSunnyDaySimpleStep() throws Exception {
|
||||
JobExecution jobExecution = jobLauncher.run(job,
|
||||
new JobParameters(Collections.singletonMap("item.three", new JobParameter("3"))));
|
||||
new JobParameters(Collections.singletonMap("item.three", new JobParameter("3", Integer.class))));
|
||||
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
|
||||
StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next();
|
||||
assertEquals(9, stepExecution.getReadCount());
|
||||
@@ -52,7 +52,7 @@ class RemoteChunkStepIntegrationTests {
|
||||
@Test
|
||||
void testFailedStep() throws Exception {
|
||||
JobExecution jobExecution = jobLauncher.run(job,
|
||||
new JobParameters(Collections.singletonMap("item.three", new JobParameter("fail"))));
|
||||
new JobParameters(Collections.singletonMap("item.three", new JobParameter("fail", String.class))));
|
||||
assertEquals(BatchStatus.FAILED, jobExecution.getStatus());
|
||||
StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next();
|
||||
assertEquals(9, stepExecution.getReadCount());
|
||||
|
||||
@@ -26,7 +26,6 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.batch.core.BatchStatus;
|
||||
import org.springframework.batch.core.Job;
|
||||
import org.springframework.batch.core.JobParametersBuilder;
|
||||
import org.springframework.batch.core.configuration.JobRegistry;
|
||||
import org.springframework.batch.core.configuration.support.ReferenceJobFactory;
|
||||
import org.springframework.batch.core.launch.JobOperator;
|
||||
@@ -61,7 +60,7 @@ class JobOperatorFunctionalTests {
|
||||
|
||||
@Test
|
||||
void testStartStopResumeJob() throws Exception {
|
||||
String params = new JobParametersBuilder().addLong("jobOperatorTestParam", 7L).toJobParameters().toString();
|
||||
String params = "jobOperatorTestParam=7,java.lang.Long,true";
|
||||
|
||||
long executionId = operator.start(job.getName(), params);
|
||||
assertEquals(params, operator.getParameters(executionId));
|
||||
|
||||
@@ -153,8 +153,8 @@ public class JobLauncherTestUtils {
|
||||
* of type {@code long}, to ensure that the job instance will be unique.
|
||||
*/
|
||||
public JobParameters getUniqueJobParameters() {
|
||||
Map<String, JobParameter> parameters = new HashMap<>();
|
||||
parameters.put("random", new JobParameter(this.secureRandom.nextLong()));
|
||||
Map<String, JobParameter<?>> parameters = new HashMap<>();
|
||||
parameters.put("random", new JobParameter(this.secureRandom.nextLong(), Long.class));
|
||||
return new JobParameters(parameters);
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ public class JobRepositoryTestUtils {
|
||||
|
||||
@Override
|
||||
public JobParameters getNext(@Nullable JobParameters parameters) {
|
||||
return new JobParameters(Collections.singletonMap("count", new JobParameter(count++)));
|
||||
return new JobParameters(Collections.singletonMap("count", new JobParameter(count++, Long.class)));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2006-2021 the original author or authors.
|
||||
* 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.
|
||||
@@ -185,8 +185,8 @@ public class StepRunner {
|
||||
* timestamp, to ensure that the job instance will be unique
|
||||
*/
|
||||
private JobParameters makeUniqueJobParameters() {
|
||||
Map<String, JobParameter> parameters = new HashMap<>();
|
||||
parameters.put("timestamp", new JobParameter(new Date().getTime()));
|
||||
Map<String, JobParameter<?>> parameters = new HashMap<>();
|
||||
parameters.put("timestamp", new JobParameter(new Date().getTime(), Long.class));
|
||||
return new JobParameters(parameters);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user