Spring configuration: Failed to read schema document

Referencing on-line schema documents

A problem one might run into when developing Spring-based configurations is the accessibility of XSD-documents referenced in xsi:schemaLocation declarations. During the development the problem goes unnoticed, but under certain circumstances the application fails to start and bails out. This is known to be valid for Spring versions 2.5.x, it probably (still) works on older and never versions using the same mechanism.

Scenario

  • Development is done in an environment with access to the public internet
  • Deployment is done in an off-line or restricted networking environment (e.g. intranet without access to the internet)

Offending configuration

An excerpt of a possible offending Spring application context I ran into was one like:

<beans
  xmlns="http://www.springframework.org/schema/beans"
  xmlns:amq="http://activemq.apache.org/schema/core"
  xmlns:beans="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core-5.3.0.xsd">
</beans>

Problem cause

The versioned ActiveMQ XSD wasn’t automagically in the libraries used by the application. Running the application in an on-line environment isn’t a problem and actually will cause the XML parser to download the schema document from the internets. But when one attempts to start the application in a restricted environment a nice wall of text crit follows, for example:

WARN  2010-06-21 11:32:08,197 [main]
org.springframework.beans.factory.xml.XmlBeanDefinitionReader:
Ignored XML validation warning org.xml.sax.SAXParseException:
schema_reference.4: Failed to read schema document
'http://activemq.apache.org/schema/core/activemq-core-5.3.0.xsd',
because
  1) could not find the document;
  2) the document could not be read;
  3) the root element of the document is not <xsd:schema>.
... a lot more stack trace elements follow ...

Work-arounds

The schema location is specified by a HTTP URL. It’s possible to change the URL to an absolute filename or a resource using the classpath:-protocol. I don’t like this solution, since a change in system environment, paths or whatever requires modifying all the context configuration files. Another ‘fix’ is to tear off the version from the filename: the schema ‘activemq-core.xsd’ is preconfigured to be found from the classpath.

Nicer solution

The schema’s are actually resolved by the Spring framework and a such there’s a clean hook. Simply create a mapping for the inaccessible schema file.

  1. Create a file that’s reachable on the classpath as META-INF\spring.schemas
  2. Add a line for the missing resource in the form of ‘<missing resource>=<actual location>’

The actual location can be a location of the classpath. So in my case, the META-INF\spring.schemas looks like this:

http\://activemq.apache.org/schema/core/activemq-core-5.3.0.xsd=activemq-core-5.3.0.xsd

Et voilá, from now on Spring will pick up the versioned XSD look for a resource ‘activemq-core-5.3.0.xsd’ when it runs into ‘http://activemq.apache.org/schema/core/activemq-core-5.3.0.xsd&#8217; as the schema location.

This approach is morally superior, since it doesn’t make the schema location system dependent in the configuration file itself, but an external configuration item. There’s a similar ‘problem’ with validating XML documents in general (outside of Spring configuration files).

Conclusion

The schema documents aren’t preconfigured for some reason and cause the context initialization failure in certain environments. Adding a spring.schemas file and the missing schema documents solves this without mutilating the well-known schema locations normally used in the context configuration.

Note

This stuff seems so basic, but I’ve run into this a couple of times (and keep forgetting what the fix was). And the ‘clean way’ to fixing this problem is pretty hard to find at the moment. Search engines usually point to suggestions to modify the context configuration file.

One Response to Spring configuration: Failed to read schema document

  1. tSamy says:

    Thx, this has been really useful. I was aware of that there was issue related to access but you have explained a “cleaner” way of solving problem

Leave a comment