Fix STS compatibility issues; other improvements
Revert changes to ParserContext, ReaderContext, and XmlReaderContext
These changes cause cross-version incompatibilities at tooling time
-- for instance, an STS version that ships with Spring 3.0.5
classloads the ParserContext defined in that version, whereas it
classloads NamespaceHandlers and BeanDefinitionParsers (by default)
from the user application classpath, which may be building against
3.1.0. If so, the changes introduced to these types in 3.1.0 are
incompatible with expectations in the 3.0.5 world and cause all
manner of problems. In this case, it was NoSuchMethodError due to
the newly-added XmlReaderContext.getProblemReporter() method; also
IncompatibleClassChangeError due to the introduction of the
ComponentRegistrar interface on ParserContext.
Each of these problems have been mitigated, though the solutions
are not ideal. The method mentioned has been removed, and instead
the problemReporter field is now accessed reflectively.
ParserContext now no longer implements ComponentRegistrar, and
rather a ComponentRegistrarAdapter class has been introduced that
passes method calls through to a ParserContext delegate.
Introduce AbstractSpecificationBeanDefinitionParser
AbstractSpecificationBeanDefinitionParser has been introduced in
order to improve the programming model for BeanDefinitionParsers
that have been refactored to the new FeatureSpecification model.
This new base class and it's template method implementation of
parse/doParse ensure that common concerns like (1) adapting a
ParserContext into a SpecificationContext, (2) setting source and
source name on the specification, and (3) actually executing the
specification are all managed by the base class. The subclass
implementation of doParse need only actually parse XML, populate
and return the FeatureSpecification object. This change removed
the many duplicate 'createSpecificationContext' methods that had
been lingering.
Minor improvement to BeanDefinitionReaderUtils API
Introduced new BeanDefinitionReaderUtils#registerWithGeneratedName
variant that accepts BeanDefinition as opposed to
AbstractBeanDefinition, as BeanDefinition is all that is actually
necessary to satisfy the needs of the method implementation. The
latter variant accepting AbstractBeanDefinition has been deprecated
but remains intact and delegates to the new variant in order to
maintain binary compatibility.
This commit is contained in:
@@ -16,12 +16,12 @@
|
||||
|
||||
package org.springframework.web.servlet.config;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.support.ManagedList;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.context.config.SpecificationContext;
|
||||
import org.springframework.context.config.AbstractSpecificationBeanDefinitionParser;
|
||||
import org.springframework.context.config.FeatureSpecification;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
@@ -30,22 +30,18 @@ import org.w3c.dom.Element;
|
||||
* to configure a Spring MVC web application.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Chris Beams
|
||||
* @since 3.0
|
||||
* @see MvcAnnotationDriven
|
||||
* @see MvcAnnotationDrivenExecutor
|
||||
*/
|
||||
class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
|
||||
class AnnotationDrivenBeanDefinitionParser extends AbstractSpecificationBeanDefinitionParser {
|
||||
|
||||
/**
|
||||
* Parses the {@code <mvc:annotation-driven/>} tag.
|
||||
*/
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
MvcAnnotationDriven spec = createSpecification(element, parserContext);
|
||||
spec.execute(createSpecificationContext(parserContext));
|
||||
return null;
|
||||
}
|
||||
|
||||
private MvcAnnotationDriven createSpecification(Element element, ParserContext parserContext) {
|
||||
@Override
|
||||
protected FeatureSpecification doParse(Element element, ParserContext parserContext) {
|
||||
MvcAnnotationDriven spec = new MvcAnnotationDriven();
|
||||
if (element.hasAttribute("conversion-service")) {
|
||||
String conversionService = element.getAttribute("conversion-service");
|
||||
@@ -70,8 +66,6 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
|
||||
spec.argumentResolvers(extractBeanSubElements(resolversElement, parserContext));
|
||||
}
|
||||
|
||||
spec.source(parserContext.extractSource(element));
|
||||
spec.sourceName(element.getTagName());
|
||||
return spec;
|
||||
}
|
||||
|
||||
@@ -86,18 +80,4 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adapt the given ParserContext instance into an SpecificationContext.
|
||||
*
|
||||
* TODO SPR-7420: consider unifying the two through a superinterface.
|
||||
* TODO SPR-7420: create a common ParserContext-to-SpecificationContext adapter util
|
||||
*/
|
||||
private SpecificationContext createSpecificationContext(ParserContext parserContext) {
|
||||
SpecificationContext executorContext = new SpecificationContext();
|
||||
executorContext.setRegistry(parserContext.getRegistry());
|
||||
executorContext.setRegistrar(parserContext);
|
||||
executorContext.setProblemReporter(parserContext.getReaderContext().getProblemReporter());
|
||||
return executorContext;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
|
||||
package org.springframework.web.servlet.config;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.context.config.SpecificationContext;
|
||||
import org.springframework.context.config.AbstractSpecificationBeanDefinitionParser;
|
||||
import org.springframework.context.config.FeatureSpecification;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
|
||||
import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter;
|
||||
@@ -31,40 +31,21 @@ import org.w3c.dom.Element;
|
||||
* register a {@link DefaultServletHttpRequestHandler}. Will also register a
|
||||
* {@link SimpleUrlHandlerMapping} for mapping resource requests, and a
|
||||
* {@link HttpRequestHandlerAdapter} if necessary.
|
||||
*
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Chris Beams
|
||||
* @since 3.0.4
|
||||
*/
|
||||
class DefaultServletHandlerBeanDefinitionParser implements BeanDefinitionParser {
|
||||
class DefaultServletHandlerBeanDefinitionParser extends AbstractSpecificationBeanDefinitionParser {
|
||||
|
||||
/**
|
||||
* Parses the {@code <mvc:default-servlet-handler/>} tag.
|
||||
*/
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
MvcDefaultServletHandler spec = createSpecification(element, parserContext);
|
||||
spec.execute(createSpecificationContext(parserContext));
|
||||
return null;
|
||||
}
|
||||
|
||||
private MvcDefaultServletHandler createSpecification(Element element, ParserContext parserContext) {
|
||||
public FeatureSpecification doParse(Element element, ParserContext parserContext) {
|
||||
String defaultServletHandler = element.getAttribute("default-servlet-handler");
|
||||
MvcDefaultServletHandler spec = StringUtils.hasText(defaultServletHandler) ? new MvcDefaultServletHandler(
|
||||
defaultServletHandler) : new MvcDefaultServletHandler();
|
||||
return spec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adapt the given ParserContext instance into an SpecificationContext.
|
||||
*
|
||||
* TODO SPR-7420: consider unifying the two through a superinterface.
|
||||
* TODO SPR-7420: create a common ParserContext-to-SpecificationContext adapter util
|
||||
*/
|
||||
private SpecificationContext createSpecificationContext(ParserContext parserContext) {
|
||||
SpecificationContext context = new SpecificationContext();
|
||||
context.setRegistry(parserContext.getRegistry());
|
||||
context.setRegistrar(parserContext);
|
||||
context.setProblemReporter(parserContext.getReaderContext().getProblemReporter());
|
||||
return context;
|
||||
return StringUtils.hasText(defaultServletHandler) ?
|
||||
new MvcDefaultServletHandler(defaultServletHandler) :
|
||||
new MvcDefaultServletHandler();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ final class MvcDefaultServletHandlerExecutor extends AbstractSpecificationExecut
|
||||
registry.registerBeanDefinition(HANDLER_ADAPTER_BEAN_NAME, handlerAdapterDef);
|
||||
registrar.registerComponent(new BeanComponentDefinition(handlerAdapterDef, HANDLER_ADAPTER_BEAN_NAME));
|
||||
}
|
||||
|
||||
|
||||
RootBeanDefinition defaultServletHandlerDef = new RootBeanDefinition(DefaultServletHttpRequestHandler.class);
|
||||
defaultServletHandlerDef.setSource(source);
|
||||
defaultServletHandlerDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
|
||||
@@ -16,10 +16,9 @@
|
||||
|
||||
package org.springframework.web.servlet.config;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.context.config.SpecificationContext;
|
||||
import org.springframework.context.config.AbstractSpecificationBeanDefinitionParser;
|
||||
import org.springframework.context.config.FeatureSpecification;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
@@ -32,32 +31,16 @@ import org.w3c.dom.Element;
|
||||
* @see MvcResources
|
||||
* @see MvcResourcesExecutor
|
||||
*/
|
||||
class ResourcesBeanDefinitionParser implements BeanDefinitionParser {
|
||||
class ResourcesBeanDefinitionParser extends AbstractSpecificationBeanDefinitionParser {
|
||||
|
||||
/**
|
||||
* Parses the {@code <mvc:resources/>} tag
|
||||
*/
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
MvcResources spec = createSpecification(element, parserContext);
|
||||
if (spec != null) {
|
||||
spec.execute(createSpecificationContext(parserContext));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private MvcResources createSpecification(Element element, ParserContext parserContext) {
|
||||
public FeatureSpecification doParse(Element element, ParserContext parserContext) {
|
||||
String mapping = element.getAttribute("mapping");
|
||||
if (!StringUtils.hasText(mapping)) {
|
||||
parserContext.getReaderContext().error("The 'mapping' attribute is required.",
|
||||
parserContext.extractSource(element));
|
||||
return null;
|
||||
}
|
||||
String[] locations = StringUtils.commaDelimitedListToStringArray(element.getAttribute("location"));
|
||||
if (locations.length == 0) {
|
||||
parserContext.getReaderContext().error("The 'location' attribute is required.",
|
||||
parserContext.extractSource(element));
|
||||
return null;
|
||||
}
|
||||
String[] locations =
|
||||
StringUtils.commaDelimitedListToStringArray(element.getAttribute("location"));
|
||||
|
||||
MvcResources spec = new MvcResources(mapping, locations);
|
||||
if (element.hasAttribute("cache-period")) {
|
||||
spec.cachePeriod(element.getAttribute("cache-period"));
|
||||
@@ -65,23 +48,8 @@ class ResourcesBeanDefinitionParser implements BeanDefinitionParser {
|
||||
if (element.hasAttribute("order")) {
|
||||
spec.order(element.getAttribute("order"));
|
||||
}
|
||||
spec.source(parserContext.extractSource(element));
|
||||
spec.sourceName(element.getTagName());
|
||||
|
||||
return spec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adapt the given ParserContext instance into an SpecificationContext.
|
||||
*
|
||||
* TODO SPR-7420: consider unifying the two through a superinterface.
|
||||
* TODO SPR-7420: create a common ParserContext-to-SpecificationContext adapter util
|
||||
*/
|
||||
private SpecificationContext createSpecificationContext(ParserContext parserContext) {
|
||||
SpecificationContext context = new SpecificationContext();
|
||||
context.setRegistry(parserContext.getRegistry());
|
||||
context.setRegistrar(parserContext);
|
||||
context.setProblemReporter(parserContext.getReaderContext().getProblemReporter());
|
||||
return context;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,10 +16,9 @@
|
||||
|
||||
package org.springframework.web.servlet.config;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.context.config.SpecificationContext;
|
||||
import org.springframework.context.config.AbstractSpecificationBeanDefinitionParser;
|
||||
import org.springframework.context.config.FeatureSpecification;
|
||||
import org.springframework.web.servlet.mvc.ParameterizableViewController;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
@@ -32,33 +31,15 @@ import org.w3c.dom.Element;
|
||||
* @see MvcViewControllers
|
||||
* @see MvcViewControllersExecutor
|
||||
*/
|
||||
class ViewControllerBeanDefinitionParser implements BeanDefinitionParser {
|
||||
class ViewControllerBeanDefinitionParser extends AbstractSpecificationBeanDefinitionParser {
|
||||
|
||||
/**
|
||||
* Parses the {@code <mvc:view-controller/>} tag.
|
||||
*/
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
public FeatureSpecification doParse(Element element, ParserContext parserContext) {
|
||||
String path = element.getAttribute("path");
|
||||
String viewName = element.getAttribute("view-name");
|
||||
new MvcViewControllers(path, viewName.isEmpty() ? null : viewName)
|
||||
.source(parserContext.extractSource(element))
|
||||
.sourceName(element.getTagName())
|
||||
.execute(createSpecificationContext(parserContext));
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adapt the given ParserContext instance into an SpecificationContext.
|
||||
*
|
||||
* TODO SPR-7420: consider unifying the two through a superinterface.
|
||||
* TODO SPR-7420: create a common ParserContext-to-SpecificationContext adapter util
|
||||
*/
|
||||
private SpecificationContext createSpecificationContext(ParserContext parserContext) {
|
||||
SpecificationContext context = new SpecificationContext();
|
||||
context.setRegistry(parserContext.getRegistry());
|
||||
context.setRegistrar(parserContext);
|
||||
context.setProblemReporter(parserContext.getReaderContext().getProblemReporter());
|
||||
return context;
|
||||
return new MvcViewControllers(path, viewName.isEmpty() ? null : viewName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user