Reorganize packaging and optimizing documentation

Documentation for native executables, CDS, and checkpoint/restore are
now under a common heading in the reference documentation, along with
sections on building container images. A few sections containing
prescriptive workflows have been moved from reference to how-to guides.
This consolidates and improves the consistency of recommendations on
how to package and run applications.

Closes gh-40977
This commit is contained in:
Scott Frederick
2024-06-05 17:20:16 -05:00
parent 16302c18b2
commit 2df0c7961a
50 changed files with 393 additions and 381 deletions

View File

@@ -935,7 +935,7 @@ readinessProbe:
NOTE: `<actuator-port>` should be set to the port that the actuator endpoints are available on.
It could be the main web server port or a separate management port if the `"management.server.port"` property has been set.
These health groups are automatically enabled only if the application xref:deployment/cloud.adoc#deployment.cloud.kubernetes[runs in a Kubernetes environment].
These health groups are automatically enabled only if the application xref:how-to:deployment/cloud.adoc#howto.deployment.cloud.kubernetes[runs in a Kubernetes environment].
You can enable them in any environment by using the configprop:management.endpoint.health.probes.enabled[] configuration property.
NOTE: If an application takes longer to start than the configured liveness period, Kubernetes mentions the `"startupProbe"` as a possible solution.
@@ -1062,7 +1062,7 @@ When a Spring Boot application shuts down:
|The application context is closed and the application is shut down.
|===
TIP: See xref:deployment/cloud.adoc#deployment.cloud.kubernetes.container-lifecycle[Kubernetes container lifecycle section] for more information about Kubernetes deployment.
TIP: See xref:how-to:deployment/cloud.adoc#howto.deployment.cloud.kubernetes.container-lifecycle[Kubernetes container lifecycle section] for more information about Kubernetes deployment.

View File

@@ -1,4 +0,0 @@
[[container-images]]
= Container Images
Spring Boot applications can be containerized xref:container-images/dockerfiles.adoc[using Dockerfiles], or by xref:container-images/cloud-native-buildpacks.adoc[using Cloud Native Buildpacks to create optimized docker compatible container images that you can run anywhere].

View File

