How to compile Spring Boot applications with Java 8 --parameter flag - spring

Spring documentation tells that, if we compile our project using Java 8 --parameters flag, we can skip giving parameter names in annotations like #PathVariable. That means, we can just use #PathVariable id instead of #PathVariable("id") id.
In a Spring Boot Maven application, I was curious to know how to tell the compiler to use the parameters flag. Is it on by default? Do we need to provide something in the pom.xml?

In Spring Boot 2.0, the --parameters flag should be enabled by default. See yuranos87's answer.
For older versions, in the pom.xml file, you can specify Java compiler options as arguments of the Maven compiler plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
</plugin>

I don't remember needing to do it explicitly in any of my projects. Maybe you just need to add spring-boot-starter-parent(I know, sometimes might not be an option). Otherwise, Spring has already taken care of everything for you.
It is mentioned multiple times in Spring Boot documentation. For example, here:
To allow the input to be mapped to the operation method’s parameters, code implementing an endpoint should be compiled with -parameters. This will happen automatically if you are using Spring Boot’s Gradle plugin or if you are using Maven and spring-boot-starter-parent.
UPDATE
The way Spring Boot does it is quite straight forward(in spring-boot-parent and spring-boot-starter-parent poms):
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<parameters>true</parameters>
</configuration>
</plugin>

Related

Quarkus Endpoints in dependency jars

I have a quarkus application which has dependencies to another maven module within the same project
within that module are REST endpoints
For some strange reason i cannot access those endpoints tho.. It seems quarkus will only accept endpoints of java classes within the quarkus module, or am I mistaken?
I foudn a solution:
if yopu add the jandex, endpoiints of other modules are being scanned, and can thus be found :
<build>
<plugins>
<plugin>
<groupId>org.jboss.jandex</groupId>
<artifactId>jandex-maven-plugin</artifactId>
<version>1.1.0</version>
<executions>
<execution>
<id>make-index</id>
<goals>
<goal>jandex</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
You can do this by creating a dummy extended class:
Lets assume your imported jar has this pattern, app\proto-gen\1.0-SNAPSHOT\proto-gen-1.0-SNAPSHOT.jar
Add the below to application.properties,
quarkus.index-dependency.mygrpc.group-id=app
quarkus.index-dependency.mygrpc.artifact-id=proto-gen
#Singleton
MyGrpc extends XImplBase{
//your implementation
}
beans you extended/implemented in your current project will be started.
Check https://quarkus.io/guides/cdi-reference. You need to add a beans.xml to external models, create an index or reference the dependency using quarkus.index-dependency in the application.properties.
Then it will work when running tests or using the runner. But not in dev, because there is a probably in the current version (1.1.1Final). This problem has been fixed in the master, though, and will be available in the next release next month.
Please check ClassCastException in Quarkus multi-module project for more details.

Best way to run spring boot 2 rest services

I am writing an app that exposes some functions via REST service.
To do this I am using Spring Boot 2, but what is the best way to put it on production environment?
Is a good idea run the jar using java?
Short answer
yes it is a good idea.
Long answer
Spring Boot features a plugin that prepends a service script (Unix-compatible) in the JAR file itself. That makes the JAR file executable in Unix/Linux environments and you can easily install it as a service. Excerpt from https://docs.spring.io/spring-boot/docs/current/reference/html/deployment-install.html follows:
To create a "fully executable" jar with Maven, use the following plugin configuration:
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
</configuration>
</plugin>
</plugins>
If packaging for Windows, the startup script isn't of much use and can be omitted. You would need to run using java -jar ... on windows, or install a service wrapper. Another excerpt from the Spring Boot doco:
A Spring Boot application can be started as a Windows service by using winsw.
A (separately maintained sample) describes step-by-step how you can create a Windows service for your Spring Boot application.
You can make it fully executable with below code in your pom.xml. You can run with shell script or as systemv or initd service[Spring Boot DOC]. This is the best tutorial link I have found explaining the multiple run as service options. You might want to take a look at spring doc for production ready features.
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
</configuration>
</plugin>
</plugins>
</build>

Required to create Maven plugin or 'some kind of wrapper' or should I use a parent pom

