Spring Boot 2.3 Maven Docker build adds "docker.io" prefix - spring-boot

I'm trying to build a Docker image for my Spring Boot service using mvn spring-boot:build-image as mentioned in the guide here. It also mentions
The result is an image called docker.io//:latest by default. You can modify the image name in Maven using
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<image>
<name>my/preferred/name</name>
</image>
</configuration>
</plugin>
</plugins>
</build>
It seems pretty straightforward... however, this results in a Docker image with the name docker.io/my/preferred/name.
How do I get rid of the docker.io prefix?

My guess is that you are confusing the parser with so many slashes (/). Since there is no reasonable way to parse my/preferred/name, it will be considered as just a name (as a whole) in which case the default docker.io/library/ will be prepended to it.
Here is how you can specify the name of the image in the name tag.
name (maps to docker.io/library/name)
domain/name
domain:port/name
domain:port/name:tag
domain:port/name#digest
Your my/preferred/name name falls under the first category.

Related

WildFly Maven Plugin - Setting Blank Context Root

I am using the Maven WildFly plugin and have the following in my pom.xml (version is 2.0.1.Final and path points to a local WildFly 8.2.1.Final server).
<build>
<plugins>
<plugin>
<groupId>org.wildfly.plugins</groupId>
<artifactId>wildfly-maven-plugin</artifactId>
<version>${wildfly.version}</version>
<configuration>
<jboss-home>${wildfly.path}</jboss-home>
</configuration>
</plugin>
</plugins>
</build>
The application is getting deployed as localhost:8080/myArtifactId-myVersion which is expected as the default behavior is to use the WAR name. However, I want to change the context root so that the application is accessible via localhost:8080/ (i.e. I want a blank context root).
Method 1: Change the Pom Configuration
I can change the finalName build setting in my pom.xml as follows.
<build>
<finalName>newContextRoot</finalName>
</build>
This correctly updates the url to localhost:8080/newContextRoot. I then tried to change it to be a blank value.
<build>
<finalName></finalName>
</build>
However, this results in a Value must not be empty error in my IDE and when I try to build it fails, saying Error assembling WAR: A zip file cannot include itself.
Method 2: Change Plugin Configuration
Probably the better solution is to change the configuration of the Maven WildFly plugin itself. Under the <configuration> section, I can add the following.
<name>anotherContextRoot.war</name>
This correctly changes the url to localhost:8080/anotherContextRoot. So then I tried again to create a blank name as in the following.
<name>.war</name>
However, this results in an IllegalArgumentException: Empty name segment is not allowed for module.
Question
Does anyone know the appropriate way to make the context root blank? Thanks in advance.
I managed to figure this out. You do not need to do anything except add a jboss-web.xml file into the WEB-INF directory as follows.
<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
<context-root>/</context-root>
<default-encoding>UTF-8</default-encoding>
</jboss-web>
This sets the context root and overrides what the plugin was doing.
Hope this helps someone else.
If you save your war with the name ROOT.war and deploy it, WildFly will configure it as root application.

Wildfly Deploy Maven - Remove Version

I want to deploy a war that I have created using maven to wildfly using the wildfly-maven-plugin.
The final name of the war is something like: my-war-1.0.war
The war also contains a jboss-web.xml specifying the context root (e.g. /my-war)
Problem Description
If I now deploy the war to wildfly I will get a "my-war-1.0.war" deployment.
If I later want to deploy a new version (e.g. the war is now named my-war-1.1.war) I get a conflict as the context root is already known but the deployment has a new name.
Is there a way using the wildfly-maven-plugin to deploy a "my-war.war" instead?
I need to keep the original final build name inside the maven build for versioning and deploying to our nexus.
The simplest solution is to use the <finalName/> element on the <build/> configuration.
<build>
<finalName>${project.artifactId}</finalName>
</build>
You can use the maven war plugin to rename the final war. For Eg:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<warName>my-war</warName>
</configuration>
</plugin>
</plugins>
</build>
This will always generate the war with the name my-war.war in your "target" directory.
I found out that I can use the parameters <name/> and <runtimeName/> inside the <configuration/> of the maven-wildfly-plugin.
That way I can specify what the deployment should be called on the server and each time just replace it. It is important to have the two parameters end in ".war", otherwise you will get a 404 error.
Using this method I can keep the original name of the final build result containing the version (my-app-1.0.war) and archive it inside our internal nexus repository.

How to add a build timestamp to the title of an application built with Tycho

