Is Maven really flexible? - maven

I understand how Maven works with .java files in src/java/main. But may it be used for a more general case? Let us put it more abstract: Suppose I already have some a.exe that reads some (not necessarily only .java) sources from directories A1, A2, A3 and puts some files (maybe some are generated .java) to directories B1, B2. I also have some b.exe that currently reads files from B1, B2, B3 and generates something else. Some more similar steps. (A real life problem stands behind).
I would like to write a POM.xml file so that maven will do this work. Is that possible? I assume that a.exe and b.exe should be warped as maven plugings.
Next, in Maven docs I see :
<build>
<sourceDirectory>${basedir}/src/main/java</sourceDirectory>
<scriptSourceDirectory>${basedir}/src/main/scripts</scriptSourceDirectory>
<testSourceDirectory>${basedir}/src/test/java</testSourceDirectory>
<outputDirectory>${basedir}/target/classes</outputDirectory>
<testOutputDirectory>${basedir}/target/test-classes</testOutputDirectory>
...
</build>
What bothers me is that "sourceDirectory" looks by itself as a hard coded name. Will Maven accept A1 and A2 tags instead?

(Will you consider accepting some of your previous questions, so that other people will be more willing to answer you?)
Maven stress for Convention over Configuration. You can treat sourceDirectory as one of the conventions, which we have predefined some elements to use with the (Java) compiler plugin.
What you want to do can be achieved. You can write a plugin/MOJO yourself, which read from whatever directory you want and invoke whatever external exe you want. By having reasonable default values in your MOJO, you can have your project POM look something like
<project>
:
:
<build>
<plugins>
<plugin>
<groupId>yourPluginGroup</group>
<artifactId>generate-A-data</artifactId>
<!-- if you want extra configuration, you can have <configuration> elements -->
</plugin>
<plugin>
<groupId>yourPluginGroup</group>
<artifactId>generate-B-data</artifactId>
</plugin>
</plugins>
</build>
<project>
Not that bad huh?
However, it is quite questionable to say whether Maven is "flexible". I believe flexibility is never the aim of Maven. Maven is specialized for building, it defines different skeletons for you to follow (e.g. build phases, dependency scopes), you can never make Maven as "flexible" as other script-based tools like Ant.

The answer is: NO, MAVEN IS NOT FLEXIBLE. Here is a simple task I could not solve even with the help from all the maven forums of this world: Write a POM that
compiles some directory full of Java files
does something else (if you please - executes a sample Hello World Mojo plugin)
compiles some other directory with some other Java files.
NO WAY !

You may be able to do this without writing plugins, by binding the exec plugin and the compiler plugin to the 'generate-sources' or 'process-classes' phases. The build helper plugin might also be useful for adding source paths.
For the original case, you could try the following bindings:
build-helper-maven-plugin bound to the initialize phase, adding any necessary source directories (eg B1 and B2)
exec-maven-plugin bound to the generate-sources phase, with two executions, one for a.exe and one for b.exe
For the Hello World Mojo case, what if you add the following to the process-classes phase (in order)?
Hello World Mojo plugin
Build Helper plugin to add source directory
Compiler plugin
The only downside I can see is that the first source directory will be recompiled. But the compiler should be smart enough to know that nothing has changed, and whether it's a problem depends on why you actually want to do this. Why do you need the class files from directory A before you run Hello World? Perhaps you're really looking at two separate pieces of code that should become separate modules?

Related

how to make `mvn package` aware that it has already built the target

In a makefile, I can easily do something like
${target}: ${sources}
mvn package
Where I have ${target} the generated jar file, and ${sources} all the java files and the pom.xml. With this makefile, the target will not be be rebuilt unless one of the sources is changed since the last build of the target. The result is
$> make target/demo-0.8.0-SNAPSHOT-jar-with-dependencies.jar
make: 'target/demo-0.8.0-SNAPSHOT-jar-with-dependencies.jar' is up to date.
But just mvn package will always run the maven-assembly-plugin even though none of the source files has changed.
Question:
Is there a way to make mvn package be aware of the source files, similar to how make knows this so it'll just say "no need, it's already built."
Whether or not something makes sense is maybe up to the use case and the developer.
In a system where integration is far more complicated than passing unit tests the only way to gain confidence is by deploying into a test Kubernetes environment.
Anyway thanks for answering my question that the maven packaging plugin is unable to handle this dependency tracking.

Make maven output show progressed sub-modules only

