Compiling only selected files in Maven - java

I want to compile only selected files or directories (including subdirectories) within source directory. I was pretty sure I can do this using <includes> of maven-compiler-plugin's configuration, but it seems to not work as I expect since it still compiles all classes into target/classes. What is really strange, Maven output suggest that the setting actually does its work, because with:
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<includes>
<include>com/example/dao/bean/*.java</include>
</includes>
</configuration>
</plugin>
I have:
[INFO] Compiling 1 source file to c:\Projects\test\target\classes
but with no compiler's configuration I have:
[INFO] Compiling 14 source file to c:\Projects\test\target\classes
In both cases however, all 14 classes are compiled into target/classes as I mentioned. Can you explain that or suggest another solution to compile only selected files?

Simple app with 3 classes.
com/company/Obj1.java
com/company/Obj2.java
com/company/inner/Obj3.java
build in pom.xml
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<includes>
<include>com/company/inner/*.java</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
result: 1 class is compiled.
And any combination of includes is working well
or you mean something else?

I have faced a similar situation. We needed to hot swap only modified files to our remote docker container in order to improve changes-deploy time. This is how we solved it.
Add includes option in build plugin with command line argument.
Note since we wanted to add multiple files, so we have used includes and not include
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<compilerVersion>1.8</compilerVersion>
<source>1.8</source>
<target>1.8</target>
<includes>${changed.classes}</includes>
</configuration>
</plugin>
Now run compile phase with argument, example:
mvn compile -Dchanged.classes=com/demo/ClassA.java,com/demo/ClassB.java,com/demo2/*

maven-compiler-plugin using Ant-like inclusion/exclusion notation.
You can see examples in Ant documentation Ant FileSet Type
If you are want include only files from one directory, you need write it like you did:
<include>com/example/dao/bean/*.java</include>
To include also subdirectories from path, it will be:
<include>com/example/dao/bean/**/*.java</include>

I had no difficulty including or excluding files for compilation with maven compiler plugin 2.5.1. Here is the dummy project I used for the purpose. Perhaps the include pattern that you use is different.

Related

Distribute plugin resource files to host project

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/...

Setting classpath for a java project with many libraries and external resources in command line

