I'm using asciidoctor-maven-plugin and asciidoctor-diagram to generate PlantUML diagrams (more specifically C4-PlantUML diagrams). When generating those diagrams, output is polluted by these kind of messages
[Log] "dynamic undefined legend colors" requires PlantUML version >= 1.2021.6, therefore only static assigned colors are used
I tracked them down to asciidoctor-diagram embedding - in its source, lo less, a reasonably old version of PlantUML (see their Github source).
Fortunatly, there is in asciidoctor-diagram plantuml converter.rb class some code to use PlantUML provided externally through an environment variable named DIAGRAM_PLANTUML_CLASSPATH.
But as I use asciidoctor-diagram through asciidoctor-maven-plugin, how can I set that environment variable from my Maven POM without setting it in the maven launch ? Indeed, I want to use a dependency from my pom and maven-dependency-plugin properties goal to have it correct on any machine without configuration.
I've already tried using asciidoctor-maven-plugin configuration attributes, but it didn't seem to work.
Is there any other way to inject environment variables into asciidoctor-maven-plugin ?
EDIT 1 I've also tried using the properties-maven-plugin to add the environment variable to my maven build this way
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0.0</version>
<executions>
<execution>
<id>Set DIAGRAM_PLANTUML_CLASSPATH from PlantUML maven dependency PATH</id>
<phase>process-resources</phase>
<goals>
<goal>set-system-properties</goal>
</goals>
<configuration>
<properties>
<property>
<name>DIAGRAM_PLANTUML_CLASSPATH</name>
<value>${net.sourceforge.plantuml:plantuml:jar}</value>
</property>
</properties>
</configuration>
</execution>
</executions>
</plugin>
But it changed nothing
EDIT 2
So, after some reflection, I had to resolve to use the age-long solution : debugging the culprit code (in this case, asciidoctor-maven-plugin).
In AsciidoctorMojo#execute(), in a long chain of calls, we initialize a JRuby interpreter (in JRubyAsciidoctor#createRubyRuntime).
When creating this interpreter, we pass the system environment. This system environment DO NOT include my DIAGRAM_PLANTUML_CLASSPATH variable, so I guess the properties-maven-plugin does not really set it as environment variable for the whole maven build - or there has been some changes in recent maven versions.
However, this JRubyAsciidoctor#createRubyRuntime method accepts as input a map of environment variables. Can we manipulate it ? Absolutely not as it is a private method.
And guess what ? DIAGRAM_PLANTUML_CLASSPATH doesn't appear in the list because it's not an environment variable, but a system property, which is quite different.
So the question is more "how can I create an environment variable ? Or inject an environment variable in my ruby env prior to running my build ?"
So, I've established in the question that what was not working was the injection of the environment variable into JRuby : As default, Java doesn't allow setting environment variable, and on the other hand asciidoctor only allow injection through environment variable. So I had to create that environment variable.
Hopefully, Stackoverflow already answers that question : How do I set environment variables from Java?.
My only point was doing that in a maven build. Enter GMaven Plus. Using this plugin the following way
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>properties</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.gmavenplus</groupId>
<artifactId>gmavenplus-plugin</artifactId>
<executions>
<execution>
<id>Put PlantUML path in that damn DIAGRAM_PLANTUML_CLASSPATH environment variable</id>
<phase>initialize</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<scripts>
<script>${project.basedir}/src/build/groovyScripts/set_PlantUML_path_in_system_environment.groovy</script>
</scripts>
</configuration>
</execution>
</executions>
</plugin>
Notice the preliminary call to dependency-maven-plugin to obtain all dependencies paths as properties.
THen I created a very small Groovy script
log.debug "PlantUML dependency path is ${project.properties['net.sourceforge.plantuml:plantuml:jar']}"
setEnvironmentVars(['DIAGRAM_PLANTUML_CLASSPATH':project.properties['net.sourceforge.plantuml:plantuml:jar']])
And it was enough to have asciidoctor-maven-plugin working.
CAVEAT: I'm quite sure this won't work with recent Java releases like Java 14 and Java 17. Anyway, in Java 11, it works!
Related
I have a POM file which includes a property (under properties section) which has an IP value that we use when pushing it to git.
<device.ip>1.2.3.4</device.ip>
But for my builds, I need to use a another IP value, so I should change it to my required IP when I start to work on a new branch.
I'd like to be able to check the variable value at build startup and abort it given the variable value is different from what I need.
Any other solutions also welcomed.
(I hope my question would not be downgraded because of lack of code - there is no really code to write here. The scenario is quite self explanatory)
Than you for your advice.
You could use the maven-enforcer-plugin which support such checks.
The usage looks like this for the requirePropery rule.
<project>
[...]
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.0.0-M2</version>
<executions>
<execution>
<id>enforce-property</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireProperty>
<property>device.ip</property>
<message>You must set a device.ip property!</message>
<regex>.*\d.*</regex> <!-- Express the value you need. -->
<regexMessage>The device.ip property contain...</regexMessage>
</requireProperty>
</rules>
<fail>true</fail>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
[...]
</project>
I would suggest splitting your project in modules.
Module 1 contains your code without any configuration.
Module 2 refers to module 1 and additionally contains what goes into production. For multiple deployments create an additional module for each. This is where your production property goes.
Module 3 refers to module 1 (but not 2) and contains whatever you need for development (configuration like this property and helper classes). For complex scenarios make an additional module for each.
This has worked well for me.
I'd like to save some unpacked files into the temp folder of a machine.
Question: How can I get the temp folder using maven?
Question: Will it work on both linux and windows environments?
Maven supports, as part of the default properties, any Java System property, hence you can use the following property:
java.io.tmpdir Default temp file path
As example:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.10</version>
<executions>
<execution>
<id>unpack</id>
<phase>package</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<!-- further conf here -->
<outputDirectory>${java.io.tmpdir}/libs</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
Note the outputDirectory element and its value.
As a further note, also note that the target folder of the Maven build is also meant to host temporary files, so you should also consider to use it for such a purpose.
Will it work on both linux and windows environments?
Yes, since it is Java property, it is supposed to be OS independent.
use the java environment tmp dir - java.io.tmpdir
you can access it from maven via ${java.io.tmpdir} without having to predefine it.
you can also customize it on a specific run by running:
mvn clean install -Djava.io.tmpdir=/tmp/where/ever
I would like to specify some system properties in my applicatio (deterined at compile time).
I am using the spring boot maven plugin to compile
Currently, according to this questions: Specify system property to Maven project
I tried the following setup (however this does not work as it is for a different plugin)
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>application.boot.AppStarter</mainClass>
<systemProperties>
<systemProperty>
<name>application.version</name>
<value>${application.version}</value>
</systemProperty>
<systemProperty>
<name>release.date</name>
<value>${timestamp}</value>
</systemProperty>
</systemProperties>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
How can i specify the properties in this plugin?
Java system properties which you add are only accessible by the process they are added to.So even if you manage to add some system properties during the Maven build, it will no longer be there when the build is done.
What will happen if you distribute your jar to someone else. How do you expect these properties to be available?
Solution
Refer this post to see how to access the artifactId and version at runtime
In a similar fashion you can add the timestamp entry as well to the src/main/resources/project.properties
buildTimestamp=${timestamp}
timestamp is not a pre-defined property like project.version or project.artifactId.So you will have to set extract the timestamp from the Maven property ${maven.build.timestamp} and set it as value to your timestamp property. This is already answered in this question.
I have this multi module project setup which uses Webstart and I need to bundle the WAR with SNAPSHOT JARs. When the JARs are bundled into the WAR, they are appended with a timestamp instead of the actual name. This is causing issues during their download.
Expected - ABC-1.0-SNAPSHOT.jar
Actual - ABC-1.0-20141002.211448-2.jar
Env:
OS: Unix
Maven: 3.2.1
JDK: 1.7
I have already tried useUniqueVersions=false by defining a maven-war-plugin and setting this in the manifest configuration.
My webstart config:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>webstart-maven-plugin</artifactId>
<version>1.0-beta-6</version>
<executions>
<execution>
<phase>process-resources</phase>
<goals>
<goal>jnlp-download-servlet</goal>
</goals>
</execution>
</executions>
<configuration>
<outputDirectoryName>.</outputDirectoryName>
<excludeTransitive>true</excludeTransitive>
<commonJarResources>
<jarResource>
...
</jarResource>
</commonJarResources>
<jnlpFiles>
<jnlpFile>
<templateFilename>JNLP-INF/APPLICATION_TEMPLATE.JNLP</templateFilename>
<outputFilename>client.jnlp</outputFilename>
<jarResources>
<jarResource>
...
</jarResource>
</jarResources>
</jnlpFile>
</jnlpFiles>
<sign>
...
</sign>
<outputJarVersions>false</outputJarVersions>
</configuration>
Appreciate any inputs.
UPDATE
Adding details about the WAR plugin I added
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.4</version>
</plugin>
The behavior continues. I read that maven 3 uses a unique snapshot system. But I am trying to work my way around it.
Also tried the following without any luck
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.4</version>
<configuration>
<outputFileNameMapping>${artifact.artifactId}-${artifact.baseVersion}.${artifact.extension}</outputFileNameMapping>
</configuration>
</plugin>
The creators of the maven-webstart-plugin have accidentally inverted the meaning of the flag useUniqueVersions. When set to true it produces jars of the form -SNAPSHOT.jar and when set to false (the default) it produces jars of the form --.jar
I found that setting the useUniqueVersions flag to true in the maven pom configuration produced my desired results.
I needed it like this because when deployed with the datestamp version of the snapshots when trying to launch it I was getting a "Resource not found" error when it tried to get the snapshot jar it was trying to launch. Presumably this means that the servlet code itself is not set up to handle the different naming on disk, despite the fact that the specific datestamp version number does end up in the jnlp itself.
I am thinking of using a template engine to generate the web.xml and other things.
Is there as way to to run a java file or a script before the maven install command? Or before the war is generated.
I am not sure what the phase should be, but basically before anyone else looks at the web.xml so I can touch it to make a new valid one.
You can use the exec-maven-plugin to run either a program/script (using the exec goal) or a Java program (using the java goal).
The phase immediately before package is prepare-package (see the Default lifecycle in the Lifecycle Reference), so you could use that. But you might prefer to generate the web.xml earlier in the lifecycle (even as early as generate-resources).
Putting these together, you might try something like this:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.3.2</version>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
<configuration>
<executable>your_packaging_script</executable>
<!-- optional -->
<workingDirectory>/tmp</workingDirectory>
<arguments>
<argument>--some-option</argument>
</arguments>
</configuration>
</plugin>
Alternatively, you might consider writing your own plugin, especially if you think the idea would be useful for more than one project.