Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring DI applicationContext.xml how exactly is xsi:schemaLocation used?

Note: the test project I'm mentioning can be downloaded with:

git clone https://github.com/mperdikeas/so-spring-di-appcontext-schemalocation.git

.. and run with 'ant run'.

I 'understand' that XML namespace names are just used as opaque identifiers and not meant to be used as URIs (wikipedia). I also 'understand' that the XML schema locations are meant to provide hints as to the actual location of schema documents and, being hints, not used in practice (w3.org). With that in mind I 've been experimenting with a simple Spring DI application (used in a simple J2SE setting) by modifying the applicationContext.xml. Here is the starting version:

<beans xmlns             = "http://www.springframework.org/schema/beans"                                             
      xmlns:xsi         = "http://www.w3.org/2001/XMLSchema-instance"                                               
      xmlns:context     = "http://www.springframework.org/schema/context"                                           
      xmlns:p           = "http://www.springframework.org/schema/p"                                                 
      xsi:schemaLocation="http://www.springframework.org/schema/beans                                               
                          http://www.springframework.org/schema/beans/spring-beans-2.5.xsd                          
                          http://www.springframework.org/schema/context                                             
                         http://www.springframework.org/schema/context/spring-context-2.5.xsd">                    

<context:component-scan base-package="atm"/>                                                                       
<context:property-placeholder location="classpath:META-INF/spring/atm.properties"/>                                

<bean id="soapTransport_" class="atm.SoapATMTransport" p:retries="${transport.retries}"/>                          

When I did a 'sudo ifconfig eth0 down' the project ran perfectly which is consistent with the runtime not bothering to fetch anything from the schemaLocations. However, when I mangled the schemaLocations by adding a simple underscore to the second URL in each pair I received the following complaint:

 [java] org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 10 in XML document from class path resource [META-INF/spring/applicationContext.xml] is invalid; nested exception is org.xml.sax.SAXParseException; lineNumber: 10; columnNumber: 100; cvc-elt.1: Cannot find the declaration of element 'beans'.
 [java]     at org.apache.tools.ant.taskdefs.ExecuteJava.execute(ExecuteJava.java:194)
 [java]     at org.apache.tools.ant.taskdefs.Java.run(Java.java:771)
 [java]     at org.apache.tools.ant.taskdefs.Java.executeJava(Java.java:221)
 [java]     at org.apache.tools.ant.taskdefs.Java.executeJava(Java.java:135)
 [java]     at org.apache.tools.ant.taskdefs.Java.execute(Java.java:108)
 [java]     at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:291)
 [java]     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 [java]     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
 [java]     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 [java]     at java.lang.reflect.Method.invoke(Method.java:601)
 [java]     at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
 [java]     at org.apache.tools.ant.Task.perform(Task.java:348)
 [java]     at org.apache.tools.ant.Target.execute(Target.java:390)
 [java]     at org.apache.tools.ant.Target.performTasks(Target.java:411)
 [java]     at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1399)
 [java]     at org.apache.tools.ant.Project.executeTarget(Project.java:1368)
 [java]     at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
 [java]     at org.apache.tools.ant.Project.executeTargets(Project.java:1251)
 [java]     at org.apache.tools.ant.Main.runBuild(Main.java:809)
 [java]     at org.apache.tools.ant.Main.startAnt(Main.java:217)
 [java]     at org.apache.tools.ant.launch.Launcher.run(Launcher.java:280)
 [java]     at org.apache.tools.ant.launch.Launcher.main(Launcher.java:109)

Which seems to suggest that Spring DI runtime uses the second URL in each pair at the xsi:schemaLocation as some kind of identifier (hardcoded in its logic since there is no network access). So my assumption would be that the Spring DI runtime uses two kind of identifiers for each namespace: the xmlns identifier to uniquely identify the namespace (used as an opaque string) and the schemaLocation identifier to uniquely identify the schema version for that namespace (again used as an opaque string). I.e. the schemaLocation is actually used (in a contorted way ? as that doesn't seem to be the intention of the w3c documents) to version the namespace. Moreover, in such a case, why doesn't the Spring DI runtime complain about the lack of a schemaLocation for the "p" namespace. Is my mental model correct?

like image 856
Marcus Junius Brutus Avatar asked May 26 '12 18:05

Marcus Junius Brutus


1 Answers

Here is what happens:

  • XML schema allows you to define aliases (short names) to XML namespaces. Technically all namespaces are identified by full URI but that would be very cumbersome - so you can use short aliases like context and p. There is also a default namespace denoted by xmlns attribute

  • By default XML parsers assume namespace URI is also a XSD file URL location. This is often the case, but is not required by the spec. This is also how XML parser in Spring works if you don't provide schemaLocation attribute.

  • schemaLocation is used to map from namespace URI to XSD file physical location (URL). It is used when schema namespace does not point to valid XSD URL (see MSDN on schemaLocation).

  • Last but not least, Spring adds yet another layer that translates Internet URLs to local files on CLASSPATH. This way your application can start without Internet connection (or when springframework.org site is down).

If you search your project libraries you'll find several files named spring.schemas. These files contain lines similar to below (extract from the file found in spring-context.jar, I added alignment):

http\://www.springframework.org/schema/context/spring-context.xsd= org/springframework/context/config/spring-context-3.1.xsd
http\://www.springframework.org/schema/jee/spring-jee.xsd=         org/springframework/ejb/config/spring-jee-3.1.xsd
http\://www.springframework.org/schema/lang/spring-lang.xsd=       org/springframework/scripting/config/spring-lang-3.1.xsd
http\://www.springframework.org/schema/cache/spring-cache.xsd=     org/springframework/cache/config/spring-cache-3.1.xsd
like image 99
Tomasz Nurkiewicz Avatar answered Nov 16 '22 00:11

Tomasz Nurkiewicz