I have the following project. It has some property files in the conf folder, some data in the data folder, some jar files in the lib folder and also some external libraries that are not shown in the photo due to size limitation. Imagine I want to run the RecDriver class. How exactly should I set the classpath so that I can run it in command line? This is how I did it but it does not work as it cannot fine some other files in the project.
C:\Users\myUserName\Downloads\librec-2.0.0\librec-2.0.0\core\src\main\java\net\librec\tool\driver> javac RecDriver.java
The project can be downloaded here:
https://github.com/guoguibing/librec
You can use bin/librec or bin/librec.cmd to run it from commandline.
If you want to build your launch command you can see those start scripts and adapt them for your purposes.
To run your app through command line, once you have the .class files in some dir (usually build) all you have to do is run your application with java -cp "path where jvm can find every .class that you project needs" MainClass.
The -cp flag only tells where to look for compiled .class files, since you are using IntellIJ you can see the command it runs when executing your program, there is a class path that it uses.
Class Path points to where your .class files are, they can be in separate folders, but you need to include every dir when giving the class path, separated by ";"
Example taken from another question in SO.
java -cp "Test.jar;lib/*" my.package.MainClass
Three things to do:
Use the Maven Shade Plugin to create a fat jar (jar with dependencies)
Use the Maven-Jar-Plugin to make the Jar executable
Set <project><build><finalName> to ${artifactId}
Now, after your build ran successfully, you can run your app with
java -jar target/YourArtifactId.jar
(Substitute your project's artifactId for "YourArtifactId")
Okay, here's the full setup.
Add a build section like this to your pom.xml (merge it with any existing one).
<build>
<plugins>
<!-- number 1 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<minimizeJar>true</minimizeJar>
</configuration>
</execution>
</executions>
</plugin>
<!-- number 2 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>fully.qualified.MainClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
<!-- number 3 -->
<finalName>${project.artifactId}</finalName>
</build>

Maven annotation processing processor not found

I'm new to annotation processing and I'm trying to automating it with Maven. I've put this in my pom.xml:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<annotationProcessors>
<annotationProcessor>
co.aurasphere.revolver.annotation.processor.InjectAnnotationProcessor</annotationProcessor>
<annotationProcessor>
co.aurasphere.revolver.annotation.processor.RevolverContextAnnotationProcessor</annotationProcessor>
</annotationProcessors>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
The problem is that when I try to build the project I get a CompilationFailureException because Maven can't find the processors.
I've found other questions like this, solved by putting the dependency outside the plugin. I tried that, but nothing changed for me.
Am I missing something?
Thank you.
EDIT
Here is my dependency on another project which contains both the processor and the annotations:
<dependencies>
<dependency>
<groupId>co.aurasphere</groupId>
<artifactId>revolver-annotation-processor</artifactId>
<version>0.0.3-SNAPSHOT</version>
</dependency>
</dependencies>
EDIT 2:
After further investigation, I decided to decompile the processor JAR (built with Maven) and it happens that... my classes are not there. For some reasons, Maven is not compiling my classes into the JAR and that's why the classes are not found. I've tried figuring out what's wrong on that build (this never happened to me before and I've used Maven for a while...).
First of all, the packaging on that project is jar.
The classes are all under src/main/java.
I've checked in my pom.xml that the classpath and source path is the same.
Here's the processor 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>co.aurasphere</groupId>
<artifactId>revolver-annotation-processor</artifactId>
<version>0.0.3-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<!-- https://mvnrepository.com/artifact/javax.inject/javax.inject -->
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.velocity/velocity -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<version>1.7</version>
</dependency>
</dependencies>
EDIT 3
Here's the output of a maven clean install on the processor project. Unfortunately the output is too long and I had to post an external link even if I know it's not good.
EDIT 4
Here are some screenshots of my dependency hierarchy: and .
Since the project was originally created as an Eclipse simple Java project and then converted to a Maven one, I tried to create a new Maven project and move everything to the new one in the hope that the problem was the Eclipse plugin that messed something up, but the error was still there.
This is an extended version of the accepted answer above provided by #Aurasphere. Hopefully this will give some explanation to how the proposed solution works.
First, some background to what is happening here. Say, we want a custom annotation processor. We implement it and put it into a JAR as Maven artefact, so that it could be consumed by other projects. When such projects are being compiled, we want our annotation processor to be recognised by Java compiler and used appropriately. To make this happen, one needs to tell the compiler about a new custom processor. Compiler looks in the resources and checks FQN of classes listed in META-INF/services/javax.annotation.processing.Processor file. It tries to find these classes in classpath and load them to run the processing of annotations used upon classes that are currently being compiled.
So, we want our custom class to be mentioned in this file. We can ask a user of our library to put this file manually, but this is not intuitive and users could be frustrated why the promised processing of annotation doesn't work. That's why we might want to prepare this file in advance and deliver it together with the processor inside JAR of our Maven artefact.
The problem is that if we simply put this file with FQN of the custom processor in it, it will trigger compiler during compilation of our artefact, and since the processor itself is not yet compiled, the compiler will show the error about it. So we need to skip annotation processing to avoid this. This can be done using -proc:none, or with Maven:
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<proc>none</proc>
</configuration>
</plugin>
We might have unit tests that will need our annotation processor. In Maven, test compilation is carried out after main sources are built, and all classes are already available including our processor. We just need to add special step during processing of test sources which would use our annotation processor. This can be done using:
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>process-test-annotations</id>
<phase>generate-test-resources</phase>
<goals>
<goal>testCompile</goal>
</goals>
<configuration>
<proc>only</proc>
<annotationProcessors>
<annotationProcessor>fully.qualified.Name</annotationProcessor>
</annotationProcessors>
</configuration>
</execution>
</executions>
</plugin>
I've found the answer myself. I've figured out that the problem was the file javax.annotation.processing.Processor in META-INF/services/ with the configuration of the annotation processor's class. In order to fix the problem I had to add the following to the pom.xml configuration of my processor project:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<compilerArgument>
-proc:none
</compilerArgument>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
This let Maven build the classes into the actual jar and fixed the problem. I don't know if this is a bug or not but it surely looks strange to me. Thank you everybody for the help!
The easiest way is to register the annotation processor in the META-INF/services directory of the revolver-annotation-processor artifact. No Maven compiler configuration is needed.
Check if it's already registered, if not, register it yourself if you control the source code.
https://docs.oracle.com/javase/8/docs/api/java/util/ServiceLoader.html
If you control the source code I also recommend to package the processor in the same artifact as the annotations. Like this, whenever you're using one of the annotations, the annotation processor is also picked-up by the compiler.
The accepted answer here works by disabling all annotation processing, which may not be suitable if other annotation processors need to run during the compilation. Instead, the SPI configuration file listing the newly compiled annotation processor can be added in a post-processing step. I added a directory src/main/post-resources to my project and this plugin configuration:
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>annotation-processor-spi</id>
<phase>process-classes</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.outputDirectory}</outputDirectory>
<resources>
<resource>
<directory>src/main/post-resources</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>