@@ -1,424 +0,0 @@
[[deployment.cloud]]
= Deploying to the Cloud
Spring Boot's executable jars are ready-made for most popular cloud PaaS (Platform-as-a-Service) providers.
These providers tend to require that you "`bring your own container`".
They manage application processes (not Java applications specifically), so they need an intermediary layer that adapts _your_ application to the _cloud's_ notion of a running process.
Two popular cloud providers, Heroku and Cloud Foundry, employ a "`buildpack`" approach.
The buildpack wraps your deployed code in whatever is needed to _start_ your application.
It might be a JDK and a call to `java`, an embedded web server, or a full-fledged application server.
A buildpack is pluggable, but ideally you should be able to get by with as few customizations to it as possible.
This reduces the footprint of functionality that is not under your control.
It minimizes divergence between development and production environments.
Ideally, your application, like a Spring Boot executable jar, has everything that it needs to run packaged within it.
In this section, we look at what it takes to get the xref:tutorial:first-application/index.adoc[application that we developed] in the "`Getting Started`" section up and running in the Cloud.
[[deployment.cloud.cloud-foundry]]
== Cloud Foundry
Cloud Foundry provides default buildpacks that come into play if no other buildpack is specified.
The Cloud Foundry https://github.com/cloudfoundry/java-buildpack[Java buildpack] has excellent support for Spring applications, including Spring Boot.
You can deploy stand-alone executable jar applications as well as traditional `.war` packaged applications.
Once you have built your application (by using, for example, `mvn clean package`) and have https://docs.cloudfoundry.org/cf-cli/install-go-cli.html[installed the `cf` command line tool], deploy your application by using the `cf push` command, substituting the path to your compiled `.jar`.
Be sure to have https://docs.cloudfoundry.org/cf-cli/getting-started.html#login[logged in with your `cf` command line client] before pushing an application.
The following line shows using the `cf push` command to deploy an application:
[source,shell]
----
$ cf push acloudyspringtime -p target/demo-0.0.1-SNAPSHOT.jar
----
NOTE: In the preceding example, we substitute `acloudyspringtime` for whatever value you give `cf` as the name of your application.
See the https://docs.cloudfoundry.org/cf-cli/getting-started.html#push[`cf push` documentation] for more options.
If there is a Cloud Foundry https://docs.cloudfoundry.org/devguide/deploy-apps/manifest.html[`manifest.yml`] file present in the same directory, it is considered.
At this point, `cf` starts uploading your application, producing output similar to the following example:
[source,subs="verbatim,quotes"]
----
Uploading acloudyspringtime... *OK*
Preparing to start acloudyspringtime... *OK*
-----> Downloaded app package (*8.9M*)
-----> Java Buildpack Version: v3.12 (offline) | https://github.com/cloudfoundry/java-buildpack.git#6f25b7e
-----> Downloading Open Jdk JRE
Expanding Open Jdk JRE to .java-buildpack/open_jdk_jre (1.6s)
-----> Downloading Open JDK Like Memory Calculator 2.0.2_RELEASE from https://java-buildpack.cloudfoundry.org/memory-calculator/trusty/x86_64/memory-calculator-2.0.2_RELEASE.tar.gz (found in cache)
Memory Settings: -Xss349K -Xmx681574K -XX:MaxMetaspaceSize=104857K -Xms681574K -XX:MetaspaceSize=104857K
-----> Downloading Container Certificate Trust Store 1.0.0_RELEASE from https://java-buildpack.cloudfoundry.org/container-certificate-trust-store/container-certificate-trust-store-1.0.0_RELEASE.jar (found in cache)
Adding certificates to .java-buildpack/container_certificate_trust_store/truststore.jks (0.6s)
-----> Downloading Spring Auto Reconfiguration 1.10.0_RELEASE from https://java-buildpack.cloudfoundry.org/auto-reconfiguration/auto-reconfiguration-1.10.0_RELEASE.jar (found in cache)
Checking status of app 'acloudyspringtime'...
0 of 1 instances running (1 starting)
...
0 of 1 instances running (1 starting)
...
0 of 1 instances running (1 starting)
...
1 of 1 instances running (1 running)
App started
----
Congratulations! The application is now live!
Once your application is live, you can verify the status of the deployed application by using the `cf apps` command, as shown in the following example:
[source,shell]
----
$ cf apps
Getting applications in ...
OK
name requested state instances memory disk urls
...
acloudyspringtime started 1/1 512M 1G acloudyspringtime.cfapps.io
...
----
Once Cloud Foundry acknowledges that your application has been deployed, you should be able to find the application at the URI given.
In the preceding example, you could find it at `\https://acloudyspringtime.cfapps.io/`.
[[deployment.cloud.cloud-foundry.binding-to-services]]
=== Binding to Services
By default, metadata about the running application as well as service connection information is exposed to the application as environment variables (for example: `$VCAP_SERVICES`).
This architecture decision is due to Cloud Foundry's polyglot (any language and platform can be supported as a buildpack) nature.
Process-scoped environment variables are language agnostic.
Environment variables do not always make for the easiest API, so Spring Boot automatically extracts them and flattens the data into properties that can be accessed through Spring's `Environment` abstraction, as shown in the following example:
include-code::MyBean[]
All Cloud Foundry properties are prefixed with `vcap`.
You can use `vcap` properties to access application information (such as the public URL of the application) and service information (such as database credentials).
See the xref:api:java/org/springframework/boot/cloud/CloudFoundryVcapEnvironmentPostProcessor.html[`CloudFoundryVcapEnvironmentPostProcessor`] Javadoc for complete details.
TIP: The https://github.com/pivotal-cf/java-cfenv/[Java CFEnv] project is a better fit for tasks such as configuring a DataSource.
[[deployment.cloud.kubernetes]]
== Kubernetes
Spring Boot auto-detects Kubernetes deployment environments by checking the environment for `"*_SERVICE_HOST"` and `"*_SERVICE_PORT"` variables.
You can override this detection with the configprop:spring.main.cloud-platform[] configuration property.
Spring Boot helps you to xref:features/spring-application.adoc#features.spring-application.application-availability[manage the state of your application] and export it with xref:actuator/endpoints.adoc#actuator.endpoints.kubernetes-probes[HTTP Kubernetes Probes using Actuator].
[[deployment.cloud.kubernetes.container-lifecycle]]
=== Kubernetes Container Lifecycle
When Kubernetes deletes an application instance, the shutdown process involves several subsystems concurrently: shutdown hooks, unregistering the service, removing the instance from the load-balancer...
Because this shutdown processing happens in parallel (and due to the nature of distributed systems), there is a window during which traffic can be routed to a pod that has also begun its shutdown processing.
You can configure a sleep execution in a preStop handler to avoid requests being routed to a pod that has already begun shutting down.
This sleep should be long enough for new requests to stop being routed to the pod and its duration will vary from deployment to deployment.
The preStop handler can be configured by using the PodSpec in the pod's configuration file as follows:
[source,yaml]
----
spec:
containers:
- name: "example-container"
image: "example-image"
lifecycle:
preStop:
exec:
command: ["sh", "-c", "sleep 10"]
----
Once the pre-stop hook has completed, SIGTERM will be sent to the container and xref:web/graceful-shutdown.adoc[graceful shutdown] will begin, allowing any remaining in-flight requests to complete.
NOTE: When Kubernetes sends a SIGTERM signal to the pod, it waits for a specified time called the termination grace period (the default for which is 30 seconds).
If the containers are still running after the grace period, they are sent the SIGKILL signal and forcibly removed.
If the pod takes longer than 30 seconds to shut down, which could be because you have increased configprop:spring.lifecycle.timeout-per-shutdown-phase[], make sure to increase the termination grace period by setting the `terminationGracePeriodSeconds` option in the Pod YAML.
[[deployment.cloud.heroku]]
== Heroku
Heroku is another popular PaaS platform.
To customize Heroku builds, you provide a `Procfile`, which provides the incantation required to deploy an application.
Heroku assigns a `port` for the Java application to use and then ensures that routing to the external URI works.
You must configure your application to listen on the correct port.
The following example shows the `Procfile` for our starter REST application:
[source]
----
web: java -Dserver.port=$PORT -jar target/demo-0.0.1-SNAPSHOT.jar
----
Spring Boot makes `-D` arguments available as properties accessible from a Spring `Environment` instance.
The `server.port` configuration property is fed to the embedded Tomcat, Jetty, or Undertow instance, which then uses the port when it starts up.
The `$PORT` environment variable is assigned to us by the Heroku PaaS.
This should be everything you need.
The most common deployment workflow for Heroku deployments is to `git push` the code to production, as shown in the following example:
[source,shell]
----
$ git push heroku main
----
Which will result in the following:
[source,subs="verbatim,quotes"]
----
Initializing repository, *done*.
Counting objects: 95, *done*.
Delta compression using up to 8 threads.
Compressing objects: 100% (78/78), *done*.
Writing objects: 100% (95/95), 8.66 MiB | 606.00 KiB/s, *done*.
Total 95 (delta 31), reused 0 (delta 0)
-----> Java app detected
-----> Installing OpenJDK... *done*
-----> Installing Maven... *done*
-----> Installing settings.xml... *done*
-----> Executing: mvn -B -DskipTests=true clean install
[INFO] Scanning for projects...
Downloading: https://repo.spring.io/...
Downloaded: https://repo.spring.io/... (818 B at 1.8 KB/sec)
....
Downloaded: https://s3pository.heroku.com/jvm/... (152 KB at 595.3 KB/sec)
[INFO] Installing /tmp/build_0c35a5d2-a067-4abc-a232-14b1fb7a8229/target/...
[INFO] Installing /tmp/build_0c35a5d2-a067-4abc-a232-14b1fb7a8229/pom.xml ...
[INFO] ------------------------------------------------------------------------
[INFO] *BUILD SUCCESS*
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 59.358s
[INFO] Finished at: Fri Mar 07 07:28:25 UTC 2014
[INFO] Final Memory: 20M/493M
[INFO] ------------------------------------------------------------------------
-----> Discovering process types
Procfile declares types -> *web*
-----> Compressing... *done*, 70.4MB
-----> Launching... *done*, v6
https://agile-sierra-1405.herokuapp.com/ *deployed to Heroku*
To git@heroku.com:agile-sierra-1405.git
* [new branch] main -> main
----
Your application should now be up and running on Heroku.
For more details, see https://devcenter.heroku.com/articles/deploying-spring-boot-apps-to-heroku[Deploying Spring Boot Applications to Heroku].
[[deployment.cloud.openshift]]
== OpenShift
https://www.openshift.com/[OpenShift] has many resources describing how to deploy Spring Boot applications, including:
* https://blog.openshift.com/using-openshift-enterprise-grade-spring-boot-deployments/[Using the S2I builder]
* https://access.redhat.com/documentation/en-us/reference_architectures/2017/html-single/spring_boot_microservices_on_red_hat_openshift_container_platform_3/[Architecture guide]
* https://blog.openshift.com/using-spring-boot-on-openshift/[Running as a traditional web application on Wildfly]
* https://blog.openshift.com/openshift-commons-briefing-96-cloud-native-applications-spring-rhoar/[OpenShift Commons Briefing]
[[deployment.cloud.aws]]
== Amazon Web Services (AWS)
Amazon Web Services offers multiple ways to install Spring Boot-based applications, either as traditional web applications (war) or as executable jar files with an embedded web server.
The options include:
* AWS Elastic Beanstalk
* AWS Code Deploy
* AWS OPS Works
* AWS Cloud Formation
* AWS Container Registry
Each has different features and pricing models.
In this document, we describe to approach using AWS Elastic Beanstalk.
[[deployment.cloud.aws.beanstalk]]
=== AWS Elastic Beanstalk
As described in the official https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create_deploy_Java.html[Elastic Beanstalk Java guide], there are two main options to deploy a Java application.
You can either use the "`Tomcat Platform`" or the "`Java SE platform`".
[[deployment.cloud.aws.beanstalk.tomcat-platform]]
==== Using the Tomcat Platform
This option applies to Spring Boot projects that produce a war file.
No special configuration is required.
You need only follow the official guide.
[[deployment.cloud.aws.beanstalk.java-se-platform]]
==== Using the Java SE Platform
This option applies to Spring Boot projects that produce a jar file and run an embedded web container.
Elastic Beanstalk environments run an nginx instance on port 80 to proxy the actual application, running on port 5000.
To configure it, add the following line to your `application.properties` file:
[configprops,yaml]
----
server:
port: 5000
----
[TIP]
.Upload binaries instead of sources
====
By default, Elastic Beanstalk uploads sources and compiles them in AWS.
However, it is best to upload the binaries instead.
To do so, add lines similar to the following to your `.elasticbeanstalk/config.yml` file:
[source,xml]
----
deploy:
artifact: target/demo-0.0.1-SNAPSHOT.jar
----
====
[TIP]
.Reduce costs by setting the environment type
====
By default an Elastic Beanstalk environment is load balanced.
The load balancer has a significant cost.
To avoid that cost, set the environment type to "`Single instance`", as described in https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/environments-create-wizard.html#environments-create-wizard-capacity[the Amazon documentation].
You can also create single instance environments by using the CLI and the following command:
[source]
----
eb create -s
----
====
[[deployment.cloud.aws.summary]]
=== Summary
This is one of the easiest ways to get to AWS, but there are more things to cover, such as how to integrate Elastic Beanstalk into any CI / CD tool, use the Elastic Beanstalk Maven plugin instead of the CLI, and others.
There is a https://exampledriven.wordpress.com/2017/01/09/spring-boot-aws-elastic-beanstalk-example/[blog post] covering these topics more in detail.
[[deployment.cloud.boxfuse]]
== CloudCaptain and Amazon Web Services
https://cloudcaptain.sh/[CloudCaptain] works by turning your Spring Boot executable jar or war into a minimal VM image that can be deployed unchanged either on VirtualBox or on AWS.
CloudCaptain comes with deep integration for Spring Boot and uses the information from your Spring Boot configuration file to automatically configure ports and health check URLs.
CloudCaptain leverages this information both for the images it produces as well as for all the resources it provisions (instances, security groups, elastic load balancers, and so on).
Once you have created a https://console.cloudcaptain.sh[CloudCaptain account], connected it to your AWS account, installed the latest version of the CloudCaptain Client, and ensured that the application has been built by Maven or Gradle (by using, for example, `mvn clean package`), you can deploy your Spring Boot application to AWS with a command similar to the following:
[source,shell]
----
$ boxfuse run myapp-1.0.jar -env=prod
----
See the https://cloudcaptain.sh/docs/commandline/run.html[`boxfuse run` documentation] for more options.
If there is a https://cloudcaptain.sh/docs/commandline/#configuration[`boxfuse.conf`] file present in the current directory, it is considered.
TIP: By default, CloudCaptain activates a Spring profile named `boxfuse` on startup.
If your executable jar or war contains an https://cloudcaptain.sh/docs/payloads/springboot.html#configuration[`application-boxfuse.properties`] file, CloudCaptain bases its configuration on the properties it contains.
At this point, CloudCaptain creates an image for your application, uploads it, and configures and starts the necessary resources on AWS, resulting in output similar to the following example:
[source]
----
Fusing Image for myapp-1.0.jar ...
Image fused in 00:06.838s (53937 K) -> axelfontaine/myapp:1.0
Creating axelfontaine/myapp ...
Pushing axelfontaine/myapp:1.0 ...
Verifying axelfontaine/myapp:1.0 ...
Creating Elastic IP ...
Mapping myapp-axelfontaine.boxfuse.io to 52.28.233.167 ...
Waiting for AWS to create an AMI for axelfontaine/myapp:1.0 in eu-central-1 (this may take up to 50 seconds) ...
AMI created in 00:23.557s -> ami-d23f38cf
Creating security group boxfuse-sg_axelfontaine/myapp:1.0 ...
Launching t2.micro instance of axelfontaine/myapp:1.0 (ami-d23f38cf) in eu-central-1 ...
Instance launched in 00:30.306s -> i-92ef9f53
Waiting for AWS to boot Instance i-92ef9f53 and Payload to start at https://52.28.235.61/ ...
Payload started in 00:29.266s -> https://52.28.235.61/
Remapping Elastic IP 52.28.233.167 to i-92ef9f53 ...
Waiting 15s for AWS to complete Elastic IP Zero Downtime transition ...
Deployment completed successfully. axelfontaine/myapp:1.0 is up and running at https://myapp-axelfontaine.boxfuse.io/
----
Your application should now be up and running on AWS.
See the blog post on https://cloudcaptain.sh/blog/spring-boot-ec2.html[deploying Spring Boot apps on EC2] as well as the https://cloudcaptain.sh/docs/payloads/springboot.html[documentation for the CloudCaptain Spring Boot integration] to get started with a Maven build to run the app.
[[deployment.cloud.azure]]
== Azure
This https://spring.io/guides/gs/spring-boot-for-azure/[Getting Started guide] walks you through deploying your Spring Boot application to either https://azure.microsoft.com/en-us/services/spring-cloud/[Azure Spring Cloud] or https://docs.microsoft.com/en-us/azure/app-service/overview[Azure App Service].
[[deployment.cloud.google]]
== Google Cloud
Google Cloud has several options that can be used to launch Spring Boot applications.
The easiest to get started with is probably App Engine, but you could also find ways to run Spring Boot in a container with Container Engine or on a virtual machine with Compute Engine.
To deploy your first app to App Engine standard environment, follow https://codelabs.developers.google.com/codelabs/cloud-app-engine-springboot#0[this tutorial].
Alternatively, App Engine Flex requires you to create an `app.yaml` file to describe the resources your app requires.
Normally, you put this file in `src/main/appengine`, and it should resemble the following file:
[source,yaml]
----
service: "default"
runtime: "java17"
env: "flex"
handlers:
- url: "/.*"
script: "this field is required, but ignored"
manual_scaling:
instances: 1
health_check:
enable_health_check: false
env_variables:
ENCRYPT_KEY: "your_encryption_key_here"
----
You can deploy the app (for example, with a Maven plugin) by adding the project ID to the build configuration, as shown in the following example:
[source,xml]
----
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>appengine-maven-plugin</artifactId>
<version>2.4.4</version>
<configuration>
<project>myproject</project>
</configuration>
</plugin>
----
Then deploy with `mvn appengine:deploy` (you need to authenticate first, otherwise the build fails).

