11/*
2- * Copyright 2006-2023 the original author or authors.
2+ * Copyright 2006-2025 the original author or authors.
33 *
44 * Licensed under the Apache License, Version 2.0 (the "License");
55 * you may not use this file except in compliance with the License.
1616
1717package org .springframework .batch .core .job ;
1818
19- import java .io .IOException ;
20- import java .io .ObjectInputStream ;
2119import java .time .LocalDateTime ;
2220import java .util .ArrayList ;
2321import java .util .Collection ;
2422import java .util .Collections ;
2523import java .util .HashSet ;
26- import java .util .LinkedHashSet ;
24+ import java .util .LinkedList ;
2725import java .util .List ;
2826import java .util .Set ;
2927import java .util .concurrent .CopyOnWriteArrayList ;
@@ -50,85 +48,38 @@ public class JobExecution extends Entity {
5048
5149 private JobInstance jobInstance ;
5250
53- private volatile Collection <StepExecution > stepExecutions = Collections .synchronizedSet (new LinkedHashSet <>());
51+ private final List <StepExecution > stepExecutions = Collections .synchronizedList (new LinkedList <>());
5452
55- private volatile BatchStatus status = BatchStatus .STARTING ;
53+ private BatchStatus status = BatchStatus .STARTING ;
5654
57- private volatile LocalDateTime startTime = null ;
55+ private LocalDateTime createTime = LocalDateTime . now () ;
5856
59- private volatile LocalDateTime createTime = LocalDateTime . now () ;
57+ private LocalDateTime startTime = null ;
6058
61- private volatile LocalDateTime endTime = null ;
59+ private LocalDateTime endTime = null ;
6260
63- private volatile LocalDateTime lastUpdated = null ;
61+ private LocalDateTime lastUpdated = null ;
6462
65- private volatile ExitStatus exitStatus = ExitStatus .UNKNOWN ;
63+ private ExitStatus exitStatus = ExitStatus .UNKNOWN ;
6664
67- private volatile ExecutionContext executionContext = new ExecutionContext ();
65+ private ExecutionContext executionContext = new ExecutionContext ();
6866
69- private transient volatile List <Throwable > failureExceptions = new CopyOnWriteArrayList <>();
67+ private final List <Throwable > failureExceptions = new CopyOnWriteArrayList <>();
7068
7169 /**
72- * Constructor that sets the state of the instance to the {@link JobExecution}
73- * parameter.
74- * @param original The {@link JobExecution} to be copied.
75- */
76- public JobExecution (JobExecution original ) {
77- this .jobParameters = original .getJobParameters ();
78- this .jobInstance = original .getJobInstance ();
79- this .stepExecutions = original .getStepExecutions ();
80- this .status = original .getStatus ();
81- this .startTime = original .getStartTime ();
82- this .createTime = original .getCreateTime ();
83- this .endTime = original .getEndTime ();
84- this .lastUpdated = original .getLastUpdated ();
85- this .exitStatus = original .getExitStatus ();
86- this .executionContext = original .getExecutionContext ();
87- this .failureExceptions = original .getFailureExceptions ();
88- this .setId (original .getId ());
89- this .setVersion (original .getVersion ());
90- }
91-
92- /**
93- * Because a JobExecution is not valid unless the job is set, this constructor is the
94- * only valid one from a modeling point of view.
95- * @param job The job of which this execution is a part.
96- * @param id A {@link Long} that represents the {@code id} for the
97- * {@code JobExecution}.
70+ * Create a new {@link JobExecution} instance. Because a JobExecution is not valid
71+ * unless the job instance is set, this constructor is the only valid one from a
72+ * modeling point of view.
73+ * @param jobInstance The job instance of which this execution is a part.
74+ * @param id of the {@code JobExecution}.
9875 * @param jobParameters A {@link JobParameters} instance for this
9976 * {@code JobExecution}.
10077 */
101- public JobExecution (JobInstance job , Long id , @ Nullable JobParameters jobParameters ) {
78+ // TODO add execution context parameter
79+ public JobExecution (long id , JobInstance jobInstance , JobParameters jobParameters ) {
10280 super (id );
103- this .jobInstance = job ;
104- this .jobParameters = jobParameters == null ? new JobParameters () : jobParameters ;
105- }
106-
107- /**
108- * Constructor for transient (unsaved) instances.
109- * @param job The enclosing {@link JobInstance}.
110- * @param jobParameters The {@link JobParameters} instance for this
111- * {@code JobExecution}.
112- */
113- public JobExecution (JobInstance job , JobParameters jobParameters ) {
114- this (job , null , jobParameters );
115- }
116-
117- /**
118- * Constructor that accepts the job execution {@code id} and {@link JobParameters}.
119- * @param id The job execution {@code id}.
120- * @param jobParameters The {@link JobParameters} for the {@link JobExecution}.
121- */
122- public JobExecution (Long id , JobParameters jobParameters ) {
123- this (null , id , jobParameters );
124- }
125-
126- /**
127- * Constructor that accepts the job execution {@code id}.
128- * @param id The job execution {@code id}.
129- */
130- public JobExecution (Long id ) {
131- this (null , id , null );
81+ this .jobInstance = jobInstance ;
82+ this .jobParameters = jobParameters ;
13283 }
13384
13485 /**
@@ -204,15 +155,14 @@ public void upgradeStatus(BatchStatus status) {
204155 }
205156
206157 /**
207- * Convenience getter for the {@code id} of the enclosing job. Useful for DAO
158+ * Convenience getter for the {@code id} of the enclosing job instance . Useful for DAO
208159 * implementations.
209- * @return the {@code id} of the enclosing job.
160+ * @return the {@code id} of the enclosing job instance .
210161 */
211- public Long getJobId () {
212- if (jobInstance != null ) {
213- return jobInstance .getId ();
214- }
215- return null ;
162+ // TODO why is that needed for DAO implementations? should not be needed with the new
163+ // model
164+ public long getJobInstanceId () {
165+ return this .jobInstance .getId ();
216166 }
217167
218168 /**
@@ -230,29 +180,18 @@ public ExitStatus getExitStatus() {
230180 }
231181
232182 /**
233- * @return the Job that is executing.
183+ * @return the Job instance that is executing.
234184 */
235185 public JobInstance getJobInstance () {
236- return jobInstance ;
186+ return this . jobInstance ;
237187 }
238188
239189 /**
240190 * Accessor for the step executions.
241191 * @return the step executions that were registered.
242192 */
243193 public Collection <StepExecution > getStepExecutions () {
244- return List .copyOf (stepExecutions );
245- }
246-
247- /**
248- * Register a step execution with the current job execution.
249- * @param stepName the name of the step the new execution is associated with.
250- * @return an empty {@link StepExecution} associated with this {@code JobExecution}.
251- */
252- public StepExecution createStepExecution (String stepName ) {
253- StepExecution stepExecution = new StepExecution (stepName , this );
254- this .stepExecutions .add (stepExecution );
255- return stepExecution ;
194+ return List .copyOf (this .stepExecutions );
256195 }
257196
258197 /**
@@ -305,11 +244,19 @@ public void setCreateTime(LocalDateTime createTime) {
305244 }
306245
307246 /**
308- * Add a step execution from an existing instance .
247+ * Add a step execution.
309248 * @param stepExecution The {@code stepExecution} execution to be added.
310249 */
311250 public void addStepExecution (StepExecution stepExecution ) {
312- stepExecutions .add (stepExecution );
251+ this .stepExecutions .add (stepExecution );
252+ }
253+
254+ /**
255+ * Add some step executions.
256+ * @param stepExecutions The step executions to add to the current list.
257+ */
258+ public void addStepExecutions (List <StepExecution > stepExecutions ) {
259+ this .stepExecutions .addAll (stepExecutions );
313260 }
314261
315262 /**
@@ -364,33 +311,11 @@ public synchronized List<Throwable> getAllFailureExceptions() {
364311 return new ArrayList <>(allExceptions );
365312 }
366313
367- /**
368- * Deserialize and ensure transient fields are re-instantiated when read back.
369- * @param stream instance of {@link ObjectInputStream}.
370- * @throws IOException if an error occurs during read.
371- * @throws ClassNotFoundException thrown if the class is not found.
372- */
373- private void readObject (ObjectInputStream stream ) throws IOException , ClassNotFoundException {
374- stream .defaultReadObject ();
375- failureExceptions = new ArrayList <>();
376- }
377-
378314 @ Override
379315 public String toString () {
380316 return super .toString () + String .format (
381317 ", startTime=%s, endTime=%s, lastUpdated=%s, status=%s, exitStatus=%s, job=[%s], jobParameters=[%s]" ,
382318 startTime , endTime , lastUpdated , status , exitStatus , jobInstance , jobParameters );
383319 }
384320
385- /**
386- * Add some step executions. For internal use only.
387- * @param stepExecutions The step executions to add to the current list.
388- */
389- public void addStepExecutions (List <StepExecution > stepExecutions ) {
390- if (stepExecutions != null ) {
391- this .stepExecutions .removeAll (stepExecutions );
392- this .stepExecutions .addAll (stepExecutions );
393- }
394- }
395-
396321}
0 commit comments