How is created a jar in maven? - java

We start from the end, after the build install, in the target folder, is possibile to see 2 important thing: the file producted from the build (war, ear, jar) and a folder called usually like the project. My question is, the file is done from the folder ? Or the folder is just a copy to see faster the result of the build ?

In a typical build, maven places in target/generated_folder all required builds assets(compiled classes, resources e.t.c).
Then, depending on the declared packaging, compresses aforesaid folder and generates the final artifact.
So to answer you question, the final generated file is derived from the folder inside target directory.

Related

How to read file from file system during Maven build of module

I have a Maven project A (packaged as a pom) containing Maven module project B (packaged as a jar).
Project B is also physically in the root of project A.
When B is being built, a plugin indirectly uses my code (inside B) to access a property file in its src/main/resources location.
When I build project B directly (mvn clean install) the code can easily find that file by using new File("src/main/resources/foo.properties");
However when I try to build project A, it first will try to build the module B, and in that case it cannot find the property file.
Apart from the 'new File' variant, I have tried using
this.getClass().getClassLoader().getResourceAsStream("src/main/resources/foo.properties");
and I tried using Spring:
Resource resource = new ClassPathResource("src/main/resources/foo.properties");
Both also with a "/" prefix. But the file simply cannot be found.
Why is that? Might it be looking for the file in the root of A? Is it possible to find the file in module B when building A?
Thanks!
new File("src/main/resources/foo.properties");
This is a path relative to the working directory. The working directory is wherever you called maven. So that's why it won't work when calling maven anywhere other than the directory of module B.
this.getClass().getClassLoader().getResourceAsStream("src/main/resources/foo.properties");
This won't work because the classpath is where maven put the classes, that is, target/classes.
What you need to do is add this file as resource in the maven build, then use the getResourceAsStream idea with the correct path. Since you used the standard maven layout, you probably don't need to anything and just use
this.getClass().getClassLoader().getResourceAsStream("foo.properties");

Can't Access resource path, only the target path

I want to access the resource's form of my project "\src\main\resources" but for any reason I can only access the target classes.
Here is my code:
System.out.println(Main.class.getResourceAsStream("/123.txt")); // java.io.BufferedInputStream#66cd51c3
System.out.println(Main.class.getResource("/123.txt")); // file:/C:/Users/Raul/workspace/Serial/target/classes/123.txt
System.out.println(Thread.currentThread().getContextClassLoader().getResource("123.txt").getPath()); // /C:/Users/Raul/workspace/Serial/target/classes/123.txt
and here my Project Dirs:
The thing is, even if I delete all the files in the target/classes and run the code, the compiler will copy the files from "src/main/ressources" into "target/classes" and read them from there.
I want to access the resource's form of my project "\src\main\resources" but for any reason i can only access the target classes.
I think the question is answered by user #VGR. Just to clarify it in another words:
You put your resources in the /src/main/resources folder, and these resouces will be copied as is into the /target/classes folder when you build your project.
Example
src/main/resouces/123.txt -> target/classes/123.txt
src/main/resources/myresources/145.txt -> target/classes/myresources/145.txt
...
Now if you run the program inside of your IDE you'll observe the following:
System.out.println(Main.class.getResource("/123.txt"));
output: file:/C:/Users/Raul/workspace/Serial/target/classes/123.txt
System.out.println(Main.class.getResource("/myresources/145.txt"));
output: file:/C:/Users/Raul/workspace/Serial/target/classes/myresources/145.txt
But if you open the generated jar file you'll not see the target folder because the file 123.txt will be on the root of the jar file and the file 145.txt will be under the folder myresources/145.txt.
The folder target is just an output directory for the build tool and will not be packaged within your jar file.
Now to the following question:
the problem is that i dont know how to export the target classes to my jar, or how can I get "src/main/ressources" as return value.
To answer this question you have to look into your pom.xml file on the root of your project. There should be a <packaging>jar</packaging> entry in it. If that is so you create the jar file as follows:
Option 1: from the command line
mvn clean install
the jar file will be created and copied into the folder target.
Option 2: from within Eclipse (for example)
right click on the pom.xml > Run AS > Maven install
the jar file should also be generated and copied into the folder target.
Note: on your screenshot there are two jar files: core-0.0.1-SNAPSHOT.jar and Serial-0.0.1-SNAPSHOT.jar; remove them (mvn clean or right click > Run AS > Maven clean) before generating the jar file. The reason is Maven can only generate one jar file per Maven module / project, afaik.
You are seeing the intended behavior. A Java program is compiled into an executable form—meaning, .class files and resources. When other users run your program, they will not have access to the source, so your code should not assume your source tree will be available.
Simply put, your code is correct as is. Do not attempt to read the source tree. If you want target/classes to contain up-to-date files, rebuild your project.
A word of caution: Never use the getPath() method of URL to convert a URL to a file name. There are many characters which are not permitted in URLs, and those characters will be “percent-escaped” in order to conform to the URL specification; as a result, the path portion of a URL is not a valid filename! The only correct way to convert a URL to a file is Paths.get(url.toURI()). However, you should not even try to convert a resource to a file at all, because once you move on to packaging your programs in .jar files, your resources will not exist as regular files at all, only as entries in .jar files (which are actually just zip files with some Java-specific entries added).

