EMMA Coverage Report (generated Thu Jan 24 13:37:04 CST 2013)
[all classes][org.springframework.batch.core.repository.support]

COVERAGE SUMMARY FOR SOURCE FILE [SimpleJobRepository.java]

nameclass, %method, %block, %line, %
SimpleJobRepository.java100% (1/1)93%  (14/15)95%  (383/402)96%  (93.3/97)

COVERAGE BREAKDOWN BY CLASS AND METHOD

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

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