The Spring team has released the Spring Native Beta. With Spring Native, Spring applications have the opportunity to run as a Native image of GraalVM. To better support Native running, Spring Native provides Maven and Gradle plugins, as well as annotations to optimize the Native configuration.

Spring released a beta version of Spring Native and ran it on start.spring. IO.

In practice, this means that since Spring was founded, we will be adding Beta support to compile Spring applications into native images using GraalVM, in addition to the regular Spring-supported Java virtual machines, providing a new way to deploy Spring applications. Support for Java and Kotlin.

These native Spring applications can be deployed as standalone executables (no JVM installed) and offer interesting features, including almost instant startup (typically <100ms), instant peak performance, and lower memory consumption, but require fewer build times and runtime optimizations than JVMS.

Using the simple MVN spring-boot:build-image or gradle bootBuildImage commands, you can generate an optimized container image that will contain a minimal OS layer and a small native executable that comes with only the JDK, Spring and the required bits in the dependencies you use in your application. See the example below for a minimal container image of a 50MB executable containing Spring Boot, Spring MVC, Jackson, Tomcat, JDK, and applications.

This native approach has value for Spring applications in a number of scenarios:

  • Serverless with Spring Cloud capabilities
  • Hosting Spring microservices in a cheaper and more sustainable way
  • Ideal for VMware Tanzu and other Kubernetes platforms
  • You want to create the best container image to package your Spring applications and services

In terms of usage scenarios, Piotr Mińkowski, for example, provides a great guide on how to build native microservices on Knative using Spring Boot and GraalVM.

1. Team work

The Spring Native Beta is the result of extensive collaboration across the Spring team and its family of projects: Spring Framework, Spring Boot also includes Spring Data, Spring Security, Spring Cloud, and Spring Initializr.

Native features are understood to work on a much wider scale than Spring because they involve a much wider JVM ecosystem, so officials have been working with the GraalVM team to improve native mirroring compatibility and resource consumption.

Here’s Vojin Jovanovic from GraalVM team.

“It’s been a pleasure working with the Spring team to build a native JVM ecosystem: their deep technical knowledge, combined with their community sensibility, always leads to the best solution. The latest release of Spring Native, along with its many uses in the JVM ecosystem, paves the way for widespread adoption of Native compilation.”

2. Scope of support

As Spring Native moves from alpha to beta, I think it’s important to figure out the scope of support we offer.

Alpha was the first step, and we experimented extensively and refined the Architecture, compatibility, and packaging of Spring Native (formerly Known as Spring GraalVM Native) with significant changes to a series of samples. We also reported on a number of issues fixed by the GraalVM team to close the gap between the JVM and the native Spring application.

While still considered experimental, beta means Spring now offers native support for a subset of the Spring ecosystem. If your project is using supported dependencies, you can try it on your project; If a problem occurs, an error is raised or a request is made. A new version of Spring Native appears with each patch release of the latest version of Spring Boot 2.x minor. Spring Native 0.9.0 supports Spring Boot 2.4.3, Spring Native 0.9.1 supports Spring Boot 2.4.4, and so on. There will be some significant changes, but we will document the migration path. Documentation quality reached a new level: reference documents were available as HTML single pages or PDFS, and we released the Javadoc public API for native hints.

3.start.spring.io

Stephane Nicoll introduced Spring Native support in his integration with start.spring. IO and related ides, so this is now the easiest way to explore how to build Native applications using Spring.

Adding Spring Native dependencies automatically configures Maven or Gradle projects with the required dependencies and plug-ins to support Native. The application code itself has not changed.

Check the auto-generated help.md file, which contains useful links and documentation, and also flags if you have selected dependencies that are not supported in the native environment.

4. Switch ahead

Native differs from the JVM: the classpath is fixed at build time, requiring reflection or resource configuration for example, there is no class lazy loading (everything that comes with the executable is loaded into memory at startup), and some code can be called at build time.