Copy directory from another project during build

In project A I have a dependency to project B which has the CSS resources directory.
Due to some framework issues I need to copy the CSS directory to project A during the build. How to do it? The css directory is inside src/main/resources/css therefore it goes to /css inside the .jar
No need to copy because Servlet 3.0 Specs sais in part 3.6, you can place the css in META-INF/resources into the jar of your project B.
It works great except maven-tomcat-plugin.
This is where the file ends up:
<outputDirectory>${basedir}/target/blah</outputDirectory>
This is where it is copied from:
<directory>src/main/otherresources</directory>
There would be an or tag to tell the file name(s)
Multiples
You need multiple executions with different ids for multiple folders:
There are two solutions. But before you have to know the path from project A to project B.
You can use the maven resource plugin.
There's a goal to copy a resource to an output directory.
Or, you can use the maven ant plugin.
Here is an example : http://www.javacodegeeks.com/2013/07/how-to-run-ant-targets-with-maven.html

Where to store resources for a java project in Eclipse (images, data files, ...)?

Not sure this basic question has already been answered on SO.
From the reference and also answers found on SO, I understand that in Eclipse a "source folder" is a folder that JDT will search for source files, and compile them.
It has been mentioned also that each source folder may have a counterpart to store compiled classes. Maybe this is why the content of the usual "src" folder of a project is compiled into a "bin" folder (when using such src/bin project option in Eclipse).
Question: Where to store additional non-source files, e.g. an icon, a security policy, or a data file? I guess this is in a "regular" folder, but at which level in the project hierarchy (usually)? Is it possible to put it in a source folder or not (why would we do that)? What happens after compilation, or export to a .jar file, under which conditions are the files copied in the .jar? Is the relative path preserved?
This is purely conventional. You can store them all in src if you want.
However, if you want to stick to Maven or Gradle conventions, then you should have something like that:
src/main/java : main source file, that will be compiled and then distributed (jar, etc)
src/main/resources : main resources, distributed.
src/test/java : test source file, aka Junit test
src/test/resources : test resources.
Maven would compile all Java into target/classes and copy all resources into target/classes. For test, it would be target/test-classes.
Beside, if you want to access a resource, that in the Jar where your classes are, you should not use new File("...") or Paths.get(...) but getResourcesAsStream or its counterpart getResource:
try (Scanner scanner = new Scanner(MyClass.class.getResourceAsStream("/myfile.txt"))) {
while (scanner.hasNextLine()) {
System.out.println(scanner.nextLine());
}
}
This would probably throw a NPE if /myfile.txt was not found.

Netbeans Clean & build classes

When I clean and build a project in NetBeans, the .jar file appears in the dist folder, like it's supposed to. But what if I have multiple files under the project? What happens to those files? E.g. I have a Game project, and under it are the different characters(knight, rogue, etc.) but I only see a game.jar file when I clean and build, I want to know what happens to the individual files. Thanks
Those files should be in the jar file as compiled .class files. It's easy to double check what's in the jar file since it's in zip format. You can use a program like 7-Zip to open it, or rename it to the zip extension (e.g. from mygame.jar to mygame.zip) and whatever OS you're using probably has some way to open it.
When you open or extract the jar file you'll find the compiled class files in a directory structure that reflects your package structure. For example, if you have Knight.java in the directory src/game/characters/Knight.java in the jar file you'll find something like classes/game/characters/Knight.class.
The name "jar" is an abbreviation of "Java archive". It stores all the classes and other resources (for example, images) in a project.
The classes you have defined in .java files will be compiled into .class files - these are contained in the .jar file.
All resources get compiled into the JAR file. If you want a separate JAR for the resources, you'll need to split the project into two maven projects: one jar for the code, one for the resources. You can then create a third project that would generate a distribution.
That's a lot of work, though. It's.a lot easier tO keep everything in one JAR unless you have explicit dynamic loading requirements.

Categories