EMMA Coverage Report (generated Fri Aug 21 15:59:46 BST 2009)
[all classes][org.springframework.batch.core.repository.support]

COVERAGE SUMMARY FOR SOURCE FILE [SimpleJobRepository.java]

nameclass, %method, %block, %line, %
SimpleJobRepository.java100% (1/1)93%  (13/14)99%  (381/386)97%  (91/94)

COVERAGE BREAKDOWN BY CLASS AND METHOD

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

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