spring-native-examples
spring-native-examples copied to clipboard
JHipster Works with Spring Native!
= Spring Native with JHipster
https://www.youtube.com/watch?v=f0yrxKRU-ME[Watch the presentation from the Garden State JUG]
For Josh's examples, see his https://github.com/spring-tips/spring-native-011x[Spring Native 0.11.x repo].
This repository contains five apps we (https://github.com/joshlong[@joshlong] and https://github.com/mraible[@mraible]) used to figure out how to make Spring Native work with JHipster.
-
spring-native-webflux
- no client, no db, just WebFlux -
spring-native-mvc
- no client, no db, just Spring MVC -
angular-webflux
- Angular client, no db -
postgres-webflux
- Angular, WebFlux, R2DBC + PostgreSQL -
postgres-mvc
- Angular, Spring MVC, JPA + PostgreSQL
If you already have a JHipster app with OIDC, you can make the changes below to make it work with Spring Native.
==== ⚡️ You can also use the https://github.com/jhipster/generator-jhipster-native[JHipster Native blueprint] to generate an app with all of these changes already included!
. Modify pom.xml
to add Spring Native support:
+
[source,xml]
<repackage.classifier/> <spring-native.version>0.11.3</spring-native.version> ...
. Delete src/main/resources/logback-spring.xml
and tone down logging. Remove src/test/resources/logback.xml
too.
+
[source,yaml]
logging: level: root: ERROR io.netty: ERROR liquibase: ERROR org.hibernate: ERROR org.springframework: ERROR com.zaxxer.hikari: ERROR org.apache.catalina: ERROR org.apache.tomcat: ERROR tech.jhipster.config: ERROR jdk.event.security: ERROR java.net: ERROR sun.net.www: ERROR
. There's an issue when using Spring WebFlux if you don't use -DskipTests
when running ./mvnw package -Pnative
:
+
[ERROR] Failed to execute goal org.springframework.experimental:spring-aot-maven-plugin:0.11.2:test-generate (test-generate) on project jhipster: Build failed during Spring AOT test code generation: Unable to execute mojo: Unable to parse configuration of mojo org.apache.maven.plugins:maven-compiler-plugin:3.9.0:testCompile for parameter compilePath: Cannot find 'compilePath' in class org.apache.maven.plugin.compiler.TestCompilerMojo -> [Help 1] [ERROR]
The error seems to be better when using Spring MVC: +
Caused by: java.lang.IllegalStateException: @MockBean is not supported yet by Spring AOT and has been detected on type org.springframework.web.client.RestTemplate
. If using Spring MVC, swap Undertow dependencies for Tomcat (in pom.xml
) and modify WebConfigurer
to comment out setLocationForStaticAssets(server)
.
. Update main App.java
to add hints for Micrometer:
+
[source,java]
import org.springframework.nativex.hint.TypeHint;
@TypeHint( types = { org.HdrHistogram.Histogram.class, org.HdrHistogram.ConcurrentHistogram.class })
. Add springdocs native dependency: + [source,xml]
. Liquibase is https://github.com/spring-projects-experimental/spring-native/issues/620[not supported yet], but you can make it work by adding files from https://github.com/liquibase/liquibase/pull/2005[this pull request] to your src/main/resources/META-INF/native-image/liquibase
directory.
. Add type hints for Liquibase and related classes. + [source,java]
@TypeHint( types = { ... liquibase.configuration.LiquibaseConfiguration.class, com.zaxxer.hikari.HikariDataSource.class, liquibase.change.core.LoadDataColumnConfig.class, tech.jhipster.domain.util.FixedPostgreSQL10Dialect.class, org.hibernate.type.TextType.class, })
. If you're using JPA, add a type hint for java.util.HashSet.class
and turn off loading of SQL in application.yml
so Liquibase works:
+
[source,yaml]
spring: ... sql: init: mode: never
Without this change, the following error happens: +
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSourceScriptDatabaseInitializer': Circular depends-on relationship between 'dataSourceScriptDatabaseInitializer' and 'liquibase'
. If you're using Spring WebFlux with R2DBC, you'll need to add @Component
to your Impl classes and add SimpleR2dbcRepository
to your type hints and com.zaxxer.hikari.util.ConcurrentBag$IConcurrentBagEntry[]
as a typeName for Liquibase.
+
@TypeHint(types = { ... org.springframework.data.r2dbc.repository.support.SimpleR2dbcRepository.class }, typeNames = "com.zaxxer.hikari.util.ConcurrentBag$IConcurrentBagEntry[]")
. If Spring MVC, add names to any @RequestParam
and @PathVariable
annotations.
+
[source,java]
@RequestParam(name = "eagerload", required = false, defaultValue = "false") boolean eagerload @PathVariable("id") Long id
. For logout to work, update LogoutResource
to remove (expression = "idToken")
, inject the OidcUser
instead, and get the token from there:
+
[source,java]
public ResponseEntity<?> logout(HttpServletRequest request, @AuthenticationPrincipal OidcUser oidcUser) { ... OidcIdToken idToken = oidcUser.getIdToken();
. Caching is https://github.com/spring-projects-experimental/spring-native/issues/465[not supported yet]. The only workaround I've found so far is to re-generate your app with "cacheProvider": "no"
in your .yo-rc.json
.
. Build with ./mvnw package -Pnative,prod -DskipTests
== Known Issues
-
-DskipTests
is needed for both Spring MVC and WebFlux. This seems to be caused by Mockito. - Several of JHipster's Administration features don't work: metrics, logs, and configuration.
- Metrics:
UnsupportedFeatureError: ThreadMXBean methods
- Logs:
/management/loggers
returns HTML instead of JSON - Configuration error:
org.springframework.http.converter.HttpMessageNotWritableException: No converter for [class org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint$ApplicationConfigurationProperties] with preset Content-Type 'null'
- H2 doesn't work if you build with the
dev
profile:
java.lang.IllegalStateException: Failed to process lifecycle methods on bean definition with name 'h2TCPServer'
I tried adding the following to the @TypeHint
in the main class, but it doesn't work.
+
[source,java]
typeNames = {"org.h2.tools.Server", "org.h2.server.web.WebServlet"}
This class is not on the classpath by default. Maybe that has something to do with it?