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

COVERAGE SUMMARY FOR SOURCE FILE [SimpleJobLauncher.java]

nameclass, %method, %block, %line, %
SimpleJobLauncher.java100% (2/2)100% (9/9)88%  (158/180)91%  (30/33)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class SimpleJobLauncher$1100% (1/1)100% (3/3)77%  (73/95)77%  (10/13)
run (): void 100% (1/1)68%  (47/69)62%  (5/8)
SimpleJobLauncher$1 (SimpleJobLauncher, Job, JobParameters, JobExecution): void 100% (1/1)100% (15/15)100% (2/2)
rethrow (Throwable): void 100% (1/1)100% (11/11)100% (3/3)
     
class SimpleJobLauncher100% (1/1)100% (6/6)100% (85/85)100% (21/21)
<static initializer> 100% (1/1)100% (4/4)100% (2/2)
SimpleJobLauncher (): void 100% (1/1)100% (3/3)100% (1/1)
afterPropertiesSet (): void 100% (1/1)100% (20/20)100% (5/5)
run (Job, JobParameters): JobExecution 100% (1/1)100% (50/50)100% (10/10)
setJobRepository (JobRepository): void 100% (1/1)100% (4/4)100% (2/2)
setTaskExecutor (TaskExecutor): void 100% (1/1)100% (4/4)100% (2/2)

1/*
2 * Copyright 2006-2008 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 */
16package org.springframework.batch.core.launch.support;
17 
18import org.apache.commons.logging.Log;
19import org.apache.commons.logging.LogFactory;
20import org.springframework.batch.core.Job;
21import org.springframework.batch.core.JobExecution;
22import org.springframework.batch.core.JobInstance;
23import org.springframework.batch.core.JobParameters;
24import org.springframework.batch.core.launch.JobLauncher;
25import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
26import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
27import org.springframework.batch.core.repository.JobRepository;
28import org.springframework.batch.core.repository.JobRestartException;
29import org.springframework.beans.factory.InitializingBean;
30import org.springframework.core.task.SyncTaskExecutor;
31import org.springframework.core.task.TaskExecutor;
32import org.springframework.util.Assert;
33 
34/**
35 * Simple implementation of the {@link JobLauncher} interface. The Spring Core
36 * {@link TaskExecutor} interface is used to launch a {@link Job}. This means
37 * that the type of executor set is very important. If a
38 * {@link SyncTaskExecutor} is used, then the job will be processed
39 * <strong>within the same thread that called the launcher.</strong> Care should
40 * be taken to ensure any users of this class understand fully whether or not
41 * the implementation of TaskExecutor used will start tasks synchronously or
42 * asynchronously. The default setting uses a synchronous task executor.
43 * 
44 * There is only one required dependency of this Launcher, a
45 * {@link JobRepository}. The JobRepository is used to obtain a valid
46 * JobExecution. The Repository must be used because the provided {@link Job}
47 * could be a restart of an existing {@link JobInstance}, and only the
48 * Repository can reliably recreate it.
49 * 
50 * @author Lucas Ward
51 * @since 1.0
52 * @see JobRepository
53 * @see TaskExecutor
54 */
55public class SimpleJobLauncher implements JobLauncher, InitializingBean {
56 
57        protected static final Log logger = LogFactory.getLog(SimpleJobLauncher.class);
58 
59        private JobRepository jobRepository;
60 
61        private TaskExecutor taskExecutor;
62 
63        /**
64         * Run the provided job with the given {@link JobParameters}. The
65         * {@link JobParameters} will be used to determine if this is an execution
66         * of an existing job instance, or if a new one should be created.
67         * 
68         * @param job the job to be run.
69         * @param jobParameters the {@link JobParameters} for this particular
70         * execution.
71         * @return JobExecutionAlreadyRunningException if the JobInstance already
72         * exists and has an execution already running.
73         * @throws JobRestartException if the execution would be a re-start, but a
74         * re-start is either not allowed or not needed.
75         * @throws JobInstanceAlreadyCompleteException if this instance has already
76         * completed successfully
77         */
78        public JobExecution run(final Job job, final JobParameters jobParameters)
79                        throws JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException {
80 
81                Assert.notNull(job, "The Job must not be null.");
82                Assert.notNull(jobParameters, "The JobParameters must not be null.");
83 
84                final JobExecution jobExecution;
85                JobExecution lastExecution = jobRepository.getLastJobExecution(job.getName(), jobParameters);
86                if (lastExecution != null) {
87                        if (!job.isRestartable()) {
88                                throw new JobRestartException("JobInstance already exists and is not restartable");
89                        }
90                        else {
91                                /*
92                                 * There is a very small probability that a non-restartable job
93                                 * can be restarted, but only if another process or thread
94                                 * manages to launch <i>and</i> fail a job execution for this
95                                 * instance between the last assertion and the next method
96                                 * returning successfully.
97                                 */
98                                jobExecution = jobRepository.createJobExecution(job.getName(), jobParameters);
99                        }
100                }
101                else {
102                        jobExecution = jobRepository.createJobExecution(job.getName(), jobParameters);
103                }
104 
105                taskExecutor.execute(new Runnable() {
106 
107                        public void run() {
108                                try {
109                                        logger.info("Job: [" + job + "] launched with the following parameters: [" + jobParameters + "]");
110                                        job.execute(jobExecution);
111                                        logger.info("Job: [" + job + "] completed with the following parameters: [" + jobParameters
112                                                        + "] and the following status: [" + jobExecution.getStatus() + "]");
113                                }
114                                catch (Throwable t) {
115                                        logger.info("Job: [" + job + "] failed unexpectedly and fatally with the following parameters: [" + jobParameters + "]", t);
116                                        rethrow(t);
117                                }
118                        }
119 
120                        private void rethrow(Throwable t) {
121                                if (t instanceof RuntimeException) {
122                                        throw (RuntimeException) t;
123                                }
124                                throw new RuntimeException(t);
125                        }
126                });
127 
128                return jobExecution;
129        }
130 
131        /**
132         * Set the JobRepsitory.
133         * 
134         * @param jobRepository
135         */
136        public void setJobRepository(JobRepository jobRepository) {
137                this.jobRepository = jobRepository;
138        }
139 
140        /**
141         * Set the TaskExecutor. (Optional)
142         * 
143         * @param taskExecutor
144         */
145        public void setTaskExecutor(TaskExecutor taskExecutor) {
146                this.taskExecutor = taskExecutor;
147        }
148 
149        /**
150         * Ensure the required dependencies of a {@link JobRepository} have been
151         * set.
152         */
153        public void afterPropertiesSet() throws Exception {
154                Assert.state(jobRepository != null, "A JobRepository has not been set.");
155                if (taskExecutor == null) {
156                        logger.info("No TaskExecutor has been set, defaulting to synchronous executor.");
157                        taskExecutor = new SyncTaskExecutor();
158                }
159        }
160 
161}

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