From 0571984cdad8c728c3daaeba6bddd2c2bb0c47e5 Mon Sep 17 00:00:00 2001 From: Scott Kurz Date: Sun, 24 Mar 2024 11:00:23 -0400 Subject: [PATCH 01/10] Draft for Spring Boot 3 WAR post Signed-off-by: Scott Kurz --- posts/2024-xx-xx-spring-boot-3.adoc | 223 ++++++++++++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 posts/2024-xx-xx-spring-boot-3.adoc diff --git a/posts/2024-xx-xx-spring-boot-3.adoc b/posts/2024-xx-xx-spring-boot-3.adoc new file mode 100644 index 000000000..2961d2105 --- /dev/null +++ b/posts/2024-xx-xx-spring-boot-3.adoc @@ -0,0 +1,223 @@ +--- +layout: post +title: "Running a Spring Boot 3.x application WAR file on Liberty" +# Do NOT change the categories section +categories: blog +author_picture: https://avatars3.githubusercontent.com/scottkurz +author_github: https://github.com/scottkurz +seo-title: Running a Spring Boot 3.x application WAR file on Liberty +seo-description: TODO In version 23.0.0.9 and later, you can easily run a Spring Boot 3.x application from a WAR file on Open Liberty. This post use the Spring Boot Petclinic sample application and the Liberty Maven plugin to create and run a WAR-based Spring Boot 3.1 application on Open Liberty. +blog_description: TODO In version 23.0.0.9 and later, you can easily run a Spring Boot 3.x application from a WAR file on Open Liberty. This post uses the Spring Boot Petclinic sample application and the Liberty Maven plugin to create and run a WAR-based Spring Boot 3.1 application on Open Liberty. +open-graph-image: https://openliberty.io/img/twitter_card.jpg +open-graph-image-alt: Open Liberty Logo +--- += Running a Spring Boot 3.x application WAR file on Liberty +Scott Kurz +:imagesdir: / +:url-prefix: +:url-about: / +//Blank line here is necessary before starting the body of the post. + +As of Liberty version 23.0.0.9 there are now two ways to deploy Spring Boot WAR files on Liberty. + +While a Spring Boot WAR can be deployed like any standard Jakarta EE WAR, it can also be deployed using an optimized deployment for Spring Boot applications. This deployment adds some additional configuration options, and provides advantages for efficiently building Docker container images. + +In this blog post we will step through a simple flow starting from the Spring Initializr. We will deploy this to Liberty via a standard WAR deployment without any Liberty modifications to the app. + +From there we'll show how to deploy using the optimized Spring Boot deployment by adding the liberty-maven-plugin and some minimal config to the pom.xml, and simple server.xml configuration using the `springBoot-3.0` feature. We will then be able to build an efficiently-layered Docker image. + +Much of the Liberty documentation relating to Spring Boot focuses on the optimized deployment associated with the Spring Boot features, and so we spend some extra time in this post explaining both options. + +== Prerequisites +- Java 21 (sample could be easily reworked with Java 17) + +== Deploy as standard WAR + +1. Create project from Spring Initializr ++ +From browser: https://start.spring.io/#!type=maven-project&language=java&platformVersion=3.2.4&packaging=war&jvmVersion=21&groupId=demo&artifactId=spring-liberty&name=spring-liberty&description=Demo%20project%20for%20Spring%20Boot&packageName=demo&dependencies=web ++ +2. Add web controller `vi src/main/java/demo/HelloController.java` ++ +[source,java] +---- +package demo; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class HelloController { + + @GetMapping("/") + public String hello() { + return "Hello from Spring Boot in Open Liberty!"; + } + +} +---- ++ +3. Run with standard WAR deployment with default configuration ++ +[source,sh] +---- +./mvnw io.openliberty.tools:liberty-maven-plugin:3.10:dev -Dtemplate=webProfile10 -DskipTests +---- ++ +4. Test the application by visiting the following URL in a browser: http://localhost:9080/spring-liberty-0.0.1-SNAPSHOT/ ++ +5. Stop the server (with `+C` or `q,` to quit dev mode). ++ +6. Recap ++ +The app is bootstrapped by the web container via the ServletInitializer, extending `SpringBootServletInitializer`. We go out of our way to run this example with only default Liberty and Maven configuration even though it'd be more typical to maintain a server.xml configuration for your app. + +== Use Liberty Spring Boot feature deployment + +We're going to reuse the app from the previous example. + +1. Add liberty-maven-plugin with Spring Boot deployment config to pom.xml: ++ +[source,xml] +---- + + io.openliberty.tools + liberty-maven-plugin + 3.10 + + apps + spring-boot-project + + +---- ++ +2. Create your Liberty server.xml by copying from the Spring Boot template ++ +[source,sh] +---- +./mvnw clean liberty:create -Dtemplate=springBoot3 +mkdir -p src/main/liberty/config/ +cp target/liberty/wlp/usr/servers/defaultServer/server.xml src/main/liberty/config/server.xml +---- ++ +3. Add application arguments to your Spring Boot application configuration in Liberty server.xml ++ +[source,xml] +---- + + --server.servlet.context-path=/testpath + --myarg=myval + +---- ++ +4. Add println to echo args in output ++ +[source,java] +---- + public static void main(String[] args) { + System.out.println("Arguments array = " + java.util.Arrays.toString(args)); + SpringApplication.run(SpringLibertyApplication.class, args); + } +---- ++ +5. Run ++ +Though we won't benefit from using dev mode, we can still use the "lifecycle" built into the 'run' goal. We do need to do a 'package' first to get the Spring Boot "repackage" packaging. ++ +[source,sh] +---- +./mvnw package liberty:run +---- ++ +6. Observe the output: ++ +[source,sh] +---- +[INFO] Arguments array = [--server.servlet.context-path=/testpath, --myarg=myval] +[INFO] . ____ _ __ _ _ +[INFO] /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ +[INFO] ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ +[INFO] \\/ ___)| |_)| | | | | || (_| | ) ) ) ) +[INFO] ' |____| .__|_| |_|_| |_\__, | / / / / +[INFO] =========|_|==============|___/=/_/_/_/ +[INFO] :: Spring Boot :: (v3.2.4) +---- ++ +and also ++ +[source,sh] +---- +[INFO] [AUDIT ] CWWKT0016I: Web application available (default_host): http://localhost:9080/testpath/ +---- ++ +7. Test the application by visiting the following URL in a browser: http://localhost:9080/testpath/ ++ +8. When you finish testing the application, stop the server by typing `+C`. ++ +9. Recap ++ +The server is configured with the https://openliberty.io/docs/latest/reference/feature/springBoot-3.0.html[springBoot-3.0] feature. The liberty-maven-plugin has been added to the pom.xml along with special configuration to use the optimized Spring Boot deployment. The app is packaged as an "executable WAR" by running the `spring-boot:repackage` goal in the `package` phase, and the app is bootstrapped via its `main()` method in `SpringLibertyApplication` passing in application arguments defined in `server.xml`. ++ +If you're wondering, yes, the "executable WAR" binary package here could still be deployed as a standard WAR (though a Spring Boot WAR must be repackaged as an executable WAR to use the optimized deployment). + +== Build container image with efficient layering + +Now that we have used the optimized Spring Boot deployment, we can efficiently build a container image. This image uses an indexed cache at `/lib.index.cache` to store Spring Boot dependencies in their own layer, separate from your application code. + +1. Create your `Dockerfile`. ++ +[source,dockerfile] +---- +# Stage and thin the application +FROM icr.io/appcafe/open-liberty:full-java21-openj9-ubi-minimal as staging + +ARG APPNAME=spring-liberty-0.0.1-SNAPSHOT.war +COPY --chown=1001:0 target/$APPNAME \ + /staging/$APPNAME + +RUN springBootUtility thin \ + --sourceAppPath=/staging/$APPNAME \ + --targetThinAppPath=/staging/thin-$APPNAME \ + --targetLibCachePath=/staging/lib.index.cache + +FROM icr.io/appcafe/open-liberty:kernel-slim-java21-openj9-ubi-minimal + +ARG APPNAME=spring-liberty-0.0.1-SNAPSHOT.war +ARG VERSION=1.0 +ARG REVISION=SNAPSHOT +COPY --chown=1001:0 src/main/liberty/config/server.xml /config/server.xml + +RUN features.sh + +COPY --chown=1001:0 --from=staging /staging/lib.index.cache /lib.index.cache +COPY --chown=1001:0 --from=staging /staging/thin-$APPNAME \ + /config/apps/thin-$APPNAME + +RUN configure.sh +---- ++ +(Note you can use the `full-java17-openj9-ubi` tag to build the equivalent Java 17 image.) ++ +2. Build then run the image ++ +[source,sh] +---- +docker build -t springboot:demo . +docker run -p 9080:9080 -p 9443:9443 -it springboot:demo +---- ++ +== Results + +To recap, a Spring Boot WAR can be deployed to Liberty like any other WAR, or it can be deployed with an optimized deployment using special liberty-maven-plugin configuration and the `springBoot-3.0` feature configured in server.xml. +Though much of the programming model is the same across the two cases, there are some differences including the bootstrap mechanism. + +== References +* Clone the https://github.com/scottkurz/spring-liberty[repository] with the finished code for this blog. +* doc: https://openliberty.io/docs/latest/deploy-spring-boot.html +* instanton: https://openliberty.io/blog/2023/09/26/spring-boot-3-instant-on.html +* GH repo: https://github.com/scottkurz/spring-liberty + +* TODO - way to note support for minor references + 24.0.0.1 (https://github.com/OpenLiberty/open-liberty/pull/27276) support for 3.2 thinning + + From 59a6f98a55bf37ad0ffcb2747a9a3bd3f78948eb Mon Sep 17 00:00:00 2001 From: Scott Kurz Date: Fri, 12 Apr 2024 10:13:58 -0400 Subject: [PATCH 02/10] Rename file correctly Signed-off-by: Scott Kurz --- ...024-xx-xx-spring-boot-3.adoc => 2024-05-01-spring-boot-3.adoc} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename posts/{2024-xx-xx-spring-boot-3.adoc => 2024-05-01-spring-boot-3.adoc} (100%) diff --git a/posts/2024-xx-xx-spring-boot-3.adoc b/posts/2024-05-01-spring-boot-3.adoc similarity index 100% rename from posts/2024-xx-xx-spring-boot-3.adoc rename to posts/2024-05-01-spring-boot-3.adoc From 5520f085e378a3b97b35d9abab2e216780cadd2b Mon Sep 17 00:00:00 2001 From: Scott Kurz Date: Mon, 15 Apr 2024 09:24:33 -0400 Subject: [PATCH 03/10] Address 1st review comments of Laura & others Signed-off-by: Scott Kurz --- posts/2024-05-01-spring-boot-3.adoc | 45 +++++++++++++++++------------ 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/posts/2024-05-01-spring-boot-3.adoc b/posts/2024-05-01-spring-boot-3.adoc index 2961d2105..20e01c8e4 100644 --- a/posts/2024-05-01-spring-boot-3.adoc +++ b/posts/2024-05-01-spring-boot-3.adoc @@ -6,8 +6,8 @@ categories: blog author_picture: https://avatars3.githubusercontent.com/scottkurz author_github: https://github.com/scottkurz seo-title: Running a Spring Boot 3.x application WAR file on Liberty -seo-description: TODO In version 23.0.0.9 and later, you can easily run a Spring Boot 3.x application from a WAR file on Open Liberty. This post use the Spring Boot Petclinic sample application and the Liberty Maven plugin to create and run a WAR-based Spring Boot 3.1 application on Open Liberty. -blog_description: TODO In version 23.0.0.9 and later, you can easily run a Spring Boot 3.x application from a WAR file on Open Liberty. This post uses the Spring Boot Petclinic sample application and the Liberty Maven plugin to create and run a WAR-based Spring Boot 3.1 application on Open Liberty. +seo-description: In version 23.0.0.9 and later, you can easily run a Spring Boot 3.x application from a WAR file on Open Liberty. This post use the Spring Boot Petclinic sample application and the Liberty Maven plugin to create and run a WAR-based Spring Boot 3.1 application on Open Liberty. +blog_description: In version 23.0.0.9 and later, you can easily run a Spring Boot 3.x application from a WAR file on Open Liberty. This post uses the Spring Boot Petclinic sample application and the Liberty Maven plugin to create and run a WAR-based Spring Boot 3.1 application on Open Liberty. open-graph-image: https://openliberty.io/img/twitter_card.jpg open-graph-image-alt: Open Liberty Logo --- @@ -18,18 +18,18 @@ Scott Kurz :url-about: / //Blank line here is necessary before starting the body of the post. -As of Liberty version 23.0.0.9 there are now two ways to deploy Spring Boot WAR files on Liberty. +As of Liberty version 23.0.0.9 there are now two ways to deploy Spring Boot WAR files on Liberty. This allows developers to take advantage of the Spring and Spring Boot libraries while leveraging the performance enhancements Liberty has built especially for Spring Boot applications, addressing https://openliberty.io/blog/2022/10/17/memory-footprint-throughput-update.html[performance] throughput and memory footprint while providing rapid application startup through https://openliberty.io/blog/2023/09/26/spring-boot-3-instant-on.html[InstantOn]. -While a Spring Boot WAR can be deployed like any standard Jakarta EE WAR, it can also be deployed using an optimized deployment for Spring Boot applications. This deployment adds some additional configuration options, and provides advantages for efficiently building Docker container images. +While a Spring Boot WAR can be deployed like any standard Jakarta EE WAR, the WAR can be optimized via a special deployment for Spring Boot applications. The optimization adds some additional configuration options, and provides advantages for efficiently building Docker container images, using some extra pom.xml and server.xml configuration. -In this blog post we will step through a simple flow starting from the Spring Initializr. We will deploy this to Liberty via a standard WAR deployment without any Liberty modifications to the app. +In this blog post, we create a simple app by using the Spring Initializr, and then deploy the app as a WAR to Liberty without any modifications, using the same deployment as for any WAR. -From there we'll show how to deploy using the optimized Spring Boot deployment by adding the liberty-maven-plugin and some minimal config to the pom.xml, and simple server.xml configuration using the `springBoot-3.0` feature. We will then be able to build an efficiently-layered Docker image. +We then show how to optimize the Spring Boot deployment by adding the Liberty Maven Plugin (`liberty-maven-plugin`) and some minimal config to the `pom.xml`, and add a simple `server.xml` configuration with the `springBoot-3.0` feature. We can then build an efficiently-layered Docker image. -Much of the Liberty documentation relating to Spring Boot focuses on the optimized deployment associated with the Spring Boot features, and so we spend some extra time in this post explaining both options. +Though the Spring Boot https://openliberty.io/docs/latest/deploy-spring-boot.html[documentation] in Open Liberty focuses mostly on the optimized deployment associated with the Spring Boot features, there are a couple advantages with using a traditional WAR deployment, which can use the same `server.xml` and `pom.xml` configuration, and maybe the same Docker build, as your non-Spring Boot WARs. So we spend some extra time in this post explaining both options. == Prerequisites -- Java 21 (sample could be easily reworked with Java 17) +- The sample requires Java 21 (though it could be easily reworked using Java 17) == Deploy as standard WAR @@ -66,15 +66,19 @@ public class HelloController { + 4. Test the application by visiting the following URL in a browser: http://localhost:9080/spring-liberty-0.0.1-SNAPSHOT/ + +You should see: ++ + Hello from Spring Boot in Open Liberty! ++ 5. Stop the server (with `+C` or `q,` to quit dev mode). + 6. Recap + The app is bootstrapped by the web container via the ServletInitializer, extending `SpringBootServletInitializer`. We go out of our way to run this example with only default Liberty and Maven configuration even though it'd be more typical to maintain a server.xml configuration for your app. -== Use Liberty Spring Boot feature deployment +== Use optimized Liberty Spring Boot deployment -We're going to reuse the app from the previous example. +We're going to reuse the app from the previous example. By adding some extra configuration in the `pom.xml` and `server.xml` we end up being able to build an efficiently-layered Docker image, and also to parameterize the app with application arguments. 1. Add liberty-maven-plugin with Spring Boot deployment config to pom.xml: + @@ -110,19 +114,19 @@ cp target/liberty/wlp/usr/servers/defaultServer/server.xml src/main/liberty/conf ---- + -4. Add println to echo args in output +4. Add println to echo args in output, `vi ./src/main/java/demo/SpringLibertyApplication.java` + [source,java] ---- - public static void main(String[] args) { + public static void main(String[] args) { System.out.println("Arguments array = " + java.util.Arrays.toString(args)); - SpringApplication.run(SpringLibertyApplication.class, args); - } + SpringApplication.run(SpringLibertyApplication.class, args); + } ---- + 5. Run + -Though we won't benefit from using dev mode, we can still use the "lifecycle" built into the 'run' goal. We do need to do a 'package' first to get the Spring Boot "repackage" packaging. +Though the Liberty Maven Plugin doesn't currently have support for using dev mode (or "loose applications") when using the optimized deployment, we can still use the "lifecycle" built into the 'run' goal. We do need to do a 'package' first to get the Spring Boot "repackage" packaging. + [source,sh] ---- @@ -152,15 +156,19 @@ and also + 7. Test the application by visiting the following URL in a browser: http://localhost:9080/testpath/ + +As before, you should see: ++ + Hello from Spring Boot in Open Liberty! ++ 8. When you finish testing the application, stop the server by typing `+C`. + 9. Recap + The server is configured with the https://openliberty.io/docs/latest/reference/feature/springBoot-3.0.html[springBoot-3.0] feature. The liberty-maven-plugin has been added to the pom.xml along with special configuration to use the optimized Spring Boot deployment. The app is packaged as an "executable WAR" by running the `spring-boot:repackage` goal in the `package` phase, and the app is bootstrapped via its `main()` method in `SpringLibertyApplication` passing in application arguments defined in `server.xml`. + -If you're wondering, yes, the "executable WAR" binary package here could still be deployed as a standard WAR (though a Spring Boot WAR must be repackaged as an executable WAR to use the optimized deployment). +If you're wondering, yes, while a Spring Boot WAR must be repackaged as an executable WAR to use the optimized deployment, that executable WAR could still be deployed as a standard WAR. -== Build container image with efficient layering +=== Build container image with efficient layering Now that we have used the optimized Spring Boot deployment, we can efficiently build a container image. This image uses an indexed cache at `/lib.index.cache` to store Spring Boot dependencies in their own layer, separate from your application code. @@ -205,7 +213,7 @@ RUN configure.sh docker build -t springboot:demo . docker run -p 9080:9080 -p 9443:9443 -it springboot:demo ---- -+ + == Results To recap, a Spring Boot WAR can be deployed to Liberty like any other WAR, or it can be deployed with an optimized deployment using special liberty-maven-plugin configuration and the `springBoot-3.0` feature configured in server.xml. @@ -216,6 +224,7 @@ Though much of the programming model is the same across the two cases, there are * doc: https://openliberty.io/docs/latest/deploy-spring-boot.html * instanton: https://openliberty.io/blog/2023/09/26/spring-boot-3-instant-on.html * GH repo: https://github.com/scottkurz/spring-liberty +* Spring Boot Open Liberty guide: https://openliberty.io/guides/spring-boot.html * TODO - way to note support for minor references 24.0.0.1 (https://github.com/OpenLiberty/open-liberty/pull/27276) support for 3.2 thinning From e69b0ff2df013115705c0f147b37ceede31f3be7 Mon Sep 17 00:00:00 2001 From: Scott Kurz Date: Fri, 26 Apr 2024 17:23:32 -0400 Subject: [PATCH 04/10] Respond to code review comments from @dmuelle Signed-off-by: Scott Kurz --- posts/2024-05-01-spring-boot-3.adoc | 84 +++++++++++++++-------------- 1 file changed, 45 insertions(+), 39 deletions(-) diff --git a/posts/2024-05-01-spring-boot-3.adoc b/posts/2024-05-01-spring-boot-3.adoc index 20e01c8e4..c14b7c4c3 100644 --- a/posts/2024-05-01-spring-boot-3.adoc +++ b/posts/2024-05-01-spring-boot-3.adoc @@ -6,8 +6,8 @@ categories: blog author_picture: https://avatars3.githubusercontent.com/scottkurz author_github: https://github.com/scottkurz seo-title: Running a Spring Boot 3.x application WAR file on Liberty -seo-description: In version 23.0.0.9 and later, you can easily run a Spring Boot 3.x application from a WAR file on Open Liberty. This post use the Spring Boot Petclinic sample application and the Liberty Maven plugin to create and run a WAR-based Spring Boot 3.1 application on Open Liberty. -blog_description: In version 23.0.0.9 and later, you can easily run a Spring Boot 3.x application from a WAR file on Open Liberty. This post uses the Spring Boot Petclinic sample application and the Liberty Maven plugin to create and run a WAR-based Spring Boot 3.1 application on Open Liberty. +seo-description: In version 23.0.0.9 and later, you can easily run a Spring Boot 3.x application from a WAR file on Open Liberty. This post use the Spring Petclinic sample application and the Liberty Maven plugin to create and run a WAR-based Spring Boot 3.1 application on Open Liberty. +blog_description: In version 23.0.0.9 and later, you can easily run a Spring Boot 3.x application from a WAR file on Open Liberty. This post uses the Spring Petclinic sample application and the Liberty Maven plugin to create and run a WAR-based Spring Boot 3.1 application on Open Liberty. open-graph-image: https://openliberty.io/img/twitter_card.jpg open-graph-image-alt: Open Liberty Logo --- @@ -18,26 +18,32 @@ Scott Kurz :url-about: / //Blank line here is necessary before starting the body of the post. -As of Liberty version 23.0.0.9 there are now two ways to deploy Spring Boot WAR files on Liberty. This allows developers to take advantage of the Spring and Spring Boot libraries while leveraging the performance enhancements Liberty has built especially for Spring Boot applications, addressing https://openliberty.io/blog/2022/10/17/memory-footprint-throughput-update.html[performance] throughput and memory footprint while providing rapid application startup through https://openliberty.io/blog/2023/09/26/spring-boot-3-instant-on.html[InstantOn]. +As of version 23.0.0.9, Liberty offers support for Spring Boot 3.1, allowing developers to take advantage of the Spring and Spring Boot libraries while providing a range of https://openliberty.io/blog/2022/10/17/memory-footprint-throughput-update.html[performance] enhancements specifically engineered to provide an industry-leading, first-class platform for Spring Boot applications. -While a Spring Boot WAR can be deployed like any standard Jakarta EE WAR, the WAR can be optimized via a special deployment for Spring Boot applications. The optimization adds some additional configuration options, and provides advantages for efficiently building Docker container images, using some extra pom.xml and server.xml configuration. +When packaging a Spring Boot app in the WAR format, developers and administrators get to choose from two Liberty deployment options, each with a different set of advantages. -In this blog post, we create a simple app by using the Spring Initializr, and then deploy the app as a WAR to Liberty without any modifications, using the same deployment as for any WAR. +A Spring Boot WAR can simply be deployed like any standard Jakarta EE WAR using the same developer tooling and server configuration, and providing a common DevOps workflow as with your other Liberty WAR deployments. -We then show how to optimize the Spring Boot deployment by adding the Liberty Maven Plugin (`liberty-maven-plugin`) and some minimal config to the `pom.xml`, and add a simple `server.xml` configuration with the `springBoot-3.0` feature. We can then build an efficiently-layered Docker image. +In addition, with Liberty, you can use a special https://openliberty.io/docs/latest/deploy-spring-boot.html[optimized deployment for Spring Boot applications]. The optimization adds some configuration options and provides advantages for efficiently building Docker container images by using some extra `pom.xml` and `server.xml` file configuration. + +In this blog post, we'll first create a simple app by using the link:https://start.spring.io/[Spring Initializr], and then deploy it as a WAR to Liberty without any modifications, using the same deployment as for any WAR. + +We then show how to optimize the Spring Boot deployment by adding the Liberty Maven Plugin (`liberty-maven-plugin`) and a simple `server.xml` configuration with the `springBoot-3.0` feature. We can then build an efficiently-layered Docker image. -Though the Spring Boot https://openliberty.io/docs/latest/deploy-spring-boot.html[documentation] in Open Liberty focuses mostly on the optimized deployment associated with the Spring Boot features, there are a couple advantages with using a traditional WAR deployment, which can use the same `server.xml` and `pom.xml` configuration, and maybe the same Docker build, as your non-Spring Boot WARs. So we spend some extra time in this post explaining both options. == Prerequisites - The sample requires Java 21 (though it could be easily reworked using Java 17) == Deploy as standard WAR -1. Create project from Spring Initializr +1. Create a project from your browser using link:https://start.spring.io/#!type=maven-project&language=java&platformVersion=3.2.5&packaging=war&jvmVersion=21&groupId=demo&artifactId=spring-liberty&name=spring-liberty&description=Demo%20project%20for%20Spring%20Boot&packageName=demo&dependencies=web[this Spring Initializr configuration]. + -From browser: https://start.spring.io/#!type=maven-project&language=java&platformVersion=3.2.4&packaging=war&jvmVersion=21&groupId=demo&artifactId=spring-liberty&name=spring-liberty&description=Demo%20project%20for%20Spring%20Boot&packageName=demo&dependencies=web +2. Add the following Spring web controller file (use the `vi` command here, or your preferred editor) : + -2. Add web controller `vi src/main/java/demo/HelloController.java` +[source,sh] +---- +vi src/main/java/demo/HelloController.java +---- + [source,java] ---- @@ -57,7 +63,7 @@ public class HelloController { } ---- + -3. Run with standard WAR deployment with default configuration +3. From the command line, run a standard WAR deployment in https://openliberty.io/docs/latest/development-mode.html[dev mode], with the configuration provided by the `webProfile10` template. + [source,sh] ---- @@ -70,17 +76,19 @@ You should see: + Hello from Spring Boot in Open Liberty! + -5. Stop the server (with `+C` or `q,` to quit dev mode). -+ -6. Recap -+ -The app is bootstrapped by the web container via the ServletInitializer, extending `SpringBootServletInitializer`. We go out of our way to run this example with only default Liberty and Maven configuration even though it'd be more typical to maintain a server.xml configuration for your app. +5. Stop the server by pressing `Ctrl`+`C` or by typing `q` and pressing `Enter` to quit dev mode. + +=== Results + +The app is deployed in dev mode, like you would with any Jakarta EE WAR, without any special configuration or steps specific to Spring Boot. + +The Spring portion of the app is bootstrapped by the web container by using the `SpringBootServletInitializer` extension generated into your application by the **Spring Initializr** and from there you can use the Spring and Spring Boot APIs. == Use optimized Liberty Spring Boot deployment -We're going to reuse the app from the previous example. By adding some extra configuration in the `pom.xml` and `server.xml` we end up being able to build an efficiently-layered Docker image, and also to parameterize the app with application arguments. +This example uses the same Spring app that is created in step 1 of the previous example. By adding some extra configuration in the `pom.xml` and `server.xml`, you can build an efficiently-layered Docker image and also parameterize the app with application arguments. -1. Add liberty-maven-plugin with Spring Boot deployment config to pom.xml: +1. Add liberty-maven-plugin with Spring Boot deployment config to the `pom.xml` file: + [source,xml] ---- @@ -95,7 +103,7 @@ We're going to reuse the app from the previous example. By adding some extra c ---- + -2. Create your Liberty server.xml by copying from the Spring Boot template +2. Create your Liberty `server.xml` file by copying from the Spring Boot template + [source,sh] ---- @@ -104,7 +112,7 @@ mkdir -p src/main/liberty/config/ cp target/liberty/wlp/usr/servers/defaultServer/server.xml src/main/liberty/config/server.xml ---- + -3. Add application arguments to your Spring Boot application configuration in Liberty server.xml +3. Add application arguments to your Spring Boot application configuration in the Liberty `server.xml` file + [source,xml] ---- @@ -114,7 +122,12 @@ cp target/liberty/wlp/usr/servers/defaultServer/server.xml src/main/liberty/conf ---- + -4. Add println to echo args in output, `vi ./src/main/java/demo/SpringLibertyApplication.java` +4. Add `println` to echo arguments in the output (use the `vi` command here, or your preferred editor) : ++ +[source,sh] +---- +vi ./src/main/java/demo/SpringLibertyApplication.java +---- + [source,java] ---- @@ -126,7 +139,7 @@ cp target/liberty/wlp/usr/servers/defaultServer/server.xml src/main/liberty/conf + 5. Run + -Though the Liberty Maven Plugin doesn't currently have support for using dev mode (or "loose applications") when using the optimized deployment, we can still use the "lifecycle" built into the 'run' goal. We do need to do a 'package' first to get the Spring Boot "repackage" packaging. +Although the Liberty Maven Plugin doesn't currently support dev mode when you use the optimized deployment, you can still use the lifecycle built into the 'run' goal. We do need to do a 'package' first to get the Spring Boot `repackage` packaging. + [source,sh] ---- @@ -160,12 +173,12 @@ As before, you should see: + Hello from Spring Boot in Open Liberty! + -8. When you finish testing the application, stop the server by typing `+C`. -+ -9. Recap -+ -The server is configured with the https://openliberty.io/docs/latest/reference/feature/springBoot-3.0.html[springBoot-3.0] feature. The liberty-maven-plugin has been added to the pom.xml along with special configuration to use the optimized Spring Boot deployment. The app is packaged as an "executable WAR" by running the `spring-boot:repackage` goal in the `package` phase, and the app is bootstrapped via its `main()` method in `SpringLibertyApplication` passing in application arguments defined in `server.xml`. -+ +8. When you finish testing the application, stop the server by pressing `Ctrl`+`C`. + +=== Results + +The server is configured with the https://openliberty.io/docs/latest/reference/feature/springBoot-3.0.html[springBoot-3.0] feature. The `liberty-maven-plugin` is added to the `pom.xml`, along with special configuration to use the optimized Spring Boot deployment. The app is packaged as an executable WAR by running the `spring-boot:repackage` goal in the `package` phase, and the app is bootstrapped by its `main()` method in `SpringLibertyApplication`, passing in application arguments defined in `server.xml`, without even the need to provide a `SpringBootServletInitializer` implementation. We can now use the https://openliberty.io/docs/latest/deploy-spring-boot.html#thin[thinning] support to build an efficiently-layered Docker image, which we will show next. + If you're wondering, yes, while a Spring Boot WAR must be repackaged as an executable WAR to use the optimized deployment, that executable WAR could still be deployed as a standard WAR. === Build container image with efficient layering @@ -216,17 +229,10 @@ docker run -p 9080:9080 -p 9443:9443 -it springboot:demo == Results -To recap, a Spring Boot WAR can be deployed to Liberty like any other WAR, or it can be deployed with an optimized deployment using special liberty-maven-plugin configuration and the `springBoot-3.0` feature configured in server.xml. +To recap, you can deploy a Spring Boot WAR to Liberty like any other WAR, or you can deploy it with an optimized deployment using special `liberty-maven-plugin` configuration and the `springBoot-3.0` feature configured in server.xml. Though much of the programming model is the same across the two cases, there are some differences including the bootstrap mechanism. == References -* Clone the https://github.com/scottkurz/spring-liberty[repository] with the finished code for this blog. -* doc: https://openliberty.io/docs/latest/deploy-spring-boot.html -* instanton: https://openliberty.io/blog/2023/09/26/spring-boot-3-instant-on.html -* GH repo: https://github.com/scottkurz/spring-liberty -* Spring Boot Open Liberty guide: https://openliberty.io/guides/spring-boot.html - -* TODO - way to note support for minor references - 24.0.0.1 (https://github.com/OpenLiberty/open-liberty/pull/27276) support for 3.2 thinning - - +* Clone the link:https://github.com/scottkurz/spring-liberty[repository](https://github.com/scottkurz/spring-liberty) with the finished code for the sample app in this blog. +* Docs: link:https://openliberty.io/docs/latest/deploy-spring-boot.html[Configure and Deploy Spring Boot applications to Open Liberty] +* Guide: link:https://openliberty.io/guides/spring-boot.html[Containerizing, packaging, and running a Spring Boot application] From 642559ff72fe410a95d4485592613bf0559ba135 Mon Sep 17 00:00:00 2001 From: Scott Kurz Date: Mon, 29 Apr 2024 16:57:06 -0400 Subject: [PATCH 05/10] Apply review suggestions from @dmuelle Co-authored-by: David Mueller <48686014+dmuelle@users.noreply.github.com> --- posts/2024-05-01-spring-boot-3.adoc | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/posts/2024-05-01-spring-boot-3.adoc b/posts/2024-05-01-spring-boot-3.adoc index c14b7c4c3..8286c4b05 100644 --- a/posts/2024-05-01-spring-boot-3.adoc +++ b/posts/2024-05-01-spring-boot-3.adoc @@ -20,25 +20,25 @@ Scott Kurz As of version 23.0.0.9, Liberty offers support for Spring Boot 3.1, allowing developers to take advantage of the Spring and Spring Boot libraries while providing a range of https://openliberty.io/blog/2022/10/17/memory-footprint-throughput-update.html[performance] enhancements specifically engineered to provide an industry-leading, first-class platform for Spring Boot applications. -When packaging a Spring Boot app in the WAR format, developers and administrators get to choose from two Liberty deployment options, each with a different set of advantages. +When you package a Spring Boot app in the WAR format, you can choose from two Liberty deployment options, each with a different set of advantages. -A Spring Boot WAR can simply be deployed like any standard Jakarta EE WAR using the same developer tooling and server configuration, and providing a common DevOps workflow as with your other Liberty WAR deployments. +You can deploy a Spring Boot WAR like any standard Jakarta EE WAR by using the same developer tooling and server configuration, and providing a common DevOps workflow with your other Liberty WAR deployments. -In addition, with Liberty, you can use a special https://openliberty.io/docs/latest/deploy-spring-boot.html[optimized deployment for Spring Boot applications]. The optimization adds some configuration options and provides advantages for efficiently building Docker container images by using some extra `pom.xml` and `server.xml` file configuration. +Alternatively, you can use a special https://openliberty.io/docs/latest/deploy-spring-boot.html[optimized Liberty deployment for Spring Boot applications]. This optimization adds some configuration options and provides advantages to efficiently build Docker container images. In this blog post, we'll first create a simple app by using the link:https://start.spring.io/[Spring Initializr], and then deploy it as a WAR to Liberty without any modifications, using the same deployment as for any WAR. -We then show how to optimize the Spring Boot deployment by adding the Liberty Maven Plugin (`liberty-maven-plugin`) and a simple `server.xml` configuration with the `springBoot-3.0` feature. We can then build an efficiently-layered Docker image. +We then show how to optimize the Spring Boot deployment by adding the Liberty Maven Plugin (`liberty-maven-plugin`) and a simple `server.xml` configuration with the `springBoot-3.0` feature. We can then build an efficiently-layered Docker image. == Prerequisites -- The sample requires Java 21 (though it could be easily reworked using Java 17) +- The sample requires Java 21 (though you could be easily rework it to use Java 17) -== Deploy as standard WAR +== Option 1: Deploy your Spring Boot app as standard WAR file 1. Create a project from your browser using link:https://start.spring.io/#!type=maven-project&language=java&platformVersion=3.2.5&packaging=war&jvmVersion=21&groupId=demo&artifactId=spring-liberty&name=spring-liberty&description=Demo%20project%20for%20Spring%20Boot&packageName=demo&dependencies=web[this Spring Initializr configuration]. + -2. Add the following Spring web controller file (use the `vi` command here, or your preferred editor) : +2. Add the following Spring web controller file (use the `vi` command here, or your preferred editor). + [source,sh] ---- @@ -84,7 +84,7 @@ The app is deployed in dev mode, like you would with any Jakarta EE WAR, without The Spring portion of the app is bootstrapped by the web container by using the `SpringBootServletInitializer` extension generated into your application by the **Spring Initializr** and from there you can use the Spring and Spring Boot APIs. -== Use optimized Liberty Spring Boot deployment +== Option 2: Use the optimized Liberty Spring Boot deployment This example uses the same Spring app that is created in step 1 of the previous example. By adding some extra configuration in the `pom.xml` and `server.xml`, you can build an efficiently-layered Docker image and also parameterize the app with application arguments. @@ -103,7 +103,7 @@ This example uses the same Spring app that is created in step 1 of the previous ---- + -2. Create your Liberty `server.xml` file by copying from the Spring Boot template +2. Create your Liberty `server.xml` file by copying from the Spring Boot template. + [source,sh] ---- @@ -112,7 +112,7 @@ mkdir -p src/main/liberty/config/ cp target/liberty/wlp/usr/servers/defaultServer/server.xml src/main/liberty/config/server.xml ---- + -3. Add application arguments to your Spring Boot application configuration in the Liberty `server.xml` file +3. Add application arguments to your Spring Boot application configuration in the Liberty `server.xml` file. + [source,xml] ---- @@ -122,7 +122,7 @@ cp target/liberty/wlp/usr/servers/defaultServer/server.xml src/main/liberty/conf ---- + -4. Add `println` to echo arguments in the output (use the `vi` command here, or your preferred editor) : +4. Add `println` to echo arguments in the output (use the `vi` command here, or your preferred editor). + [source,sh] ---- @@ -219,7 +219,7 @@ RUN configure.sh + (Note you can use the `full-java17-openj9-ubi` tag to build the equivalent Java 17 image.) + -2. Build then run the image +2. Build then run the image. + [source,sh] ---- @@ -229,8 +229,8 @@ docker run -p 9080:9080 -p 9443:9443 -it springboot:demo == Results -To recap, you can deploy a Spring Boot WAR to Liberty like any other WAR, or you can deploy it with an optimized deployment using special `liberty-maven-plugin` configuration and the `springBoot-3.0` feature configured in server.xml. -Though much of the programming model is the same across the two cases, there are some differences including the bootstrap mechanism. +To recap, you can deploy a Spring Boot WAR to Liberty like any other WAR, or you can configure an optimized deployment using special `liberty-maven-plugin` configuration and the `springBoot-3.0` feature in the `server.xml` file. +Though much of the programming model is the same across the two cases, there are some differences, including the bootstrap mechanism and the ability to create more efficient Docker layers with the optimized deployment. == References * Clone the link:https://github.com/scottkurz/spring-liberty[repository](https://github.com/scottkurz/spring-liberty) with the finished code for the sample app in this blog. From 1e4d618773450edfbe7e2658378c464a597c985a Mon Sep 17 00:00:00 2001 From: Scott Kurz Date: Mon, 29 Apr 2024 17:27:41 -0400 Subject: [PATCH 06/10] More comments after @dmuelle review Signed-off-by: Scott Kurz --- posts/2024-05-01-spring-boot-3.adoc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/posts/2024-05-01-spring-boot-3.adoc b/posts/2024-05-01-spring-boot-3.adoc index 8286c4b05..c6f8fd626 100644 --- a/posts/2024-05-01-spring-boot-3.adoc +++ b/posts/2024-05-01-spring-boot-3.adoc @@ -22,7 +22,7 @@ As of version 23.0.0.9, Liberty offers support for Spring Boot 3.1, allowing dev When you package a Spring Boot app in the WAR format, you can choose from two Liberty deployment options, each with a different set of advantages. -You can deploy a Spring Boot WAR like any standard Jakarta EE WAR by using the same developer tooling and server configuration, and providing a common DevOps workflow with your other Liberty WAR deployments. +You can deploy a Spring Boot WAR like any standard Jakarta EE WAR by using the same developer tooling and server configuration, and providing a common DevOps workflow with your other Liberty WAR deployments. Alternatively, you can use a special https://openliberty.io/docs/latest/deploy-spring-boot.html[optimized Liberty deployment for Spring Boot applications]. This optimization adds some configuration options and provides advantages to efficiently build Docker container images. @@ -88,7 +88,7 @@ The Spring portion of the app is bootstrapped by the web container by using the This example uses the same Spring app that is created in step 1 of the previous example. By adding some extra configuration in the `pom.xml` and `server.xml`, you can build an efficiently-layered Docker image and also parameterize the app with application arguments. -1. Add liberty-maven-plugin with Spring Boot deployment config to the `pom.xml` file: +1. Add the `liberty-maven-plugin` plus the configuration for the optimized Spring Boot deployment to your `pom.xml` file. + [source,xml] ---- @@ -137,7 +137,7 @@ vi ./src/main/java/demo/SpringLibertyApplication.java } ---- + -5. Run +5. Run the application with the Liberty Maven Plugin + Although the Liberty Maven Plugin doesn't currently support dev mode when you use the optimized deployment, you can still use the lifecycle built into the 'run' goal. We do need to do a 'package' first to get the Spring Boot `repackage` packaging. + From 3caccc4cc16b33f9c61a2d6cf5b652d972463b0b Mon Sep 17 00:00:00 2001 From: Scott Kurz Date: Tue, 30 Apr 2024 13:30:59 -0400 Subject: [PATCH 07/10] Explain flow between parts 1 and 2 Signed-off-by: Scott Kurz --- posts/2024-05-01-spring-boot-3.adoc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/posts/2024-05-01-spring-boot-3.adoc b/posts/2024-05-01-spring-boot-3.adoc index c6f8fd626..7754d29e7 100644 --- a/posts/2024-05-01-spring-boot-3.adoc +++ b/posts/2024-05-01-spring-boot-3.adoc @@ -30,11 +30,10 @@ In this blog post, we'll first create a simple app by using the link:https://sta We then show how to optimize the Spring Boot deployment by adding the Liberty Maven Plugin (`liberty-maven-plugin`) and a simple `server.xml` configuration with the `springBoot-3.0` feature. We can then build an efficiently-layered Docker image. - == Prerequisites - The sample requires Java 21 (though you could be easily rework it to use Java 17) -== Option 1: Deploy your Spring Boot app as standard WAR file +== Part 1: Deploy your Spring Boot app as standard WAR file 1. Create a project from your browser using link:https://start.spring.io/#!type=maven-project&language=java&platformVersion=3.2.5&packaging=war&jvmVersion=21&groupId=demo&artifactId=spring-liberty&name=spring-liberty&description=Demo%20project%20for%20Spring%20Boot&packageName=demo&dependencies=web[this Spring Initializr configuration]. + @@ -84,9 +83,9 @@ The app is deployed in dev mode, like you would with any Jakarta EE WAR, without The Spring portion of the app is bootstrapped by the web container by using the `SpringBootServletInitializer` extension generated into your application by the **Spring Initializr** and from there you can use the Spring and Spring Boot APIs. -== Option 2: Use the optimized Liberty Spring Boot deployment +== Part 2: Use the optimized Liberty Spring Boot deployment -This example uses the same Spring app that is created in step 1 of the previous example. By adding some extra configuration in the `pom.xml` and `server.xml`, you can build an efficiently-layered Docker image and also parameterize the app with application arguments. +This example uses the same Spring app that is created in step 1 of the example in Part 1. By adding some extra configuration in the `pom.xml` and `server.xml`, you can build an efficiently-layered Docker image and also parameterize the app with application arguments. 1. Add the `liberty-maven-plugin` plus the configuration for the optimized Spring Boot deployment to your `pom.xml` file. + @@ -232,6 +231,8 @@ docker run -p 9080:9080 -p 9443:9443 -it springboot:demo To recap, you can deploy a Spring Boot WAR to Liberty like any other WAR, or you can configure an optimized deployment using special `liberty-maven-plugin` configuration and the `springBoot-3.0` feature in the `server.xml` file. Though much of the programming model is the same across the two cases, there are some differences, including the bootstrap mechanism and the ability to create more efficient Docker layers with the optimized deployment. +(**Note:** the flow through Parts 1 and 2 of this blog post are a bit contrived to show the two deployment options, and your real development workflow would probably look a bit different. When using a traditional WAR deployment you would likely maintain your own `server.xml` file rather than continuing to use the template configuration. When using the optimized Liberty deployment there's no need to do a traditional deployment first.) + == References * Clone the link:https://github.com/scottkurz/spring-liberty[repository](https://github.com/scottkurz/spring-liberty) with the finished code for the sample app in this blog. * Docs: link:https://openliberty.io/docs/latest/deploy-spring-boot.html[Configure and Deploy Spring Boot applications to Open Liberty] From 98bcd73e4675c48f94ac75663877547d491a8ec4 Mon Sep 17 00:00:00 2001 From: Scott Kurz Date: Tue, 30 Apr 2024 15:46:45 -0400 Subject: [PATCH 08/10] last changes Signed-off-by: Scott Kurz --- posts/2024-05-01-spring-boot-3.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/posts/2024-05-01-spring-boot-3.adoc b/posts/2024-05-01-spring-boot-3.adoc index 7754d29e7..f6caeaab1 100644 --- a/posts/2024-05-01-spring-boot-3.adoc +++ b/posts/2024-05-01-spring-boot-3.adoc @@ -180,7 +180,7 @@ The server is configured with the https://openliberty.io/docs/latest/reference/f If you're wondering, yes, while a Spring Boot WAR must be repackaged as an executable WAR to use the optimized deployment, that executable WAR could still be deployed as a standard WAR. -=== Build container image with efficient layering +=== Part 3: Build container image with efficient layering Now that we have used the optimized Spring Boot deployment, we can efficiently build a container image. This image uses an indexed cache at `/lib.index.cache` to store Spring Boot dependencies in their own layer, separate from your application code. @@ -234,6 +234,6 @@ Though much of the programming model is the same across the two cases, there are (**Note:** the flow through Parts 1 and 2 of this blog post are a bit contrived to show the two deployment options, and your real development workflow would probably look a bit different. When using a traditional WAR deployment you would likely maintain your own `server.xml` file rather than continuing to use the template configuration. When using the optimized Liberty deployment there's no need to do a traditional deployment first.) == References -* Clone the link:https://github.com/scottkurz/spring-liberty[repository](https://github.com/scottkurz/spring-liberty) with the finished code for the sample app in this blog. +* Clone the link:https://github.com/scottkurz/spring-liberty[repository] with the finished code for the sample app in this blog. * Docs: link:https://openliberty.io/docs/latest/deploy-spring-boot.html[Configure and Deploy Spring Boot applications to Open Liberty] * Guide: link:https://openliberty.io/guides/spring-boot.html[Containerizing, packaging, and running a Spring Boot application] From c1d39b9199707ac7494a73384e339ac57f0a21b0 Mon Sep 17 00:00:00 2001 From: Scott Kurz Date: Tue, 30 Apr 2024 16:29:57 -0400 Subject: [PATCH 09/10] Update posts/2024-05-01-spring-boot-3.adoc Co-authored-by: David Mueller <48686014+dmuelle@users.noreply.github.com> --- posts/2024-05-01-spring-boot-3.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/posts/2024-05-01-spring-boot-3.adoc b/posts/2024-05-01-spring-boot-3.adoc index f6caeaab1..be693e88a 100644 --- a/posts/2024-05-01-spring-boot-3.adoc +++ b/posts/2024-05-01-spring-boot-3.adoc @@ -180,7 +180,7 @@ The server is configured with the https://openliberty.io/docs/latest/reference/f If you're wondering, yes, while a Spring Boot WAR must be repackaged as an executable WAR to use the optimized deployment, that executable WAR could still be deployed as a standard WAR. -=== Part 3: Build container image with efficient layering +== Part 3: Build a container image with efficient layering Now that we have used the optimized Spring Boot deployment, we can efficiently build a container image. This image uses an indexed cache at `/lib.index.cache` to store Spring Boot dependencies in their own layer, separate from your application code. From 99252cf34be96dc870bc8d55cdf0b3b973e63d29 Mon Sep 17 00:00:00 2001 From: Scott Kurz Date: Tue, 30 Apr 2024 16:30:26 -0400 Subject: [PATCH 10/10] Update posts/2024-05-01-spring-boot-3.adoc Co-authored-by: David Mueller <48686014+dmuelle@users.noreply.github.com> --- posts/2024-05-01-spring-boot-3.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/posts/2024-05-01-spring-boot-3.adoc b/posts/2024-05-01-spring-boot-3.adoc index be693e88a..522dc53b5 100644 --- a/posts/2024-05-01-spring-boot-3.adoc +++ b/posts/2024-05-01-spring-boot-3.adoc @@ -231,7 +231,7 @@ docker run -p 9080:9080 -p 9443:9443 -it springboot:demo To recap, you can deploy a Spring Boot WAR to Liberty like any other WAR, or you can configure an optimized deployment using special `liberty-maven-plugin` configuration and the `springBoot-3.0` feature in the `server.xml` file. Though much of the programming model is the same across the two cases, there are some differences, including the bootstrap mechanism and the ability to create more efficient Docker layers with the optimized deployment. -(**Note:** the flow through Parts 1 and 2 of this blog post are a bit contrived to show the two deployment options, and your real development workflow would probably look a bit different. When using a traditional WAR deployment you would likely maintain your own `server.xml` file rather than continuing to use the template configuration. When using the optimized Liberty deployment there's no need to do a traditional deployment first.) +**Note:** The flow through Parts 1 and 2 of this blog post is a bit contrived to show the two deployment options, and your real development workflow would probably look a bit different. When using a traditional WAR deployment, you would likely maintain your own `server.xml` file rather than continuing to use the template configuration. When using the optimized Liberty deployment, there's no need to do a traditional deployment first. == References * Clone the link:https://github.com/scottkurz/spring-liberty[repository] with the finished code for the sample app in this blog.