View File

@@ -1,110 +0,0 @@
[[deployment.efficient]]
= Efficient Deployments
[[deployment.efficient.unpacking]]
== Unpacking the Executable JAR
You can run your application using the executable jar, but loading the classes from nested jars has a small cost.
Depending on the size of the jar, running the application from an exploded structure is faster and recommended in production.
Certain PaaS implementations may also choose to extract archives before they run.
For example, Cloud Foundry operates this way.
Spring Boot supports extracting your application to a directory using different layouts.
The default layout is the most efficient, and is xref:#deployment.efficient.cds[CDS friendly].
In this layout, the libraries are extracted to a `lib/` folder, and the application JAR
contains the application classes and a manifest which references the libraries in the `lib/` folder.
[source,shell]
----
$ java -Djarmode=tools -jar my-app.jar extract
$ java -jar my-app/my-app.jar
----
After startup, you should not expect any differences.
TIP: Run `java -Djarmode=tools -jar my-app.jar help extract` to see all possible options.
[[deployment.efficient.cds]]
== Optimize Startup Time with CDS
Class Data Sharing (CDS) is a https://docs.oracle.com/en/java/javase/17/vm/class-data-sharing.html[JVM feature] that can help reduce the startup time and memory footprint of Java applications.
To use it, you should first perform a training run on your application in exploded form:
[source,shell]
----
$ java -Djarmode=tools -jar my-app.jar extract --destination application
$ cd application
$ java -XX:ArchiveClassesAtExit=application.jsa -Dspring.context.exit=onRefresh -jar my-app.jar
----
This creates an `application.jsa` file that can be reused as long as the application is not updated.
To use the cache, you need to add an extra parameter when starting the application:
[source,shell]
----
$ java -XX:SharedArchiveFile=application.jsa -jar my-app.jar
----
NOTE: For more details about CDS, refer to the {url-spring-framework-docs}/integration/cds.html[Spring Framework reference documentation]
[[deployment.efficient.aot]]
== Using Ahead-of-time Processing With the JVM
It's beneficial for the startup time to run your application using the AOT generated initialization code.
First, you need to ensure that the jar you are building includes AOT generated code.
NOTE: CDS and AOT can be combined to further improve startup time.
For Maven, this means that you should build with `-Pnative` to activate the `native` profile:
[source,shell]
----
$ mvn -Pnative package
----
For Gradle, you need to ensure that your build includes the `org.springframework.boot.aot` plugin.
When the JAR has been built, run it with `spring.aot.enabled` system property set to `true`. For example:
[source,shell]
----
$ java -Dspring.aot.enabled=true -jar myapplication.jar
........ Starting AOT-processed MyApplication ...
----
Beware that using the ahead-of-time processing has drawbacks.
It implies the following restrictions:
* The classpath is fixed and fully defined at build time
* The beans defined in your application cannot change at runtime, meaning:
- The Spring `@Profile` annotation and profile-specific configuration xref:how-to:aot.adoc#howto.aot.conditions[have limitations].
- Properties that change if a bean is created are not supported (for example, `@ConditionalOnProperty` and `.enable` properties).
To learn more about ahead-of-time processing, please see the xref:native-image/introducing-graalvm-native-images.adoc#native-image.introducing-graalvm-native-images.understanding-aot-processing[Understanding Spring Ahead-of-Time Processing section].
[[deployment.efficient.checkpoint-restore]]
== Checkpoint and Restore With the JVM
https://wiki.openjdk.org/display/crac/Main[Coordinated Restore at Checkpoint] (CRaC) is an OpenJDK project that defines a new Java API to allow you to checkpoint and restore an application on the HotSpot JVM.
It is based on https://github.com/checkpoint-restore/criu[CRIU], a project that implements checkpoint/restore functionality on Linux.
The principle is the following: you start your application almost as usual but with a CRaC enabled version of the JDK like https://bell-sw.com/pages/downloads/?package=jdk-crac[BellSoft Liberica JDK with CRaC] or https://www.azul.com/downloads/?package=jdk-crac#zulu[Azul Zulu JDK with CRaC].
Then at some point, potentially after some workloads that will warm up your JVM by executing all common code paths, you trigger a checkpoint using an API call, a `jcmd` command, an HTTP endpoint, or a different mechanism.
A memory representation of the running JVM, including its warmness, is then serialized to disk, allowing a fast restoration at a later point, potentially on another machine with a similar operating system and CPU architecture.
The restored process retains all the capabilities of the HotSpot JVM, including further JIT optimizations at runtime.
Based on the foundations provided by Spring Framework, Spring Boot provides support for checkpointing and restoring your application, and manages out-of-the-box the lifecycle of resources such as socket, files and thread pools https://github.com/spring-projects/spring-lifecycle-smoke-tests/blob/main/STATUS.adoc[on a limited scope].
Additional lifecycle management is expected for other dependencies and potentially for the application code dealing with such resources.
You can find more details about the two modes supported ("on demand checkpoint/restore of a running application" and "automatic checkpoint/restore at startup"), how to enable checkpoint and restore support and some guidelines in {url-spring-framework-docs}/integration/checkpoint-restore.html[the Spring Framework JVM Checkpoint Restore support documentation].

View File

@@ -1,8 +0,0 @@
[[deployment]]
= Deploying Spring Boot Applications
Spring Boot's flexible packaging options provide a great deal of choice when it comes to deploying your application.
You can deploy Spring Boot applications to a variety of cloud platforms, to virtual/real machines, or make them fully executable for Unix systems.
This section covers some of the more common deployment scenarios.

View File

