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
Related
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!
What is(are) the simpler way(s), using just "native" Apache Maven plugins, to inject a script at the beginning of a jar file to make the jar an executable file?
Actually, any way to "edit" the built jar file as a regular file concatenating it with another file may work. Like the shell cat example down below:
$ cat ${projectRoot}/src/main/stubs/runstub.sh target/${builtJarPath} > target/${builtJarPathWithoutExtention}-autorun.jar
$ chmod +x target/${builtJarPathWithoutExtention}-autorun.jar
In case you want to know the reason to inject a shell script at the beginning of a jar file, check the internet about "converting jar file to Linux executable", example:
How to convert a .java or a .jar file into a Linux executable file ( without a .jar extension, which means it's not a .jar file )
https://coderwall.com/p/ssuaxa/how-to-make-a-jar-file-linux-executable
You can use exec-maven-plugin
<plugin>
<artifactId>exec-maven-plugin</artifactId>
<groupId>org.codehaus.mojo</groupId>
<executions>
<execution>
<id>Inject stub</id>
<phase>install</phase> <!-- Select a phase that is after package generation -->
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>${basedir}/scripts/inject-stub.sh</executable>
</configuration>
</execution>
</executions>
</plugin>
I've created a simple Micronaut application using
mn create-app app_name --build maven
with a JDK 11 in case that matters.
This creates a maven project which compiles fine, but includes a Dockerfile like this:
FROM adoptopenjdk/openjdk11-openj9:jdk-11.0.1.13-alpine-slim
COPY target/app_name*.jar app_name.jar
EXPOSE 8080
CMD java -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -Dcom.sun.management.jmxremote -noverify ${JAVA_OPTS} -jar app_name.jar
However, there is no docker build included in the Maven AFAICT.
So I included this
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>${dockerfile-maven-version}</version>
<executions>
<execution>
<id>default</id>
<goals>
<goal>build</goal>
<goal>push</goal>
</goals>
</execution>
</executions>
<configuration>
<repository>dockerUser/app_name</repository>
<tag>${project.version}</tag>
<buildArgs>
<JAR_FILE>${project.build.finalName}.jar</JAR_FILE>
</buildArgs>
</configuration>
</plugin>
which does manage to build a docker image, but not without manual intervention. The reason is that upon mvn package, three jars get created in target/:
app_name-0.1.jar
app_name-0.1-shaded.jar
original-app_name-0.1.jar
which makes the docker target fail with
When using COPY with more than one source file, the destination must be a directory and end with a /
That message does make sense because all the jars match the COPY source pattern in the Dockerfile.
Right now, I just delete the other two jars (original and shaded) and run the docker target on its own, but that's only fine as long as I work in local manual mode.
Am I missing something or is this an oversight on the Micronaut project creation?
I can't help you with the micronaut configuration, unfortunately. However, if the purpose is to copy the main jar file and the unknown version suffix is the cause of the wildcard being used while copying, a finalName element can be added to the pom.xml in order to strip the version info from the name of the JAR file:
<build>
<finalName>app_name</finalName>
</build>
Am I missing something or is this an oversight on the Micronaut
project creation?
The latter.
If you file an issue at https://github.com/micronaut-projects/micronaut-profiles/issues we can get it straightened out.
Relevant files:
https://github.com/micronaut-projects/micronaut-profiles/blob/c391ef02b5ca087bbdec79f80b129240b29cc246/service/skeleton/maven-build/Dockerfile
https://github.com/micronaut-projects/micronaut-profiles/blob/c391ef02b5ca087bbdec79f80b129240b29cc246/service/skeleton/gradle-build/Dockerfile
Thanks for the input.
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'd like to add *.dlls as third party libs to my repository and during packaging process just pack them to *.jar, sign them and copy to some specific folder.
Signing and coping are well done and work correctly (as expected by using maven-dependency-plugin and maven-jarsigner-plugin). But I didn't find any method to automatically pack single dll to jar (without any sources like maven-assembly-plugin does).
Solution that I see by the time: add to my repository not a "pure" dll, but already packed to jar lib (packed by myself)... but it's not a good idea, I guess)
It sounds like you've successfully retrieved your .dll (with dependency plugin) and signed it (jarsigner plugin), and it's somewhere in your ${project.build.directory} (which defaults to target).
If that's correct, give this a try:
Define the packaging of your project as jar
Retrieve dlls
Make sure the jarsigner:sign goal is bound to the prepare-package phase. It binds to package by default and we need to ensure jarsigner:sign runs before jar:jar.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jarsigner-plugin</artifactId>
<version>1.2</version>
<executions>
<execution>
<id>sign</id>
<phase>prepare-package</phase> <!-- important -->
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
Configure the jar plugin to include the signed dll(s)
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<!-- using this ID merges this config with default -->
<!-- So it should not be necessary to specify phase or goals -->
<!-- Change classes directory because it will look in target/classes
by default and that probably isn't where your dlls are. If
the dlls are in target then directoryContainingSignedDlls is
simply ${project.build.directory}. -->
<id>default-jar</id>
<configuration>
<classesDirectory>directoryContainingSignedDlls</classesDirectory>
<includes>
<include>**/*.dll</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
Now, running mvn clean package should give you a jar containing your signed dlls.
If JACOB requires manifest config there are docs explaining how to do this.
Good luck!
I would recommend to pack your dll's as a zip archive via maven-assembly-plugin and let that module deploy the zip archive as attached to your usual pom. The packaging of that project should be pom instead of default.
I would be a little bit confused if i download a jar and find dll's inside it,
but if you prefer you could create jar via the maven-assembly-plugin or use the maven-jar-plugin.