diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespaceHandler.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespaceHandler.java index b09bb7b1c..9373665bb 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespaceHandler.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespaceHandler.java @@ -37,4 +37,5 @@ public class CoreNamespaceHandler extends NamespaceHandlerSupport { this.registerBeanDefinitionParser("job-listener", new TopLevelJobListenerParser()); this.registerBeanDefinitionParser("step-listener", new TopLevelStepListenerParser()); } + } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobParser.java index e08c2d3eb..aac11cf2a 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobParser.java @@ -58,6 +58,14 @@ public class JobParser extends AbstractSingleBeanDefinitionParser { @Override protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { + if (!namespaceMatchesVersion(element) + || !namespaceMatchesVersion(element.getOwnerDocument().getDocumentElement())) { + parserContext.getReaderContext().error( + "You cannot use spring-batch-2.0.xsd with Spring Batch 2.1. Please upgrade your schema declarations " + + "(or use the spring-batch.xsd alias if you are feeling lucky).", element); + return; + } + CoreNamespaceUtils.autoregisterBeansForNamespace(parserContext, parserContext.extractSource(element)); String jobName = element.getAttribute("id"); @@ -107,7 +115,7 @@ public class JobParser extends AbstractSingleBeanDefinitionParser { } Element description = DomUtils.getChildElementByTagName(element, "description"); - if (description!=null) { + if (description != null) { builder.getBeanDefinition().setDescription(description.getTextContent()); } @@ -134,4 +142,21 @@ public class JobParser extends AbstractSingleBeanDefinitionParser { } + /** + * Check that the schema location declared in the source file being parsed + * matches the Spring Batch version. (The old 2.0 schema is not 100% + * compatible with the new parser, so it is an error to explicitly define + * 2.0. It might be an error to declare spring-batch.xsd as an alias, but + * you are only going to find that out when one of the sub parses breaks.) + * + * @param element the element that is to be parsed next + * @return true if we find a schema declaration that matches + */ + private boolean namespaceMatchesVersion(Element element) { + String schemaLocation = element.getAttributeNS("http://www.w3.org/2001/XMLSchema-instance", "schemaLocation"); + return schemaLocation.matches("(?m).*spring-batch-2.1.xsd.*") + || schemaLocation.matches("(?m).*spring-batch.xsd.*") + || !schemaLocation.matches("(?m).*spring-batch.*"); + } + } diff --git a/spring-batch-core/src/main/resources/META-INF/spring.schemas b/spring-batch-core/src/main/resources/META-INF/spring.schemas index 63bf58424..17fec72a7 100644 --- a/spring-batch-core/src/main/resources/META-INF/spring.schemas +++ b/spring-batch-core/src/main/resources/META-INF/spring.schemas @@ -1,2 +1,3 @@ http\://www.springframework.org/schema/batch/spring-batch.xsd=/org/springframework/batch/core/configuration/xml/spring-batch-2.1.xsd -http\://www.springframework.org/schema/batch/spring-batch-2.1.xsd=/org/springframework/batch/core/configuration/xml/spring-batch-2.1.xsd \ No newline at end of file +http\://www.springframework.org/schema/batch/spring-batch-2.1.xsd=/org/springframework/batch/core/configuration/xml/spring-batch-2.1.xsd +http\://www.springframework.org/schema/batch/spring-batch-2.0.xsd=/org/springframework/batch/core/configuration/xml/spring-batch-2.0-error.xsd \ No newline at end of file diff --git a/spring-batch-core/src/main/resources/org/springframework/batch/core/configuration/xml/spring-batch-2.0-error.xsd b/spring-batch-core/src/main/resources/org/springframework/batch/core/configuration/xml/spring-batch-2.0-error.xsd new file mode 100644 index 000000000..2ec0ea03b --- /dev/null +++ b/spring-batch-core/src/main/resources/org/springframework/batch/core/configuration/xml/spring-batch-2.0-error.xsd @@ -0,0 +1,16 @@ + + + + + + diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobParserExceptionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobParserExceptionTests.java index 25600f80c..3c17970da 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobParserExceptionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/JobParserExceptionTests.java @@ -5,6 +5,7 @@ import static org.junit.Assert.fail; import org.junit.Test; import org.springframework.beans.factory.BeanCreationException; +import org.springframework.beans.factory.BeanDefinitionStoreException; import org.springframework.beans.factory.parsing.BeanDefinitionParsingException; import org.springframework.context.support.ClassPathXmlApplicationContext; @@ -48,4 +49,20 @@ public class JobParserExceptionTests { } } + @Test + public void testWrongSchemaInRoot() { + try { + new ClassPathXmlApplicationContext( + "org/springframework/batch/core/configuration/xml/JobParserWrongSchemaInRootTests-context.xml"); + fail("Error expected"); + } + catch (BeanDefinitionParsingException e) { + String message = e.getMessage(); + assertTrue("Wrong message: "+message, message.matches("(?s).*You cannot use spring-batch-2.0.xsd.*")); + } catch (BeanDefinitionStoreException e) { + // Probably the internet is not available and the schema validation failed. + // We don't want an automated build to fail if that happens. + } + } + } diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/JobParserWrongSchemaInRootTests-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/JobParserWrongSchemaInRootTests-context.xml new file mode 100644 index 000000000..3da70a6d7 --- /dev/null +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/configuration/xml/JobParserWrongSchemaInRootTests-context.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + +