Java resources - Use file far off in directory tree - java

I have a newbie Java question.
I had to make suite of J/DBUnit tests for some stored procedures we use in SQL Server. These tests use some XML files in a couple of sub-directories that I originally had placed in the same directory as my Java project.
Anyway, upon checking these tests in, our SVN manager wanted to keep the .java files in one part of the tree, and resources (like the XML files and required JARs) in another part of the tree.
So, my tests had originally referenced the XML files with a relative path which doesn't work now.
My question is:
Can I make the directories with my XML files available with the CLASSPATH (I hope so).
Assuming that works, how do I reference a file in my code that was included this way?
If I shouldn't be using the CLASSPATH for this, I'm open to other solutions.

Forget calsspath. Provide your tests with a parameter/configuration which defines the root dir for the relative paths of the XML files.

Using the classpath is no problem, the standard maven project layout looks like the following:
src
main
java
resources
test
java
resources
target
classes
test-classes
The compiler compiles src/main/java to target/classes, the resources of src/main/resources are copied to the target/classes folder, similar for the tests. If the tests have a classpath containing classes and test-classes, all works fine.
How is your project layout is, how is it build?

No, you should not use CLASSPATH in this instance since it is used by Java. However, you can use a similar approach by loading a value from an environment variable or configuration file which indicates the directory where the XML files are stored.

You can do this without making any changes to your classpath. The idea is to store the resource files in a separate directory, but have them copied to a directory in your classpath when you run your build process.
Here is an example configuration:
source Directory is ${basedir}/src/main/java
resource directory is ${basedir}/src/main/resources
In your build script, copy both the .java files and the resource files (.xml) to a directory in your classpath, say:
${basedir}/target/classes
Your test code runs against the target dir. The target directory is not checked in to SVN, keeping your SVN admin happy, and you don't have to make changes to your code.

Related

How to give relative path in a executable jar?

I have a Spring app that I am deploying as a .jar.
The app has to write to a folder located in /src (precisely /src/main/resources/patches). I have this path directly in the code.
In application.properties: PATCH_DIR = src/main/resources/patches
The app has to also read a json file from src/main/resources/myJson.json, the path also being directly written in the code.
Prior to deploying, while running from the IDE everything goes well, the app sees the file and the folder and reads and writes correctly.
After building the .jar the paths change, the file is located in myJar.jar/BOOT-if/classes/myJson.json and the folder is respectively in myJar.jar/BOOT-if/classes/patches.
How can I specify these paths in the code in a way that even after building the jar they stay relevant to my application?
Edit: I can specify the path of the file as: PatchApplication.class.getClassLoader().getResource("myJson.json").getPath();
This should solve the problem, as the path is relative to the class and not to the root of the project, but it does not improve anything.
You should specify a path in your file system,instead of the path inside a .jar.When you run your app ,it would access the given path.
generally all the classes goes to classes folder in jar.
all the classes ending after src/main/java goes to /classes/ folder
and similarly all the resources file
Eg. your source folder have src/main/java/com/mypack/ABC.java than you will find this in jar as /classes/com/mypack/ABC.class .
Try using /classes/patches and /classes/myJson.json.
This should work

Maven resource folder

Hy,
I want to get the resource folder (ex: C:\Users\Raul\workspace\Serial\src\test\resources) in a Maven project but every time I run this java code:
System.out.println(getClass().getResource("").getPath());
it returns me this path: C:/Users/Raul/workspace/Serial/target/test-classes/
The last time I used Maven, worked that way without any changes from me.
Thx in advance.
With a typical setup, Maven copies the resources to the target/classes (or target/test-classes) directory. Also, the target/classes (or target/test-classes) directory is added to the classpath.
If you have a file src/test/resources/foo.txt, then you would access the file using getResource("/foo.txt").
Generally speaking, you would not want your code to refer to source folders to access resources. Resources might be put in multiple locations and it is pretty common to "filter" the resources (replace tokens with build property values). In the filtering case, you absolutely do not want the processed resource files to be in the source directory.

Launch .jar with config outside of jar, but be able to do it from ANY current directory

