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

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");

Related

How is created a jar in maven?

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.

Configuring log4j2 in a multi-module J2EE web project without maven

I've been searching the web and SO for a while now to find the answer for my question, but everything I could find addressed multi-module projects that were implemented with Maven. My project does not use maven and so it doesn't help my scenario.
I'm building a Java 8 J2EE web services project that runs on Tomcat 8 and is broken into a few separate projects (see project tree below). I am not using maven, I'm defining all of the dependencies through eclipse (I am hoping to learn about maven at some point and "mavenize" my projects, but I'm not there yet).
How can I achieve the following:
Have a single log4j2.xml file that would be used by the dynamic web project and all the Java sub-projects. The only thing that has worked for me so far is to have a copy of the log4j2.xml file present in the src folder of each of the projects.
I've attempted various things, such as placing the configuration file in a shared folder and adding the folder to each of the projects' class path, or placing the file in the CommonLib project, which is used by all, but each time I keep getting a log4j warning that no configuration file was found.
Here's my project tree:
Services (Dynamic web project)
^
|__ BusinessCore (Java project)
| ^
| |___ DAO (Java project)
| | ^
|_________|_____|__CommonLib (Java project)
It sounds like you're trying to use log4j2 automatic configuration by including the log4j2 config file on the classpath.
I further assume that you're trying to run your code from within Eclipse. The only way it will work correctly with automatic configuration (without specifying the path to the config file via system property) is if the log4j2 config file is inside of a "source folder" that is included on the build path or if you put your config file inside of a jar and add that jar to your build path.
So, assuming you're using a log4j2.xml file, if you place log4j2.xml inside of a source folder of your CommonLib project and include this project on the build path of your other projects (along with the necessary log4j2 jars) it should work fine.
Here is how I have set up an example project:
Content of root level project folder non-maven-web-project-log4j2:
Content of BusinessCore:
Content of CommonLib:
Note that the "config" folder is a source folder (you will see this again later) in Eclipse and that the log4j2.xml is contained in the config folder.
Build Path configuration:
non-maven-web-project-log4j2 has a dependency on the BusinessCore project
BusinessCore has a dependency on CommonLib (no screenshot, it's almost identical to the previous)
CommonLib has an extra source folder called config:
and this config folder contains the log4j2.xml file:
Each project has one simple class in its source folder that references a class from its child project. In the non-maven-web-project-log4j2 project there is a class that refers to the class in BusinessCore, and in BusinessCore there is a class referring to the class in CommonLib. Every class generates a log4j2 message. When I run the class from the root project (non-maven-web-project-log4j2) I am able to see all of the logs and the logs have the pattern I specified in my log4j2 config file which confirms that log4j2 is able to find its configuration.
As a final note - I added the extra "config" source folder just to emphasize the point that you can place your log4j2 config file in any source folder in the build path, it is not necessary to create a separate folder for it if you don't want to - you could instead just include it in the src directory as you already noted in your question.

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

Java - read files from different maven modules

I have an application consisting of three modules: Module A, Module B and Module C (which is a web module). I am using Maven to build the application.
I have the following logic implemented: Module A is included in Module B using a maven dependency and Module B is included in Module C, also by using a dependency (I have separate pom files for each module). Module C is the one that gets deployed.
In Module C I want to have a folder called files, that would contain some content files. This particular folder would be located under the webapp folder. I want to be able to read these files in Module B.
Is there a way to do this? I have tried reading files with getClass().getResourceAsStream("files/file_name") but the returned value was null.
Most clean solution:
Create a new module D.
Put the files into D/src/main/resources/WEB-INF/
Add D as a dependency to B
That makes the files available to B as resource on the classpath while keeping them mostly separate from everything else. Note that to get the files, you have to use
getClass().getResourceAsStream("/WEB-INF/...");
otherwise Java will try to load them relative to the current class.
Be careful that you don't have file in C and D with the same names. If you do, then it can be somewhat random which file Java will pick.
You should consider to put all these files into /src/main/resources directory in order to allow these files being in the application classpath when it is deployed. So, you can consider from your B module that all those files are available in the classpath.
Obviously, you have to take in consideration to copy those files in the /src/main/resources module B's directory.

Accessing XMLBeans generated schemas.jar in Maven project

I have a schemas.jar supplied to me and am trying to access it from within a simple Maven project. I have put the schemas.jar file in my src/main/resources directory, which is in my classpath.
When I am trying to access the created documents with something like:
GetOrdersRequestDocument getOrdersRequestDocument = GetOrdersRequestDocument.Factory.newInstance();
It complains about the GetOrdersRequestDocument (can't find it).
How do I get the project to pick up these classes? Do I need to import anything specific?
I have put the schemas.jar file in my src/main/resources directory, which is in my classpath.
Yes, the files in src/main/resources directory are on your classpath. But this doesn't mean that the content of the jar itself is directly available. You could use a URLClassLoader to load the JAR though.
But... this is not how I would do things. If this is an option, I would just install the JAR in your corporate or local repository (using install:install-file) and declare it as a dependency. This would make the content of your JAR available to your code, like any other dependency.

Categories