Spring inside war cannot find classpath resource in an inner jar file - spring

I have a project organized like this:
core
-- /src/main/resources/company/config/spring-config.xml
webapp
-- /WEB-INF/applicationContext.xml
The webapp depends on core.jar, which is included correctly in WEB-INF/lib when I deploy.
In web.xml I have:
<param-value>
/WEB-INF/applicationContext.xml
</param-value>
And in applicationContext.xml I have:
<import resource="classpath:/company/config/spring-config.xml" />
But when I run, I get this error:
2012-10-04 20:03:39,156 [localhost-startStop-1] springframework.web.context.ContextLoader ERROR: Context initialization failed
org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Failed to import bean definitions from URL location [classpath:/company/config/spring-config.xml]
Offending resource: ServletContext resource [/WEB-INF/applicationContext.xml]; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [company/config/spring-config.xml]; nested exception is java.io.FileNotFoundException: class path resource [company/config/spring-config.xml] cannot be opened because it does not exist
at org.springframework.beans.factory.parsing.FailFastProblemReporter.error(FailFastProblemReporter.java:68)
....
Caused by: java.io.FileNotFoundException: class path resource [company/config/spring-config.xml] cannot be opened because it does not exist
at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:142)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:336)
... 36 more
When spring-config.xml is in webapp, everything works fine.
I noticed the leading / is removed from some of the errors on the stack trace, and I wonder if this has anything to do with it.
Also, I am (unfortunately) using Spring 2.5, if that matters.

For future reference, I figured out the problem after much debugging. It turns out Eclipse was building my "core" library as a jar, but with a web application package layout, so instead of my resource being located here:
/company/config/spring-config.xml
it was located here:
/WEB-INF/company/config/spring-config.xml
which caused the problem. I had checked the jar a few times before, but had never noticed the sneaky "/WEB-INF" hiding in plain sight.
Removing the project and re-importing it into Eclipse (via the Maven pom.xml file) was not enough to fix the problem.
I had to manually delete the Eclipse-specific .project, .classpath, and .settings files. When I did that and re-imported the project everything was fixed.
The moral of the lesson is: ALWAYS check your resource paths when the exception says "File Not Found".

Related

Spring import resource: Skip if file does not exist

I added this to my Spring configuration inside my WAR file:
<import resource="classpath:myapp-custom-settings.xml"/>
This way, users can create a myapp-custom-settings.xml file (in a folder listed in shared.loader) to modify the beans they want without having to unzip the WAR.
Very convenient, but most users don't have such a file, in which case a FileNotFoundException happens and the app does not start:
ERROR: org.springframework.web.context.ContextLoader - Context initialization failed
org.springframework.beans.factory.parsing.BeanDefinitionParsingException:Configuration problem: Failed to import bean definitions from URL location [file:/home/nico/tomcat/conf/myapp-custom-settings.xml]
Offending resource: ServletContext resource [/WEB-INF/spring/root-context.xml]; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from URL [file:/home/nico/tomcat/conf/myapp-custom-settings.xml]; nested exception is
java.io.FileNotFoundException: /home/nico/tomcat/conf/myapp-custom-settings.xml (No such file or directory)
at org.springframework.beans.factory.parsing.FailFastProblemReporter.error(FailFastProblemReporter.java:70)
at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.java:85)
at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.java:76)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.importBeanDefinitionResource(DefaultBeanDefinitionDocumentReader.java:233)
QUESTION: Is there a way to make this import failsafe?
I mean, load the file if it exists, but skip if it does not exist.
The trick is to use classpath* instead of classpath. Note the * asterisk character.
Example:
<import resource="classpath*:myapp-custom-settings.xml"/>
The app will now start normally even if no myapp-custom-settings.xml file is found.

Getting error in trying to read applicationContext.xml in Standalone java

ApplicationContext context=new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
InvGroupDelegate igcd = (InvGroupDelegate) context.getBean("invGroupDelegate");
Giving error:
Caused by: java.io.FileNotFoundException: class path resource [applicationContext.xml] cannot be opened because it does not exist
at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:157)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:328)
The appContext file is present in myProject/properties
And this is also added to 'Src folders in the build path'.
Resolved it. Was an eclipse issue. Closed the project and reopned it. Then cleaned up everything and built once more. Then things were fine.

Cannot load resource in spring-data project