I am working with an automatic build script in maven 3.x. The parent project contains of more than 60 modules. The compilation is done in a shell script simplified this way:
for each module:
cd module
mvn clean install > compile.$module.log
echo "Compiled $module"
I like to see a list of compiled modules in order to see the progress or the build. I like to have a big maven command and avoid the manual for loop. I hope to speed up the build this way, since splitting the parent project into more independent modules is not a short time option, yet.
The --quiet flag might be enough already. Alternatively a user defined logging implementation would be fine as well, as described in the manual (https://maven.apache.org/maven-logging.html)
The questions are:
What is the prefered way to modify maven log output?
Does anyone already know a ready-to-use plugin for my purpose?
Thanks

Maven Thrift Plugin

I am trying to automate the generation of source files from the .thrift files and later the packaging. As far as I know, the maven-thrift-plugin is restrictive in the sense that source and destination directories are fixed. Is there any way I can specify the source and destination directories? I could probably achieve this by using the maven-antrun-plugin but I don't want to pollute my pom unnecessarily if I don't have to.
Thanks.
As far as I can see from the source (https://github.com/dtrott/maven-thrift-plugin/blob/master/src/main/java/org/apache/thrift/maven/ThriftCompileMojo.java) there are configuration properties that control this behaviour.
Try these properties, they should work:
thriftSourceRoot
thriftTestSourceRoot
outputDirectory
These props should be added to the <configuration> section along with <thriftExecutable>, etc:
<plugin>
<groupId>org.apache.thrift.tools</groupId>
<artifactId>maven-thrift-plugin</artifactId>
<version>0.1.10</version>
<configuration>
<thriftExecutable>/usr/local/bin/thrift</thriftExecutable>
<thriftSourceRoot>${basedir}/src/main/my_custom_thrift_root</thriftSourceRoot>
</configuration>
<executions>
...
</plugin>
I also ended up going the maven-antrun-plugin route, here is a functional example: https://github.com/cobbzilla/cobbzilla-wizard/tree/master/wizard-thrift
pom.xml uses maven-antrun-plugin to exec the thrift target in build.xml
build.xml does the thrift compilation and packaging.
Generated sources go back into the source tree; I don't like derived files polluting my upstream source control, so the generated files are under a thrift package, and the package directory is in a .gitignore file. A bit kludgy.
A better way I learned about since writing that code is to compile multiple java source directories in a single maven project, which would be cleaner.

Manipulating __artifactId__ during file generation by maven archetype

Building a Maven archetype where files are generated using _artifactId_. archetype.xml looks like:
<sources>
<source>src/main/java/__artifactId__.java</source>
<source>src/main/java/__artifactId__CommandExecutor.java</source>
<source>src/main/java/__artifactId__EventListener.java</source>
</sources>
Generating a project using this archetype can lead to Java file names that do not follow the naming convention such as sample-plugin.java and sample-pluginCommandExecutor.java.
How can I make sure _artifactId_ is converted to appropriate Java file name, such as SamplePlugin.java and SamplePluginCommandExecutor.java.
I'm not an archetype expert, in fact I just did it once but
faced with a very similar problem.
I was not able to find a way to customize file or directory names
in any way, I mean use one of the archetype parameters and transform
it.
So there are 2 kinds of solution I used
Add a new archetype parameter where you specify the class name
Use a standard Name (like ArtifactClass.java) and then create an maven profile (enabled if this file is present) with an ant script that changes the name (just remember inside your files you can use velocity to customize it)
Hope it helps
tonio

Maven Plugin to mark empty directories

Is there something for Maven that I can use to create "placeholders" (e.g. a .empty or EMPTY) file for empty directories? Mercurial does not include empty directories so I need these directories filled hopefully via some automated way.
In the past, I used a Python script that does exactly this. I was hoping for a more Java-esque or Maven-esque approach.
Thanks
You could always use maven-antrun-plugin or gmaven-plugin to script putting a file in your directories. And then submit those empty files to your source control.
HOWEVER, this would have maven generate source code that is going to be checked in. Which is a bad idea (or at least not what you want to regular build to do).
If your source control does not keep track of empty directories, but they're needed for your build, I would recommend instead having a generate-source hook in your maven lifeycle that creates those. (Ideally, in your target directory to keep it clean, however since your source control won't keep track of them there is little harm in putting them right in your source folders if that makes your life easier).
Something like (consider that pseudo-code, absolutely not tested):
<build>
<plugins>
<plugins>
<artifactId>maven-antrun-plugin</...>
<executions>
<execution>
<phase>generate-source</phase>
<goals><goal>antrun</...
<configuration>
<tasks>
<mkdir dir="my directory1"/>
<mkdir dir="my directory2"/>

Resources