Maven resource folder - java

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.

Related

Jar file contains a duplicate of every image

I am generating my jar file with Intellij Idea, and it works. However, I extracted the jar to see why it was mysteriously bigger in size then expected. I found the resources directory, containing all my images, as expected, but... for some reason, outside the resources directory, in the 'main' folder when you first open the extracted jar, are all the images again.. duplicated. This does not reflect my project structure or anything, the only place I have images are in resources. Anyone know what's going on, and how to stop this?
Project Structure:
Check the jar artifact configuration, make sure it's not set to package the contents of the resources directory inside the jar (just the compiler output entry would be enough since it will contain the resources already).
If it's not the case, check the output directory of your project. The files from the resources directory should be present inside the root of the output directory. If there is resources subdirectory, delete it and rebuild the project, ensure it doesn't appear in the output again.
In case the resources subdirectory appears in the module output after rebuild, verify the module roots configuration. It could be that the directory above resources is configured as resources (or sources) itself.
If you can't figure out the problem, please share a complete sample project illustrating it and I'll point you to the exact configuration you should change.

Java read a folder from project base directory

I have a maven project with typical project structure. At the base of the project, I have a directory names res that has some resources (> 500 MB).
I am trying to use
this.class().getClassLoader().getResourceAsStream("res/xxx")
this code fragment to read from that folder, but it returns a null resource stream.
I have a few workarounds below, but none of these are acceptable due to reasons explained below.
I can move the folder to {base}/target/classes, and it will be read, but it will also get cleaned when I do a mvn clean. Hence, this approach doesn't work. For some reason, specifying the path as ../../res/xxx also doesn't work.
I can move the folder to {base}/src/resources, but then it will get copied to target/classes and the jar. Hence this is also not acceptable.
Though I am open to trying some other java APIs, I may have to use the class loader mechanism only as there is some external library component that is also trying to access the res folder using the similar approach.
Is there some way I can read the res folder from projects base directory? Is there some setting in pom.xml file that can help me with that?
Use this.class().getClassLoader().getResourceAsStream("/res/xxx") and then you will be reading from the root of the classpath irrespective of the actual file/folder location in windows or Linux. This is actually one of the safest ways to read files especially when you do not know how your application will eventually be deployed.
It means though that your classpath must include the parent of res and that res/ must be copied over when you deploy your app
Otherwise, if you want to use relative paths, try this snippet (taken from this SO answer):
String filePath = new File("").getAbsolutePath();
filePath.concat("path to the property file");
If you use this.class().getClassLoader().getResourceAsStream("/res/xxx"), it is going to try to load resources from the classpath. If that's not want you want to do, you're going to need to specify an absolute path.
Resource on Classpath
If you don't want the resource built into your JAR, I'd suggest having a different maven project with the file in it, under the src/main/resources directory. This will create a jar file with the file in it, which will be ~500MB.
After this, you can include a dependency on this project in your project containing your application code. This will then be able to reference it from the jar file using getResourceAsStream(...).
If you don't want this large jar file to ship with your application, make sure you mark the dependency with <scope>provided</scope>.
File from Absolute Path
You will need to take the file location as a parameter in your main method, and then use new File("C:\\path\\to\\your\\file.txt") and then use a FileReader to read it in.

Java resources - Use file far off in directory tree

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.

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.

how to filter files from the root "classes" and "test-classes" folders in Eclipse?

I am using ClearCase in my application which generates a whole load of ".copyarea.db" files (one in every folder).
These cause conflicts when publishing to Tomcat as Eclipse will bundle the "classes" and "test-classes" folders into one JAR (not sure why it does this - as there is no need to have test classes available on the application server).
Any folders with the same names will have a separate .copyarea.db in the classes and test-classes branches.
I managed to get around this problem in general by adding ".copyarea.db" to the Filtered resources on the Java->Compiler->Building->Output Folder preference page. This stops the file appearing in source output (package/class folders), the vast majority of cases.
However there remains the problem of the root folder, i.e. "target/classes/.copyarea.db" and "target/test-classes/.copyarea.db".
These files are not filtered as they are not part of the compile task.
Just deleting the files manually doesn't help either, as Eclipse expects to find them and doesn't.
How can I exclude these ".copyarea.db" files from the root "classes" and "test-classes" folders?
This file .copyarea.db is created in each directory of a web view (through CCRC, the remote client of ClearCase).
The simplest solution would be to not put under source control the directories classes and test-classes.
Then, as illustrated by this technote:
Otherwise, the directory should not be controlled.
If the directory is not controlled, then the .copyarea.db file within it should never be created.
If the directory was accidentally added to source control, this could be prevented in the future by adding classes to the ignore list. This would avoid the directory being passed to ClearCase during the Share.
Since you don't usually version the binaries produced under classes and test-classes, removing those folder, and adding them again manually (keeping them private to your view) is an acceptable solution.
If those folders are not under version control, then those copyarea.db come from versioned folders which contain them, and have been copied to the destination folder.
In that case, you can simply remove the copyarea.db files.
But since you said that Eclipse "expects to find them and doesn't", I assume those "classes" and "test-classes" folders are not private folder.
concerning
These cause conflicts when publishing to Tomcat as Eclipse will bundle the "classes" and "test-classes" folders into one JAR (not sure why it does this - as there is no need to have test classes available on the application server)
you can configure this in project properties, build path, order and export, or use maven and m2eclipse!

Categories

Resources