Native Image with Spring Boot 3.0.0 logging trouble - java

When I start native Image of Spring Boot 3.0.0 spring-boot-starter-web with Docker, it shows strange log messages like this:
:: Spring Boot :: (v3.0.0)
%PARSER_ERROR[d] %PARSER_ERROR[p] 1 --- [%PARSER_ERROR[t]] %PARSER_ERROR[logger] : %PARSER_ERROR[m]%PARSER_ERROR[n]%PARSER_ERROR[d] %PARSER_ERROR[p] 1 --- [%PARSER_ERROR[t]] %PARSER_ERROR[logger] : %PARSER_ERROR[m]%PARSER_ERROR[n]%PARSER_ERROR[d] %PARSER_ERROR[p] 1 ---
Before I tried dependency spring-boot-starter-webflux in this case the build of the native image failed with error:
com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: No instances of ch.qos.logback.classic.Logger are allowed in the image heap
With Spring Initializr I generated a new project:
Maven
Java 17
Spring Boot version 3.0.0
Jar
Dependencies: spring-boot-starter-web & lombok
Then I build native Image with Maven "mvn -p native spring-boot:build-image".
I had the expectation, that native Images just work with the new Spring release for simple configuration like the one I made here. Am I missing something or has Spring Boot 3.0.0 big issues in supporting native Images?

At the time when I asked this question, Spring Initializr did not offer (plugin-)dependency "GraalVM Native Support" for Spring Boot 3.0.0.
Now this dependency is available. As confirmed at SpringOne event, it has to be used. After adding it the mentioned errors do not appear. The minimal required part in Maven config is this:
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
</plugin>

You need to make sure you add reachability of metadata goal in your build plugin see github issue
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<configuration>
<classesDirectory>${project.build.outputDirectory}</classesDirectory>
<metadataRepository>
<enabled>true</enabled>
</metadataRepository>
<requiredVersion>22.3</requiredVersion>
</configuration>
<executions>
<execution>
<id>add-reachability-metadata</id>
<goals>
<goal>add-reachability-metadata</goal>
</goals>
</execution>
</executions>
</plugin>

Related

How can I specify java interfaces file names using openapi.yaml and swagger-codegen-maven-plugin

I'm trying to generate 2 controller classes for 2 scopes in my project.
I can do that with 2 separate openapi.yaml files, and 2 maven executions.
I'm using swagger-codegen-maven-plugin to get it done, and I could only find code that uses swagger.yaml or openapi.yaml with a different plugin.
I can't find this combination, though I'm positive it's possible.
The question is if I have 2 scopes such as 'DB' and 'Browse', and I want to have 2 interfaces created for the 2 scopes such as DBApi.java and BrowseApi.java, how can it be done, and if it can be done using 1 openapi.yaml file?
I did see example projects where 1 openapi.yaml file resulted in PetApi.java and StoreApi.java, but I couldn't find how to configure this in my setup.
Thanks.
The relevant part in the maven pom file is:
<groupId>io.swagger.codegen.v3</groupId>
<artifactId>swagger-codegen-maven-plugin</artifactId>
<executions>
<execution>
<id>raptor-codegen</id>
<configuration>
<apiPackage>com.app.seo.graph.rest.v1.api</apiPackage>
<modelPackage>com.app.seo.graph.rest.v1.model</modelPackage>
<inputSpec>${project.basedir}/src/main/resources/api/openapi.yaml</inputSpec>
<configOptions>
<dateLibrary>java8</dateLibrary>
<additional-properties>preAuthorize=hasAuthority,useJsonPropertyOrder=true,resourceMetaType=com.ebay.jaxrs.server.ResourceOperation</additional-properties>
</configOptions>
</configuration>
</execution>
</executions>
</plugin>
I've used <useTags>true</useTags> under <configOptions> in my Maven file and it works for me. YAML definition
paths:
'/operation/':
get:
tags:
- Some-Service
generates "SomeServiceApi" class name with the SpringCodegen generator. Using "openapi-generator-maven-plugin" in the "6.2.0" version.