Is there a way to have the product name, which is shown in the title of the started application, set by the Tycho build?
Currently, the title of my application is the static product name set in the product configuration file. However I want to add a build number or timestamp to that title to better distinguish the different builds of the application.
So instead of My Application, I would like to have My Application (<buildNr>-<date>) with the build number and date expanded.
If this is not possible with Tycho, any other solution is welcome.
I am not sure if it is an ideal solution but I did the following:
To properly set the application title the product name has to be set, as it is also used in the About <productName>-menu item, furthermore it is returned when Platform.getProduct().getName() is called. (Which is used sometimes in my legacy product.)
To set the product name while building I do the following:
read the product name from the plugin.properties file
modify the plugin.properties with Tycho (Maven)
1. Read the product name from the plugin.properties file
To make it easier to modify the product name via Maven, that String is externalized to plugin.properties.
In the plugin configuration file and in the plugin.xml, the product name should be set to %product.name.
Then in the plugin.properties add the following line:
product.name=#productName#
If you start your product now, the application title should be #productName#.
2. Modify the plugin.properties with Tycho (Maven)
To change #productName# to the desired text the Maven filtering is used. Eclipse can not start the product anymore if the standard filter delimiters (${productName}) are used, therefore I use the Ant like delimiters. This snippet needs to be added to the pom:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.4.3</version>
<configuration>
<encoding>UTF-8</encoding>
<delimiters>
<delimiter>${*}</delimiter><!-- to keep the default behavior -->
<delimiter>#</delimiter><!-- to add Ant-like tokens style, this is needed as RCP has problems with the accolades -->
</delimiters>
</configuration>
</plugin>
I found this solution here on SO.
To replace #productName# with the actual value the Maven property <productName> has to be defined in the pom:
<properties>
<productName>MyApp_${maven.build.timestamp}</productName>
</properties>
<productName> can contain any value e.g. ${buildNumber} from the Build Number Maven Plugin.
Now the the only missing part is the following snippet which activates the filtering:
<resources>
<resource>
<directory>./</directory>
<includes>
<include>plugin.properties</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>

Why is my ${user.home} variable resoled at build time

I have a JHipster generated application with an YAML property file that looks like this:
storage:
location: ${user.home}/my/folder
My problem is that the variable ${user.home} is resolved at build time, when I run mvn package (on Jenkins). So the property is already resolved in the resulting artifact, hence when I deploy on on my server, that path contains the resolved home of the user Jenkins.
Anybody know who is doing this and why? I was expecting that the variable would be resolved at runtime.
Thanks.
Valentin
I'm not totally sure of how JHipster builds on top of Spring Boot, but my guess would be that it's Maven's resource filtering that's expanding ${user.home} at build time. It's enabled by default by spring-boot-starter-parent for application.properties and application.yaml in src/main/resources.
This Spring Boot issue contains some more information, along with details of a configuration change that you may like to make so that ${…} entries are no longer filtered:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
<configuration>
<encoding>UTF-8</encoding>
<delimiters>
<delimiter>#</delimiter>
</delimiters>
<useDefaultDelimiters>false</useDefaultDelimiters>
</configuration>
</plugin>

How to access maven.build.timestamp for resource filtering

I am using maven 3.0.4 and would like to make the build timestamp accessible to my application. For this, I'm putting a placeholder in a .properties file and let maven filter on build. While this is working fine for ${project.version}, ${maven.build.timestamp} is not substituted on filtering.
The property seems to be available on build - I can use it to modify the artifact name:
<finalName>${project.artifactId}-${maven.build.timestamp}</finalName>
So why is it not available for resource filtering? And, more importantly, how do I make it accessible?
I have discovered this article, explaining that due to a bug in maven, the build timestamp does not get propagated to the filtering. The workaround is to wrap the timestamp in another property:
<properties>
<timestamp>${maven.build.timestamp}</timestamp>
<maven.build.timestamp.format>yyyy-MM-dd HH:mm</maven.build.timestamp.format>
</properties>
Filtering then works as expected for
buildTimestamp=${timestamp}
I can confirm as of Maven 3.x {maven.build.timestamp} is "working" now. They work arounded the problem, apparently. No additional properties workaround needed anymore.
However, be careful your "filtering" plugin (maven-resources-plugin) is up to date. It needs to be relatively new, so if mvn help:effective-pom shows an old version (ex: 2.6), bump it to something newer, fixed it for me, 3.x ex:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<properties><timestamp>... workaround is no longer required...
This also cleared up, kind of, why it was working in IntelliJ but not the command line. IntelliJ probably uses their own "modified/internal" maven constants, so it was working there, but not from maven command line.
Also note if you add a filtering resource directory to you pom, you may need to also "re-add" the default directory, it gets lost, ex:
<resource>
<directory>src/main/resources-filtered</directory> <!-- to get "maven.build.timestamp" into resource properties file -->
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/resources</directory> <!-- apparently have to add this is you have the other... -->
</resource>
NB if you're using spring boot as your parent, you have to use #maven.build.timestamp# instead. Also note if you're using spring boot there's a file META-INF/build-info.properties that is optionally created by the spring-boot-maven-plugin that you can read (spring provides a BuildProperties bean for convenience reading it).
In order to enrich the Stackoverflow content for others, that like me, found this post as a way to solve the "problem" of ${maven.build.timestamp}. This is not a maven bug, but an expected behavior of m2e, as can be seen in this post.
Therefore, I believe that we can not expect the solution to be "corrected", since, from what I understand, the correction involves conceptual issues.
In my case, what I did was use the plugin (buildnumber-maven-plugin) as described in this other post.
Adding Maven properties at the pom project level doesn't take into account correct local Timezone, so timestamp may appear wrong :
<properties><timestamp>${maven.build.timestamp}</timestamp></properties>
Using the build-helper-maven-plugin applies the correct timezone and current daylight saving to the timestamp :
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.9.1</version>
<executions>
<execution>
<id>timestamp-property</id>
<goals>
<goal>timestamp-property</goal>
</goals>
<configuration>
<name>timestamp</name>
<pattern>yyyy-MM-dd HH:mm:ss</pattern>
<timeZone>Europe/Zurich</timeZone>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
When packaging, Maven will replace any token timestamp in /resources folder, e.g. resources/version.properties :
build.timestamp=${timestamp}
You can then load this properties file in your Application.

Resources