How to inject a Resource from classpath in Spring? - java

I want to inject a file from src/main/resources like this:
#Value("classpath:myfile.txt")
private Resource res;
When I run this from eclipse it works fine.
But from a standalone folder, the file is not found:
Caused by: java.io.FileNotFoundException: class path resource [myfile.txt] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/D:/myapp/myapp-1.0.0.jar!/myfile.txt
at org.springframework.util.ResourceUtils.getFile(ResourceUtils.java:212) ~[spring-core-4.1.4.RELEASE.jar:4.1.4.RELEASE]
How can I tell spring that the file to be injected is actually in the root of the jar, not an absolute path?
Same result if I try to load it programmatically.
res = new ClassPathResource("myfile.txt");

It turned out the injection itself did work, BUT I accessed the file using res.getFile() which threw the NPE.
When just retrieving the URL and fetching the file explicit with File file = ResourceUtils.getFile(res.getURL().getFile()); it worked as expected.
Though I'm not sure wether this is a bug or works as expected.

You said this works in eclipse:
#Value("classpath:myfile.txt")
private Resource res;
Now try this in eclipse (notice the *), if it works, standalone should be ok:
#Value("classpath*:myfile.txt")
private Resource res;
When deploying outside eclipse, make sure myfile.txt is on the classpath; the best location is in the root directory where Java class file packages are located (com, org)

Related

java.io.FileNotFoundException: class path resource cannot be opened because it does not exist

I create a streamHelper function to load any file that is on the classpath, this is the path for my json file, but I got error when I using this function
streamHelper("/Users/my/IdeaProjects/rules-management/data_tacos-sample/post-migration/sourceData/config_-e48059402bd4.json")
java.io.FileNotFoundException: class path resource [/Users/my/IdeaProjects/rules-management/data_tacos-sample/post-migration/sourceData/config_-e48059402bd4.json] cannot be opened because it does not exist
private InputStream streamHelper(String resourcePath) {
DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
Resource resource = resourceLoader.getResource(resourcePath);
return resource.getInputStream();
}
I print the file name on console, when I click that link it can direct me to the file which means the path is good, why I got this error? How to fix that.
The DefaultResourceLoader is a Spring class. According to Spring docs, the DefaultResourceLoader
Will return a UrlResource if the location value is a URL, and a ClassPathResource if it is a non-URL path or a "classpath:" pseudo-URL.
By default, Spring looks for all your resources in a folder called resources.
By default, this handler serves static content from any of the /static, /public, /resources, and /META-INF/resources directories that are on the classpath. Since src/main/resources is typically on the classpath by default, we can place any of these directories there.
Move your json into a folder called resources, make sure that folder is on your classpath, and then call the streamHelper as follows:
streamHelper("classpath:config_-e48059402bd4.json")

Java find the relative path of the configuration file in the war file

I am trying to access the config.properties file which was previously placed in the config folder. after some research, I moved it to the WEB-INF folder. but even after I moved it, it still return java.lang.NullPointerException whenenver I run my my program. code used to store some password information as below:
ClassLoader resource = ConnectionManager.class.getClass().getClassLoader();
URL path = ConnectionManager.class.getClass().getResource("/WEB-INF/config.properties");
props.load(new FileInputStream(path.getFile()));
String passwordds = props.getProperty("datasource.password");
these are the codes that I found and I try to use it but still I got the null exception.
I cannot use absolute path due to this project will be deploy to production server as in .war file. please advise what is the best way as I am still beginner.
You should check the war your build tool generated, and find where your config file really are.
For maven project, the default resource dir is /src/main/resources/
So /src/main/resources/config.properties will be put at /WEB-INF/classes/config.properties in a war.
You can use getClass().getResourceStream("/config.properties") (getResource sometimes not work will in j2ee environment) to get it.

Loading File in External Tomcat Container vs Bootrun

I am trying to load a file in Spring.
The file contains Rules based on OpenRules engine.
The problem is when I am using Spring BootRun it is loaded properly.
But when I am trying to deploy the same file in External Tomcat I am getting error FileNotFound.
I am mentioning the file path in property file in the following way:
rules.open.main.decision.path=file:rules/main/Decision.xls
The rules folder is directly under the Project Folder.
In Java I am loading the file:
public Decision getDecisionEngine(){
String decisionName = "CustomerPreventStrategies";
//String fileName = "file:rules/main/Decision.xls";
String fileName = env.getProperty("rules.open.main.decision.path");
System.out.println("rules.open.main.decision.path:"+fileName);
Decision decision = new Decision(decisionName,fileName);
return decision;
}
When I am creating the WAR for external Tomcat I am keeping it in 2 locations. But it is not helping.
war {
baseName = 'MyOpenRules'
version = '0.1.0'
from("rules") {
into("WEB-INF/classes/rules")
}
from("rules") {
into("rules")
}
}
I am getting:
Caused by: java.io.FileNotFoundException: rules\main\Decision.xls (The system cannot find the path specified)
Try using
rules.open.main.decision.path=file:/rules/main/Decision.xls
This makes the Springs to pick from location WEB-INF/classes/rules/main/Decision.xml
When you use
rules.open.main.decision.path=file:rules/main/Decision.xls
the file is expected to be in the current directory. When us start tomcat server through catalina.bat or startup.bat which is inside Tomcat_HOME/bin then bin directory is the current folder for that process. Hence when u kept the file inside tomcat bin that worked.
When u put / spring uses relative path to look for file.

