Skip to content

Commit 34cf4d7

Browse files
committed
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: * spring-projects#3960 * spring-projects#2122 * spring-projects#1035 * spring-projects#1983
1 parent 0273024 commit 34cf4d7

File tree

69 files changed

+2482
-901
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+2482
-901
lines changed

spring-batch-core/src/main/java/org/springframework/batch/core/DefaultJobKeyGenerator.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,14 @@ public class DefaultJobKeyGenerator implements JobKeyGenerator<JobParameters> {
4444
public String generateKey(JobParameters source) {
4545

4646
Assert.notNull(source, "source must not be null");
47-
Map<String, JobParameter> props = source.getParameters();
47+
Map<String, JobParameter<?>> props = source.getParameters();
4848
StringBuilder stringBuffer = new StringBuilder();
4949
List<String> keys = new ArrayList<>(props.keySet());
5050
Collections.sort(keys);
5151
for (String key : keys) {
52-
JobParameter jobParameter = props.get(key);
52+
JobParameter<?> jobParameter = props.get(key);
5353
if (jobParameter.isIdentifying()) {
54-
String value = jobParameter.getValue() == null ? "" : jobParameter.toString();
54+
String value = jobParameter.toString();
5555
stringBuffer.append(key).append("=").append(value).append(";");
5656
}
5757
}

spring-batch-core/src/main/java/org/springframework/batch/core/JobParameter.java

Lines changed: 30 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,14 @@
1717
package org.springframework.batch.core;
1818

1919
import java.io.Serializable;
20-
import java.util.Date;
2120

2221
import org.springframework.lang.NonNull;
2322
import org.springframework.util.Assert;
2423

2524
/**
26-
* Domain representation of a parameter to a batch job. Only the following types can be
27-
* parameters: String, Long, Date, and Double. The identifying flag is used to indicate if
28-
* the parameter is to be used as part of the identification of a job instance.
25+
* Domain representation of a parameter to a batch job. The identifying flag is used to
26+
* indicate if the parameter is to be used as part of the identification of a job
27+
* instance.
2928
*
3029
* @author Lucas Ward
3130
* @author Dave Syer
@@ -34,87 +33,35 @@
3433
* @since 2.0
3534
*
3635
*/
37-
public class JobParameter implements Serializable {
36+
public class JobParameter<T> implements Serializable {
3837

39-
private final Object parameter;
38+
private T value;
4039

41-
private final ParameterType parameterType;
40+
private Class<T> type;
4241

43-
private final boolean identifying;
42+
private boolean identifying;
4443

4544
/**
46-
* Construct a new {@code JobParameter} from a {@link String}.
47-
* @param parameter {@link String} instance. Must not be {@code null}.
48-
* @param identifying {@code true} if the {@code JobParameter} should be identifying.
45+
* reate a new {@link JobParameter}.
46+
* @param value the value of the parameter. Must not be {@code null}.
47+
* @param type the type of the parameter. Must not be {@code null}.
48+
* @param identifying true if the parameter is identifying. false otherwise.
4949
*/
50-
public JobParameter(@NonNull String parameter, boolean identifying) {
51-
this(parameter, identifying, ParameterType.STRING);
52-
}
53-
54-
/**
55-
* Construct a new {@code JobParameter} from a {@link Long}.
56-
* @param parameter {@link Long} instance. Must not be {@code null}.
57-
* @param identifying {@code true} if the {@code JobParameter} should be identifying.
58-
*/
59-
public JobParameter(@NonNull Long parameter, boolean identifying) {
60-
this(parameter, identifying, ParameterType.LONG);
61-
}
62-
63-
/**
64-
* Construct a new {@code JobParameter} from a {@link Date}.
65-
* @param parameter {@link Date} instance. Must not be {@code null}.
66-
* @param identifying {@code true} if the {@code JobParameter} should be identifying.
67-
*/
68-
public JobParameter(@NonNull Date parameter, boolean identifying) {
69-
this(parameter, identifying, ParameterType.DATE);
70-
}
71-
72-
/**
73-
* Construct a new {@code JobParameter} from a {@link Double}.
74-
* @param parameter {@link Double} instance. Must not be {@code null}.
75-
* @param identifying {@code true} if the {@code JobParameter} should be identifying.
76-
*/
77-
public JobParameter(@NonNull Double parameter, boolean identifying) {
78-
this(parameter, identifying, ParameterType.DOUBLE);
79-
}
80-
81-
private JobParameter(Object parameter, boolean identifying, ParameterType parameterType) {
82-
Assert.notNull(parameter, "parameter must not be null");
83-
this.parameter = parameter;
84-
this.parameterType = parameterType;
50+
public JobParameter(@NonNull T value, @NonNull Class<T> type, boolean identifying) {
51+
Assert.notNull(value, "value must not be null");
52+
Assert.notNull(value, "type must not be null");
53+
this.value = value;
54+
this.type = type;
8555
this.identifying = identifying;
8656
}
8757

8858
/**
89-
* Construct a new {@code JobParameter} from a {@link String}.
90-
* @param parameter A {@link String} instance.
59+
* Create a new identifying {@link JobParameter}.
60+
* @param value the value of the parameter. Must not be {@code null}.
61+
* @param type the type of the parameter. Must not be {@code null}.
9162
*/
92-
public JobParameter(String parameter) {
93-
this(parameter, true);
94-
}
95-
96-
/**
97-
* Construct a new {@code JobParameter} from a {@link Long}.
98-
* @param parameter A {@link Long} instance.
99-
*/
100-
public JobParameter(Long parameter) {
101-
this(parameter, true);
102-
}
103-
104-
/**
105-
* Construct a new {@code JobParameter} as a {@link Date}.
106-
* @param parameter A {@link Date} instance.
107-
*/
108-
public JobParameter(Date parameter) {
109-
this(parameter, true);
110-
}
111-
112-
/**
113-
* Construct a new {@code JobParameter} from a {@link Double}.
114-
* @param parameter A {@link Double} instance.
115-
*/
116-
public JobParameter(Double parameter) {
117-
this(parameter, true);
63+
public JobParameter(@NonNull T value, @NonNull Class<T> type) {
64+
this(value, type, true);
11865
}
11966

12067
/**
@@ -128,15 +75,16 @@ public boolean isIdentifying() {
12875
/**
12976
* @return the value contained within this {@code JobParameter}.
13077
*/
131-
public Object getValue() {
132-
return parameter;
78+
public T getValue() {
79+
return value;
13380
}
13481

13582
/**
136-
* @return a {@link ParameterType} representing the type of this parameter.
83+
* Return the type of the parameter.
84+
* @return the type of the parameter
13785
*/
138-
public ParameterType getType() {
139-
return parameterType;
86+
public Class<T> getType() {
87+
return type;
14088
}
14189

14290
@Override
@@ -150,41 +98,17 @@ public boolean equals(Object obj) {
15098
}
15199

152100
JobParameter rhs = (JobParameter) obj;
153-
return parameterType == rhs.parameterType && parameter.equals(rhs.parameter);
101+
return type == rhs.type && value.equals(rhs.value);
154102
}
155103

156104
@Override
157105
public String toString() {
158-
return parameterType == ParameterType.DATE ? "" + ((Date) parameter).getTime() : parameter.toString();
106+
return "{" + "value=" + value + ", type=" + type + ", identifying=" + identifying + '}';
159107
}
160108

161109
@Override
162110
public int hashCode() {
163-
return 7 + 21 * parameter.hashCode();
164-
}
165-
166-
/**
167-
* Enumeration representing the type of {@link JobParameter}.
168-
*/
169-
public enum ParameterType {
170-
171-
/**
172-
* String parameter type.
173-
*/
174-
STRING,
175-
/**
176-
* Date parameter type.
177-
*/
178-
DATE,
179-
/**
180-
* Long parameter type.
181-
*/
182-
LONG,
183-
/**
184-
* Double parameter type.
185-
*/
186-
DOUBLE;
187-
111+
return 7 + 21 * value.hashCode();
188112
}
189113

190114
}

spring-batch-core/src/main/java/org/springframework/batch/core/JobParameters.java

Lines changed: 50 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,17 @@
1717
package org.springframework.batch.core;
1818

1919
import java.io.Serializable;
20+
import java.util.ArrayList;
2021
import java.util.Collections;
2122
import java.util.Date;
2223
import java.util.LinkedHashMap;
24+
import java.util.List;
2325
import java.util.Map;
2426
import java.util.Objects;
2527
import java.util.Properties;
2628

2729
import org.springframework.lang.Nullable;
30+
import org.springframework.util.Assert;
2831

2932
/**
3033
* Value object representing runtime parameters to a batch job. Because the parameters
@@ -46,7 +49,7 @@
4649
@SuppressWarnings("serial")
4750
public class JobParameters implements Serializable {
4851

49-
private final Map<String, JobParameter> parameters;
52+
private final Map<String, JobParameter<?>> parameters;
5053

5154
/**
5255
* Default constructor.
@@ -61,7 +64,7 @@ public JobParameters() {
6164
* @param parameters The {@link Map} that contains a {@code String} key and a
6265
* {@link JobParameter} value.
6366
*/
64-
public JobParameters(Map<String, JobParameter> parameters) {
67+
public JobParameters(Map<String, JobParameter<?>> parameters) {
6568
this.parameters = new LinkedHashMap<>(parameters);
6669
}
6770

@@ -75,8 +78,11 @@ public Long getLong(String key) {
7578
if (!parameters.containsKey(key)) {
7679
return null;
7780
}
78-
Object value = parameters.get(key).getValue();
79-
return value == null ? null : ((Long) value).longValue();
81+
JobParameter<?> jobParameter = parameters.get(key);
82+
if (!jobParameter.getType().equals(Long.class)) {
83+
throw new IllegalArgumentException("Key " + key + " is not of type Long");
84+
}
85+
return (Long) jobParameter.getValue();
8086
}
8187

8288
/**
@@ -104,8 +110,14 @@ public Long getLong(String key, @Nullable Long defaultValue) {
104110
*/
105111
@Nullable
106112
public String getString(String key) {
107-
JobParameter value = parameters.get(key);
108-
return value == null ? null : value.toString();
113+
if (!parameters.containsKey(key)) {
114+
return null;
115+
}
116+
JobParameter<?> jobParameter = parameters.get(key);
117+
if (!jobParameter.getType().equals(String.class)) {
118+
throw new IllegalArgumentException("Key " + key + " is not of type String");
119+
}
120+
return (String) jobParameter.getValue();
109121
}
110122

111123
/**
@@ -136,8 +148,11 @@ public Double getDouble(String key) {
136148
if (!parameters.containsKey(key)) {
137149
return null;
138150
}
139-
Double value = (Double) parameters.get(key).getValue();
140-
return value == null ? null : value.doubleValue();
151+
JobParameter<?> jobParameter = parameters.get(key);
152+
if (!jobParameter.getType().equals(Double.class)) {
153+
throw new IllegalArgumentException("Key " + key + " is not of type Double");
154+
}
155+
return (Double) jobParameter.getValue();
141156
}
142157

143158
/**
@@ -165,7 +180,14 @@ public Double getDouble(String key, @Nullable Double defaultValue) {
165180
*/
166181
@Nullable
167182
public Date getDate(String key) {
168-
return this.getDate(key, null);
183+
if (!parameters.containsKey(key)) {
184+
return null;
185+
}
186+
JobParameter<?> jobParameter = parameters.get(key);
187+
if (!jobParameter.getType().equals(Date.class)) {
188+
throw new IllegalArgumentException("Key " + key + " is not of type java.util.Date");
189+
}
190+
return (Date) jobParameter.getValue();
169191
}
170192

171193
/**
@@ -179,19 +201,24 @@ public Date getDate(String key) {
179201
@Nullable
180202
public Date getDate(String key, @Nullable Date defaultValue) {
181203
if (parameters.containsKey(key)) {
182-
return (Date) parameters.get(key).getValue();
204+
return getDate(key);
183205
}
184206
else {
185207
return defaultValue;
186208
}
187209
}
188210

211+
@Nullable
212+
public JobParameter<?> getParameter(String key) {
213+
Assert.notNull(key, "key must not be null");
214+
return parameters.get(key);
215+
}
216+
189217
/**
190-
* Get a map of all parameters, including {@link String}, {@link Long}, and
191-
* {@link Date} types.
218+
* Get a map of all parameters.
192219
* @return an unmodifiable map containing all parameters.
193220
*/
194-
public Map<String, JobParameter> getParameters() {
221+
public Map<String, JobParameter<?>> getParameters() {
195222
return Collections.unmodifiableMap(parameters);
196223
}
197224

@@ -223,17 +250,25 @@ public int hashCode() {
223250

224251
@Override
225252
public String toString() {
226-
return parameters.toString();
253+
List<String> parameters = new ArrayList<>();
254+
for (Map.Entry<String, JobParameter<?>> entry : this.parameters.entrySet()) {
255+
parameters.add(String.format("'%s':'%s'", entry.getKey(), entry.getValue()));
256+
}
257+
return new StringBuilder("{").append(String.join(",", parameters)).append("}").toString();
227258
}
228259

229260
/**
230261
* @return The {@link Properties} that contain the key and values for the
231262
* {@link JobParameter} objects.
263+
* @deprecated since 5.0, scheduled for removal in 5.2. Use
264+
* {@link org.springframework.batch.core.converter.JobParametersConverter#getProperties(JobParameters)}
265+
*
232266
*/
267+
@Deprecated(since = "5.0", forRemoval = true)
233268
public Properties toProperties() {
234269
Properties props = new Properties();
235270

236-
for (Map.Entry<String, JobParameter> param : parameters.entrySet()) {
271+
for (Map.Entry<String, JobParameter<?>> param : parameters.entrySet()) {
237272
if (param.getValue() != null) {
238273
props.put(param.getKey(), Objects.toString(param.getValue().toString(), ""));
239274
}

0 commit comments

Comments
 (0)