custom runtime issue with native-maven-plugin having metadataRepository enabled - spring-boot

I have an app built with Spring Boot 3.0.0-M5, Spring Cloud 2022.0.0-M4, Java 17. Its GitHub repo is https://github.com/wenqiglantz/springboot3-webclient/tree/metadata. I am trying to achieve the following:
Enable metadataRepository configuration in native-maven-plugin in my app to assist in my native image build as this plugin automatically searches for GraalVM reachability metadata repo.
Need to create a custom runtime (in a zip format) using maven-assembly-plugin as I need to deploy my app to AWS Lambda since Lambda doesn't yet support Java 17 runtime.
I was able to generate the custom runtime in a zip file with maven-assembly-plugin and a few config files in my source code and deploy to Lambda (my github actions workflow run https://github.com/wenqiglantz/springboot3-webclient/actions/runs/3146602388/jobs/5115233455). However, after adding native-maven-plugin to enable metadataRepository, my custom runtime build broke, it no longer generates the zip file (github actions workflow run https://github.com/wenqiglantz/springboot3-webclient/actions/runs/3151692666/jobs/5125968700). Also see attached the comparison screenshot. The maven command I use in my workflow is mvn -ntp clean package -Pnative -e -X. In my root pom. Unfortunately I have not been able to find any good documentation on either GraalVM side or Spring Boot side on how to configure such plugins to achieve what I want. I have the plugins configured as the following, let me know what's the best way to handle configuring both maven-assembly-plugin and native-maven-plugin so I can accomplish my two goals listed above.
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>native-zip</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<inherited>false</inherited>
</execution>
</executions>
<configuration>
<descriptors>
<descriptor>src/assembly/native.xml</descriptor>
</descriptors>
</configuration>
</plugin>
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<version>0.9.14</version>
<extensions>true</extensions>
<executions>
<execution>
<id>build-native</id>
<goals>
<goal>compile-no-fork</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
<configuration>
<metadataRepository>
<enabled>true</enabled>
</metadataRepository>
</configuration>
</plugin>
</plugins>
</build>

Related

Running maven-shade and dockerfile-maven in different phases

My app uses maven-shade-plugin to pack things into single fatjar and then I would like to build a docker image using dockerfile-maven-plugin, my problem is that I can set the pom file properly so it would work.
What happens is that the docker plugin runs before the jar file was created...
I've tried to force the jar creation on prepare-package and the docker image build on package but it didn't work as expected...
any ideas?
EDIT: added pom snippet
<build>
<plugins>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>${dockerfile-maven.version}</version>
<configuration>
<repository>test-docker-image</repository>
<tag>${docker.tag}</tag>
<buildArgs>
<JAR_FILE>${project.artifactId}-${project.version}-fat.jar</JAR_FILE>
<CONFIGURATION_FILE>configuration.json</CONFIGURATION_FILE>
</buildArgs>
</configuration>
<executions>
<execution>
<goals>
<goal>build</goal>
<!-- <goal>push</goal> -->
</goals>
<phase>install</phase>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>${maven.shade.plugin.version}</version>
<executions>
<execution>
<goals>
<goal>shade</goal>
</goals>
<phase>package</phase>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>io.vertx.core.Launcher</Main-Class>
<Main-Verticle>MyVerticle</Main-Verticle>
</manifestEntries>
</transformer>
</transformers>
<minimizeJar>false</minimizeJar>
<outputFile>${project.build.directory}/deploy/${project.artifactId}-${project.version}-fat.jar</outputFile>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
I had both of these same plugins listed in the same order you have (docker-maven-plugin before maven-shade-plugin) and was seeing the same issue. I discovered that Maven executes plugins in the same phase in the order that they are listed, so moving maven-shade-plugin to be first resolved the issue for me locally. (Older versions of Maven don't order plugins this way, so use the latest if possible.)
This doesn't explain why it is not working for you when you change them to use different phases, but I'd suggest at least trying it out that reordering. Also be sure that you are using the latest versions of related plugins, like maven-release-plugin.
I was still seeing the undesired behavior in my build environment after doing all of the above, due to the parent of my project containing an execution for docker-maven-plugin; the fact that I was customizing it and reordering it in my own project didn't help, although it is unclear why it worked locally. Maven build profiles can also have a similar impact on ordering. My solution there was to bind the docker-maven-plugin:build execution to the install phase.
The output of mvn help:effective-pom should let you see the exact listing of plugins, executions, and profiles so that you can see exactly what the ordering will be for your project. Note that profiles are executed bottom-to-top, which is the opposite of plugins!

is it possible to version and deploy a configuration file to nexus via maven commands

I am working on a java project and I would like to version and store a configuration file on nexus. Lets assume the file structure of java project is as below.
src/
conf/application.config
pom.xml
Is it possible to deploy application.config file to nexus when I run mvn clean install. After each build I expect an application artifact and a configuration artifact to be deployed to nexus. Is there any maven plugin for this purpose.
I manged to deploy file with maven-deploy-plugin.
http://maven.apache.org/plugins/maven-deploy-plugin/usage.html
You can find an example below.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
<executions>
<execution>
<id>deploy-file</id>
<!-- change to deploy-->
<phase>install</phase>
<goals>
<goal>deploy-file</goal>
</goals>
</execution>
</executions>
<configuration>
<file>app.properties</file>
<repositoryId>stack.example.release</repositoryId>
<url>http://nexusserver/nexus/content/repositories/releases/</url>
<groupId>com.stack.example.config</groupId>
<artifactId>app</artifactId>
<packaging>properties</packaging>
<version>1.0.0</version>
</configuration>
</plugin>
</plugins>
</build>

Regarding updating pom file

I am working on a continuous integration tool and here i need to integrate jacoco plugin after checking out. I do not want to enforce developer to add jacoco plugin while checkin instead i would like to add it while running the jenkins based continuous integration tool.
Is it possible to achieve any of these options?:
1. to modify the pom file checked in by the developer and inject the dependency and plugin required for jacoco?
OR
to add the jacoco plugin super pom and mention that in jenkins configuration.
I tried this super pom approach, and it was reading super pom from a common repository, but not generating jacoco-exec file. I used below in super pom.
http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
pom
<dependencies>
<dependency>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.6.201602180812</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.6.201602180812</version>
<configuration>
<destFile>${basedir}/target/jacoco-unit.exec</destFile>
<dataFile>${basedir}/target/jacoco-unit.exec</dataFile>
</configuration>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Any help will be appreciated. Thanks
You can create a separate profile in the pom.xml, name it as jenkins profile and include jacoco plugin in that profile. You can then configure the mvn command in your jenkins job to include -P jenkins_profile_name. So the build would be done using the jenkins profile configuration.
Mark the existing profile as default and developers won't need to do anything specific.
For more details, refer to maven documentation for build profiles:
http://maven.apache.org/guides/introduction/introduction-to-profiles.html

Redirecting the nexus-staging-maven-plugin to an internal repository

I have a webjars project that I'd like to build snapshots and have them deployed locally (within our infrastructure) but have the releases be managed by webjars.org.
https://github.com/webjars/oscar/blob/15.0.0-RC1/pom.xml
The problem I'm facing is that they need the nexus-staging-maven-plugin defined as part of their release process. So I'd like to keep the POM tailored for them as much as possible, and just make our own deviations via command line (or worst case, profile) if possible.
Typically, if doing this from scratch, you'd probably introduce the staging plugin in a profile, but I don't think I have that option. (I might have to make the modification though and discuss it with them.)
I've never used the staging plugin before, so this is my first exposure and it isn't a pleasant one given what I'm trying to do. I feel like I'm fighting the system.
I thought I had something by specifying:
-DsonatypeOssDistMgmtSnapshotsUrl=http://myurl
and that pushes the artifact at the correct location, but then I can't figure out how to supply credentials. (401 unauthorized) I thought specifying the serverId might work, but no.
-DserverId=public-snapshots
http://books.sonatype.com/nexus-book/reference/staging-deployment.html
I then tried creating a profile, where I'd do something like this:
<profile>
<id>disable-staging</id>
<build>
<plugins>
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
<version>1.6.5</version>
<configuration combine.self="override">
<executions>
<execution>
<id>injected-nexus-deploy</id>
<phase>none</phase>
</execution>
</executions>
</configuration>
</plugin>
</plugins>
</build>
</profile>
but that doesn't help. The effective-pom shows this:
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
<version>1.6.5</version>
<extensions>true</extensions>
<executions>
<execution>
<id>injected-nexus-deploy</id>
<phase>deploy</phase>
<goals>
<goal>deploy</goal>
</goals>
<configuration combine.self="override">
<executions>
<execution>
<id>injected-nexus-deploy</id>
<phase>none</phase>
</execution>
</executions>
</configuration>
</execution>
</executions>
<configuration combine.self="override">
<executions>
<execution>
<id>injected-nexus-deploy</id>
<phase>none</phase>
</execution>
</executions>
</configuration>
</plugin>
and I can't unbind the deploy phase.
I'm wondering if anyone has any ideas on what to do in this type of scenario?
You can use the Nexus Staging Plugin's property skipNexusStagingDeployMojo to achieve this:
mvn clean package deploy:deploy -DskipNexusStagingDeployMojo=true
-DaltDeploymentRepository=snapshots::default::https://my.nexus.host/content/repositories/snapshots-local
It is important to explicitly invoke package and then deploy:deploy, as otherwise (when only invoking mvn deploy) the default execution of the maven-deploy-plugin is suppressed by the Nexus Staging Plugin (even with the skip set to true).

Executing cmd command using Maven

I want to execute this command:
zipalign [-f] [-v] <alignment> infile.apk outfile.apk
Using Maven. I have to execute this command in the Android SDK/ tools directory. Can anyone help me on how to do this? I think this can be done using batch file but I am not sure how to create a batch file. I need this command to be executed when I type "mvn clean install". Thanks
Executing commands using Maven
You can use the Maven Exec Plugin bound to the install phase.
In the snippet below, the commant ping with the argument 8.8.8.8 will be executed every time you do a mvn install:
<project>
...
<build>
<plugins>
<plugin>
<artifactId>exec-maven-plugin</artifactId>
<groupId>org.codehaus.mojo</groupId>
<version>1.2.1</version>
<executions>
<execution>
<id>My Command Runner</id>
<phase>install</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>ping</executable>
<arguments>
<argument>8.8.8.8</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
</project>
 
And that's it.
 
 
Update:
I see now what you really having trouble with is executing zipalign, not an arbitrary command. For that, there are two ways.
Using the built-in zipalign of the maven-android-plugin
As of release 2.5.0 of the Android Maven Plugin the zipalign goal is part of the plugin. To activate simply add the goal zipalign as an execution (e.g. to the package phase) and set the skip parameter in the plugin configuration to false:
<zipalign><skip>false</skip></zipalign>
Full <plugin> tag example:
<plugin>
<groupId>com.jayway.maven.plugins.android.generation2</groupId>
<artifactId>maven-android-plugin</artifactId>
<inherited>true</inherited>
<configuration>
<sign>
<debug>false</debug>
</sign>
<zipalign>
<verbose>true</verbose>
<inputApk>${project.build.directory}/${project.artifactId}.apk</inputApk>
<outputApk>${project.build.directory}/${project.artifactId}-signed-aligned.apk
</outputApk>
</zipalign>
</configuration>
<executions>
<execution>
<id>alignApk</id>
<phase>package</phase>
<goals>
<goal>zipalign</goal>
</goals>
</execution>
</executions>
</plugin>
Sources:
Here you'll find an example using the an older version (still called android-maven-plugin);
ZipalignAPKBuiltByMAven: Describes how to automatically zipalign an APK that has been built by Maven.
Simpligility: Maven Android Plugin with zipalign and improved verification
Another example: A full pom.xml that uses the zipalign.
Zipalign using Exec-Maven Plugin
The code below will bind the functionality of zip aligning to the package phase, overwriting previous zip aligned file without asking.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.1.1</version>
<executions>
<execution>
<id>zipalign</id>
<goals>
<goal>exec</goal>
</goals>
<phase>package</phase>
<configuration>
<executable>${ANDROID_HOME}/tools/zipalign</executable>
<arguments>
<argument>-f</argument>
<argument>4</argument>
<argument>target/${project.build.finalName}.apk</argument>
<argument>target/${project.build.finalName}-zipped.apk</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
Please note that this profile has to be added to the pom for the actual APK. You can't add it to a parent pom. The reason for this is that it uses the Maven property that defines the artefact name (project.build.finalName).
If you're building an Android project with Maven, you should be using the maven-android-plugn, which supports the zipalign tool directly.

Resources