@@ -1,389 +0,0 @@
[[deployment.installing]]
= Installing Spring Boot Applications
In addition to running Spring Boot applications by using `java -jar` directly, it is also possible to run them as `systemd`, `init.d` or Windows services.
[[deployment.installing.system-d]]
== Installation as a systemd Service
`systemd` is the successor of the System V init system and is now being used by many modern Linux distributions.
Spring Boot applications can be launched by using `systemd` '`service`' scripts.
Assuming that you have a Spring Boot application packaged as an uber jar in `/var/myapp`, to install it as a `systemd` service, create a script named `myapp.service` and place it in `/etc/systemd/system` directory.
The following script offers an example:
[source]
----
[Unit]
Description=myapp
After=syslog.target network.target
[Service]
User=myapp
Group=myapp
Environment="JAVA_HOME=/path/to/java/home"
ExecStart=${JAVA_HOME}/bin/java -jar /var/myapp/myapp.jar
ExecStop=/bin/kill -15 $MAINPID
SuccessExitStatus=143
[Install]
WantedBy=multi-user.target
----
IMPORTANT: Remember to change the `Description`, `User`, `Group`, `Environment` and `ExecStart` fields for your application.
NOTE: The `ExecStart` field does not declare the script action command, which means that the `run` command is used by default.
The user that runs the application, the PID file, and the console log file are managed by `systemd` itself and therefore must be configured by using appropriate fields in the '`service`' script.
Consult the https://www.freedesktop.org/software/systemd/man/systemd.service.html[service unit configuration man page] for more details.
To flag the application to start automatically on system boot, use the following command:
[source,shell]
----
$ systemctl enable myapp.service
----
Run `man systemctl` for more details.
[[deployment.installing.init-d]]
== Installation as an init.d Service (System V)
To use your application as `init.d` service, configure its build to produce a xref:deployment/installing.adoc[fully executable jar].
CAUTION: Fully executable jars work by embedding an extra script at the front of the file.
Currently, some tools do not accept this format, so you may not always be able to use this technique.
For example, `jar -xf` may silently fail to extract a jar or war that has been made fully executable.
It is recommended that you make your jar or war fully executable only if you intend to execute it directly, rather than running it with `java -jar` or deploying it to a servlet container.
CAUTION: A zip64-format jar file cannot be made fully executable.
Attempting to do so will result in a jar file that is reported as corrupt when executed directly or with `java -jar`.
A standard-format jar file that contains one or more zip64-format nested jars can be fully executable.
To create a '`fully executable`' jar with Maven, use the following plugin configuration:
[source,xml]
----
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
</configuration>
</plugin>
----
The following example shows the equivalent Gradle configuration:
[source,gradle]
----
tasks.named('bootJar') {
launchScript()
}
----
It can then be symlinked to `init.d` to support the standard `start`, `stop`, `restart`, and `status` commands.
The default launch script that is added to a fully executable jar supports most Linux distributions and is tested on CentOS and Ubuntu.
Other platforms, such as OS X and FreeBSD, require the use of a custom script.
The default scripts supports the following features:
* Starts the services as the user that owns the jar file
* Tracks the application's PID by using `/var/run/<appname>/<appname>.pid`
* Writes console logs to `/var/log/<appname>.log`
Assuming that you have a Spring Boot application installed in `/var/myapp`, to install a Spring Boot application as an `init.d` service, create a symlink, as follows:
[source,shell]
----
$ sudo ln -s /var/myapp/myapp.jar /etc/init.d/myapp
----
Once installed, you can start and stop the service in the usual way.
For example, on a Debian-based system, you could start it with the following command:
[source,shell]
----
$ service myapp start
----
TIP: If your application fails to start, check the log file written to `/var/log/<appname>.log` for errors.
You can also flag the application to start automatically by using your standard operating system tools.
For example, on Debian, you could use the following command:
[source,shell]
----
$ update-rc.d myapp defaults <priority>
----
[[deployment.installing.init-d.securing]]
=== Securing an init.d Service
NOTE: The following is a set of guidelines on how to secure a Spring Boot application that runs as an init.d service.
It is not intended to be an exhaustive list of everything that should be done to harden an application and the environment in which it runs.
When executed as root, as is the case when root is being used to start an init.d service, the default executable script runs the application as the user specified in the `RUN_AS_USER` environment variable.
When the environment variable is not set, the user who owns the jar file is used instead.
You should never run a Spring Boot application as `root`, so `RUN_AS_USER` should never be root and your application's jar file should never be owned by root.
Instead, create a specific user to run your application and set the `RUN_AS_USER` environment variable or use `chown` to make it the owner of the jar file, as shown in the following example:
[source,shell]
----
$ chown bootapp:bootapp your-app.jar
----
In this case, the default executable script runs the application as the `bootapp` user.
TIP: To reduce the chances of the application's user account being compromised, you should consider preventing it from using a login shell.
For example, you can set the account's shell to `/usr/sbin/nologin`.
You should also take steps to prevent the modification of your application's jar file.
Firstly, configure its permissions so that it cannot be written and can only be read or executed by its owner, as shown in the following example:
[source,shell]
----
$ chmod 500 your-app.jar
----
Second, you should also take steps to limit the damage if your application or the account that is running it is compromised.
If an attacker does gain access, they could make the jar file writable and change its contents.
One way to protect against this is to make it immutable by using `chattr`, as shown in the following example:
[source,shell]
----
$ sudo chattr +i your-app.jar
----
This will prevent any user, including root, from modifying the jar.
If root is used to control the application's service and you xref:deployment/installing.adoc#deployment.installing.init-d.script-customization.when-running.conf-file[use a `.conf` file] to customize its startup, the `.conf` file is read and evaluated by the root user.
It should be secured accordingly.
Use `chmod` so that the file can only be read by the owner and use `chown` to make root the owner, as shown in the following example:
[source,shell]
----
$ chmod 400 your-app.conf
$ sudo chown root:root your-app.conf
----
[[deployment.installing.init-d.script-customization]]
=== Customizing the Startup Script
The default embedded startup script written by the Maven or Gradle plugin can be customized in a number of ways.
For most people, using the default script along with a few customizations is usually enough.
If you find you cannot customize something that you need to, use the `embeddedLaunchScript` option to write your own file entirely.
[[deployment.installing.init-d.script-customization.when-written]]
==== Customizing the Start Script When It Is Written
It often makes sense to customize elements of the start script as it is written into the jar file.
For example, init.d scripts can provide a "`description`".
Since you know the description up front (and it need not change), you may as well provide it when the jar is generated.
To customize written elements, use the `embeddedLaunchScriptProperties` option of the Spring Boot Maven plugin or the xref:gradle-plugin:packaging.adoc#packaging-executable.configuring.launch-script[`properties` property of the Spring Boot Gradle plugin's `launchScript`].
The following property substitutions are supported with the default script:
[cols="1,3,3,3"]
|===
| Name | Description | Gradle default | Maven default
| `mode`
| The script mode.
| `auto`
| `auto`
| `initInfoProvides`
| The `Provides` section of "`INIT INFO`"
| `${task.baseName}`
| `${project.artifactId}`
| `initInfoRequiredStart`
| `Required-Start` section of "`INIT INFO`".
| `$remote_fs $syslog $network`
| `$remote_fs $syslog $network`
| `initInfoRequiredStop`
| `Required-Stop` section of "`INIT INFO`".
| `$remote_fs $syslog $network`
| `$remote_fs $syslog $network`
| `initInfoDefaultStart`
| `Default-Start` section of "`INIT INFO`".
| `2 3 4 5`
| `2 3 4 5`
| `initInfoDefaultStop`
| `Default-Stop` section of "`INIT INFO`".
| `0 1 6`
| `0 1 6`
| `initInfoShortDescription`
| `Short-Description` section of "`INIT INFO`".
| Single-line version of `${project.description}` (falling back to `${task.baseName}`)
| `${project.name}`
| `initInfoDescription`
| `Description` section of "`INIT INFO`".
| `${project.description}` (falling back to `${task.baseName}`)
| `${project.description}` (falling back to `${project.name}`)
| `initInfoChkconfig`
| `chkconfig` section of "`INIT INFO`"
| `2345 99 01`
| `2345 99 01`
| `confFolder`
| The default value for `CONF_FOLDER`
| Folder containing the jar
| Folder containing the jar
| `inlinedConfScript`
| Reference to a file script that should be inlined in the default launch script.
This can be used to set environmental variables such as `JAVA_OPTS` before any external config files are loaded
|
|
| `logFolder`
| Default value for `LOG_FOLDER`.
Only valid for an `init.d` service
|
|
| `logFilename`
| Default value for `LOG_FILENAME`.
Only valid for an `init.d` service
|
|
| `pidFolder`
| Default value for `PID_FOLDER`.
Only valid for an `init.d` service
|
|
| `pidFilename`
| Default value for the name of the PID file in `PID_FOLDER`.
Only valid for an `init.d` service
|
|
| `useStartStopDaemon`
| Whether the `start-stop-daemon` command, when it is available, should be used to control the process
| `true`
| `true`
| `stopWaitTime`
| Default value for `STOP_WAIT_TIME` in seconds.
Only valid for an `init.d` service
| 60
| 60
|===
[[deployment.installing.init-d.script-customization.when-running]]
==== Customizing a Script When It Runs
For items of the script that need to be customized _after_ the jar has been written, you can use environment variables or a xref:deployment/installing.adoc#deployment.installing.init-d.script-customization.when-running.conf-file[config file].
The following environment properties are supported with the default script:
[cols="1,6"]
|===
| Variable | Description
| `MODE`
| The "`mode`" of operation.
The default depends on the way the jar was built but is usually `auto` (meaning it tries to guess if it is an init script by checking if it is a symlink in a directory called `init.d`).
You can explicitly set it to `service` so that the `stop\|start\|status\|restart` commands work or to `run` if you want to run the script in the foreground.
| `RUN_AS_USER`
| The user that will be used to run the application.
When not set, the user that owns the jar file will be used.
| `USE_START_STOP_DAEMON`
| Whether the `start-stop-daemon` command, when it is available, should be used to control the process.
Defaults to `true`.
| `PID_FOLDER`
| The root name of the pid folder (`/var/run` by default).
| `LOG_FOLDER`
| The name of the folder in which to put log files (`/var/log` by default).
| `CONF_FOLDER`
| The name of the folder from which to read .conf files (same folder as jar-file by default).
| `LOG_FILENAME`
| The name of the log file in the `LOG_FOLDER` (`<appname>.log` by default).
| `APP_NAME`
| The name of the app.
If the jar is run from a symlink, the script guesses the app name.
If it is not a symlink or you want to explicitly set the app name, this can be useful.
| `RUN_ARGS`
| The arguments to pass to the program (the Spring Boot app).
| `JAVA_HOME`
| The location of the `java` executable is discovered by using the `PATH` by default, but you can set it explicitly if there is an executable file at `$JAVA_HOME/bin/java`.
| `JAVA_OPTS`
| Options that are passed to the JVM when it is launched.
| `JARFILE`
| The explicit location of the jar file, in case the script is being used to launch a jar that it is not actually embedded.
| `DEBUG`
| If not empty, sets the `-x` flag on the shell process, allowing you to see the logic in the script.
| `STOP_WAIT_TIME`
| The time in seconds to wait when stopping the application before forcing a shutdown (`60` by default).
|===
NOTE: The `PID_FOLDER`, `LOG_FOLDER`, and `LOG_FILENAME` variables are only valid for an `init.d` service.
For `systemd`, the equivalent customizations are made by using the '`service`' script.
See the https://www.freedesktop.org/software/systemd/man/systemd.service.html[service unit configuration man page] for more details.
[[deployment.installing.init-d.script-customization.when-running.conf-file]]
===== Using a Conf File
With the exception of `JARFILE` and `APP_NAME`, the settings listed in the preceding section can be configured by using a `.conf` file.
The file is expected to be next to the jar file and have the same name but suffixed with `.conf` rather than `.jar`.
For example, a jar named `/var/myapp/myapp.jar` uses the configuration file named `/var/myapp/myapp.conf`, as shown in the following example:
.myapp.conf
[source,properties]
----
JAVA_OPTS=-Xmx1024M
LOG_FOLDER=/custom/log/folder
----
TIP: If you do not like having the config file next to the jar file, you can set a `CONF_FOLDER` environment variable to customize the location of the config file.
To learn about securing this file appropriately, see xref:deployment/installing.adoc#deployment.installing.init-d.securing[the guidelines for securing an init.d service].
[[deployment.installing.windows-services]]
== Microsoft Windows Services
A Spring Boot application can be started as a Windows service by using https://github.com/kohsuke/winsw[`winsw`].
A (https://github.com/snicoll/spring-boot-daemon[separately maintained sample]) describes step-by-step how you can create a Windows service for your Spring Boot application.

View File

@@ -230,7 +230,7 @@ We can also update the state of the application, when the application breaks and
include-code::MyLocalCacheVerifier[]
Spring Boot provides xref:actuator/endpoints.adoc#actuator.endpoints.kubernetes-probes[Kubernetes HTTP probes for "Liveness" and "Readiness" with Actuator Health Endpoints].
You can get more guidance about xref:deployment/cloud.adoc#deployment.cloud.kubernetes[deploying Spring Boot applications on Kubernetes in the dedicated section].
You can get more guidance about xref:how-to:deployment/cloud.adoc#howto.deployment.cloud.kubernetes[deploying Spring Boot applications on Kubernetes in the dedicated section].

View File

@@ -1,3 +1,3 @@
= Reference
This section provides information on using the feature and capabilities of Spring Boot.
This section provides information on using the features and capabilities of Spring Boot.

View File

@@ -1,281 +0,0 @@
[[native-image.developing-your-first-application]]
= Developing Your First GraalVM Native Application
Now that we have a good overview of GraalVM Native Images and how the Spring ahead-of-time engine works, we can look at how to create an application.
There are two main ways to build a Spring Boot native image application:
* Using Spring Boot support for Cloud Native Buildpacks to generate a lightweight container containing a native executable.
* Using GraalVM Native Build Tools to generate a native executable.
TIP: The easiest way to start a new native Spring Boot project is to go to https://start.spring.io[start.spring.io], add the "`GraalVM Native Support`" dependency and generate the project.
The included `HELP.md` file will provide getting started hints.
[[native-image.developing-your-first-application.sample-application]]
== Sample Application
We need an example application that we can use to create our native image.
For our purposes, the simple "`Hello World!`" web application that's covered in the "`xref:tutorial:first-application/index.adoc[Developing Your First Spring Boot Application]`" section will suffice.
To recap, our main application code looks like this:
include-code::MyApplication[]
This application uses Spring MVC and embedded Tomcat, both of which have been tested and verified to work with GraalVM native images.
[[native-image.developing-your-first-application.buildpacks]]
== Building a Native Image Using Buildpacks
Spring Boot includes buildpack support for native images directly for both Maven and Gradle.
This means you can just type a single command and quickly get a sensible image into your locally running Docker daemon.
The resulting image doesn't contain a JVM, instead the native image is compiled statically.
This leads to smaller images.
NOTE: The builder used for the images is `paketobuildpacks/builder-jammy-tiny:latest`.
It has small footprint and reduced attack surface, but you can also use `paketobuildpacks/builder-jammy-base:latest` or `paketobuildpacks/builder-jammy-full:latest` to have more tools available in the image if required.
[[native-image.developing-your-first-application.buildpacks.system-requirements]]
=== System Requirements
Docker should be installed. See https://docs.docker.com/installation/#installation[Get Docker] for more details.
https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user[Configure it to allow non-root user] if you are on Linux.
NOTE: You can run `docker run hello-world` (without `sudo`) to check the Docker daemon is reachable as expected.
Check the xref:maven-plugin:build-image.adoc#build-image.docker-daemon[Maven] or xref:gradle-plugin:packaging-oci-image.adoc#build-image.docker-daemon[Gradle] Spring Boot plugin documentation for more details.
TIP: On macOS, it is recommended to increase the memory allocated to Docker to at least `8GB`, and potentially add more CPUs as well.
See this https://stackoverflow.com/questions/44533319/how-to-assign-more-memory-to-docker-container/44533437#44533437[Stack Overflow answer] for more details.
On Microsoft Windows, make sure to enable the https://docs.docker.com/docker-for-windows/wsl/[Docker WSL 2 backend] for better performance.
[[native-image.developing-your-first-application.buildpacks.maven]]
=== Using Maven
To build a native image container using Maven you should ensure that your `pom.xml` file uses the `spring-boot-starter-parent` and the `org.graalvm.buildtools:native-maven-plugin`.
You should have a `<parent>` section that looks like this:
[source,xml,subs="verbatim,attributes"]
----
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>{version-spring-boot}</version>
</parent>
----
You additionally should have this in the `<build> <plugins>` section:
[source,xml,subs="verbatim,attributes"]
----
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
</plugin>
----
The `spring-boot-starter-parent` declares a `native` profile that configures the executions that need to run in order to create a native image.
You can activate profiles using the `-P` flag on the command line.
TIP: If you don't want to use `spring-boot-starter-parent` you'll need to configure executions for the `process-aot` goal from Spring Boot's plugin and the `add-reachability-metadata` goal from the Native Build Tools plugin.
To build the image, you can run the `spring-boot:build-image` goal with the `native` profile active:
[source,shell]
----
$ mvn -Pnative spring-boot:build-image
----
[[native-image.developing-your-first-application.buildpacks.gradle]]
=== Using Gradle
The Spring Boot Gradle plugin automatically configures AOT tasks when the GraalVM Native Image plugin is applied.
You should check that your Gradle build contains a `plugins` block that includes `org.graalvm.buildtools.native`.
As long as the `org.graalvm.buildtools.native` plugin is applied, the `bootBuildImage` task will generate a native image rather than a JVM one.
You can run the task using:
[source,shell]
----
$ gradle bootBuildImage
----
[[native-image.developing-your-first-application.buildpacks.running]]
=== Running the example
Once you have run the appropriate build command, a Docker image should be available.
You can start your application using `docker run`:
[source,shell]
----
$ docker run --rm -p 8080:8080 docker.io/library/myproject:0.0.1-SNAPSHOT
----
You should see output similar to the following:
[source,shell]
----
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v{version-spring-boot})
....... . . .
....... . . . (log output here)
....... . . .
........ Started MyApplication in 0.08 seconds (process running for 0.095)
----
NOTE: The startup time differs from machine to machine, but it should be much faster than a Spring Boot application running on a JVM.
If you open a web browser to `http://localhost:8080`, you should see the following output:
[source]
----
Hello World!
----
To gracefully exit the application, press `ctrl-c`.
[[native-image.developing-your-first-application.native-build-tools]]
== Building a Native Image using Native Build Tools
If you want to generate a native executable directly without using Docker, you can use GraalVM Native Build Tools.
Native Build Tools are plugins shipped by GraalVM for both Maven and Gradle.
You can use them to perform a variety of GraalVM tasks, including generating a native image.
[[native-image.developing-your-first-application.native-build-tools.prerequisites]]
=== Prerequisites
To build a native image using the Native Build Tools, you'll need a GraalVM distribution on your machine.
You can either download it manually on the {url-download-liberica-nik}[Liberica Native Image Kit page], or you can use a download manager like SDKMAN!.
[[native-image.developing-your-first-application.native-build-tools.prerequisites.linux-macos]]
==== Linux and macOS
To install the native image compiler on macOS or Linux, we recommend using SDKMAN!.
Get SDKMAN! from https://sdkman.io and install the Liberica GraalVM distribution by using the following commands:
[source,shell,subs="verbatim,attributes"]
----
$ sdk install java {version-graal}.r17-nik
$ sdk use java {version-graal}.r17-nik
----
Verify that the correct version has been configured by checking the output of `java -version`:
[source,shell,subs="verbatim,attributes"]
----
$ java -version
openjdk version "17.0.5" 2022-10-18 LTS
OpenJDK Runtime Environment GraalVM 22.3.0 (build 17.0.5+8-LTS)
OpenJDK 64-Bit Server VM GraalVM 22.3.0 (build 17.0.5+8-LTS, mixed mode)
----
[[native-image.developing-your-first-application.native-build-tools.prerequisites.windows]]
==== Windows
On Windows, follow https://medium.com/graalvm/using-graalvm-and-native-image-on-windows-10-9954dc071311[these instructions] to install either https://www.graalvm.org/downloads/[GraalVM] or {url-download-liberica-nik}[Liberica Native Image Kit] in version {version-graal}, the Visual Studio Build Tools and the Windows SDK.
Due to the https://docs.microsoft.com/en-US/troubleshoot/windows-client/shell-experience/command-line-string-limitation[Windows related command-line maximum length], make sure to use x64 Native Tools Command Prompt instead of the regular Windows command line to run Maven or Gradle plugins.
[[native-image.developing-your-first-application.native-build-tools.maven]]
=== Using Maven
As with the xref:native-image/developing-your-first-application.adoc#native-image.developing-your-first-application.buildpacks.maven[buildpack support], you need to make sure that you're using `spring-boot-starter-parent` in order to inherit the `native` profile and that the `org.graalvm.buildtools:native-maven-plugin` plugin is used.
With the `native` profile active, you can invoke the `native:compile` goal to trigger `native-image` compilation:
[source,shell]
----
$ mvn -Pnative native:compile
----
The native image executable can be found in the `target` directory.
[[native-image.developing-your-first-application.native-build-tools.gradle]]
=== Using Gradle
When the Native Build Tools Gradle plugin is applied to your project, the Spring Boot Gradle plugin will automatically trigger the Spring AOT engine.
Task dependencies are automatically configured, so you can just run the standard `nativeCompile` task to generate a native image:
[source,shell]
----
$ gradle nativeCompile
----
The native image executable can be found in the `build/native/nativeCompile` directory.
[[native-image.developing-your-first-application.native-build-tools.running]]
=== Running the Example
At this point, your application should work. You can now start the application by running it directly:
[tabs]
======
Maven::
+
[source,shell]
----
$ target/myproject
----
Gradle::
+
[source,shell]
----
$ build/native/nativeCompile/myproject
----
======
You should see output similar to the following:
[source,shell,subs="verbatim,attributes"]
----
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v{version-spring-boot})
....... . . .
....... . . . (log output here)
....... . . .
........ Started MyApplication in 0.08 seconds (process running for 0.095)
----
NOTE: The startup time differs from machine to machine, but it should be much faster than a Spring Boot application running on a JVM.
If you open a web browser to `http://localhost:8080`, you should see the following output:
[source]
----
Hello World!
----
To gracefully exit the application, press `ctrl-c`.

