Sunday, July 22, 2007

XML Schema-based configuration introduced in Spring 2.0

Problem
When the application server that runs our J2EE project disconnected from the internet, the project will not start and the exception below occurred:

org.xml.sax.SAXParseException: schema_reference.4: Failed to read schema document 'http://www.springframework.org/schema/beans/spring-beans-2.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 ...


Research
In our J2EE project, we used spring frame work to handle the transaction management for some classes like MockGMMManager for example

Spring frame work runs when the deployed project on the server initialized
Spring frame work Default behavior:

Spring frame work will read in some point this file mockApplicationContext.xml "For example" to load the MockGMMManager "For example" class in spring container

mockApplicationContext.xml
You will find this in teh file
...
DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
...

NOTE: The Spring frame work need’s XML schema definition file to read this xml file It will request this XSD from http://www.springframework.org/dtd/spring-beans-2.0.dtd and this is our problem!
When there is no internet connection, spring frame work will not be able to read this file and will throw org.xml.sax.SAXParseException


Solution
We should change this default behavior by locating the required XSD file locally from our server not remotely


1. Download the latest spring updates (spring-framework-2.0.6)
2. Put the new spring.jar in the project classpath
3. Create these files:
- \META-INF\spring.handlers
- \META-INF\spring.schemas
These files not required, but spring frame work will search for them in \META-INF\ folder by default to locate the required XSD’s and if they are not exist, it will locate them from the URL in mockApplicationContext.xml

"You can get a copy of spring.handlers and spring.schemas files in Spring-framework-2.0.6 package after you download it, just copy and paste"

Open spring.schemas you will find this:


...
http\://www.springframework.org/schema/beans/spring-beans-2.0.xsd=org/springframework/beans/factory/xml/spring-beans-2.0.xsd
...


This is one of the required XSD files spring-beans-2.0.xsd, if you open spring.jar you will see this file in org/springframework/beans/factory/xml/ The red text is the name for the schema location, and you will use in mockApplicationContext.xml

The rest of the file ...

http\://www.springframework.org/schema/tool/spring-tool-2.0.xsd=org/springframework/beans/factory/xml/spring-tool-2.0.xsd http\://www.springframework.org/schema/util/spring-util-2.0.xsd=org/springframework/beans/factory/xml/spring-util-2.0.xsd http\://www.springframework.org/schema/aop/spring-aop-2.0.xsd=org/springframework/aop/config/spring-aop-2.0.xsd http\://www.springframework.org/schema/lang/spring-lang-2.0.xsd=org/springframework/scripting/config/spring-lang-2.0.xsd http\://www.springframework.org/schema/tx/spring-tx-2.0.xsd=org/springframework/transaction/config/spring-tx-2.0.xsd http\://www.springframework.org/schema/jee/spring-jee-2.0.xsd=org/springframework/ejb/config/spring-jee-2.0.xsd http\://www.springframework.org/schema/beans/spring-beans.xsd=org/springframework/beans/factory/xml/spring-beans-2.0.xsd http\://www.springframework.org/schema/tool/spring-tool.xsd=org/springframework/beans/factory/xml/spring-tool-2.0.xsd http\://www.springframework.org/schema/util/spring-util.xsd=org/springframework/beans/factory/xml/spring-util-2.0.xsd http\://www.springframework.org/schema/aop/spring-aop.xsd=org/springframework/aop/config/spring-aop-2.0.xsd http\://www.springframework.org/schema/lang/spring-lang.xsd=org/springframework/scripting/config/spring-lang-2.0.xsd http\://www.springframework.org/schema/tx/spring-tx.xsd=org/springframework/transaction/config/spring-tx-2.0.xsd http\://www.springframework.org/schema/jee/spring-jee.xsd=org/springframework/ejb/config/spring-jee-2.0.xsd


4. Change the mockApplicationContext.xml to be like this:

Remove this:

DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">

Put these inside the beans tag
xmlns="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.0.xsd"

4. Try to disconnect the server from the internet to test the solution
5. Restart the application server
6. Redeploy the project

You will not see the exception and the project will be started :-)



2 comments:

ashr said...

Just thought I'd tell you that all of that wasn't really necessary. You just had a classpath problem...

I had the same problem and went down this route of yours and realised it can't be right. Fixed my classpath to include spring and spring-security (which is the lib I had issues with) and voila.

No internet access - still works.

Anonymous said...

The information here is great. I will invite my friends here.

Thanks