I am using spring-data project in combination with hadoop to run map-red jobs. My application context seems not to resolve classpath resources.
<hdp:job id="myjob" input-path="wordcount/in/" output-path="wordcount/outtttt/"
mapper="org.apache.hadoop.examples.WordCount.TokenizerMapper"
reducer="org.apache.hadoop.examples.WordCount.IntSumReducer"
jar="classpath:hadoop-examples-1.0-SNAPSHOT.jar"
jar-by-class="org.apache.hadoop.examples.WordCount"/>
<hdp:job-runner id="myjob-runner" job-ref="myjob" run-at-startup="true"/>
I see from my classpath when I run a program that jar is present:
-classpath "C:\Program Files\Java\jdk1.7.0_25\jre\lib\charsets.jar;... atd;C:\Users\JS185350\WorkSpace\HBasePlaying\hadoop-examples\target\hadoop-examples-1.0-SNAPSHOT.jar;
Error creating bean with name 'myjob': Invocation of init method failed; nested exception is java.io.FileNotFoundException: class path resource [classpath:hadoop-examples-1.0-SNAPSHOT.jar] cannot be resolved to URL because it does not exist
Any guess what might be wrong?
try adding a slash / in front of the hadoop-examples...
<hdp:job id="myjob" input-path="wordcount/in/" output-path="wordcount/outtttt/"
mapper="org.apache.hadoop.examples.WordCount.TokenizerMapper"
reducer="org.apache.hadoop.examples.WordCount.IntSumReducer"
jar="classpath:/hadoop-examples-1.0-SNAPSHOT.jar"
jar-by-class="org.apache.hadoop.examples.WordCount"/>
<hdp:job-runner id="myjob-runner" job-ref="myjob" run-at-startup="true"/>

FileNotFound exception thrown when trying to create application-context object using ClassPathXmlApplicationContext on Weblogic server

Scenario
There was a requirement in my project to multi-thread calls made to a Webservice. This is implemented using ThreadPoolTaskExecutor (Spring).
As the thread class required values to be fed at runtime, had implemented the code as below -
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application-context.xml");
for (DocumentData documentData : documentDataList){
MinerThread minerThread = applicationContext.getBean("minerThread",MinerThread.class);
minerThread.setHeader(header);
minerThread.setDocumentData(documentData);
minerThread.setBatchSize(batchSize);
minerThreadExecutor.execute(minerThread);
}
Issue
In local I have tomcat server and this implementation works as expected. However on Weblogic (on the client machine, I don't have access to Weblogic) when the war is deployed it throws FileNotFound Exception.
As the application context object is created via ClassPathXmlApplicationContext API thought the error was thrown because the location was not under the Weblogic classpath. There was nothing set in the Weblogic server classpath. However even after including WEB-INF/classes in the classpath the same exception is thrown.
Exception
2013/01/29 09:19:12,853 [ERROR] RequestQueueListener - org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Failed to import bean definitions from relative location [../shared-common-context.xml]
Offending resource: class path resource [application-context.xml]; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [../shared-common-context.xml]; nested exception is java.io.FileNotFoundException: class path resource [../shared-common-context.xml] cannot be opened because it does not exist
BeanDefinitionParsingException is caused because of the relative path that was added in the Weblogic classpath.
On the Weblogic the file is at the location -
./wls10.3.4/ColorisPPT1/user_projects/domains/Coloris_PPT1_Domain/servers/Coloris_PPT1_AdminServer/tmp/.appmergegen_1336142780924_documentservice.war/WEB-INF/classes
When the war if built (Maven is used) the application-context.xml is placed under WEB-INF/classes folder.
Could someone please suggest how to proceed with this.

How to use local xsd for EhCache with Spring

We are facing one issue about EhCache and Spring, when we point XSD file in ehcache.xml to http://ehcache.org/ehcache.xsd, everything is ok, our application can startup correct.
But our server can't access external website, so we changed XSD location to local as below, but the application can't startup with following exception (already copy ehcache.xsd to classes folder, same as ehcache.xml).
I have googled many solution, but it still can't be fixed. I need your help about this. Thank you very much.
Spring: 3.1.0
EhCache: 2.4.2
Server: Tomcat 6.0
Java : 1.6
Config:
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd"
updateCheck="false" monitoring="autodetect" dynamicConfig="true">
Exception:
2012-11-07 16:54:42,003 WARN [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] - <Ignored XML validation warning>
org.xml.sax.SAXParseException: schema_reference.4: Failed to read schema document 'ehcache.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>.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:195)
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.warning(ErrorHandlerWrapper.java:96)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:380)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:318)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.findSchemaGrammar(XMLSchemaValidator.java:2440)
... more
2012-11-07 16:54:42,007 ERROR [org.springframework.web.context.ContextLoader] - <Context initialization failed>
org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 3 in XML document from ServletContext resource [/WEB-INF/classes/META-INF/ehcache.xml] is invalid; nested exception is org.xml.sax.SAXParseException: cvc-elt.1: Cannot find the declaration of element 'ehcache'.
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:396)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:334)
... more
Caused by: org.xml.sax.SAXParseException: cvc-elt.1: Cannot find the declaration of element 'ehcache'.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:195)
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:131)
... more
Download ehcache.xsd, put it to the same folder where is your config xml file.
modify the xml head like below, notice the classpath prefix:
<ehcache
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="classpath:ehcache.xsd">
This will work in the development and production environment.
usually I set xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd", But this can't work in a offline environment.
My Workaround is add this xsd file to absolute path, such as: c:/ehcache.xsd and point to this location in ehcache.xml.
Hope this will help someone who facing the same issue.
Still looking forward to find out other solution.
Thanks.
In my case just downloading the file from http://ehcache.org/ehcache.xsd into src/main/resources solves the problem
cd src/main/resources
wget http://ehcache.org/ehcache.xsd

Resources