We are using the frontend-maven-plugin in several (10+) projects.
These projects are build in combination with our own CMS. These projects are using a specific 'parent' in the pom, such as:
<parent>
<groupId>nl.companyname</groupId>
<artifactId>companyname-corporate-pom</artifactId>
<version>2.0.13</version>
</parent>
In this 'corporate pom', we have some predefined configuration and 'plugin management', such as:
<project.frontendmavenplugin.version>1.3</project.frontendmavenplugin.version>
<project.frontendmavenplugin.workingDirectory>./</project.frontendmavenplugin.workingDirectory>
<project.node.downloadRoot>http://nodejs.COMPANYURL.nl/dist/</project.node.downloadRoot>
<project.node.version>v6.9.1</project.node.version>
<project.yarn.version>v0.17.9</project.yarn.version>
<project.yarn.downloadRoot>http://yarnpkg.COMPANYURL.nl/</project.yarn.downloadRoot>
<project.npm.registryUrl>http://nexus.COMPANYURL.nl/content/groups/npm-all/</project.npm.registryUrl>
and
<build>
<pluginManagement>
<!-- Generic configuration for plugins used by (almost) all projects. -->
<plugins>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>${project.frontendmavenplugin.version}</version>
<executions>
<execution>
<id>install node and yarn</id>
<goals>
<goal>install-node-and-yarn</goal>
</goals>
<phase>generate-resources</phase>
<configuration>
<workingDirectory>${project.frontendmavenplugin.workingDirectory}</workingDirectory>
<nodeVersion>${project.node.version}</nodeVersion>
<nodeDownloadRoot>${project.node.downloadRoot}</nodeDownloadRoot>
<yarnVersion>${project.yarn.version}</yarnVersion>
<yarnDownloadRoot>${project.yarn.downloadRoot}</yarnDownloadRoot>
</configuration>
</execution>
etc.
This way we don't have to copy/manage all configuration in each project.
This works great.
But: we are now also creating more and more new applications (based on Spring Boot) which are independent from our CMS and where we cannot use this 'parent pom' because Spring Boot has it's own (spring-boot-starter-parent) and our 'corporate pom' also contains very specific plugins / configuration which only applies to our CMS (which we are not including in these Spring Boot projects).
So what I need is something more 'standalone' for the frontend-maven-plugin configuration (and maybe in the future more 'platform' independent config/plugins). As far as I know, it's not possible to have more then 1 parent, so are there any other options?
I thought of creating a new 'companyname-frontend-maven-plugin' which both contains the PluginManagement as all the (extendable) configuration for the Frontend Maven Plugin. But I don't know if this will work and also it's a lot of work creating and maintaining this in git / Jenkins etc.
Are there any other options I could look in to?
Thank you all for your time!
maybe you can use a profile.
You can create a "corporate" pom that inherit from spring-boot-starter-parent and that contains a maven profile with all the properties and plugins required by your cms. So, when you are working on the CMS you will enable the "cms-profile".
Kind regards.

TypeNotPresentExceptionProxy error at integration-test with maven-failsafe-plugin spring-boot 1.4

I'm getting ArrayStoreException: TypeNotPresentExceptionProxy when running integration-test with maven-failsafe-plugin and spring-boot 1.4.
You can see this error if you run joinfaces-example with
mvn -Pattach-integration-test clean install
I realized that the error does not occur if I change spring-boot-maven-plugin to run at pre-integration-test phase instead of package one.
More, this error started when I upgraded spring boot to 1.4. No error occurs if I change jsf-spring-boot-parent version to 2.0.0 which uses spring boot 1.3 version.
I actually found the answer in Spring Boot 1.4 release notes, short answer is that maven-failsafe-plugin is not compatible with Spring Boot 1.4's new executable layout. Full explanation below :
As of Failsafe 2.19, target/classes is no longer on the classpath and
the project’s built jar is used instead. The plugin won’t be able to
find your classes due to the change in the executable jar layout.
There are two ways to work around this issue:
Downgrade to 2.18.1 so that you use target/classes instead
Configure the spring-boot-maven-plugin to use a classifier for the
repackage goal. That way, the original jar will be available and used
by the plugin. For example :
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<classifier>exec</classifier>
</configuration>
</plugin>
An alternative is documented here: https://github.com/spring-projects/spring-boot/issues/6254
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<!--
Make failsafe and spring-boot repackage play nice together,
see https://github.com/spring-projects/spring-boot/issues/6254
-->
<configuration>
<classesDirectory>${project.build.outputDirectory}</classesDirectory>
</configuration>
</plugin>
This worked better for me, because when I used the "exec" solution, Spring failed to find my configuration files when starting the container. Which could probably be fixed by adding some further configuration parameters, I suppose, but this solution works "out of the box" for me.

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>

Resources