diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobRepositoryParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobRepositoryParser.java index 4fec5cd11..ff13ed4e1 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobRepositoryParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobRepositoryParser.java @@ -51,6 +51,8 @@ public class JobRepositoryParser extends AbstractSingleBeanDefinitionParser { String tablePrefix = element.getAttribute("table-prefix"); + String lobHandler = element.getAttribute("lob-handler"); + RuntimeBeanReference ds = new RuntimeBeanReference(dataSource); builder.addPropertyValue("dataSource", ds); RuntimeBeanReference tx = new RuntimeBeanReference(transactionManager); @@ -61,6 +63,9 @@ public class JobRepositoryParser extends AbstractSingleBeanDefinitionParser { if (StringUtils.hasText(tablePrefix)) { builder.addPropertyValue("tablePrefix", tablePrefix); } + if (StringUtils.hasText(lobHandler)) { + builder.addPropertyReference("lobHandler", lobHandler); + } builder.setRole(BeanDefinition.ROLE_SUPPORT); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/JobRepositoryFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/JobRepositoryFactoryBean.java index c8de08778..a21b2d12f 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/JobRepositoryFactoryBean.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/JobRepositoryFactoryBean.java @@ -40,6 +40,8 @@ import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.jdbc.core.simple.SimpleJdbcOperations; import org.springframework.jdbc.core.simple.SimpleJdbcTemplate; +import org.springframework.jdbc.support.lob.LobHandler; +import org.springframework.jdbc.support.lob.OracleLobHandler; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -68,6 +70,21 @@ public class JobRepositoryFactoryBean extends AbstractJobRepositoryFactoryBean i private int exitMessageLength = AbstractJdbcBatchMetadataDao.DEFAULT_EXIT_MESSAGE_LENGTH; + private LobHandler lobHandler; + + /** + * A special handler for large objects. The default is usually fine, except + * for some (usually older) versions of Oracle. The default is determined + * from the data base type. + * + * @param lobHandler the {@link LobHandler} to set + * + * @see LobHandler + */ + public void setLobHandler(LobHandler lobHandler) { + this.lobHandler = lobHandler; + } + /** * Public setter for the exit message length in database. Do not set this if * you haven't modified the schema. Note this value will be used for both @@ -122,6 +139,10 @@ public class JobRepositoryFactoryBean extends AbstractJobRepositoryFactoryBean i databaseType = DatabaseType.fromMetaData(dataSource).name(); logger.info("No database type set, using meta data indicating: " + databaseType); } + + if (lobHandler==null && databaseType.equalsIgnoreCase(DatabaseType.ORACLE.toString())) { + lobHandler = new OracleLobHandler(); + } Assert.isTrue(incrementerFactory.isSupportedIncrementerType(databaseType), "'" + databaseType + "' is an unsupported database type. The supported database types are " @@ -173,6 +194,9 @@ public class JobRepositoryFactoryBean extends AbstractJobRepositoryFactoryBean i dao.setJdbcTemplate(jdbcTemplate); dao.setTablePrefix(tablePrefix); dao.setClobTypeToUse(determineClobTypeToUse(this.databaseType)); + if (lobHandler != null) { + dao.setLobHandler(lobHandler); + } dao.afterPropertiesSet(); return dao; } diff --git a/spring-batch-core/src/main/resources/org/springframework/batch/core/configuration/xml/spring-batch-2.1.xsd b/spring-batch-core/src/main/resources/org/springframework/batch/core/configuration/xml/spring-batch-2.1.xsd index 77b655028..e0fc3a75a 100644 --- a/spring-batch-core/src/main/resources/org/springframework/batch/core/configuration/xml/spring-batch-2.1.xsd +++ b/spring-batch-core/src/main/resources/org/springframework/batch/core/configuration/xml/spring-batch-2.1.xsd @@ -190,6 +190,20 @@ ]]> + + + + + + + + + + diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobRepositoryParserReferenceTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobRepositoryParserReferenceTests.java new file mode 100644 index 000000000..20eadf2f5 --- /dev/null +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobRepositoryParserReferenceTests.java @@ -0,0 +1,46 @@ +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.configuration.xml; + +import static org.junit.Assert.assertNotNull; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + + +/** + * @author Dave Syer + * + */ +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class JobRepositoryParserReferenceTests { + + @Autowired + @Qualifier("jobRepo1") + private JobRepository jobRepository; + + @Test + public void testOneStep() throws Exception { + assertNotNull(jobRepository); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/JobRepositoryFactoryBeanTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/JobRepositoryFactoryBeanTests.java index 554371f72..0ddfcef03 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/JobRepositoryFactoryBeanTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/JobRepositoryFactoryBeanTests.java @@ -15,22 +15,33 @@ */ package org.springframework.batch.core.repository.support; -import static junit.framework.Assert.*; -import static org.easymock.EasyMock.*; +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertTrue; +import static junit.framework.Assert.fail; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.createNiceMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import java.sql.Connection; +import java.sql.DatabaseMetaData; + +import javax.sql.DataSource; + +import org.junit.Before; +import org.junit.Test; import org.springframework.batch.core.JobParameters; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.item.database.support.DataFieldMaxValueIncrementerFactory; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer; +import org.springframework.jdbc.support.lob.DefaultLobHandler; +import org.springframework.jdbc.support.lob.LobHandler; +import org.springframework.jdbc.support.lob.OracleLobHandler; +import org.springframework.test.util.ReflectionTestUtils; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.support.DefaultTransactionDefinition; -import org.junit.Before; -import org.junit.Test; - -import javax.sql.DataSource; -import java.sql.Connection; -import java.sql.DatabaseMetaData; /** * @author Lucas Ward @@ -85,6 +96,46 @@ public class JobRepositoryFactoryBeanTests { } + @Test + public void testOracleLobHandler() throws Exception { + + factory.setDatabaseType("ORACLE"); + + incrementerFactory = createNiceMock(DataFieldMaxValueIncrementerFactory.class); + expect(incrementerFactory.isSupportedIncrementerType("ORACLE")).andReturn(true); + expect(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_SEQ")).andReturn(new StubIncrementer()); + expect(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_EXECUTION_SEQ")).andReturn(new StubIncrementer()); + expect(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "STEP_EXECUTION_SEQ")).andReturn(new StubIncrementer()); + replay(dataSource,incrementerFactory); + factory.setIncrementerFactory(incrementerFactory); + + factory.afterPropertiesSet(); + LobHandler lobHandler = (LobHandler) ReflectionTestUtils.getField(factory, "lobHandler"); + assertTrue(lobHandler instanceof OracleLobHandler); + + } + + @Test + public void testCustomLobHandler() throws Exception { + + factory.setDatabaseType("ORACLE"); + + incrementerFactory = createNiceMock(DataFieldMaxValueIncrementerFactory.class); + expect(incrementerFactory.isSupportedIncrementerType("ORACLE")).andReturn(true); + expect(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_SEQ")).andReturn(new StubIncrementer()); + expect(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_EXECUTION_SEQ")).andReturn(new StubIncrementer()); + expect(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "STEP_EXECUTION_SEQ")).andReturn(new StubIncrementer()); + replay(dataSource,incrementerFactory); + factory.setIncrementerFactory(incrementerFactory); + + LobHandler lobHandler = new DefaultLobHandler(); + factory.setLobHandler(lobHandler); + + factory.afterPropertiesSet(); + assertEquals(lobHandler, ReflectionTestUtils.getField(factory, "lobHandler")); + + } + @Test public void testMissingDataSource() throws Exception { diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/JobRepositoryParserReferenceTests-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/JobRepositoryParserReferenceTests-context.xml new file mode 100644 index 000000000..72d2e69cb --- /dev/null +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/JobRepositoryParserReferenceTests-context.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/JobRepositoryParserTests-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/JobRepositoryParserTests-context.xml index 3de5e8421..e9e1950bb 100644 --- a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/JobRepositoryParserTests-context.xml +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/JobRepositoryParserTests-context.xml @@ -1,7 +1,7 @@ @@ -11,7 +11,8 @@ + - + \ No newline at end of file