View File

@@ -1,114 +0,0 @@
[[native-image.testing]]
= Testing GraalVM Native Images
When writing native image applications, we recommend that you continue to use the JVM whenever possible to develop the majority of your unit and integration tests.
This will help keep developer build times down and allow you to use existing IDE integrations.
With broad test coverage on the JVM, you can then focus native image testing on the areas that are likely to be different.
For native image testing, you're generally looking to ensure that the following aspects work:
* The Spring AOT engine is able to process your application, and it will run in an AOT-processed mode.
* GraalVM has enough hints to ensure that a valid native image can be produced.
[[native-image.testing.with-the-jvm]]
== Testing Ahead-of-time Processing With the JVM
When a Spring Boot application runs, it attempts to detect if it is running as a native image.
If it is running as a native image, it will initialize the application using the code that was generated during at build-time by the Spring AOT engine.
If the application is running on a regular JVM, then any AOT generated code is ignored.
Since the `native-image` compilation phase can take a while to complete, it's sometimes useful to run your application on the JVM but have it use the AOT generated initialization code.
Doing so helps you to quickly validate that there are no errors in the AOT generated code and nothing is missing when your application is eventually converted to a native image.
To run a Spring Boot application on the JVM and have it use AOT generated code you can set the `spring.aot.enabled` system property to `true`.
For example:
[source,shell]
----
$ java -Dspring.aot.enabled=true -jar myapplication.jar
----
NOTE: You need to ensure that the jar you are testing includes AOT generated code.
For Maven, this means that you should build with `-Pnative` to activate the `native` profile.
For Gradle, you need to ensure that your build includes the `org.graalvm.buildtools.native` plugin.
If your application starts with the `spring.aot.enabled` property set to `true`, then you have higher confidence that it will work when converted to a native image.
You can also consider running integration tests against the running application.
For example, you could use the Spring `WebClient` to call your application REST endpoints.
Or you might consider using a project like Selenium to check your application's HTML responses.
[[native-image.testing.with-native-build-tools]]
== Testing With Native Build Tools
GraalVM Native Build Tools includes the ability to run tests inside a native image.
This can be helpful when you want to deeply test that the internals of your application work in a GraalVM native image.
Generating the native image that contains the tests to run can be a time-consuming operation, so most developers will probably prefer to use the JVM locally.
They can, however, be very useful as part of a CI pipeline.
For example, you might choose to run native tests once a day.
Spring Framework includes ahead-of-time support for running tests.
All the usual Spring testing features work with native image tests.
For example, you can continue to use the `@SpringBootTest` annotation.
You can also use Spring Boot xref:testing/spring-boot-applications.adoc#testing.spring-boot-applications.autoconfigured-tests[test slices] to test only specific parts of your application.
Spring Framework's native testing support works in the following way:
* Tests are analyzed in order to discover any `ApplicationContext` instances that will be required.
* Ahead-of-time processing is applied to each of these application contexts and assets are generated.
* A native image is created, with the generated assets being processed by GraalVM.
* The native image also includes the JUnit `TestEngine` configured with a list of the discovered tests.
* The native image is started, triggering the engine which will run each test and report results.
[[native-image.testing.with-native-build-tools.maven]]
=== Using Maven
To run native tests using Maven, ensure that your `pom.xml` file uses the `spring-boot-starter-parent`.
You should have a `<parent>` section that looks like this:
[source,xml,subs="verbatim,attributes"]
----
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>{version-spring-boot}</version>
</parent>
----
The `spring-boot-starter-parent` declares a `nativeTest` profile that configures the executions that are needed to run the native tests.
You can activate profiles using the `-P` flag on the command line.
TIP: If you don't want to use `spring-boot-starter-parent` you'll need to configure executions for the `process-test-aot` goal from the Spring Boot plugin and the `test` goal from the Native Build Tools plugin.
To build the image and run the tests, use the `test` goal with the `nativeTest` profile active:
[source,shell]
----
$ mvn -PnativeTest test
----
[[native-image.testing.with-native-build-tools.gradle]]
=== Using Gradle
The Spring Boot Gradle plugin automatically configures AOT test tasks when the GraalVM Native Image plugin is applied.
You should check that your Gradle build contains a `plugins` block that includes `org.graalvm.buildtools.native`.
To run native tests using Gradle you can use the `nativeTest` task:
[source,shell]
----
$ gradle nativeTest
----

