EMMA Coverage Report (generated Thu May 22 12:08:10 CDT 2014)
[all classes][org.springframework.batch.core.repository.support]

COVERAGE SUMMARY FOR SOURCE FILE [SimpleJobRepository.java]

nameclass, %method, %block, %line, %
SimpleJobRepository.java100% (1/1)94%  (15/16)96%  (416/435)96%  (106/110)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class SimpleJobRepository100% (1/1)94%  (15/16)96%  (416/435)96%  (106/110)
SimpleJobRepository (): void 0%   (0/1)0%   (0/3)0%   (0/2)
createJobExecution (String, JobParameters): JobExecution 100% (1/1)88%  (98/112)95%  (21/22)
getLastStepExecution (JobInstance, String): StepExecution 100% (1/1)98%  (84/86)95%  (19/20)
<static initializer> 100% (1/1)100% (4/4)100% (1/1)
SimpleJobRepository (JobInstanceDao, JobExecutionDao, StepExecutionDao, Execu... 100% (1/1)100% (15/15)100% (6/6)
add (StepExecution): void 100% (1/1)100% (18/18)100% (5/5)
addAll (Collection): void 100% (1/1)100% (32/32)100% (8/8)
checkForInterruption (StepExecution): void 100% (1/1)100% (16/16)100% (6/6)
getLastJobExecution (String, JobParameters): JobExecution 100% (1/1)100% (25/25)100% (7/7)
getStepExecutionCount (JobInstance, String): int 100% (1/1)100% (42/42)100% (10/10)
isJobInstanceExists (String, JobParameters): boolean 100% (1/1)100% (10/10)100% (1/1)
update (JobExecution): void 100% (1/1)100% (22/22)100% (6/6)
update (StepExecution): void 100% (1/1)100% (21/21)100% (6/6)
updateExecutionContext (JobExecution): void 100% (1/1)100% (5/5)100% (2/2)
updateExecutionContext (StepExecution): void 100% (1/1)100% (12/12)100% (4/4)
validateStepExecution (StepExecution): void 100% (1/1)100% (12/12)100% (4/4)

1/*
2 * Copyright 2006-2013 the original author or authors.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 
17package org.springframework.batch.core.repository.support;
18 
19import java.util.ArrayList;
20import java.util.Collection;
21import java.util.Date;
22import java.util.List;
23 
24import org.apache.commons.logging.Log;
25import org.apache.commons.logging.LogFactory;
26import org.springframework.batch.core.BatchStatus;
27import org.springframework.batch.core.JobExecution;
28import org.springframework.batch.core.JobInstance;
29import org.springframework.batch.core.JobParameters;
30import org.springframework.batch.core.StepExecution;
31import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
32import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
33import org.springframework.batch.core.repository.JobRepository;
34import org.springframework.batch.core.repository.JobRestartException;
35import org.springframework.batch.core.repository.dao.ExecutionContextDao;
36import org.springframework.batch.core.repository.dao.JobExecutionDao;
37import org.springframework.batch.core.repository.dao.JobInstanceDao;
38import org.springframework.batch.core.repository.dao.StepExecutionDao;
39import org.springframework.batch.item.ExecutionContext;
40import org.springframework.util.Assert;
41 
42/**
43 *
44 * <p>
45 * Implementation of {@link JobRepository} that stores JobInstances,
46 * JobExecutions, and StepExecutions using the injected DAOs.
47 * <p>
48 *
49 * @author Lucas Ward
50 * @author Dave Syer
51 * @author Robert Kasanicky
52 * @author David Turanski
53 *
54 * @see JobRepository
55 * @see JobInstanceDao
56 * @see JobExecutionDao
57 * @see StepExecutionDao
58 *
59 */
60public class SimpleJobRepository implements JobRepository {
61 
62        private static final Log logger = LogFactory.getLog(SimpleJobRepository.class);
63 
64        private JobInstanceDao jobInstanceDao;
65 
66        private JobExecutionDao jobExecutionDao;
67 
68        private StepExecutionDao stepExecutionDao;
69 
70        private ExecutionContextDao ecDao;
71 
72        /**
73         * Provide default constructor with low visibility in case user wants to use
74         * use aop:proxy-target-class="true" for AOP interceptor.
75         */
76        SimpleJobRepository() {
77        }
78 
79        public SimpleJobRepository(JobInstanceDao jobInstanceDao, JobExecutionDao jobExecutionDao,
80                        StepExecutionDao stepExecutionDao, ExecutionContextDao ecDao) {
81                super();
82                this.jobInstanceDao = jobInstanceDao;
83                this.jobExecutionDao = jobExecutionDao;
84                this.stepExecutionDao = stepExecutionDao;
85                this.ecDao = ecDao;
86        }
87 
88        @Override
89        public boolean isJobInstanceExists(String jobName, JobParameters jobParameters) {
90                return jobInstanceDao.getJobInstance(jobName, jobParameters) != null;
91        }
92 
93        @Override
94        public JobExecution createJobExecution(String jobName, JobParameters jobParameters)
95                        throws JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException {
96 
97                Assert.notNull(jobName, "Job name must not be null.");
98                Assert.notNull(jobParameters, "JobParameters must not be null.");
99 
100                /*
101                 * Find all jobs matching the runtime information.
102                 *
103                 * If this method is transactional, and the isolation level is
104                 * REPEATABLE_READ or better, another launcher trying to start the same
105                 * job in another thread or process will block until this transaction
106                 * has finished.
107                 */
108 
109                JobInstance jobInstance = jobInstanceDao.getJobInstance(jobName, jobParameters);
110                ExecutionContext executionContext;
111 
112                // existing job instance found
113                if (jobInstance != null) {
114 
115                        List<JobExecution> executions = jobExecutionDao.findJobExecutions(jobInstance);
116 
117                        // check for running executions and find the last started
118                        for (JobExecution execution : executions) {
119                                if (execution.isRunning()) {
120                                        throw new JobExecutionAlreadyRunningException("A job execution for this job is already running: "
121                                                        + jobInstance);
122                                }
123 
124                                BatchStatus status = execution.getStatus();
125                                if (status == BatchStatus.COMPLETED || status == BatchStatus.ABANDONED) {
126                                        throw new JobInstanceAlreadyCompleteException(
127                                                        "A job instance already exists and is complete for parameters=" + jobParameters
128                                                        + ".  If you want to run this job again, change the parameters.");
129                                }
130                        }
131                        executionContext = ecDao.getExecutionContext(jobExecutionDao.getLastJobExecution(jobInstance));
132                }
133                else {
134                        // no job found, create one
135                        jobInstance = jobInstanceDao.createJobInstance(jobName, jobParameters);
136                        executionContext = new ExecutionContext();
137                }
138 
139                JobExecution jobExecution = new JobExecution(jobInstance, jobParameters);
140                jobExecution.setExecutionContext(executionContext);
141                jobExecution.setLastUpdated(new Date(System.currentTimeMillis()));
142 
143                // Save the JobExecution so that it picks up an ID (useful for clients
144                // monitoring asynchronous executions):
145                jobExecutionDao.saveJobExecution(jobExecution);
146                ecDao.saveExecutionContext(jobExecution);
147 
148                return jobExecution;
149 
150        }
151 
152        @Override
153        public void update(JobExecution jobExecution) {
154 
155                Assert.notNull(jobExecution, "JobExecution cannot be null.");
156                Assert.notNull(jobExecution.getJobId(), "JobExecution must have a Job ID set.");
157                Assert.notNull(jobExecution.getId(), "JobExecution must be already saved (have an id assigned).");
158 
159                jobExecution.setLastUpdated(new Date(System.currentTimeMillis()));
160                jobExecutionDao.updateJobExecution(jobExecution);
161        }
162 
163        @Override
164        public void add(StepExecution stepExecution) {
165                validateStepExecution(stepExecution);
166 
167                stepExecution.setLastUpdated(new Date(System.currentTimeMillis()));
168                stepExecutionDao.saveStepExecution(stepExecution);
169                ecDao.saveExecutionContext(stepExecution);
170        }
171 
172        @Override
173        public void addAll(Collection<StepExecution> stepExecutions) {
174                Assert.notNull(stepExecutions, "Attempt to save a null collection of step executions");
175                for (StepExecution stepExecution : stepExecutions) {
176                        validateStepExecution(stepExecution);
177                        stepExecution.setLastUpdated(new Date(System.currentTimeMillis()));
178                }
179                stepExecutionDao.saveStepExecutions(stepExecutions);
180                ecDao.saveExecutionContexts(stepExecutions);
181        }
182 
183        @Override
184        public void update(StepExecution stepExecution) {
185                validateStepExecution(stepExecution);
186                Assert.notNull(stepExecution.getId(), "StepExecution must already be saved (have an id assigned)");
187 
188                stepExecution.setLastUpdated(new Date(System.currentTimeMillis()));
189                stepExecutionDao.updateStepExecution(stepExecution);
190                checkForInterruption(stepExecution);
191        }
192 
193        private void validateStepExecution(StepExecution stepExecution) {
194                Assert.notNull(stepExecution, "StepExecution cannot be null.");
195                Assert.notNull(stepExecution.getStepName(), "StepExecution's step name cannot be null.");
196                Assert.notNull(stepExecution.getJobExecutionId(), "StepExecution must belong to persisted JobExecution");
197        }
198 
199        @Override
200        public void updateExecutionContext(StepExecution stepExecution) {
201                validateStepExecution(stepExecution);
202                Assert.notNull(stepExecution.getId(), "StepExecution must already be saved (have an id assigned)");
203                ecDao.updateExecutionContext(stepExecution);
204        }
205 
206        @Override
207        public void updateExecutionContext(JobExecution jobExecution) {
208                ecDao.updateExecutionContext(jobExecution);
209        }
210 
211        @Override
212        public StepExecution getLastStepExecution(JobInstance jobInstance, String stepName) {
213                List<JobExecution> jobExecutions = jobExecutionDao.findJobExecutions(jobInstance);
214                List<StepExecution> stepExecutions = new ArrayList<StepExecution>(jobExecutions.size());
215 
216                for (JobExecution jobExecution : jobExecutions) {
217                        stepExecutionDao.addStepExecutions(jobExecution);
218                        for (StepExecution stepExecution : jobExecution.getStepExecutions()) {
219                                if (stepName.equals(stepExecution.getStepName())) {
220                                        stepExecutions.add(stepExecution);
221                                }
222                        }
223                }
224 
225                StepExecution latest = null;
226                for (StepExecution stepExecution : stepExecutions) {
227                        if (latest == null) {
228                                latest = stepExecution;
229                        }
230                        if (latest.getStartTime().getTime() < stepExecution.getStartTime().getTime()) {
231                                latest = stepExecution;
232                        }
233                }
234 
235                if (latest != null) {
236                        ExecutionContext executionContext = ecDao.getExecutionContext(latest);
237                        latest.setExecutionContext(executionContext);
238                }
239 
240                return latest;
241        }
242 
243        /**
244         * @return number of executions of the step within given job instance
245         */
246        @Override
247        public int getStepExecutionCount(JobInstance jobInstance, String stepName) {
248                int count = 0;
249                List<JobExecution> jobExecutions = jobExecutionDao.findJobExecutions(jobInstance);
250                for (JobExecution jobExecution : jobExecutions) {
251                        stepExecutionDao.addStepExecutions(jobExecution);
252                        for (StepExecution stepExecution : jobExecution.getStepExecutions()) {
253                                if (stepName.equals(stepExecution.getStepName())) {
254                                        count++;
255                                }
256                        }
257                }
258                return count;
259        }
260 
261        /*
262         * Check to determine whether or not the JobExecution that is the parent of
263         * the provided StepExecution has been interrupted. If, after synchronizing
264         * the status with the database, the status has been updated to STOPPING,
265         * then the job has been interrupted.
266         *
267         * @param stepExecution
268         */
269        private void checkForInterruption(StepExecution stepExecution) {
270                JobExecution jobExecution = stepExecution.getJobExecution();
271                jobExecutionDao.synchronizeStatus(jobExecution);
272                if (jobExecution.isStopping()) {
273                        logger.info("Parent JobExecution is stopped, so passing message on to StepExecution");
274                        stepExecution.setTerminateOnly();
275                }
276        }
277 
278        @Override
279        public JobExecution getLastJobExecution(String jobName, JobParameters jobParameters) {
280                JobInstance jobInstance = jobInstanceDao.getJobInstance(jobName, jobParameters);
281                if (jobInstance == null) {
282                        return null;
283                }
284                JobExecution jobExecution = jobExecutionDao.getLastJobExecution(jobInstance);
285 
286                if (jobExecution != null) {
287                        jobExecution.setExecutionContext(ecDao.getExecutionContext(jobExecution));
288                }
289                return jobExecution;
290 
291        }
292}

[all classes][org.springframework.batch.core.repository.support]
EMMA 2.0.5312 (C) Vladimir Roubtsov