I've been wrestling with a particular problem. I have a Java program in a .jar file, and I have a lib directory and a config directory outside of the .jar, but in the same directory as the jar itself exists in.
I am trying to reference config/foo.config from within the code. Referencing it as a relative file works if I'm in the same directory as the jar. I've also tried using getResourceAsStream and making sure config is in the classpath.
So far, so good, but I also have to be able to launch the .jar from any directory.
So, if my structure is like so:
/prog/util/myprog/myprog.jar
/prog/util/myprog/config
/prog/util/myprog/config/foo.config
/prog/util/myprog/lib
(and a whole bunch of 3rd party jars within lib)
How do I correctly set up the classpath in my Manifest file so that config can be referenced?
The classpath in my manifest looks like so:
Class-Path: config/ lib/jar1.jar lib/jar2.jar (etc)
I am currently using getResourceAsStream("/foo.config").
This all works if I am in the /prog/util/myprog directory and run:
java -jar myproj.jar
However, I cannot, say, be in /prog and run:
java -jar util/myprog/myprog.jar
When I do this, the config file cannot be found.
How do I solve this issue?
EDIT: Some additional notes based on comments/suggestions, though I'm not sure this is feasible:
1) We can't use an absolute path for the file system, we don't know where the program will be stored, just that the config directory will be in the same directory as the jar.
2) I would like to be able to have something that works both when the code is jar'd, but also would work not-jar'd such as when I'm running in debug mode in Eclipse. At that point, the config directory is a sibling of the src, bin, and lib directories.
EDIT Part 2: Ok, between a colleague and myself, we came up with the following:
String configDirectory = new File(QueueMonitor.class.getProtectionDomain().getCodeSource().getLocation().getPath()).getParent() + "/config";
When we are in Eclipse and running in debug mode, the File object points to the bin directory, so getting the parent then appending "/config" works for our needs during development/testing.
Likewise, from a .jar file, the File object points to the jar itself, so getting the parent and appending "/config" gives us what we need as well.
I'm a little hesitant, though. I'm wondering if there's some potential problem or unintended consequence that I am not seeing in this solution. Any thoughts on that?
You should be able to use the Finding the path to a jar from a Class inside it? technique to find the location of your jar. From there it's just a matter of climbing in/out of folders.

Why isn't my file under /src/main/resources readable on execution?

I have a Java project and used the standard maven archetype to create the dir structure.
It looks like this:
|-src/main/java
|-src/main/resources
|-target/classes
|- ...
Now one of my classes uses a .properties file to read in some settings. I placed it in src/main/resources and read it through File propertiesFile = new File("./src/main/resources/starter.properties");.
When I use the eclipse run-configuration, everything works fine. But recently I tried to start the same Java-class from my console using java some.package.Class, and since the .class-file is located in target/classes I got the message, that ./src/main/resources/starter.properties couldn't be found.
What am I doing wrong? Is the .properties file not supposed to be located in the resources-folder or do I have to use an other way to load it?
The two previous answers are correct, but I wanted to give a bit more context.
This file is in two places. It starts off in /src/main/resources and when you build the project, Maven copies it to /target/classes.
At runtime, you shouldn't access the copy that is in your source code. Otherwise, your software would need access to the source code in order to run. Rather, you should access the copy that is in your deliverable. At execution time, you can safely assume that you will find it on the classpath. It's in the same place as your compiled classes, so if it weren't on the classpath, you wouldn't have been able to run the program in the first place. This is why you should use getResourceAsStream() as mentioned by the other answerers.
(Though for production software, I do recommend Spring's Resource abstraction for accessing these kinds of things.)
use
YourClass.class.getResourceAsStream("/filename.properties");
To expand on the two answers already given, when you build your Maven project the files in src/main/resources are copied into your JAR at the root of the classpath. If you did a jar tvf *yourjarname* you would notice there is neither a src/main/java or src/main/resources folder in it. So trying to manually read from those (now non-existent) paths will fail when you run via JAR. The other two answers have excellent suggestions, use the getResourceAsStream method to read in your file. Theres even a method on the Properties object that makes this very convenient and easy to use:
URL resourceURL = Thread.currentThread().getContextClassLoader()
.getResource(yourpropertyfilename);
Properties props = new Properties();
props.load(resourceURL.openStream());
At runtime this file will be in your classpath. Use Class.getResourceAsStream() to access it.

home folder changes when using java classes from matlab

I am writing a java application with a matlab ui. For this I use java objects in matlab as explained here: http://www.mathworks.com/help/techdoc/matlab_external/f4873.html
those java classes reference (using a relative path) to resources in some other folder in the parent map. In eclipse or as an executable jar this all works fine.
The problem is that when classes are used in matlab the homefolder changes. So instead of looking in JAR/resources or PROJECTMAP/resources it looks for the resources in MATLAB/resources and returns a file not found exception.
how I currently solved it is kinda lame:
I simply put a copy of the resource folder in the MATLAB directory which makes the code execute.
Yet this is a poor solution.
What I would want is
1: to include the resource folder in the jar (generated in eclipse) an make it possible to use these classes in matlab (in short: independency current directory)
2: Being able to run the same code from eclipse (to debug/profile...).
3: That the code should execute independantly of the location the jar is in as long as it is added to the matlab classpath. (so the jar does not have to be in a specific folder (eg MATLAB folder))
So I 'simply' need a way to specify the location of the resource folder in my code as to achieve 1,2,3 (1,2 most important).
Not sure how you're reading and what you're doing with these resources (so this might not be the correct solution for your case), but you indeed might want to put these on your classpath. If you put them in their own source folder in eclipse you can setup your build to include them in your jar. (Maven by convention has a /src/main/resources directory that is for sticking arbitrary files into a the compiled jar).
With these resources on the classpath... You can then use the classloader to load files through getClass().getResourceAsStream() or getResource() and run with it.

Categories

Resources