View File

@@ -0,0 +1,35 @@
[[packaging.aot]]
= Ahead-of-time Processing With the JVM
It's beneficial for the startup time to run your application using the AOT generated initialization code.
First, you need to ensure that the jar you are building includes AOT generated code.
NOTE: CDS and AOT can be combined to further improve startup time.
For Maven, this means that you should build with `-Pnative` to activate the `native` profile:
[source,shell]
----
$ mvn -Pnative package
----
For Gradle, you need to ensure that your build includes the `org.springframework.boot.aot` plugin.
When the JAR has been built, run it with `spring.aot.enabled` system property set to `true`. For example:
[source,shell]
----
$ java -Dspring.aot.enabled=true -jar myapplication.jar
........ Starting AOT-processed MyApplication ...
----
Beware that using the ahead-of-time processing has drawbacks.
It implies the following restrictions:
* The classpath is fixed and fully defined at build time
* The beans defined in your application cannot change at runtime, meaning:
- The Spring `@Profile` annotation and profile-specific configuration xref:how-to:aot.adoc#howto.aot.conditions[have limitations].
- Properties that change if a bean is created are not supported (for example, `@ConditionalOnProperty` and `.enable` properties).
To learn more about ahead-of-time processing, please see the xref:packaging/native-image/introducing-graalvm-native-images.adoc#packaging.native-image.introducing-graalvm-native-images.understanding-aot-processing[Understanding Spring Ahead-of-Time Processing] section.

View File

@@ -0,0 +1,16 @@
[[packaging.checkpoint-restore]]
= Checkpoint and Restore With the JVM
https://wiki.openjdk.org/display/crac/Main[Coordinated Restore at Checkpoint] (CRaC) is an OpenJDK project that defines a new Java API to allow you to checkpoint and restore an application on the HotSpot JVM.
It is based on https://github.com/checkpoint-restore/criu[CRIU], a project that implements checkpoint/restore functionality on Linux.
The principle is the following: you start your application almost as usual but with a CRaC enabled version of the JDK like https://bell-sw.com/pages/downloads/?package=jdk-crac[BellSoft Liberica JDK with CRaC] or https://www.azul.com/downloads/?package=jdk-crac#zulu[Azul Zulu JDK with CRaC].
Then at some point, potentially after some workloads that will warm up your JVM by executing all common code paths, you trigger a checkpoint using an API call, a `jcmd` command, an HTTP endpoint, or a different mechanism.
A memory representation of the running JVM, including its warmness, is then serialized to disk, allowing a fast restoration at a later point, potentially on another machine with a similar operating system and CPU architecture.
The restored process retains all the capabilities of the HotSpot JVM, including further JIT optimizations at runtime.
Based on the foundations provided by Spring Framework, Spring Boot provides support for checkpointing and restoring your application, and manages out-of-the-box the lifecycle of resources such as socket, files and thread pools https://github.com/spring-projects/spring-lifecycle-smoke-tests/blob/main/STATUS.adoc[on a limited scope].
Additional lifecycle management is expected for other dependencies and potentially for the application code dealing with such resources.
You can find more details about the two modes supported ("on demand checkpoint/restore of a running application" and "automatic checkpoint/restore at startup"), how to enable checkpoint and restore support and some guidelines in {url-spring-framework-docs}/integration/checkpoint-restore.html[the Spring Framework JVM Checkpoint Restore support documentation].

View File

@@ -0,0 +1,24 @@
[[packaging.class-data-sharing]]
= Class Data Sharing
Class Data Sharing (CDS) is a https://docs.oracle.com/en/java/javase/17/vm/class-data-sharing.html[JVM feature] that can help reduce the startup time and memory footprint of Java applications.
To use it, you should first perform a training run on your application in exploded form:
[source,shell]
----
$ java -Djarmode=tools -jar my-app.jar extract --destination application
$ cd application
$ java -XX:ArchiveClassesAtExit=application.jsa -Dspring.context.exit=onRefresh -jar my-app.jar
----
This creates an `application.jsa` file that can be reused as long as the application is not updated.
To use the cache, you need to add an extra parameter when starting the application:
[source,shell]
----
$ java -XX:SharedArchiveFile=application.jsa -jar my-app.jar
----
NOTE: For more details about CDS, refer to the {url-spring-framework-docs}/integration/cds.html[Spring Framework reference documentation]

View File

