View Javadoc

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   */
16  package org.springframework.batch.core.repository.support;
17  
18  import static junit.framework.Assert.assertEquals;
19  import static junit.framework.Assert.assertTrue;
20  import static junit.framework.Assert.fail;
21  import static org.easymock.EasyMock.createMock;
22  import static org.easymock.EasyMock.createNiceMock;
23  import static org.easymock.EasyMock.expect;
24  import static org.easymock.EasyMock.replay;
25  import static org.easymock.EasyMock.verify;
26  
27  import java.sql.Connection;
28  import java.sql.DatabaseMetaData;
29  
30  import javax.sql.DataSource;
31  
32  import org.junit.Before;
33  import org.junit.Test;
34  import org.springframework.batch.core.JobParameters;
35  import org.springframework.batch.core.repository.JobRepository;
36  import org.springframework.batch.item.database.support.DataFieldMaxValueIncrementerFactory;
37  import org.springframework.dao.DataAccessException;
38  import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer;
39  import org.springframework.jdbc.support.lob.DefaultLobHandler;
40  import org.springframework.jdbc.support.lob.LobHandler;
41  import org.springframework.jdbc.support.lob.OracleLobHandler;
42  import org.springframework.test.util.ReflectionTestUtils;
43  import org.springframework.transaction.PlatformTransactionManager;
44  import org.springframework.transaction.support.DefaultTransactionDefinition;
45  
46  /**
47   * @author Lucas Ward
48   * 
49   */
50  public class JobRepositoryFactoryBeanTests {
51  
52  	private JobRepositoryFactoryBean factory;
53  
54  	private DataFieldMaxValueIncrementerFactory incrementerFactory;
55  
56  	private DataSource dataSource;
57  
58  	private PlatformTransactionManager transactionManager;
59  
60  	private String tablePrefix = "TEST_BATCH_PREFIX_";
61  
62  	@Before
63  	public void setUp() throws Exception {
64  
65  		factory = new JobRepositoryFactoryBean();
66  		dataSource = createMock(DataSource.class);
67  		transactionManager = createMock(PlatformTransactionManager.class);
68  		factory.setDataSource(dataSource);
69  		factory.setTransactionManager(transactionManager);
70  		incrementerFactory = createMock(DataFieldMaxValueIncrementerFactory.class);
71  		factory.setIncrementerFactory(incrementerFactory);
72  		factory.setTablePrefix(tablePrefix);
73  
74  	}
75  
76  	@Test
77  	public void testNoDatabaseType() throws Exception {
78  
79  		DatabaseMetaData dmd = createMock(DatabaseMetaData.class);
80  		Connection con = createMock(Connection.class);
81  		expect(dataSource.getConnection()).andReturn(con);
82  		expect(con.getMetaData()).andReturn(dmd);
83  		expect(dmd.getDatabaseProductName()).andReturn("Oracle");
84  		
85  		expect(incrementerFactory.isSupportedIncrementerType("ORACLE")).andReturn(true);
86  		expect(incrementerFactory.getSupportedIncrementerTypes()).andReturn(new String[0]);
87  		expect(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_SEQ")).andReturn(new StubIncrementer());
88  		expect(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_EXECUTION_SEQ")).andReturn(new StubIncrementer());
89  		expect(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "STEP_EXECUTION_SEQ")).andReturn(new StubIncrementer());
90  		replay(dataSource,con,dmd, incrementerFactory);
91  		
92  		factory.afterPropertiesSet();
93  		factory.getObject();
94  
95  		verify(incrementerFactory);
96  		
97  	}
98  
99  	@Test
100 	public void testOracleLobHandler() throws Exception {
101 
102 		factory.setDatabaseType("ORACLE");
103 		
104 		incrementerFactory = createNiceMock(DataFieldMaxValueIncrementerFactory.class);
105 		expect(incrementerFactory.isSupportedIncrementerType("ORACLE")).andReturn(true);
106 		expect(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_SEQ")).andReturn(new StubIncrementer());
107 		expect(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_EXECUTION_SEQ")).andReturn(new StubIncrementer());
108 		expect(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "STEP_EXECUTION_SEQ")).andReturn(new StubIncrementer());
109 		replay(dataSource,incrementerFactory);
110 		factory.setIncrementerFactory(incrementerFactory);
111 
112 		factory.afterPropertiesSet();
113 		LobHandler lobHandler = (LobHandler) ReflectionTestUtils.getField(factory, "lobHandler");
114 		assertTrue(lobHandler instanceof OracleLobHandler);
115 		
116 	}
117 
118 	@Test
119 	public void testCustomLobHandler() throws Exception {
120 
121 		factory.setDatabaseType("ORACLE");
122 		
123 		incrementerFactory = createNiceMock(DataFieldMaxValueIncrementerFactory.class);
124 		expect(incrementerFactory.isSupportedIncrementerType("ORACLE")).andReturn(true);
125 		expect(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_SEQ")).andReturn(new StubIncrementer());
126 		expect(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_EXECUTION_SEQ")).andReturn(new StubIncrementer());
127 		expect(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "STEP_EXECUTION_SEQ")).andReturn(new StubIncrementer());
128 		replay(dataSource,incrementerFactory);
129 		factory.setIncrementerFactory(incrementerFactory);
130 		
131 		LobHandler lobHandler = new DefaultLobHandler();
132 		factory.setLobHandler(lobHandler);
133 
134 		factory.afterPropertiesSet();
135 		assertEquals(lobHandler, ReflectionTestUtils.getField(factory, "lobHandler"));
136 		
137 	}
138 
139 	@Test
140 	public void testMissingDataSource() throws Exception {
141 
142 		factory.setDataSource(null);
143 		try {
144 			factory.afterPropertiesSet();
145 			fail();
146 		}
147 		catch (IllegalArgumentException ex) {
148 			// expected
149 			String message = ex.getMessage();
150 			assertTrue("Wrong message: " + message, message.indexOf("DataSource") >= 0);
151 		}
152 
153 	}
154 
155 	@Test
156 	public void testMissingTransactionManager() throws Exception {
157 
158 		factory.setDatabaseType("mockDb");
159 		factory.setTransactionManager(null);
160 		try {
161 			expect(incrementerFactory.isSupportedIncrementerType("mockDb")).andReturn(true);
162 			expect(incrementerFactory.getSupportedIncrementerTypes()).andReturn(new String[0]);
163 			replay(incrementerFactory);
164 			
165 			factory.afterPropertiesSet();
166 			fail();
167 		}
168 		catch (IllegalArgumentException ex) {
169 			// expected
170 			String message = ex.getMessage();
171 			assertTrue("Wrong message: " + message, message.indexOf("TransactionManager") >= 0);
172 		}
173 
174 	}
175 
176 	@Test
177 	public void testInvalidDatabaseType() throws Exception {
178 
179 		factory.setDatabaseType("foo");
180 		try {
181 			expect(incrementerFactory.isSupportedIncrementerType("foo")).andReturn(false);
182 			expect(incrementerFactory.getSupportedIncrementerTypes()).andReturn(new String[0]);
183 			replay(incrementerFactory);
184 			factory.afterPropertiesSet();
185 			fail();
186 		}
187 		catch (IllegalArgumentException ex) {
188 			// expected
189 			String message = ex.getMessage();
190 			assertTrue("Wrong message: " + message, message.indexOf("foo") >= 0);
191 		}
192 
193 	}
194 
195 	@Test
196 	public void testCreateRepository() throws Exception {
197 		String databaseType = "HSQL";
198 		factory.setDatabaseType(databaseType);
199 
200 		expect(incrementerFactory.isSupportedIncrementerType("HSQL")).andReturn(true);
201 		expect(incrementerFactory.getSupportedIncrementerTypes()).andReturn(new String[0]);
202 		expect(incrementerFactory.getIncrementer(databaseType, tablePrefix + "JOB_SEQ")).andReturn(new StubIncrementer());
203 		expect(incrementerFactory.getIncrementer(databaseType, tablePrefix + "JOB_EXECUTION_SEQ")).andReturn(new StubIncrementer());
204 		expect(incrementerFactory.getIncrementer(databaseType, tablePrefix + "STEP_EXECUTION_SEQ")).andReturn(new StubIncrementer());
205 		replay(incrementerFactory);
206 
207 		factory.afterPropertiesSet();
208 		factory.getObject();
209 
210 		verify(incrementerFactory);
211 
212 	}
213 
214 	@Test
215 	public void testTransactionAttributesForCreateMethodNullHypothesis() throws Exception {
216 		testCreateRepository();
217 		JobRepository repository = (JobRepository) factory.getObject();
218 		DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition(
219 				DefaultTransactionDefinition.PROPAGATION_REQUIRES_NEW);
220 		expect(transactionManager.getTransaction(transactionDefinition)).andReturn(null);
221 		replay(transactionManager);
222 		try {
223 			repository.createJobExecution("foo", new JobParameters());
224 			// we expect an exception from the txControl because we provided the
225 			// wrong meta data
226 			fail("Expected IllegalArgumentException");
227 		}
228 		catch (AssertionError e) {
229 			// expected exception from txControl - wrong isolation level used in
230 			// comparison
231 			assertEquals("Unexpected method call", e.getMessage().substring(3, 25));
232 		}
233 
234 	}
235 
236 	@Test
237 	public void testTransactionAttributesForCreateMethod() throws Exception {
238 
239 		testCreateRepository();
240 		JobRepository repository = (JobRepository) factory.getObject();
241 		DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition(
242 				DefaultTransactionDefinition.PROPAGATION_REQUIRES_NEW);
243 		transactionDefinition.setIsolationLevel(DefaultTransactionDefinition.ISOLATION_SERIALIZABLE);
244 		expect(transactionManager.getTransaction(transactionDefinition)).andReturn(null);
245 		Connection conn = createNiceMock(Connection.class);
246 		expect(dataSource.getConnection()).andReturn(conn);
247 		replay(dataSource);
248 		replay(transactionManager);
249 		try {
250 			repository.createJobExecution("foo", new JobParameters());
251 			// we expect an exception but not from the txControl because we
252 			// provided the correct meta data
253 			fail("Expected IllegalArgumentException");
254 		}
255 		catch (IllegalArgumentException e) {
256 			// expected exception from DataSourceUtils
257 			assertEquals("No Statement specified", e.getMessage());
258 		}
259 
260 	}
261 
262 	@Test
263 	public void testSetTransactionAttributesForCreateMethod() throws Exception {
264 
265 		factory.setIsolationLevelForCreate("ISOLATION_READ_UNCOMMITTED");
266 		testCreateRepository();
267 		JobRepository repository = (JobRepository) factory.getObject();
268 		DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition(
269 				DefaultTransactionDefinition.PROPAGATION_REQUIRES_NEW);
270 		transactionDefinition.setIsolationLevel(DefaultTransactionDefinition.ISOLATION_READ_UNCOMMITTED);
271 		expect(transactionManager.getTransaction(transactionDefinition)).andReturn(null);
272 		Connection conn = createNiceMock(Connection.class);
273 		expect(dataSource.getConnection()).andReturn(conn);
274 		replay(dataSource);
275 		replay(transactionManager);
276 		try {
277 			repository.createJobExecution("foo", new JobParameters());
278 			// we expect an exception but not from the txControl because we
279 			// provided the correct meta data
280 			fail("Expected IllegalArgumentException");
281 		}
282 		catch (IllegalArgumentException e) {
283 			// expected exception from DataSourceUtils
284 			assertEquals("No Statement specified", e.getMessage());
285 		}
286 
287 	}
288 
289 	private static class StubIncrementer implements DataFieldMaxValueIncrementer {
290 
291 		public int nextIntValue() throws DataAccessException {
292 			return 0;
293 		}
294 
295 		public long nextLongValue() throws DataAccessException {
296 			return 0;
297 		}
298 
299 		public String nextStringValue() throws DataAccessException {
300 			return null;
301 		}
302 
303 	}
304 
305 }