I have a few directories in my Java project that hold deprecated code: com.company.deprecated and com.partner.company.deprecated. I want to exclude everything in these two "deprecated" directories from Maven compilation, regardless of content or directory structure inside them, so I have created a build tag like this at the very end of my POM:
<!-- Exclude directories that hold deprecated code -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/com/company/deprecated</exclude>
<exclude>**/com/partner/company/deprecated</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
This POM handles a module inside a larger project, but the deprecated code isn't used anywhere else inside other modules, so I don't think there are any conflict issues going on with other POMs. I have tried putting the "build" element at the end of either the specific module POM or the project POM, and get the same compilation errors each time.
As far as I can tell, this should exclude the deprecated directories from my Maven build, but I keep getting compilation errors in files within the "deprecated" directories. I have tried the double asterisk syntax above, absolute paths, and wildcards after "deprecated" but nothing seems to work. I've gone through StackOverflow and haven't found anything exactly like what I'm trying to do, although I am still relatively new to Maven so it is very possible there is something I'm just being dense about.
Can anyone please help me with the proper syntax (or perhaps a different plugin?) for this issue? Thank you!
Related
I believe this problem has been asked before on stackoverflow. And I'd like to mention that I tried the solutions that came with the questions related to mine. The one that came the closest to my problem was:
Load properties file in JAR?. Sadly the solution described there didn't work for me. And due the age of the question I thought asking it again is the way to go.
Heading on to describing my problem.
So currently I'm working on a library project which has been setup with maven and creates an extension for the current Spring AMQP project.
The goal here is to supply a JAR file which can be included into another project to support a specific way of communicating over a message broker.
At this point I'm implementing the configuration option to allow users to configure the messaging client to their liking. But while i was testing the functionality of this feature I hit a problem while using the library in an executable JAR.
While running it in the Eclipse workspace everything seems to work just fine. But when I try to run it from my desktop (as a runnable JAR) the properties file does not seem to be found anywhere.
Just to give a quick overview of the workspace/projects setup as described above:
The project structure of both project reflects the Maven default one:
- src/main/java
- java source files
- src/main/resources
- resource files
- src/test/java
- java test files
- src/test/resources
- test resource files
Where the library file contains a default.properties file in the src/main/resources folder and the chatclient project a custom.properties file.
Once the runnable JAR file has been build it has the following structure in it.
- com
- junit
- META-INF
- org
- resources
- default.resources
- custom.resources
I believe the resource files should not be located there. but in the META-INF/maven folder instead. After trying out stuff like:
Adding a META-INF folder into my src/main/resources folder and putting the property files there.
Adding a MANIFEST file with Class-Path: . in it.
Loading the file in multiple ways in code.
But nothing seems to work. I guess it is Maven related and a simple change in the pom.xml could fix it. Sadly my knowledge on the Maven project setup and pom related subjects is very basic (this is my first project using maven). And I can't seem to find any documentation on it, even though I know it should be there (probably a problem caused by me).
Before I forget to mention it. I load the property files using this way:
Properties props = new Properties();
prop.load(<custom static class>.class.getResourceAsStream(filename));
return props;
Also the pom.xml for my library looks like:
-- Artifact stuff --
<packaging>jar</packaging>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
-- Dependency stuff --
And the one for the project that uses the library look like:
-- Artifact stuff --
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.maxxton</groupId>
<artifactId>async-amqp-messaging</artifactId>
<version>0.2</version>
</dependency>
</dependencies>
-- Other stuff --
I hope there is someone who's a little more advanced on this subject and could help find a solution for this problem. And if you need any additional information on the project files/structure, please let me know. I'd gladly share it with you.
Update (28-04-2015 {1})
For testing I created a sample project which tries to load property files the same way as the scenario described above.
Even while following the Maven documentation (Using the META-INF folder) I was not able to load the properties.
For the sake of this question I uploaded the testing workspace here.
I hope someone could help me fix this, as the normal way as described on the Maven website does not seem to work for me.
Update (28-04-2015 {2})
Well I managed to fix a part of the problem.
Since I added the configuration for the maven-assembly-plugin (building runnable JAR with deps), I was able to get the correct structure within my JAR file.
The thing I added was:
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<finalName>project</finalName>
<appendAssemblyId>false</appendAssemblyId>
<archive>
<manifest>
<mainClass>com.test.project.Application</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Then when running clean compile assembly:single I managed to get the right structure.
JAR root
- com
- META-INF
- MANIFEST.MF
- default.properties
- custom.properties
While this fixes a part of the problem. The file loading still results in a NullPointerException.
Final Update (04-05-2015)
After a long Maven struggle I managed to get everything the way I want it to be.
Following the advice given by both #Deepak and #Joop Eggen, I did some research on how to have all the dependencies in a lib folder as jar instead of unpacking them in a 'uber' jar. After trying loads of stuff I stumbled upon this answer. Following the instruction there seems to create this structure:
- runnable.jar
- lib
- spring-amqp.jar
- spring-core.jar
...
When following #Joop Eggen's advice I managed to get the property loaded the way I want to. So it seems this question has been answered. Currently I'm still figuring out how to award each answer as I'm not able to split the bounty into two pieces. I'll get back on that.
Side Note
Although I awarded both the bounty and the answer to #Joop Eggen does not mean that #Deepak's answer did not contribute. It did give some great information on best practice, but was not as complete as the accepted answer. So please when finding your answer here give him some of the credit too.
There are two ways to get resources,
with a ClassLoader against the entire class path using absolute paths (without /...),
with a class, using a relative (...) or absolute (/...) path inside the jar of that class.
The latter seems more direct, and can be used as:
getClass().getResource("/...");
ClassInJar.class.getResource("/...");
Now getClass() is only possible in a non-static object and is dangerous too: the actual class might be some child, not in the library jar.
On the actual structure of your application. I know a maven directory convention:
src/main/java/...
src/main/resources/...
where /... gets into the jar/war; the package directory.
Reassembling jars is not good. There always is the Class-Path: ... entry in META-INF/MANIFEST.MF. Following the basic maven conventions is best.
The solution to this is simpler, however there are couple of concepts that I would like you to be aware off.
It is not a good practice to create one big jar by using maven assembly plugin. In your examples, you are using small jars both developed by you, so it might seem okay. But as your real projects get bigger, this is not ideal, you would want separation of different modules and not one big jar. The ideal practice is opposite to what you are trying to achieve - you should aim to have smaller and smaller jars. You might in future want the convenience of replacing these smaller jars without having to deliver the entire package again.
You would surely not want to unpack 3PP jars and package them as your own jar!
Based on the above, you might wonder how do you create executable jars. Well, the answer is having the dependent jars in the class-path. When executing the "project" jar, you should have the "library" jar in the class-path and it will be able to find the properties file inside as expected.
You places the properties files in META-INF directory. The right place for them is the resources folder. And if you follow the point No.1, things will work as expected.
I have a 3 module maven project with parent pom. From parent when I run a maven clean-compile-test. It fails at test phase and gives tons of compilation errors saying "symbol not found" for my local classes.
I discovered using IntelliJ ide if I use the "Make Project" button before I run a maven test, then maven test works!
Edit: Now I figured out that probelem is maven compile does not create class files in target folder for some reason this is my maven compiler plugin configuration in parent pom file:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<excludes>
<exclude>**/*.*</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
Any ideas?
One more thing.
Look in pom.xml, tag <packaging>. If it sets in pom, Maven shouldn`t create class-files for you. Change it for appropriate package - jar, war ...
Maven doesn't care about missing symbols in the package phase; missing symbols will only be reported during the compile phase (= when the Java compiler is run by Maven).
To find out why it can't find the symbols, you need to examine one of the errors. Look into the folder target and check if the missing class exists in there (at the right place).
mvn clean deletes this folder but mvn compile should put new files in there.
If you can't see anything obvious, then save a list of all the files in the target folder somewhere. Then build the project in IDEA. Again create a list of all files.
Sort both lists and then compare them. That might give you an idea what is wrong. My guess is that you configured Maven in an odd way (moving source folders or target folders).
EDIT The configuration
<excludes>
<exclude>**/*.*</exclude>
</excludes>
tells Maven "ignore all source files" which is equivalent to "don't do anything". Remove this and try again.
I'd like to set an alternate JavaDoc location for all my modules in a multi-module maven project. Unfortunately, I have to rely on relative paths, or else use maven properties like ${basedir}, since this is a team project on subversion, and no absolute path will be the same for all of us.
What is the best way to do this? If I have a project structure
parent
sub1
sub2
sub3
docs
And I want to place the API in sub3/docs, then how can I point all my modules to output HTML files in sub3/docs, when the parent module will recognize a different path to it than the submodules?
Thanks in advance.
You want to pollute your project build as little as possible, especially with repeated build tweaks. Instead, you're better off creating a separate build process that assembles the javadoc output from its standard location in all projects and publishes it somewhere desirable.
Add the following to the parent pom and make sure the child pom does not define their own javadoc plugin.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.7</version>
<configuration>
<outputDirectory>${project.parent.basedir}/sub3</outputDirectory>
<reportOutputDirectory>${project.parent.basedir}/sub3</reportOutputDirectory>
<destDir>docs</destDir>
</configuration>
</plugin>
</plugins>
</build>
I tried to convert a project to a maven one... it has its .java files in other location than /src/main/java , when i run maven install, all the files (.hbm , .xml) except those .class occurs in my jar.
This is build part from pom.xml :
<build>
<resources>
<resource>
<directory>${basedir}/src</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
<fork>true</fork>
<compilerVersion>1.5</compilerVersion>
<compilerArguments>
<encoding>UTF-8</encoding>
</compilerArguments>
</configuration>
</plugin>
</plugins>
</build>
Using the above code, .class files are missing from my jar... and no error messages are displayed on console, is it necessary to move them to /src/main/java package structure ?
Also, what could be the reason for this behavior , some missing dependencies ?
I did a change moving them to , src/main/java and i got some exceptions on console , but i am still confused if i "must" add them to this "src/main/java" structure...
Please give me an idea about this...
Thanks
You can configure the source directory to be the same as the resources like this:
<build>
<sourceDirectory>${basedir}/src</sourceDirectory>
<resources>
<resource>
<directory>${basedir}/src</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources>
</build>
It not strictly necessary - its configurable - but Maven comes with a standardized project layout and it is highly recommended to embrace it, like others Maven conventions (don't fight against Maven, adopt it).
I understood that you are migrating from Ant to Maven but you are IMO not on the right path, bending Maven to make it fit in your existing project structure/workflow is just not the recommended approach:
Maven strongly suggests using its conventions (over configuration) to ease things. Not doing so makes things more complicated and generate useless configuration overhead.
When deviating from the defaults, you're kinda on your own.
Not using defaults might result in bad surprises, some (poorly) implemented plugins might be using hard-coded paths (like src/main/java, target/classes, etc) and won't like changing defaults.
etc, etc, etc.
The recommended way would be to transform your existing structure into a maven compatible modular structure and to adopt the standard Maven layout.
Adopting Maven standards and conventions will just make your Maven life easier in the long run and you get a standardized structure, which Maven is much about.
I think enough people wrote similar advices so I won't insist more. But you should listen to these advices (and not insist trying to make Maven fit in your existing structure), especially since you're new to Maven. From my point of view, you're not migrating from Ant to Maven, you're trying to migrate Maven to an Ant build.
See also
How to convert from Ant to Maven in 5 minutes
Convert Ant Projects into Maven Safely in Five Phases
Have a look at the Super POM. That is the place you get the 'convention' from. You might have to change some settings in your project POM if you have a differnet project layout but it is no good advice as mentioned here before.
By far the easiest solution (if possible in your circumstances) is to move the code to /src/main/java, since that is where maven expects it. It that is not possible, you at least need to tell maven where to find the sources. From your POM I don't see anywhere where you did that.
If you want to use Maven, the path of least resistance is adhering to the Maven conventions. Surely you can have a different source path, but it is definitely more complicated (it seems that the only way is to pass the source directory as a compiler argument), and what do you gain? I believe moving your source directory is much easier.
I have a simple java maven project. One of my classes when executing needs to load an xml configuration file from the classpath. I don't want to package such xml file when producing the jar but I want to include a default xml file in a zip assembly under a conf subfolder and I also want this default xml to be available in the unit tests to test against it.
As I see it there are 2 possible places of this default xml:
src/main/resources/conf/default.xml
src/main/conf/default.xml
Both solutions demand special pom actions:
In solution 1, I get the auto copy to target folder during build which means it is available in testing but I also get it in the produced jar which i don't want.
In solution 2, I get the jar as I want it(free of the xml) but I manually have to copy the xml to the target folder to be available for testing. (I don't want to add src's subfolders in test classpath. I think it is bad practice).
Question: what is the best solution of the two?
- If the correct is 2, what is the best way to copy it to target folder?
- Is there any other solution better and more common than those two?
(I also read Where should I put application configuration files for a Maven project? but I would like to know the most "correct solution" from the "convention over configuration" point of view and this link provides some configuration type solutions but not any convention oriented. Maybe there isn't one but I ask anyway. Also the solutions provided include AntRun plugin and appAssembler plugin and I wonder if I could do it with out them.)
The question is what is the best solution of the two? If the correct is 2, what is the best way to copy it to target folder? Is there any other solution better and more common than those two?
Since you want that file to be copied to the target/classes folder, it has somehow to be considered as a resource (so either put in under src/main/resources or declare src/main/conf as resource directory). And if you don't want it in the final jar, configure the Maven JAR Plugin to exclude it:
<project>
...
<build>
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.1</version>
<configuration>
<excludes>
<exclude>**/conf/*</exclude>
</excludes>
</configuration>
</plugin>
...
</plugins>
</build>
...
</project>
For the assembly part, assembly descriptors are pretty flexible so it should be possible to achieve what you want regardless of the choice. I'd suggest using the easiest setup though.
My solution was to use two profiles: Development (default) and Packaging
My default / section contains both src/main/resources and src/main/conf. I call this my Development profile, which is an implicit profile.
My packaging profile is an explicit profile which is defined under section. There under / I only mentioned src/main/resources. When I'm running my packaging script (we currently have this external to maven since its building an RPM out of our WAR), I'm running 'mvn install -Drpm' to activate my Packaging profile (rpm is the id for the Packaging profile.
If this wasn't clear enough, feel free to ask more questions.
You could place it in src/test/conf/default.xml. Your testclasses can find it, but it wont be packaged using the standard method.
With an additional assembly you can package it from there. That step is always necessary.
A different solution could be to create a separate maven module and place it in /src/main/resources/conf/... .Then make this jar a test dependency. You do not need to do any special plugin configuration, but I think it is overkill for a single file.
If your packaging is war, you can use the packagingExcudes configuration option of the maven-war-plugin:
<project>
...
<build>
<plugins>
...
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<!-- Exclude abc.properties found in src/main/resources/ (ends up getting packaged in WEB-INF/classes/) -->
<packagingExcludes>
WEB-INF/classes/abc.properties
</packagingExcludes>
</configuration>
</plugin>
...
</plugins>
</build>
...
</project>
Use commas to separate between multiple resources you want to exclude. Also, you can use wildcards and regex in your excluded paths. For regex, it's in the %regex[YOUR_REGEX_HERE] syntax. Check the documentation for more details.