@@ -1,8 +1,7 @@
[[container-images.buildpacks]]
[[packaging.container-images.buildpacks]]
= Cloud Native Buildpacks
Dockerfiles are just one way to build docker images.
Another way to build docker images is directly from your Maven or Gradle plugin, using buildpacks.
Docker images can be built directly from your Maven or Gradle plugin using https://buildpacks.io[Cloud Native Buildpacks].
If youve ever used an application platform such as Cloud Foundry or Heroku then youve probably used a buildpack.
Buildpacks are the part of the platform that takes your application and converts it into something that the platform can actually run.
For example, Cloud Foundrys Java buildpack will notice that youre pushing a `.jar` file and automatically add a relevant JRE.
@@ -13,8 +12,8 @@ This means you can just type a single command and quickly get a sensible image i
See the individual plugin documentation on how to use buildpacks with xref:maven-plugin:build-image.adoc#build-image[Maven] and xref:gradle-plugin:packaging-oci-image.adoc[Gradle].
NOTE: The https://github.com/paketo-buildpacks/spring-boot[Paketo Spring Boot buildpack] supports the `layers.idx` file, so any customization that is applied to it will be reflected in the image created by the buildpack.
NOTE: The https://github.com/paketo-buildpacks/spring-boot[Paketo Spring Boot buildpack] supports the `layers.idx` file, so any xref:packaging/container-images/efficient-images.adoc#packaging.container-images.efficient-images.layering[layer customization] that is applied to it will be reflected in the image created by the buildpacks.
NOTE: In order to achieve reproducible builds and container image caching, Buildpacks can manipulate the application resources metadata (such as the file "last modified" information).
NOTE: In order to achieve reproducible builds and container image caching, buildpacks can manipulate the application resources metadata (such as the file "last modified" information).
You should ensure that your application does not rely on that metadata at runtime.
Spring Boot can use that information when serving static resources, but this can be disabled with configprop:spring.web.resources.cache.use-last-modified[].

View File

@@ -1,11 +1,11 @@
[[container-images.dockerfiles]]
[[packaging.container-images.dockerfiles]]
= Dockerfiles
While it is possible to convert a Spring Boot uber jar into a docker image with just a few lines in the Dockerfile, we will use the xref:container-images/efficient-images.adoc#container-images.efficient-images.layering[layering feature] to create an optimized docker image.
While it is possible to convert a Spring Boot uber jar into a Docker image with just a few lines in the Dockerfile, using the xref:packaging/container-images/efficient-images.adoc#packaging.container-images.efficient-images.layering[layering feature] will result in an optimized image.
When you create a jar containing the layers index file, the `spring-boot-jarmode-tools` jar will be added as a dependency to your jar.
With this jar on the classpath, you can launch your application in a special mode which allows the bootstrap code to run something entirely different from your application, for example, something that extracts the layers.
CAUTION: The `tools` mode can not be used with a xref:deployment/installing.adoc[fully executable Spring Boot archive] that includes a launch script.
CAUTION: The `tools` mode can not be used with a xref:how-to:deployment/installing.adoc[fully executable Spring Boot archive] that includes a launch script.
Disable launch script configuration when building a jar file that is intended to be used with `layertools`.
Heres how you can launch your jar with a `tools` jar mode:
@@ -28,7 +28,7 @@ Available commands:
help Help about any command
----
The `extract` command can be used to easily split the application into layers to be added to the dockerfile.
The `extract` command can be used to easily split the application into layers to be added to the Dockerfile.
Here is an example of a Dockerfile using `jarmode`.
[source,dockerfile]
@@ -48,17 +48,17 @@ COPY --from=builder /builder/extracted/application/ ./
ENTRYPOINT ["java", "-jar", "application.jar"]
----
Assuming the above `Dockerfile` is in the current directory, your docker image can be built with `docker build .`, or optionally specifying the path to your application jar, as shown in the following example:
Assuming the above `Dockerfile` is in the current directory, your Docker image can be built with `docker build .`, or optionally specifying the path to your application jar, as shown in the following example:
[source,shell]
----
$ docker build --build-arg JAR_FILE=path/to/myapp.jar .
----
This is a multi-stage dockerfile.
This is a multi-stage Dockerfile.
The builder stage extracts the directories that are needed later.
Each of the `COPY` commands relates to the layers extracted by the jarmode.
Of course, a Dockerfile can be written without using the jarmode.
You can use some combination of `unzip` and `mv` to move things to the right layer but jarmode simplifies that.
Additionally, the layout created by the jarmode is CDS friendly out of the box.
Of course, a Dockerfile can be written without using the `jarmode`.
You can use some combination of `unzip` and `mv` to move things to the right layer but `jarmode` simplifies that.
Additionally, the layout created by the `jarmode` is CDS friendly out of the box.

View File

@@ -1,16 +1,16 @@
[[container-images.efficient-images]]
[[packaging.container-images.efficient-images]]
= Efficient Container Images
It is easily possible to package a Spring Boot uber jar as a docker image.
However, there are various downsides to copying and running the uber jar as is in the docker image.
Theres always a certain amount of overhead when running a uber jar without unpacking it, and in a containerized environment this can be noticeable.
The other issue is that putting your application's code and all its dependencies in one layer in the Docker image is sub-optimal.
It is easily possible to package a Spring Boot uber jar as a Docker image.
However, there are various downsides to copying and running the uber jar as-is in the Docker image.
Theres always a certain amount of overhead when running an uber jar without unpacking it, and in a containerized environment this can be noticeable.
The other issue is that putting your application's code and all its dependencies in one layer in the Docker image is not optimal.
Since you probably recompile your code more often than you upgrade the version of Spring Boot you use, its often better to separate things a bit more.
If you put jar files in the layer before your application classes, Docker often only needs to change the very bottom layer and can pick others up from its cache.
[[container-images.efficient-images.layering]]
[[packaging.container-images.efficient-images.layering]]
== Layering Docker Images
To make it easier to create optimized Docker images, Spring Boot supports adding a layer index file to the jar.

View File

@@ -0,0 +1,4 @@
[[packaging.container-images]]
= Container Images
Spring Boot applications can be containerized xref:packaging/container-images/dockerfiles.adoc[using Dockerfiles], or by xref:packaging/container-images/cloud-native-buildpacks.adoc[using Cloud Native Buildpacks] to create optimized docker compatible container images that you can run anywhere.

View File

@@ -0,0 +1,30 @@
[[packaging.efficient]]
= Efficient Deployments
[[packaging.efficient.unpacking]]
== Unpacking the Executable JAR
You can run your application using the executable jar, but loading the classes from nested jars has a small startup cost.
Depending on the size of the jar, running the application from an exploded structure is faster and recommended in production.
Certain PaaS implementations may also choose to extract archives before they run.
For example, Cloud Foundry operates this way.
Spring Boot supports extracting your application to a directory using different layouts.
The default layout is the most efficient, and is xref:#deployment.efficient.cds[CDS friendly].
In this layout, the libraries are extracted to a `lib/` folder, and the application JAR
contains the application classes and a manifest which references the libraries in the `lib/` folder.
[source,shell]
----
$ java -Djarmode=tools -jar my-app.jar extract
$ java -jar my-app/my-app.jar
----
After startup, you should not expect any differences in execution time between running an executable jar and running an extracted jar.
TIP: Run `java -Djarmode=tools -jar my-app.jar help extract` to see all possible options.

View File

@@ -0,0 +1,7 @@
[[packaging]]
= Packaging Spring Boot Applications
Spring Boot supports several technologies for optimizing applications for deployment, including xref:packaging/native-image/index.adoc[GraalVM native images], xref:packaging/class-data-sharing.adoc[Class Data Sharing], and xref:packaging/checkpoint-restore.adoc[Checkpoint and Restore].
Spring Boot applications can be packaged in Docker containers using techniques described in xref:packaging/container-images/index.adoc[Container Images].

View File