Classpath Resource in Tomcat6 (Works in Jetty)

I'm having trouble with a legacy Web Application that I'm migrating to Maven3.
I need to obtain a file from the Classpath that in the directory structure is located in:
/src/main/resources/com/thinkglish/geoip/GeoIP.dat
When I create the .war file with the Maven build, I can confirm that this .dat file is located (as it should be) in:
WEB-INF/classes/com/thinkglish/geoip/GeoIP.dat
I'm trying two different approaches to get the resource from one of my classes, which implements javax.servlet.Filter:
ClassPathResource resource = new ClassPathResource("com/thinkglish/geoip/GeoIp.dat");
and
URL resource = getClass().getResource("/com/thinkglish/geoip/GeoIp.dat");
If I start the application using Maven's Jetty plugin, that works fine in both ways. However, when I deploy the application in a Tomcat and start the server, the resource cannot be located.
In the first case I get a java.io.FileNotFoundException: class path resource [com/thinkglish/geoip/GeoIp.dat] cannot be resolved to URL because it does not exist and in the second case the resource is null.
A curious thing about all this is that if I use one method or the other trying to obtain another resource from the Classpath (e.g. com/thinkglish/struts/i18n/MessageResources.properties or com/thinkglish/filter/LanguageFilter.class) it works without any problems.
Do you have any guess about this? Is it possible that the .dat extension has anything to do with this?
Edited - More data!
I added a new .properties mock file to the exact same directory in which the .dat file lives:
/src/main/resources/com/thinkglish/geoip/mock.properties
I tried to obtain it in Tomcat6 and it worked!
ClassPathResource resource = new ClassPathResource("com/thinkglish/geoip/mock.properties");
I'm starting to think that I need to do something else configuration-wise to make Tomcat6 accept the .dat file as a Classpath resource.
Thanks in advance!
I might be barking up completely the wrong tree here... but have you checked the capitalisation of GeoIP.dat / GeoIp.dat? Is Tomcat running on a case-sensitive OS?
Following should work:
String classpathLocation = "com/thinkglish/geoip/GeoIp.dat";
URL classpathResource = Thread.currentThread().getContextClassLoader().getResource(classpathLocation);
// Or:
InputStream input = Thread.currentThread().getContextClassLoader().getResourceAsStream(classpathLocation);

Java file path in web project

I need to access the resource files in my web project from a class. The problem is that the paths of my development environment are different from the ones when the project is deployed.
For example, if I want to access some css files while developing I can do like this:
File file = new File("src/main/webapp/resources/styles/some.css/");
But this may not work once it's deployed because there's no src or main directories in the target folder. How could I access the files consistently?
You seem to be storing your CSS file in the classpath for some unobvious reason. The folder name src is typical as default name of Eclipse's project source folder. And that it apparently magically works as being a relative path in the File constructor (bad, bad), only confirms that you're running this in the IDE context.
This is indeed not portable.
You should not be using File's constructor. If the resource is in the classpath, you need to get it as resource from the classpath.
InputStream input = getClass().getResourceAsStream("/main/webapp/resources/styles/some.css");
// ...
Assuming that the current class is running in the same context, this will work regardless of the runtime environment.
See also:
getResourceAsStream() vs FileInputStream
Update: ah, the functional requirement is now more clear.
Actually I want to get lastModified from the file. Is it possible with InputStream? –
Use getResource() instead to obtain it as an URL. Then you can open the connection on it and request for the lastModified.
URL url = getClass().getResource("/main/webapp/resources/styles/some.css");
long lastModified = url.openConnection().getLastModified();
// ...
If what you're looking to do is open a file that's within the browser-visible part of the application, I'd suggest using ServletContext.getRealPath(...)
Thus:
File f = new File(this.getServletContext().getRealPath("relative/path/to/your/file"));
Note: if you're not within a servlet, you may have to jump through some additional hoops to get the ServletContext, but it should always be available to you in a web environment. This solution also allows you to put the .css file where the user's browser can see it, whereas putting it under /WEB-INF/ would hide the file from the user.
Put your external resources in a sub-directory of your project's WEB-INF folder. E.g., put your css resources in WEB-INF/styles and you should be able to access them as:
new File("styles/some.css");
Unless you're not using a standard WAR for deployment, in which case, you should explain your setup.
Typically resource files are placed in your war along with your class files. Thus they will be on the classpath and can be looked up via
getClass.getResource("/resources/styles/some.css")
or by opening a File as #ig0774 mentioned.
If the resource is in a directory that is not deployed in the WAR (say you need to change it without redeploying), then you can use a VM arg to define the path to your resource.
-Dresource.dir=/src/main/webapp/resources
and do a lookup via that variable to load it.
In Java web project, the standard directory like:
{WEB-ROOT} /
/WEB-INF/
/WEB-INF/lib/
/WEB-INF/classes
So, if you can get the class files path in file system dynamic,
you can get the resources file path.
you can get the path ( /WEB-INF/classes/ ) by:
this.getClass().getProtectionDomain().getCodeSource().getLocation().getPath()
so, then the next ...

Categories

Resources