001/*
002 * Copyright 2002-2013 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.batch.core.explore.support;
018
019import javax.sql.DataSource;
020
021import org.springframework.batch.core.explore.JobExplorer;
022import org.springframework.batch.core.repository.ExecutionContextSerializer;
023import org.springframework.batch.core.repository.dao.AbstractJdbcBatchMetadataDao;
024import org.springframework.batch.core.repository.dao.ExecutionContextDao;
025import org.springframework.batch.core.repository.dao.Jackson2ExecutionContextStringSerializer;
026import org.springframework.batch.core.repository.dao.JdbcExecutionContextDao;
027import org.springframework.batch.core.repository.dao.JdbcJobExecutionDao;
028import org.springframework.batch.core.repository.dao.JdbcJobInstanceDao;
029import org.springframework.batch.core.repository.dao.JdbcStepExecutionDao;
030import org.springframework.batch.core.repository.dao.JobExecutionDao;
031import org.springframework.batch.core.repository.dao.JobInstanceDao;
032import org.springframework.batch.core.repository.dao.StepExecutionDao;
033import org.springframework.batch.core.repository.dao.XStreamExecutionContextStringSerializer;
034import org.springframework.batch.item.ExecutionContext;
035import org.springframework.beans.factory.FactoryBean;
036import org.springframework.beans.factory.InitializingBean;
037import org.springframework.jdbc.core.JdbcOperations;
038import org.springframework.jdbc.core.JdbcTemplate;
039import org.springframework.jdbc.support.incrementer.AbstractDataFieldMaxValueIncrementer;
040import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer;
041import org.springframework.jdbc.support.lob.LobHandler;
042import org.springframework.util.Assert;
043
044/**
045 * A {@link FactoryBean} that automates the creation of a
046 * {@link SimpleJobExplorer} using JDBC DAO implementations. Requires the user
047 * to describe what kind of database they are using.
048 *
049 * @author Dave Syer
050 * @since 2.0
051 */
052public class JobExplorerFactoryBean extends AbstractJobExplorerFactoryBean
053implements InitializingBean {
054
055        private DataSource dataSource;
056
057        private JdbcOperations jdbcOperations;
058
059        private String tablePrefix = AbstractJdbcBatchMetadataDao.DEFAULT_TABLE_PREFIX;
060
061        private DataFieldMaxValueIncrementer incrementer = new AbstractDataFieldMaxValueIncrementer() {
062                @Override
063                protected long getNextKey() {
064                        throw new IllegalStateException("JobExplorer is read only.");
065                }
066        };
067
068        private LobHandler lobHandler;
069
070        private ExecutionContextSerializer serializer;
071
072        /**
073         * A custom implementation of the {@link ExecutionContextSerializer}.
074         * The default, if not injected, is the {@link XStreamExecutionContextStringSerializer}.
075         *
076         * @param serializer used to serialize/deserialize an {@link org.springframework.batch.item.ExecutionContext}
077         * @see ExecutionContextSerializer
078         */
079        public void setSerializer(ExecutionContextSerializer serializer) {
080                this.serializer = serializer;
081        }
082
083        /**
084         * Public setter for the {@link DataSource}.
085         *
086         * @param dataSource
087         *            a {@link DataSource}
088         */
089        public void setDataSource(DataSource dataSource) {
090                this.dataSource = dataSource;
091        }
092        
093        /**
094         * Public setter for the {@link JdbcOperations}. If this property is not set explicitly,
095         * a new {@link JdbcTemplate} will be created for the configured DataSource by default.
096         * @param jdbcOperations a {@link JdbcOperations}
097         */
098        public void setJdbcOperations(JdbcOperations jdbcOperations) {
099                this.jdbcOperations = jdbcOperations;
100        }       
101
102        /**
103         * Sets the table prefix for all the batch meta-data tables.
104         *
105         * @param tablePrefix prefix for the batch meta-data tables
106         */
107        public void setTablePrefix(String tablePrefix) {
108                this.tablePrefix = tablePrefix;
109        }
110
111        /**
112         * The lob handler to use when saving {@link ExecutionContext} instances.
113         * Defaults to null which works for most databases.
114         *
115         * @param lobHandler Large object handler for saving {@link org.springframework.batch.item.ExecutionContext}
116         */
117        public void setLobHandler(LobHandler lobHandler) {
118                this.lobHandler = lobHandler;
119        }
120
121        @Override
122        public void afterPropertiesSet() throws Exception {
123
124                Assert.notNull(dataSource, "DataSource must not be null.");
125
126                if (jdbcOperations == null) {
127                        jdbcOperations = new JdbcTemplate(dataSource);  
128                }       
129
130                if(serializer == null) {
131                        serializer = new Jackson2ExecutionContextStringSerializer();
132                }
133        }
134
135        private JobExplorer getTarget() throws Exception {
136                return new SimpleJobExplorer(createJobInstanceDao(),
137                                createJobExecutionDao(), createStepExecutionDao(),
138                                createExecutionContextDao());
139        }
140
141        @Override
142        protected ExecutionContextDao createExecutionContextDao() throws Exception {
143                JdbcExecutionContextDao dao = new JdbcExecutionContextDao();
144                dao.setJdbcTemplate(jdbcOperations);
145                dao.setLobHandler(lobHandler);
146                dao.setTablePrefix(tablePrefix);
147                dao.setSerializer(serializer);
148                dao.afterPropertiesSet();
149                return dao;
150        }
151
152        @Override
153        protected JobInstanceDao createJobInstanceDao() throws Exception {
154                JdbcJobInstanceDao dao = new JdbcJobInstanceDao();
155                dao.setJdbcTemplate(jdbcOperations);
156                dao.setJobIncrementer(incrementer);
157                dao.setTablePrefix(tablePrefix);
158                dao.afterPropertiesSet();
159                return dao;
160        }
161
162        @Override
163        protected JobExecutionDao createJobExecutionDao() throws Exception {
164                JdbcJobExecutionDao dao = new JdbcJobExecutionDao();
165                dao.setJdbcTemplate(jdbcOperations);
166                dao.setJobExecutionIncrementer(incrementer);
167                dao.setTablePrefix(tablePrefix);
168                dao.afterPropertiesSet();
169                return dao;
170        }
171
172        @Override
173        protected StepExecutionDao createStepExecutionDao() throws Exception {
174                JdbcStepExecutionDao dao = new JdbcStepExecutionDao();
175                dao.setJdbcTemplate(jdbcOperations);
176                dao.setStepExecutionIncrementer(incrementer);
177                dao.setTablePrefix(tablePrefix);
178                dao.afterPropertiesSet();
179                return dao;
180        }
181
182        @Override
183        public JobExplorer getObject() throws Exception {
184                return getTarget();
185        }
186}