@@ -1,9 +1,9 @@
[[native-image.advanced]]
[[packaging.native-image.advanced]]
= Advanced Native Images Topics
[[native-image.advanced.nested-configuration-properties]]
[[packaging.native-image.advanced.nested-configuration-properties]]
== Nested Configuration Properties
Reflection hints are automatically created for configuration properties by the Spring ahead-of-time engine.
@@ -34,7 +34,7 @@ NOTE: Please use public getters and setters in all cases, otherwise the properti
[[native-image.advanced.converting-executable-jars]]
[[packaging.native-image.advanced.converting-executable-jars]]
== Converting a Spring Boot Executable Jar
It is possible to convert a Spring Boot xref:specification:executable-jar/index.adoc[executable jar] into a native image as long as the jar contains the AOT generated assets.
@@ -49,7 +49,7 @@ NOTE: Your executable jar must include AOT generated assets such as generated cl
[[native-image.advanced.converting-executable-jars.buildpacks]]
[[packaging.native-image.advanced.converting-executable-jars.buildpacks]]
=== Using Buildpacks
Spring Boot applications usually use Cloud Native Buildpacks through the Maven (`mvn spring-boot:build-image`) or Gradle (`gradle bootBuildImage`) integrations.
@@ -82,7 +82,7 @@ $ docker run --rm -p 8080:8080 docker.io/library/myproject:0.0.1-SNAPSHOT
[[native-image.advanced.converting-executable-jars.native-image]]
[[packaging.native-image.advanced.converting-executable-jars.native-image]]
=== Using GraalVM native-image
Another option to turn an AOT processed Spring Boot executable jar into a native executable is to use the GraalVM `native-image` tool.
@@ -111,7 +111,7 @@ You need to ensure that all jars are listed (the command above uses `find` and `
[[native-image.advanced.using-the-tracing-agent]]
[[packaging.native-image.advanced.using-the-tracing-agent]]
== Using the Tracing Agent
The GraalVM native image {url-graal-docs-native-image}/metadata/AutomaticMetadataCollection[tracing agent] allows you to intercept reflection, resources or proxy usage on the JVM in order to generate the related hints.
@@ -130,7 +130,7 @@ To address this problem the agent supports an access-filter file that will cause
[[native-image.advanced.using-the-tracing-agent.launch]]
[[packaging.native-image.advanced.using-the-tracing-agent.launch]]
=== Launch the Application Directly
Use the following command to launch the application with the native image tracing agent attached:
@@ -154,7 +154,7 @@ For further reading, please see {url-graal-docs-native-image}/metadata/Automatic
[[native-image.advanced.custom-hints]]
[[packaging.native-image.advanced.custom-hints]]
== Custom Hints
If you need to provide your own hints for reflection, resources, serialization, proxy usage etc. you can use the `RuntimeHintsRegistrar` API.
@@ -170,7 +170,7 @@ But when you work with `WebClient`, `RestClient` or `RestTemplate` directly, you
[[native-image.advanced.custom-hints.testing]]
[[packaging.native-image.advanced.custom-hints.testing]]
=== Testing custom hints
The `RuntimeHintsPredicates` API can be used to test your hints.
@@ -182,7 +182,7 @@ include-code::MyRuntimeHintsTests[]
[[native-image.advanced.known-limitations]]
[[packaging.native-image.advanced.known-limitations]]
== Known Limitations
GraalVM native images are an evolving technology and not all libraries provide support.

View File

@@ -1,5 +1,5 @@
[[native-image]]
= GraalVM Native Image Support
[[packaging.native-image]]
= GraalVM Native Images
https://www.graalvm.org/native-image/[GraalVM Native Images] are standalone executables that can be generated by processing compiled Java applications ahead-of-time.
Native Images generally have a smaller memory footprint and start faster than their JVM counterparts.

View File

@@ -1,4 +1,4 @@
[[native-image.introducing-graalvm-native-images]]
[[packaging.native-image.introducing-graalvm-native-images]]
= Introducing GraalVM Native Images
GraalVM Native Images provide a new way to deploy and run Java applications.
@@ -12,11 +12,11 @@ This ahead-of-time processing involves statically analyzing your application cod
A GraalVM Native Image is a complete, platform-specific executable.
You do not need to ship a Java Virtual Machine in order to run a native image.
TIP: If you just want to get started and experiment with GraalVM you can skip ahead to the "`xref:native-image/developing-your-first-application.adoc[Developing Your First GraalVM Native Application]`" section and return to this section later.
TIP: If you just want to get started and experiment with GraalVM you can jump to the xref:how-to:native-image/developing-your-first-application.adoc[Developing Your First GraalVM Native Application] section and return to this section later.
[[native-image.introducing-graalvm-native-images.key-differences-with-jvm-deployments]]
[[packaging.native-image.introducing-graalvm-native-images.key-differences-with-jvm-deployments]]
== Key Differences with JVM Deployments
The fact that GraalVM Native Images are produced ahead-of-time means that there are some key differences between native and JVM based applications.
@@ -29,14 +29,14 @@ The main differences are:
* There is no lazy class loading, everything shipped in the executables will be loaded in memory on startup.
* There are some limitations around some aspects of Java applications that are not fully supported.
On top of those differences, Spring uses a process called xref:native-image/introducing-graalvm-native-images.adoc#native-image.introducing-graalvm-native-images.understanding-aot-processing[Spring Ahead-of-Time processing], which imposes further limitations.
On top of those differences, Spring uses a process called xref:packaging/native-image/introducing-graalvm-native-images.adoc#packaging.native-image.introducing-graalvm-native-images.understanding-aot-processing[Spring Ahead-of-Time processing], which imposes further limitations.
Please make sure to read at least the beginning of the next section to learn about those.
TIP: The {url-graal-docs-native-image}/metadata/Compatibility/[Native Image Compatibility Guide] section of the GraalVM reference documentation provides more details about GraalVM limitations.
[[native-image.introducing-graalvm-native-images.understanding-aot-processing]]
[[packaging.native-image.introducing-graalvm-native-images.understanding-aot-processing]]
== Understanding Spring Ahead-of-Time Processing
Typical Spring Boot applications are quite dynamic and configuration is performed at runtime.
@@ -45,7 +45,7 @@ In fact, the concept of Spring Boot auto-configuration depends heavily on reacti
Although it would be possible to tell GraalVM about these dynamic aspects of the application, doing so would undo most of the benefit of static analysis.
So instead, when using Spring Boot to create native images, a closed-world is assumed and the dynamic aspects of the application are restricted.
A closed-world assumption implies, besides xref:native-image/introducing-graalvm-native-images.adoc#native-image.introducing-graalvm-native-images.key-differences-with-jvm-deployments[the limitations created by GraalVM itself], the following restrictions:
A closed-world assumption implies, besides xref:packaging/native-image/introducing-graalvm-native-images.adoc#packaging.native-image.introducing-graalvm-native-images.key-differences-with-jvm-deployments[the limitations created by GraalVM itself], the following restrictions:
* The beans defined in your application cannot change at runtime, meaning:
- The Spring `@Profile` annotation and profile-specific configuration xref:how-to:aot.adoc#howto.aot.conditions[have limitations].
@@ -65,7 +65,7 @@ A Spring AOT processed application will typically generate:
[[native-image.introducing-graalvm-native-images.understanding-aot-processing.source-code-generation]]
[[packaging.native-image.introducing-graalvm-native-images.understanding-aot-processing.source-code-generation]]
=== Source Code Generation
Spring applications are composed of Spring Beans.
@@ -112,7 +112,7 @@ Generated source files can be found in `target/spring-aot/main/sources` when usi
[[native-image.introducing-graalvm-native-images.understanding-aot-processing.hint-file-generation]]
[[packaging.native-image.introducing-graalvm-native-images.understanding-aot-processing.hint-file-generation]]
=== Hint File Generation
In addition to generating source files, the Spring AOT engine will also generate hint files that are used by GraalVM.
@@ -128,7 +128,7 @@ TIP: Generated hint files can be found in `target/spring-aot/main/resources` whe
[[native-image.introducing-graalvm-native-images.understanding-aot-processing.proxy-class-generation]]
[[packaging.native-image.introducing-graalvm-native-images.understanding-aot-processing.proxy-class-generation]]
=== Proxy Class Generation
Spring sometimes needs to generate proxy classes to enhance the code you've written with additional features.

View File

@@ -1,8 +1,9 @@
[[using.packaging-for-production]]
= Packaging Your Application for Production
Executable jars can be used for production deployment.
As they are self-contained, they are also ideally suited for cloud-based deployment.
Once your Spring Boot application is ready for production deployment, there are many options for packaging and optimizing
the application.
See the xref:packaging/index.adoc[Packaging] section of the documentation to read about these features.
For additional "`production ready`" features, such as health, auditing, and metric REST or JMX end-points, consider adding `spring-boot-actuator`.
See _xref:how-to:actuator.adoc[Actuator]_ for details.
For additional "production ready" features, such as health, auditing, and metric REST or JMX end-points, consider adding `spring-boot-actuator`.
See xref:how-to:actuator.adoc[Actuator] for details.

View File

@@ -5,6 +5,9 @@ One of the biggest advantages of packaging your application as a jar and using a
The sample applies to debugging Spring Boot applications.
You do not need any special IDE plugins or extensions.
NOTE: The options below are best suited for running an application locally for development.
For production deployment, see xref:reference:using/packaging-for-production.adoc[Packaging for Production].
NOTE: This section only covers jar-based packaging.
If you choose to package your application as a war file, see your server and IDE documentation.

View File

@@ -478,7 +478,7 @@ To get started with Jersey, include the `spring-boot-starter-jersey` as a depend
include-code::MyJerseyConfig[]
WARNING: Jersey's support for scanning executable archives is rather limited.
For example, it cannot scan for endpoints in a package found in a xref:deployment/installing.adoc[fully executable jar file] or in `WEB-INF/classes` when running an executable war file.
For example, it cannot scan for endpoints in a package found in a xref:how-to:deployment/installing.adoc[fully executable jar file] or in `WEB-INF/classes` when running an executable war file.
To avoid this limitation, the `packages` method should not be used, and endpoints should be registered individually by using the `register` method, as shown in the preceding example.
For more advanced customizations, you can also register an arbitrary number of beans that implement `ResourceConfigCustomizer`.

View File

@@ -63,10 +63,18 @@
*** xref:reference:testing/testcontainers.adoc[]
*** xref:reference:testing/test-utilities.adoc[]
** xref:reference:container-images/index.adoc[]
*** xref:reference:container-images/efficient-images.adoc[]
*** xref:reference:container-images/dockerfiles.adoc[]
*** xref:reference:container-images/cloud-native-buildpacks.adoc[]
** xref:reference:packaging/index.adoc[]
*** xref:reference:packaging/efficient.adoc[]
*** xref:reference:packaging/class-data-sharing.adoc[]
*** xref:reference:packaging/aot.adoc[]
*** xref:reference:packaging/native-image/index.adoc[]
**** xref:reference:packaging/native-image/introducing-graalvm-native-images.adoc[]
**** xref:reference:packaging/native-image/advanced-topics.adoc[]
*** xref:reference:packaging/checkpoint-restore.adoc[]
*** xref:reference:packaging/container-images/index.adoc[]
**** xref:reference:packaging/container-images/efficient-images.adoc[]
**** xref:reference:packaging/container-images/dockerfiles.adoc[]
**** xref:reference:packaging/container-images/cloud-native-buildpacks.adoc[]
** xref:reference:actuator/index.adoc[]
*** xref:reference:actuator/enabling.adoc[]
@@ -82,14 +90,4 @@
*** xref:reference:actuator/process-monitoring.adoc[]
*** xref:reference:actuator/cloud-foundry.adoc[]
** xref:reference:deployment/index.adoc[]
*** xref:reference:deployment/cloud.adoc[]
*** xref:reference:deployment/installing.adoc[]
*** xref:reference:deployment/efficient.adoc[]
** xref:reference:native-image/index.adoc[]
*** xref:reference:native-image/introducing-graalvm-native-images.adoc[]
*** xref:reference:native-image/developing-your-first-application.adoc[]
*** xref:reference:native-image/testing-native-applications.adoc[]
*** xref:reference:native-image/advanced-topics.adoc[]