To take advantage of these features and allow Spring applications to run with maximum compatibility and minimal footprint on the local machine, Brian Clozel has introduced Spring Ahead (AOT) Maven and Gradle plug-ins in this release, which can perform transformations on your applications ahead of time.

The first transformation aims to generate GraalVM native configurations (reflection, resources, proxies, native image options) based on an inference engine designed and implemented by the amazing Andy Clement that understands what the Spring programming model and infrastructure are. For example, for each annotated class @controller, an entry will be added to the generated reflect-config.json file.

In cases where Native configurations cannot be inferred, we have introduced Native hint annotations (see Javadoc for more details), which make Spring Native more maintenable and type-safe and flexible to support Native configurations than regular JSON-based Native image configurations. Json, resource-config.json, and native-image.properties as follows:

@NativeHint(
    trigger = Driver.class,
    options = "--enable-all-security-services",
    types = @TypeHint(types = {
       FailoverConnectionUrl.class,
       FailoverDnsSrvConnectionUrl.class,
       // ...
    }), resources = {
	@ResourceHint(patterns = "com/mysql/cj/TlsSettings.properties"),
	@ResourceHint(patterns = "com.mysql.cj.LocalizedErrorMessages",
                      isBundle = true)
})
public class MySqlHints implements NativeConfiguration {}

Copy the code

NativeConfiguration and other dynamic configuration mechanisms allow more powerful and dynamic configuration generation, but be aware that their apis will evolve considerably in upcoming releases.

Spring developers can also directly annotate their @Configuration or @SpringBootApplication classes with native application-specific prompts, for example, Book serializes the class to JSON WebClient via a programming API such as RestTemplate or:

@TypeHint(types = Book.class)
@SpringBootApplication
public class WebClientApplication {
    // ...
}
Copy the code

The last and perhaps most powerful mechanism, when used with a forward-conversion system, is the closed-world assumption introduced using the Spring Boot deployment model in conjunction with GraalVM Native’s ability to automatically generate native optimized code (source code and bytecode). Image features. The goal here is to limit the number of additional native configurations required to improve compatibility by using code constructs that the native image compiler can analyze out of the box, and to reduce footprint, resources, or agents by reducing the number of configurations required for reflection. A concrete example is various forms of pre-conversion spring.factories (the extension mechanism behind Spring Boot) to an optimized version of the program design that does not require reflection and can filter out unnecessary entries in the context of the application.

This is just the beginning of Spring AOT, and we intend to add more powerful transformations to the [@Configuration feature Configuration to replace runtime reflection with a pre-analysis that automatically generates Configuration classes, These configuration classes will use programmatic constructs such as lambdas and method references. This will enable GraalVM’s native image compiler to instantly learn about Spring configuration without any reflection configuration or *.class resources.

One key point to keep in mind is that aoT-generated code is also used on the JVM by default when using Spring Native, allowing you to exercise “native-friendly code paths” using the short feedback loops allowed by the JVM. Your debugger and all the usual tools.

Although Spring AOT transformations are currently driven primarily by native requirements, many of them are not native-specific, and perhaps some of them can provide optimizations to run Spring Boot applications on the JVM. As with such topics, it is important to be data-driven so that we measure efficiency and performance to determine our decisions.

We may improve IDE integration, but now make sure you read the documentation for potential manual configuration steps to update the generated source code before running the application in the IDE.

5 conclusion

The Spring strategy to localize has two main pillars. The first is to adapt the Spring infrastructure to native use without major changes to millions of existing Spring Boot applications. These include the changes we made in the Spring top-level project to make it native-friendly, @nativeHint we will build plug-ins on mature infrastructure in Spring Native (for example) and Spring AOT.

The second pillar is broader than Spring itself, native is a platform with different features than the JVM, but the Java ecosystem needs to be as consistent as possible to avoid two very different Java styles that would be difficult to maintain. That’s why we’re working in depth with the GraalVM team to close this gap. In the coming months, this collaboration will focus on improving native testing and native configuration for the broader JVM ecosystem.

Source: spring. IO/blog / 2021/0…