Is there a way to exclude a source directory in Maven? I've searched on this topic and find plenty of discussion about excluding Resources, but very little on excluding Sources.
I have a repo with shared projects and several POM files. Most coexist well, but one project has a conflict with one of the source directories and I need to exclude it only from that pom-file.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
...
<build>
<sourceDirectory>src/main/java</sourceDirectory>
# I would like to add this but is not supported
<excludeSourceDir>src/main/java/com/company/project/conflict-dir</excludeSourceDir>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
Edit 1:
Following the recommendations, I implemented a parent-pom and converted the existing pom files into modules -- each module referencing the parent (excellent instructions here). I also implemented a "maven-compiler-plugin" which allows one to <exclude> files. Most projects compile and package correctly, except the original troublemaker project is still refusing to compile. Still researching options.
After many hours on this and after converting the code to use modules, I found two things:
Instead of excluding files, I needed to specify the includes instead:
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.source}</target>
<encoding>UTF-8</encoding>
<includes>
<include>com/company/my_module/*.java</include>
</includes>
</configuration>
</plugin>
The test code from the other modules was being run by default. Yet this modules was not including the code for those tests. I added -Dmaven.test.skip=true to prevent that.
Related
I have a maven plugin that exposes a Mojo, with a goal that runs at the compile stage. The project was generated using mvn archetype:generate, and the POM contains all the standard stuff that comes with running that, very little deviation. The project includes a couple of resource files, e.g. filea.txt and fileb.txt, that are packaged up as part of the jar.
When the plugin is used in a project, I'd like the files that are included in the jar to be extracted and copied to the target\test-classes directory of the host project. I'm trying to use the plugin jar to both distribute some files + expose some functionality that can then use those files.
Is this a valid approach, and if so, are there settings I can add to the plugin POM to indicate that content from the plugin should be extracted and copied? I want to centralise this logic in the plugin, rather than having to do in the plugin host.
I feel like it's something with maven-dependency-plugin or maven-resources-plugin or build-helper-maven-plugin:attach-artifact, have tried a couple of different approaches but think I'm missing something obvious:
e.g. something like this in plugin POM?
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<outputDirectory>${basedir}/target/test-classes</outputDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>filea.txt</include>
<include>fileb.txt</include>
</includes>
</resource>
</resources>
</configuration>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-plugin-plugin</artifactId>
<version>3.6.0</version>
</plugin>
// etc etc
Google fu has let me down, keep ending up on maven resources page. Can post directory structure / more information if needed.
Cheers
First I would suggest to put resources which needs to be distributed into src/main/resources which looks like you have done ...but remove the configuration for the maven-resources-plugin and let maven do it's work. This is automatically copied into target/classes/ which in result is packaged into the resulting jar later.
If your plugin needs to get those files those can accessed as a usual resource via this.getClass().getResourcesAsStream("/...") and reading and writing them into a new location preferable into target/...
It was a little bit hard to come up with a meaningful title, hope it will become clear enough after the explanation. I have searched through a number of Qs and As on SO, and they were all very close to the problem I am experiencing, but still not close enough.
In general, what I want to accomplish is to store project version in DB by accessing the maven property #project.version# from a .csv file which is loaded by a Liquibase script.
My maven project structure looks like this:
parentModule
pom.xml
|
---moduleA
|__pom.xml
---moduleB
|__pom.xml
---moduleC
|__pom.xml
...
Pom.xml are defined as:
**PARENT POM**
<project ...>
<groupId>com.parent</groupId>
<artifactId>parent</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
<name>parent</name>
<parent>
<artifactId>spring-boot-starter-parent</artifactId>
<groupId>org.springframework.boot</groupId>
<version>2.2.1.RELEASE</version>
<relativePath />
</parent>
<properties>
<java.version>8</java.version>
</properties>
<modules>
<module>moduleA</module>
<module>moduleB</module>
<module>moduleC</module>
...
</modules>
<build>
<defaultGoal>package</defaultGoal>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>
----------------------------------------------------------------------
**CHILD POM**
<project ...>
<artifactId>moduleC</artifactId>
<name>moduleC</name>
<parent>
<groupId>com.parent</groupId>
<artifactId>parent</artifactId>
<version>1.0</version>
</parent>
<dependencies>
<dependency>
...
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>moduleC/src/main/resources/db/changelog/</directory>
<filtering>true</filtering>
<includes>
<include>**/app_version.csv/</include>
</includes>
</resource>
</resources>
</build>
</project>
Liquibase scripts are defined in moduleC/src/main/resources/db/changelog/changelog-master.xml etc., while the .csv files with initial values are located in moduleC/src/main/resources/db/users.csv etc. In one of those csv files, I want to push #project.version# value, like this:
id;app_key;app_value;created_by;last_modified_by
1;app-version;#project.version#;system;system
Since that file is located in moduleC, I used maven resource filtering even inparentModule <build/> to filter that file so it can resolve #project.version# property, but with no luck:
<build>
<resources>
<resource>
<directory>moduleC/src/main/resources/db/changelog/</directory>
<filtering>true</filtering>
<includes>
<include>**/app_version.csv/</include>
</includes>
</resource>
</resources>
<defaultGoal>package</defaultGoal>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
There are errors, one that says that master changelog cannot be found, while in other cases just string value #project.version# is stored. Seems to me I should include app_version.csv and its location (moduleC) as resource inside <build> tag withing parentModule pom.xml, but every combination of referencing it fails. Is there a solution to reference it properly (either from parentModule or moduleC pom.xml) or there might be an easier way to store #project.version# with liquibase?
I am extremely sorry for not replying on time, was temporarily removed from the project after posting the question and was not able to access the git repository due to change of location. So far, I have tried all of the proposed actions, but with no result. In the end, what I found to work was an accepted answer posted here. I have added the build block inside mavenC module pom.xml and it worked. Nevertheless, thank you all immensely for posting and helping.
I think you need to use the maven-replacer-plugin in your build cycle. It will be configured to process the 'app_version.csv' file and output the substituted file content to the 'target/classes' folder. The subsequent packaging phase will ensure the csv file with the current pom version will be bundled into the artifact that the liquidbase tool then handles.
Looks like you're using the wrong syntax for filtering in the CSV-file. Instead of using #project.version#, try ${project.version} instead:
Check the <directory>moduleC/src/main/resources/...</directory>, if the resources plugin lives in the child POM of moduleC then there is no need for the prefix.
Try replacing with <directory>src/main/resources/..</directory>
Resources filtering of a module should be in the build of the module itself.
The project.version property will be inherited from the parent.
Be careful so the filtering does not mess with your xml files.
I think the syntax should be ${project.version}
Can you share your liquibase maven plugin configuration ?
The markup should point to your master changelog.
Here is two other solutions:
Another solution would be to create a liquibase changeset every time you create a new version. You can do it programmatically using liquibase java SDK in a spring component which run on startup of your project or create the changeset yourself.
Another solution would be to use Spring Boot Actuator to retrieve project version.
For this you need to add <goal>build-info</goal> in the goals of spring-boot-maven-plugin
This is my project structure:
This is my code, trying to read the file in the resources folder:
package passgen;
public class Application {
public static void main(String[] args) {
System.out.println(Application.class.getResourceAsStream("/configuration.properties"));
System.out.println(Application.class.getResource("/configuration.properties"));
System.out.println(Application.class.getClassLoader().getResourceAsStream("/configuration.properties"));
System.out.println(Application.class.getClassLoader().getResource("/configuration.properties"));
System.out.println(new Application().getClass().getResourceAsStream("/configuration.properties"));
System.out.println(new Application().getClass().getResource("/configuration.properties"));
System.out.println(new Application().getClass().getClassLoader().getResourceAsStream("/configuration.properties"));
System.out.println(new Application().getClass().getClassLoader().getResource("/configuration.properties"));
System.out.println(Application.class.getResourceAsStream("configuration.properties"));
System.out.println(Application.class.getResource("configuration.properties"));
System.out.println(Application.class.getClassLoader().getResourceAsStream("configuration.properties"));
System.out.println(Application.class.getClassLoader().getResource("configuration.properties"));
System.out.println(new Application().getClass().getResourceAsStream("configuration.properties"));
System.out.println(new Application().getClass().getResource("configuration.properties"));
System.out.println(new Application().getClass().getClassLoader().getResourceAsStream("configuration.properties"));
System.out.println(new Application().getClass().getClassLoader().getResource("configuration.properties"));
}
The results are all null:
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
Replacing "configuration.properties" with "src/main/resources/configuration.properties" (both with slash and without slash) doesn't make any difference.
Other answers, like this, tell to use .getClass().getClassLoader().getResource(fileName) but this is already one of the lines. Why are they all null and how do I get the resource?
POM:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>passgen</groupId>
<artifactId>passgen</artifactId>
<version>1</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<build>
<finalName>passgen</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<targetPath>${project.build.directory}/dist</targetPath>
<includes>
<include>**/*<!-- all resources that go to folder, rest will go into the jar --></include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<excludes>
<exclude>**/*<!-- all resources that go to folder, rest will go into the jar --></exclude>
</excludes>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<configuration>
<outputDirectory>${project.build.directory}/dist</outputDirectory>
<archive>
<manifest>
<!-- <addClasspath>true</addClasspath> -->
<mainClass>
passgen.Application
</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
You have to provide the full path to the class loader in case you want to load it from the project directories.
System.out.println(Application.class.getResourceAsStream("/main/resources/configuration.properties"));
Hope this helps.
Found the answer. For some reason Eclipse puts an exclusion pattern of "**" on the main/java/resources folder. If someone else has the same problem: right click on the project -> Build Path -> Configure Build Path -> Source tab. For all entries check the "Excluded" voice, it should be "(None)". If you have an exlcusion pattern that excludes your files from the classpath (like "**") click on Remove to remove it.
EDIT: for some reason Eclipse adds an exclusion pattern of ** to the src/main/resource folder when you run Maven -> Update project
EDIT 2: I found that the exclusion pattern in Eclipse on src/main/resource folder is normal (see this answer). The exclusion means that it's not Eclipse handling the src/main/resources folder compilation but it's Maven (the Maven plugin of Eclipse to be precise, M2Eclipse). The fact that those resources weren't found in the classpath was due to the exclusion present in the pom.xml:
<resource>
<directory>src/main/resources</directory>
<excludes>
<!-- these resources will be excluded from the classpath; they will not go in to the target/classes folder and will not be packaged into the artifact -->
<exclude>**/*</exclude>
</excludes>
</resource>
which I removed to get the output listed below.
Now the output of the code above is this:
java.io.BufferedInputStream#7852e922
file:/C:/Users/Taiano/eclipse-workspace/sharedProjects/passgen/target/classes/configuration.properties
null
null
java.io.BufferedInputStream#4e25154f
file:/C:/Users/Taiano/eclipse-workspace/sharedProjects/passgen/target/classes/configuration.properties
null
null
null
null
java.io.BufferedInputStream#70dea4e
file:/C:/Users/Taiano/eclipse-workspace/sharedProjects/passgen/target/classes/configuration.properties
null
null
java.io.BufferedInputStream#5c647e05
file:/C:/Users/Taiano/eclipse-workspace/sharedProjects/passgen/target/classes/configuration.properties
If you want to exclude a resource from the jar exclude it in the maven-jar-plugin section. If you want to produce in output the resources that you excluded from the jar, configure the maven-resources-plugin with the goal copy-resources specifing the destination folder (by default resources are packaged into the artifact, if you just exclude them from the artifact you will have resources nowhere).
I have a Jenkins build server that automatically builds the project into a jar when a new commit has been pushed to the GitHub project. I looked at file size of the artifacts that Jenkins creates and I was surprised. I came to the conclusion that all the third-party dependencies were included in the jar artifact!
I don't need Maven to include them in the artifact as that will increase the size dramatically and it isn't useful. So I fiddled around with my pom.xml file, but I couldn't get it working. The dependencies keep being included in the jar.
I'm relatively new to Maven and I would appreciate it a lot if someone can help me out!
Sources (if you need any):
Pom.xml
You can avoid packaging your dependencies inside your jar file by providing the scope they should be wrapped in. But since I looked to your pom.xml descriptor and find nothing misconfigured, I will suggest to use the maven-jar-plugin to exclude all third party libraries as follows:
<project>
...
<build>
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>${maven-jar-plugin.version}</version>
<configuration>
<excludes>
<exclude>*.jar</exclude>
</excludes>
</configuration>
</plugin>
...
</plugins>
</build>
...
</project>
Hope this helps.
BR.
My guess is that this is the root cause:
<resource>
<directory>libs</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
if you (also) have all your jars in this folder, then they will end up on the classpath ( see target/classes ), hence they will be part of the jar.
You only have to specify the jars as dependencies, Maven will do the rest.
Resources are used for non-java (or non-compilable) files, which should end up at the classpath as well, like config files for Spring or Hibernate
I am attempting to learn maven on a small project of my own, using eclipse. I converted the existing project to the maven standard directory configuration, and it was building; now I'm trying to get maven to produce the jar for the application. The following is pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion> 4.0.0 </modelVersion>
<groupId> com.rc </groupId>
<artifactId> SpaceCheck </artifactId>
<version> 0.9.1-SNAPSHOT </version>
<name> SpaceCheck </name>
<packaging> jar </packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId> org.apache.maven.plugins </groupId>
<artifactId>maven-jar-plugin </artifactId>
<version> 2.3.2 </version>
<configuration>
<includes>**/src/*</includes>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>spacecheck.SpaceCheck</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
I didn't use to have the 'includes' clause; as near as I can tell, that's what the example I got pointed to told me to do to fix the problem. It does not.
When I attempt to build, I get:
[ERROR] Failed to execute goal
org.apache.maven.plugins:maven-jar-plugin:2.3.2:jar (default-jar) on
project SpaceCheck: Unable to parse configuration of mojo
org.apache.maven.plugins:maven-jar-plugin:2.3.2:jar for parameter
includes: Cannot assign configuration entry 'includes' with value
'*/src/' of type java.lang.String to property of type
java.lang.String[] -> [Help 1]
The "Help 1" link points me to the tutorial that I followed to get this far.
The problem I have with the tutorial is that it doesn't explain how things work -- it gives you an example and expects you to extract general workings from the example. There's nothing wrong with examples, but they rarely match exactly what one wants to do.
I'm sure many people can tell me what's wrong, and I would appreciate it. But it would be even better if they could ALSO tell me where this is explained, not just where there is an example that does something similar. The explanation, to be complete, would explain what element needs to be added, just where in the XML that goes, and what the various options are for the thing that goes there.
Instead of
<includes>**/src/*</includes>
try
<includes>
<include>**/src/*</include>
</includes>
And if you are learning Maven you definitely want to check out The Complete Reference.
Since you're asking for the documentation (and not the direct answer), have a look at http://maven.apache.org/guides/mini/guide-configuring-plugins.html
The problem is maven version
Following format for list/set is support in maven 3.3.9 and onward versions but in lower versions it not supported.
<includes>**/src/*</includes>
But in maven version less than 3.3.9, above is not supported
To fix make it backward compatible
<includes>
<include>**/src/*</include>
</includes>
PS: for more details check this link