1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.batch.core;
18
19 import java.io.IOException;
20 import java.io.ObjectInputStream;
21 import java.util.ArrayList;
22 import java.util.Collection;
23 import java.util.Collections;
24 import java.util.Date;
25 import java.util.HashSet;
26 import java.util.List;
27 import java.util.Set;
28 import java.util.concurrent.CopyOnWriteArrayList;
29 import java.util.concurrent.CopyOnWriteArraySet;
30
31 import org.springframework.batch.item.ExecutionContext;
32
33
34
35
36
37
38
39 @SuppressWarnings("serial")
40 public class JobExecution extends Entity {
41
42 private JobInstance jobInstance;
43
44 private volatile Collection<StepExecution> stepExecutions = new CopyOnWriteArraySet<StepExecution>();
45
46 private volatile BatchStatus status = BatchStatus.STARTING;
47
48 private volatile Date startTime = null;
49
50 private volatile Date createTime = new Date(System.currentTimeMillis());
51
52 private volatile Date endTime = null;
53
54 private volatile Date lastUpdated = null;
55
56 private volatile ExitStatus exitStatus = ExitStatus.UNKNOWN;
57
58 private volatile ExecutionContext executionContext = new ExecutionContext();
59
60 private transient volatile List<Throwable> failureExceptions = new CopyOnWriteArrayList<Throwable>();
61
62
63
64
65
66
67
68 public JobExecution(JobInstance job, Long id) {
69 super(id);
70 this.jobInstance = job;
71 }
72
73
74
75
76
77
78 public JobExecution(JobInstance job) {
79 this(job, null);
80 }
81
82 public JobExecution(Long id) {
83 super(id);
84 }
85
86 public Date getEndTime() {
87 return endTime;
88 }
89
90 public void setJobInstance(JobInstance jobInstance) {
91 this.jobInstance = jobInstance;
92 }
93
94 public void setEndTime(Date endTime) {
95 this.endTime = endTime;
96 }
97
98 public Date getStartTime() {
99 return startTime;
100 }
101
102 public void setStartTime(Date startTime) {
103 this.startTime = startTime;
104 }
105
106 public BatchStatus getStatus() {
107 return status;
108 }
109
110
111
112
113
114
115 public void setStatus(BatchStatus status) {
116 this.status = status;
117 }
118
119
120
121
122
123
124
125
126 public void upgradeStatus(BatchStatus status) {
127 this.status = this.status.upgradeTo(status);
128 }
129
130
131
132
133
134
135
136 public Long getJobId() {
137 if (jobInstance != null) {
138 return jobInstance.getId();
139 }
140 return null;
141 }
142
143
144
145
146 public void setExitStatus(ExitStatus exitStatus) {
147 this.exitStatus = exitStatus;
148 }
149
150
151
152
153 public ExitStatus getExitStatus() {
154 return exitStatus;
155 }
156
157
158
159
160 public JobInstance getJobInstance() {
161 return jobInstance;
162 }
163
164
165
166
167
168
169 public Collection<StepExecution> getStepExecutions() {
170 return Collections.unmodifiableList(new ArrayList<StepExecution>(stepExecutions));
171 }
172
173
174
175
176
177 public StepExecution createStepExecution(String stepName) {
178 StepExecution stepExecution = new StepExecution(stepName, this);
179 this.stepExecutions.add(stepExecution);
180 return stepExecution;
181 }
182
183
184
185
186
187
188
189 public boolean isRunning() {
190 return endTime == null;
191 }
192
193
194
195
196
197
198 public boolean isStopping() {
199 return status == BatchStatus.STOPPING;
200 }
201
202
203
204
205
206
207 public void stop() {
208 for (StepExecution stepExecution : stepExecutions) {
209 stepExecution.setTerminateOnly();
210 }
211 status = BatchStatus.STOPPING;
212 }
213
214
215
216
217
218
219 public void setExecutionContext(ExecutionContext executionContext) {
220 this.executionContext = executionContext;
221 }
222
223
224
225
226
227
228
229 public ExecutionContext getExecutionContext() {
230 return executionContext;
231 }
232
233
234
235
236 public Date getCreateTime() {
237 return createTime;
238 }
239
240
241
242
243 public void setCreateTime(Date createTime) {
244 this.createTime = createTime;
245 }
246
247
248
249
250
251
252 void addStepExecution(StepExecution stepExecution) {
253 stepExecutions.add(stepExecution);
254 }
255
256
257
258
259
260
261
262 public Date getLastUpdated() {
263 return lastUpdated;
264 }
265
266
267
268
269
270
271 public void setLastUpdated(Date lastUpdated) {
272 this.lastUpdated = lastUpdated;
273 }
274
275 public List<Throwable> getFailureExceptions() {
276 return failureExceptions;
277 }
278
279
280
281
282
283
284 public synchronized void addFailureException(Throwable t) {
285 this.failureExceptions.add(t);
286 }
287
288
289
290
291
292
293
294
295 public synchronized List<Throwable> getAllFailureExceptions() {
296
297 Set<Throwable> allExceptions = new HashSet<Throwable>(failureExceptions);
298 for (StepExecution stepExecution : stepExecutions) {
299 allExceptions.addAll(stepExecution.getFailureExceptions());
300 }
301
302 return new ArrayList<Throwable>(allExceptions);
303 }
304
305
306
307
308
309 private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
310 stream.defaultReadObject();
311 failureExceptions = new ArrayList<Throwable>();
312 }
313
314
315
316
317
318
319 @Override
320 public String toString() {
321 return super.toString()
322 + String.format(", startTime=%s, endTime=%s, lastUpdated=%s, status=%s, exitStatus=%s, job=[%s]",
323 startTime, endTime, lastUpdated, status, exitStatus, jobInstance);
324 }
325
326
327
328
329
330 public void addStepExecutions(List<StepExecution> stepExecutions) {
331 if (stepExecutions!=null) {
332 this.stepExecutions.removeAll(stepExecutions);
333 this.stepExecutions.addAll(stepExecutions);
334 }
335 }
336
337 }