How to integrate an Angular 4 app with a Spring Boot stack?

i would like to integrate an Angular 4 client app with a Java Spring application working on http://localhost:8080/ and offering some Rest endpoints.
My goal is to be able to call the Angular app from a url like http://localhost:8080/adminisitration. How can I do that?
Thanks in advance,
You would need to prod build your ng app and place that in spring-boot folder:
Create a public folder under resources in your spring-boot project
ng build --prod, type this command on you angular project which will create a dist folder under your angular project directory
Copy files from you dist folder and place it in public folder under resources of your spring-boot project.
This will help you run your angular-app under spring-boot.
Then hit http://localhost:8080/adminisitration, it should work fine
There are two ways first is that you serve angular app from your spring boot application as static resources so you need to pack it into jar and that's not easy when you have two different repositories for frontend and backend and doesn't look to good from maintenance point of view.
Second is that you have angular static resources on nginx and spring boot app is reachable to angular thru reverse proxy configured on nginx like
location /api/ {
proxy_pass http://localhost:8080/api/;
}
So when angular asks for GET http://localhost/api/somerest it forwards it to GET http://localhost:8080/api/somerest
The easiest way to serve an angular front-end from a spring-boot application , is to have a multi-module project. Then automate the build process to copy the dist folder from the ui module into the service module during maven clean install itself.This way, you could have a single executable jar that serves the angular as well.For instance, consider the following project structure :
SampleMultiModuleProject
|__SampleMultiModuleService
|__SampleMultiModuleUI
In this case, you will have three different pom files like as follows.
SampleMultiModuleProject main pom.xml : (where all main dependencies are present)
<modules>
<module>SampleMultiModuleUI</module>
<module>SampleMultiModuleService</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/>
</parent>
//add rest of the dependencies here.
SampleMultiModuleService service pom.xml : (for service module and add the springboot maven plugin to make it executable with embedded tomcat, and add other dependencies that are needed in service module , for instance lombok)
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
and finally configure the ui module to build angular like SampleMultiModuleUI pom.xml :
<build>
<plugins>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>1.9.1</version>
<configuration>
<workingDirectory>./</workingDirectory>
<nodeVersion>v13.3.0</nodeVersion>
<npmVersion>6.13.1</npmVersion>
<nodeDownloadRoot>http://nodejs.org/dist/</nodeDownloadRoot>
<npmDownloadRoot>http://registry.npmjs.org/npm/-/</npmDownloadRoot>
<installDirectory>./</installDirectory>
<npmInheritsProxyConfigFromMaven>false</npmInheritsProxyConfigFromMaven>
</configuration>
<executions>
<execution>
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
<phase>generate-resources</phase>
</execution>
<execution>
<id>npm install</id>
<goals>
<goal>npm</goal>
</goals>
<phase>generate-resources</phase>
<configuration>
<arguments>install</arguments>
</configuration>
</execution>
<execution>
<id>npm run-script build-prod</id>
<phase>prepare-package</phase>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>run-script build</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
So what happens is when you do maven clean install, it will trigger the build of the ui module which in turn uses the frontend builder to install a local npm which runs the command specified in the arguments. The package.json file in your angular application will by default contain something like :
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build --prod",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
"stats": "webpack-bundle-analyzer dist/stats.json"
},
So you are essentially calling this ng build --prod through this process.Also in angular.json set the output path as the resources folder under the service module in your project, so that the assets will be created there.
"newProjectRoot": "projects",
"projects": {
"SampleMultiModuleUI": {
"projectType": "application",
"schematics": {},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "#angular-devkit/build-angular:browser",
"options": {
"outputPath": "../SampleMultiModuleService/src/main/resources/static",
//rest of the config
as i understand your question just create new file named proxy.config.json and paste below code in that file, place file next to .angular-cli.json
{
"/": {
"target": "http://localhost:8080",
"secure": false,
"logLevel": "debug"
}
}
for hitting url to backend server don't use http://localhost:8080/administration instead use /administration as we use http://localhost:8080/ in our proxy file.
in app.component.ts file place below code in ngOnInit()
this.http.get('/adminisitration',someRequestOption).subscribe(res =>{
console.log('happy...!');
})
start backend server: (tomcat on port 8080) and
start frontend server:
ng serve --proxy-config proxy.config.json open browser and type url http://localhost:4200 you will see logs on server and client if any.
NOTE:
above ports are default as provided by spring boot and angular 4
I think best way is to separate angular 4 app and java spring app.
In my case java spring app is API handling all requests from angular 4 app via proxy (angular-cli proxy -> easy to configure).
Angular 4 app on node.js, developed in visual studio code, and java spring on embedded tomcat (undertow) developed in eclipse. They can be on separated servers (eg. my angular 4 app is on localhost:4200 while java spring API is on http://mydomain.ch:8900)
If you need more info then add comment.
Hope in helps
PS. proxy is handled on client side (angular 4 app) not on server side (java spring)

How to debug Spring Boot with Netbeans via Maven

After fiddling around for way too long till I got proper debuging setup in Netbeans 8.2 with Spring Boot 1.4.3 I figured I write down my findings as Q&A for others.
The problem is that the default configuration for Netbeans fails to properly launch Spring in debug mode and when you search the internet you only find the outdated information in the Spring docs that won't work.
The solution is simple if you know how. Please find the correct setup instructions below.
Tested and works with Netbeans 8.2 and Spring-Boot 1.4.3:
First of all make sure you have the Spring Maven plugin included (this should be already included when making a new Netbeans Spring project):
<plugins>
...
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
...
</plugins>
Also it is a good idea to include the Spring Devtools like this:
<dependencies>
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
...
</dependencies>
Now navigate to your project settings -> Actions -> Debug project and set the following:
Execute goals:
spring-boot:run
Set properties:
run.jvmArguments=-Xdebug -Xrunjdwp:transport=dt_socket,server=n,address=${jpda.address}
jpda.listen=true
Now run your application via the usual debug button and Spring should properly connect to the JVM debugger.
Spring Boot 2.x
To enable Netbeans debugging for a Spring Boot 2.x project (and more specifically version 2.x of the spring-boot-maven-plugin) the procedure is exactly the same, except the run.jvmArguments property name has changed to spring-boot.run.jvmArguments:
spring-boot.run.jvmArguments=-Xdebug -Xrunjdwp:transport=dt_socket,server=n,address=${jpda.address}
jpda.listen=true
Testing NetBeans 8.2 and Spring Boot 2.0.1, I was not able to make things work following #TwoThe's instructions. First, I encountered an issue where all I saw was "JPDA Listening Start..." in the output window. To resolve that problem, I added Spring Devtools as an optional dependency. Second, even though debugging appeared to be running okay, the "Debugging" window, which normally displays the list of active threads, was empty and breakpoints that I set were not triggered. Third, attempting to stop the debugging session by pressing the red "Finish Debugger Session" button would not stop the Tomcat server.
Instead of changing the execute goals to "spring-boot:run", I found that it was sufficient to use the default "Debug project" action execute goals:
process-classes org.codehaus.mojo:exec-maven-plugin:1.2.1:exec
.. and properties:
exec.args=-Xdebug -Xrunjdwp:transport=dt_socket,server=n,address=${jpda.address} -classpath %classpath ${packageClassName}
exec.executable=java
jpda.listen=true
(As a sidenote, debugging as a regular Java application is apparently the recommended approach to debugging Spring Boot applications in Eclipse; see How to debug Spring Boot application with Eclipse?)
One helpful tip is that if you want to debug using a certain Spring Boot profile, say "debug", you can prepend "-Dspring.profiles.active=debug " to the "exec.args" property. See also: Spring boot running a fully executable JAR and specify -D properties
Tested on NetBeans9
Action: Add any name
Set Properties: select Add> button, select Debug Maven Build
And debug as always -> IDE debug button
If you are still having the problem after applying all above mentioned fixes, remove all your breakpoints and try again.
Window -> Debugging -> Breakpoints -> Delete All Breakpoints
POW
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
buld
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
Debug Project
Excute Goals : package
Set Properties:netbeans.deploy.debugmode=true netbeans.deploy=true
Change
Excute Goals : spring-boot:run
Set Properties: spring-boot.run.jvmArguments=-Xdebug -Xrunjdwp:transport=dt_socket,server=n,address=${jpda.address}
jpda.listen=true
and Netbeans Press debug project -- not navigator--> spring-boo-run ... What was the difference? spring-boot.run.jvmArguments:

tell grails maven plugin to use servlet 2.5 instead of 3.0

I might have a stupid and really obvious question:
I basically have a grails 2.3.8 project, build using maven 3.2, with the grails maven plugin 2.4.3
<plugin>
<groupId>org.grails</groupId>
<artifactId>grails-maven-plugin</artifactId>
<version>2.4.3</version>
<configuration>
<!-- Whether for Fork a JVM to run Grails commands -->
<fork>true</fork>
<grailsVersion>${grails.version}</grailsVersion>
</configuration>
<extensions>true</extensions>
</plugin>
when I do a
mvn clean install
I keep getting the following exception:
java.lang.NoClassDefFoundError: javax/servlet/AsyncContext
at java.lang.Class.privateGetDeclaredMethods(Class.java:2484)
at java.lang.Class.getDeclaredMethods(Class.java:1827)
at org.codehaus.groovy.util.LazyReference.getLocked(LazyReference.java:46)
my BuildConfig specifies grails to utilize, servlet 2.5
grails.servlet.version = "2.5"
and all my test's are working fine, if I run them from grails directly using:
grails test-app :integration
but fail with the given exception, if I run them from the command line
mvn clean install
my dependency report lists the correct servlet version:
javax.servlet:servlet-api:jar:2.5:provided
anybody has an idea how to solve this?
thanks

Getting application version from pom

I have a rest endpoint used to return information about application (so far only app version)
But so far this info is hardcoded, and it's pretty easy to forget to change it.
I will be better to retrieve app version from pom or manifest file. Is there any project that brings such functionality?
Spring Boot can refer to the project version defined in pom.xml and expose it via REST using Actuator:
# application.properties
endpoints.info.enabled=true
info.app.version=#project.version#
Then accessing the /info URL (e.g. http://localhost:8080/info) will return:
{"app": {"version": "<major.minor.incremental>"}}
See also: spring boot/spring web app embedded version number
You better use build-in manifest.
new Manifest(Application.class.getResourceAsStream("/META-INF/manifest.mf"))
For the concrete impl-version:
new Manifest(Application.class.getResourceAsStream("/META-INF/manifest.mf"))
.getMainAttributes()
.get(Attributes.Name.IMPLEMENTATION_VERSION)
Using maven do not forget to create the manifest using:
<?xml version="1.0" encoding="UTF-8"?>
<project>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
There is amazing project named Appinfo, please use it and enjoy! (It has an ugly page, I know - but it works :)
AppInfo allows to automatically feed your application with a current version number, build date or build number.
Also excellent Spring Boot Actuator provides feature named Info Endpoint which can publish version information to web or REST.
By default the Actuator adds an /info endpoint to the main server. It contains the commit and timestamp information from git.properties (if that file exists) and also any properties it finds in the environment with prefix "info".
You could use the resource filtering of maven or something like the maven-substitute-plugin.

Categories

Resources