File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Spring and the fly likes Spring cannot find file in classpath (within JAR) Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Frameworks » Spring
Bookmark "Spring cannot find file in classpath (within JAR)" Watch "Spring cannot find file in classpath (within JAR)" New topic
Author

Spring cannot find file in classpath (within JAR)

François Coupal
Greenhorn

Joined: Dec 07, 2009
Posts: 3
I'm stumped rigth now by some strange behavior by Spring's resource locations in my main project. I've made a smaller, simpler Spring projet to replicate my problem and I can't get it to work (ie: I've got the same problem as my main project).

Basically, I'm using a JAR file to stock all non-class files, which includes the spring xml bean configuration, and other files (text ones). I'm also using Eclipse as an IDE, if that could be the source of the problem.

Steps are this:
I got a bean class that is resource loader aware. It has two properties, one string and one Resource. It also got an init method once all properties are set. It should be able the get a resource from it's resourceLoader using the String property. However, Spring is not even able to create the Resource property using the file name I give it.
All files I try to get are located in the same JAR as the spring bean XML. The thing is, since Spring breaks during the bean instanciation, that should mean the JAR is accessible and that the files within it are accessible as well.
But, for all my tests, both files in the JAR (besides the XML) remain invisible to Spring.

Here is the source code for all classes:

Main class:


Bean class:


The Spring bean configuration XML:


The JAR file "fichier.jar" is in the classpath during execution and contains the following files:


Here is an error message that I get when I try to execute the main class:


Any help would be appreciated. Thanks in advance.

(Edit: inserted line breaks in extremely long stack-trace lines to make post a reasonable width -- Paul C)

Perfection cannot be attained, but must be aimed for.
Mark Spritzler
ranger
Sheriff

Joined: Feb 05, 2001
Posts: 17249
    
    6

Well it definitely finds the config.xml, so you know that it is reading in the jar file. But is it possible that the other file is in a subdirectory in the jar file.

Open the jar file in an app like WinZip or 7Zip and go to the far right to see the path of the file. Let us know what that path shows.

Also just as a test, try putting a "/" in the config file for the location of the test2.txt

like

classpath:/test2.txt

Just a test, not sure if it will help.

Mark


Perfect World Programming, LLC - Two Laptop Bag - Tube Organizer
How to Ask Questions the Smart Way FAQ
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18127
    
    8

Hidden way over there in the far right of the error message, three screens to the right with the horizontal scroll bar, is this
fragment:
cannot be resolved to absolute file path because it does not reside in the file system

And you're getting a FileNotFoundException. So something in the bean creation is under the mistaken impression that you
are giving it a file name. Perhaps that's because of line 17 in your bean class which calls a getFile() method? I'm just guessing,
I know very little about Spring.
François Coupal
Greenhorn

Joined: Dec 07, 2009
Posts: 3
I tried to put the text file location as this in the config.xml: "classpath:/test2.txt" (same for the other), but the error message is exactly the same (ie: the last part of the URL reads as fichiers.jar!/test2.txt, same as before).

I should have mentioned it clearly in the original post, but the three files are at the root of the "fichiers.jar" archive. In the original project that was not the case, but I quickly found with this test that it did not matter either way, as Spring did not manage to find it.

As for your question Paul, the stacktrace shows that the error occurs during Spring bean initialisation, and not in the class itself. Even then, the whole point of this little project is to act like a test case, it must not fail anywhere because it mimics the desired outcome, which is to have access to the files from within the class for further use, from resources given by Spring.

A few things I noticed since yesterday:
1- In the end of the output the last three lines show that the bean methods were called (#setResource, #init, etc...). I'll do more tests in those method to test the output, just in case the error message was a false positive.
2- Earlier tests (in the original project) showed that files in the root directory or in specific locations (file system) did work. However, this is not a desirable solution because the project is meant to be executed as an applet, and therefore must be totally contained within signed jars.
3- I was using an ApplicationContext before (ClassPathXmlApplicationContext to be exact), but the result was the same.
4- I'll try to find all three files using ClassPathResource instances before the BeanFactory initialization, to see how it goes.

I'll post new developments soon.
François Coupal
Greenhorn

Joined: Dec 07, 2009
Posts: 3
Ok, I got help from a fellow programmer and the problem was thus:

But first, an exerpt from the Spring documentation:
4.3.2. ClassPathResource

This class represents a resource which should be obtained from the classpath. This uses either the thread context class loader, a given class loader, or a given class for loading resources.

This Resource implementation supports resolution as java.io.File if the class path resource resides in the file system, but not for classpath resources which reside in a jar and have not been expanded (by the servlet engine, or whatever the environment is) to the filesystem. To address this the various Resource implementations always support resolution as a java.net.URL.

A ClassPathResource is created by Java code explicitly using the ClassPathResource constructor, but will often be created implicitly when you call an API method which takes a String argument which is meant to represent a path. For the latter case, a JavaBeans PropertyEditor will recognize the special prefix classpathn the string path, and create a ClassPathResource in that case.


In a nutshell, this means that you must NOT use a normal File(String) constructor with a Spring resource, because the underlying implementation will try to use some kind of absolute path. Therefore, to prevent this, you must use the getFile() method from a URL object (as the documentation says in a weird way). That URL object can be fetched from the Resource instance. The resulting path will be the correct one.

That means that Paul's hunch was correct: the error was not in the Spring loading sequence (despite the stacktrace) but in the bean class setters. I was fooled, but to my defense it really was counter-intuitive.

I corrected the code and it works. See below.

Also, I corrected another error in the code: the ResourceLoaderAware interface only calls the SetResourceLoader() method in a context. Therefore, we must use an ApplicationContext instead of a bean factory in the main class for it to work. It will throw an NullPointerException otherwise because the init() method will be called without the resourceLoader being initialized.

Main class:


test class:


The other files have not been altered. (Edit: as a matter of fact, both file paths in the config.xml have been modified to the following form: "classpath:filename.txt")

My problem is solved. Thank you for your input.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Spring cannot find file in classpath (within JAR)
 
Similar Threads
DI - Beginners Question
Error while executing simple application with jdk1.5
Example for JMS sender - receiver
BeanCreationException in an standalone application using Spring
jibx binding Error: Nonstatic field name not found in