How can I build maven project with foreign class names?

I'am trying to build war file for my project, that is containing russian class names. When I just run my app on development environment, it works good, but if I build that war file, all russian filenames are mangled. I cannot rename these files in the project so they could be in english. The only way out is to make my own refactoring utility for them, and run it every time these files are regenerated.
So I want to know if there is a way to make maven build it with locale specific configuration.
These files are having proper names while theq are on my filesystem. But theqy are changed when I look at them in war archive.
pom.xml snippet
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<compilerArgument>-Xlint:all</compilerArgument>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
You should always fix the encoding of source files:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
Also read the http://maven.apache.org/general.html#encoding-warning and How to configure encoding in Maven? for additional information.

How can I add files to the bootclasspath in maven correctly?

I'm using some JSR166 classes with Java 1.6, some of which are under java.util.concurrent. I am on OSX, though I expect this to ultimately run on Linux.
If I set this environment variable I can run my project:
export MAVEN_OPTS=-Xbootclasspath/p:/Users/me/.m2/repository/org/codehaus/jsr166-mirror/jsr166/1.7.0/jsr166-1.7.0.jar
I tried following the instructions here and putting the setting in my pom.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<version>3.0</version>
<compilerArguments>
<verbose/>
<bootclasspath>/Users/me/.m2/repository/org/codehaus/jsr166-mirror/jsr166/1.7.0/jsr166-1.7.0.jar</bootclasspath>
</compilerArguments>
</configuration>
</plugin>
Unfortunately this gave an error about not being able to find java.lang. If I add a reference to classes.jar (apparently OSX's version of rt.jar) in the bootclasspath I can fix that error, but that just puts me back where I started:
java.lang.SecurityException: Prohibited package name: java.util.concurrent
How should I set up maven to use this argument correctly?
You should check security manager. Unfortunately, I don't know specific on OSX. By default, the JVMuses security policies defined in the java.security and java.policy files located under the JAVA_HOME/jre/lib/security folder. Check also -Djava.security.manager and –Djava.security.policy option for your JVM.
Shouldn't you use extdir for this, instead of bootclasspath?
<project>
[...]
<build>
[...]
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<compilerArgs>
<arg>-verbose</arg>
<arg>-extdir /Users/me/.m2/repository/org/codehaus/jsr166-mirror/jsr166/1.7.0/</arg>
</compilerArgs>
</plugin>
</plugins>
[...]
</build>
[...]
</project>
From http://maven.apache.org/plugins/maven-compiler-plugin/examples/pass-compiler-arguments.html

Categories