diff --git a/.gitbook/assets/common-static-analysis-list.png b/.gitbook/assets/common-static-analysis-list.png new file mode 100644 index 00000000..abc006d4 Binary files /dev/null and b/.gitbook/assets/common-static-analysis-list.png differ diff --git a/.gitbook/assets/configure-build.patch b/.gitbook/assets/configure-build.patch new file mode 100644 index 00000000..cfb0aea7 --- /dev/null +++ b/.gitbook/assets/configure-build.patch @@ -0,0 +1,91 @@ +diff --git a/build.gradle b/build.gradle +index c517cfc..c040d7d 100644 +--- a/build.gradle ++++ b/build.gradle +@@ -1,17 +1,18 @@ +-buildscript { +- dependencies { +- classpath 'ro.isdc.wro4j.gradle:wro4j-gradle-plugin:1.8.0.Beta4' +- } +-} ++//buildscript { ++// dependencies { ++// classpath 'ro.isdc.wro4j.gradle:wro4j-gradle-plugin:1.8.0.Beta4' ++// } ++//} + + plugins { + id 'org.springframework.boot' version '2.4.5' + id 'io.spring.dependency-management' version '1.0.11.RELEASE' + id 'java' ++ id 'org.openrewrite.rewrite' version '6.4.3' + } + + apply plugin: 'java' +-apply plugin: 'wro4j' ++//apply plugin: 'wro4j' + + group = 'org.springframework.samples' + version = '2.4.5' +@@ -32,29 +33,35 @@ dependencies { + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-validation' + implementation 'javax.cache:cache-api' +- webjarsRuntime 'org.webjars:webjars-locator-core' +- webjarsRuntime "org.webjars:jquery:${webjarsJqueryVersion}" +- webjarsRuntime "org.webjars:jquery-ui:${webjarsJqueryUiVersion}" +- webjarsRuntime "org.webjars:bootstrap:${webjarsBootstrapVersion}" +- webjarsRuntime "org.webjars:bootstrap:${webjarsBootstrapVersion}" ++// webjarsRuntime 'org.webjars:webjars-locator-core' ++// webjarsRuntime "org.webjars:jquery:${webjarsJqueryVersion}" ++// webjarsRuntime "org.webjars:jquery-ui:${webjarsJqueryUiVersion}" ++// webjarsRuntime "org.webjars:bootstrap:${webjarsBootstrapVersion}" ++// webjarsRuntime "org.webjars:bootstrap:${webjarsBootstrapVersion}" + runtimeOnly 'org.ehcache:ehcache' + runtimeOnly 'com.h2database:h2' + runtimeOnly 'mysql:mysql-connector-java' + developmentOnly 'org.springframework.boot:spring-boot-devtools' + testImplementation 'org.springframework.boot:spring-boot-starter-test' ++ ++ rewrite 'org.openrewrite.recipe:rewrite-static-analysis:latest.release' ++} ++ ++rewrite { ++ activeRecipe 'org.openrewrite.staticanalysis.CommonStaticAnalysis' + } + + test { + useJUnitPlatform() + } + +-webResources { +- srcMainDir = layout.projectDirectory.dir('src/main').asFile +- dstStaticFolder = 'static/resources/css' +- bundle ('petclinic') { +- css 'webjars/bootstrap/3.3.6/less/bootstrap.less' +- css 'less/petclinic.less' +- preProcessor 'lessCssImport' +- postProcessor 'less4j' +- } +-} ++//webResources { ++// srcMainDir = layout.projectDirectory.dir('src/main').asFile ++// dstStaticFolder = 'static/resources/css' ++// bundle ('petclinic') { ++// css 'webjars/bootstrap/3.3.6/less/bootstrap.less' ++// css 'less/petclinic.less' ++// preProcessor 'lessCssImport' ++// postProcessor 'less4j' ++// } ++//} +diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties +index 442d913..98debb8 100644 +--- a/gradle/wrapper/gradle-wrapper.properties ++++ b/gradle/wrapper/gradle-wrapper.properties +@@ -1,5 +1,5 @@ + distributionBase=GRADLE_USER_HOME + distributionPath=wrapper/dists +-distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip ++distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.2-bin.zip + zipStoreBase=GRADLE_USER_HOME + zipStorePath=wrapper/dists diff --git a/.gitbook/assets/image (1) (1) (1) (1) (1) (1).png b/.gitbook/assets/image (1) (1) (1) (1) (1) (1).png new file mode 100644 index 00000000..5868e8be Binary files /dev/null and b/.gitbook/assets/image (1) (1) (1) (1) (1) (1).png differ diff --git a/.gitbook/assets/image (1) (1) (1) (1) (1).png b/.gitbook/assets/image (1) (1) (1) (1) (1).png index 5868e8be..202fc7d9 100644 Binary files a/.gitbook/assets/image (1) (1) (1) (1) (1).png and b/.gitbook/assets/image (1) (1) (1) (1) (1).png differ diff --git a/.gitbook/assets/image (1) (1) (1) (1).png b/.gitbook/assets/image (1) (1) (1) (1).png index 202fc7d9..e39a3afb 100644 Binary files a/.gitbook/assets/image (1) (1) (1) (1).png and b/.gitbook/assets/image (1) (1) (1) (1).png differ diff --git a/.gitbook/assets/image (1) (1) (1).png b/.gitbook/assets/image (1) (1) (1).png index e39a3afb..02baf9da 100644 Binary files a/.gitbook/assets/image (1) (1) (1).png and b/.gitbook/assets/image (1) (1) (1).png differ diff --git a/.gitbook/assets/image (1) (1).png b/.gitbook/assets/image (1) (1).png index 02baf9da..81169ce0 100644 Binary files a/.gitbook/assets/image (1) (1).png and b/.gitbook/assets/image (1) (1).png differ diff --git a/.gitbook/assets/image (1).png b/.gitbook/assets/image (1).png index 81169ce0..4c6b30bc 100644 Binary files a/.gitbook/assets/image (1).png and b/.gitbook/assets/image (1).png differ diff --git a/.gitbook/assets/image.png b/.gitbook/assets/image.png index 4c6b30bc..47d5230a 100644 Binary files a/.gitbook/assets/image.png and b/.gitbook/assets/image.png differ diff --git a/.gitbook/assets/init.gradle b/.gitbook/assets/init.gradle new file mode 100644 index 00000000..85d17342 --- /dev/null +++ b/.gitbook/assets/init.gradle @@ -0,0 +1,26 @@ +initscript { + repositories { + maven { url "https://plugins.gradle.org/m2" } + } + + dependencies { + classpath("org.openrewrite:plugin:latest.release") + } +} + +rootProject { + plugins.apply(org.openrewrite.gradle.RewritePlugin) + dependencies { + rewrite("org.openrewrite.recipe:rewrite-spring:latest.release") + } + rewrite { + activeRecipe("org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1") + } + afterEvaluate { + if (repositories.isEmpty()) { + repositories { + mavenCentral() + } + } + } +} \ No newline at end of file diff --git a/.gitbook/assets/mod-org (1).png b/.gitbook/assets/mod-org (1).png new file mode 100644 index 00000000..5538b0be Binary files /dev/null and b/.gitbook/assets/mod-org (1).png differ diff --git a/.gitbook/assets/mod-org (2).png b/.gitbook/assets/mod-org (2).png new file mode 100644 index 00000000..5538b0be Binary files /dev/null and b/.gitbook/assets/mod-org (2).png differ diff --git a/.gitbook/assets/mod-org.png b/.gitbook/assets/mod-org.png new file mode 100644 index 00000000..8c1eeb0b Binary files /dev/null and b/.gitbook/assets/mod-org.png differ diff --git a/.gitbook/assets/more-details.png b/.gitbook/assets/more-details.png new file mode 100644 index 00000000..183d084f Binary files /dev/null and b/.gitbook/assets/more-details.png differ diff --git a/.gitbook/assets/organizations-and-repos.png b/.gitbook/assets/organizations-and-repos.png new file mode 100644 index 00000000..f8bc319a Binary files /dev/null and b/.gitbook/assets/organizations-and-repos.png differ diff --git a/.gitbook/assets/support-timelines.png b/.gitbook/assets/support-timelines.png new file mode 100644 index 00000000..5eb221b5 Binary files /dev/null and b/.gitbook/assets/support-timelines.png differ diff --git a/.gitbook/assets/why-did-this-change (1).png b/.gitbook/assets/why-did-this-change (1).png new file mode 100644 index 00000000..316fb1b3 Binary files /dev/null and b/.gitbook/assets/why-did-this-change (1).png differ diff --git a/.gitbook/assets/why-did-this-change.png b/.gitbook/assets/why-did-this-change.png index 316fb1b3..2396465a 100644 Binary files a/.gitbook/assets/why-did-this-change.png and b/.gitbook/assets/why-did-this-change.png differ diff --git a/SUMMARY.md b/SUMMARY.md index c24c48e5..f1c9153a 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -63,6 +63,16 @@ * [Concepts](administrator-documentation/references/concepts/README.md) * [Lossless semantic trees](administrator-documentation/references/concepts/lossless-semantic-trees.md) +## Workshops + +* [Spring Boot migration workshop](workshops/spring-boot-migration-workshop/README.md) + * [Maven plugin exercise](workshops/spring-boot-migration-workshop/maven-plugin-exercise.md) + * [Gradle plugin exercise](workshops/spring-boot-migration-workshop/gradle-plugin-exercise.md) + * [Moderne CLI exercise](workshops/spring-boot-migration-workshop/moderne-cli-exercise.md) + * [Moderne platform exercise](workshops/spring-boot-migration-workshop/moderne-platform-exercise.md) + * [Migrate your own project](workshops/spring-boot-migration-workshop/migrate-your-own-project.md) + * [Recipe development](workshops/spring-boot-migration-workshop/recipe-development.md) + ## Releases * [Agent releases](releases/agent-releases.md) diff --git a/administrator-documentation/references/reporting.md b/administrator-documentation/references/reporting.md index 3d5736c3..b293125e 100644 --- a/administrator-documentation/references/reporting.md +++ b/administrator-documentation/references/reporting.md @@ -16,9 +16,9 @@ Moderne offers three types of reports for administrators: Audit logs are accessible from https://\.moderne.io/admin/audit-logs, and can be viewed in the UI, accessed from the API, or downloaded in [CEF format](https://www.microfocus.com/documentation/arcsight/arcsight-smartconnectors-8.3/cef-implementation-standard/#CEF/Chapter%201%20What%20is%20CEF.htm?TocPath=\_\_\_\_\_2). -
+
-To download audit logs, use the "Export to CEF" button: ![](<../../.gitbook/assets/image (1) (1) (1).png>) +To download audit logs, use the "Export to CEF" button: ![](<../../.gitbook/assets/image (1) (1) (1) (1).png>) ## Other reports (recipe runs and commits) diff --git a/releases/changelog.md b/releases/changelog.md index 1a61ff9a..fd82193d 100644 --- a/releases/changelog.md +++ b/releases/changelog.md @@ -40,7 +40,7 @@ feat/add-yielded-state We have plans to overhaul the iconography to create better visual consistency and clarity. This journey begins this version with a rework of the left navigation icons:\ -![](<../.gitbook/assets/image (1).png>) +![](<../.gitbook/assets/image (1) (1).png>) ### UI v9.173.0 (2023/10/17) @@ -249,7 +249,7 @@ We've done a little tidying up on the recipe run result page. _**Visualizations* #### Add dropdown options to share button -![](<../.gitbook/assets/image (1) (1) (1) (1).png>) +![](<../.gitbook/assets/image (1) (1) (1) (1) (1).png>) When sharing a recipe from the recipes details, you can now select whether or not to include your current organizations. diff --git a/user-documentation/getting-started/code-quality.md b/user-documentation/getting-started/code-quality.md index 06503e4a..68c71448 100644 --- a/user-documentation/getting-started/code-quality.md +++ b/user-documentation/getting-started/code-quality.md @@ -43,7 +43,7 @@ You can click on any of the repositories to look at the suggested changes and le If you want to learn more about _why_ the code is changing, you can press the three dots (`...`) in the top right-hand corner of any file and select `Why did this change?`: -![](../../.gitbook/assets/why-did-this-change.png) +![](<../../.gitbook/assets/why-did-this-change (1).png>) This will display a list of all of the recipes that affected the selected file along with a sentence or two describing the rule in more detail: diff --git a/workshops/spring-boot-migration-workshop/README.md b/workshops/spring-boot-migration-workshop/README.md new file mode 100644 index 00000000..ddf46e3c --- /dev/null +++ b/workshops/spring-boot-migration-workshop/README.md @@ -0,0 +1,31 @@ +# Spring Boot migration workshop + +In this workshop, you'll find a variety of exercises that demonstrate the different ways you can automatically migrate or upgrade an application to Spring Boot 3. The core technology behind each of these exercises is [OpenRewrite](https://github.com/openrewrite/rewrite). + +You do not need to complete all of these exercises. Instead, please pick the ones that are more interesting or relevant to your needs. + +Regardless of which exercise you pick, you will migrate an old version of the [Spring PetClinic repository ](https://github.com/spring-projects/spring-petclinic/)to Spring Boot 3. + +### Introduction + +There's a small introductory presentation to accompany this workshop that you can find at the following link: [Spring Boot 3 is here; Where are you?](https://docs.google.com/presentation/d/1JZYjOfnmFX3l2q1wrOPpcGLba-kwmA\_gbuX5V\_2lZNg/edit#slide=id.g27b5a4473e1\_0\_187) + +### Requirements + +To complete our exercises, you will need: + +* Some basic Spring and Git knowledge +* To have Java 8 and Java 17 installed +* A GitHub account +* An IDE of your choice (although we recommend [Visual Studio Code](../../user-documentation/getting-started/) for the Spring Tools 4 exercise). + +### Exercises + +Get started with any of the following exercises: + +* [Maven plugin exercise](maven-plugin-exercise.md) +* [Gradle plugin exercise](gradle-plugin-exercise.md) +* [Moderne CLI exercise](moderne-cli-exercise.md) +* [Moderne platform exercise](moderne-platform-exercise.md) +* [Migrate your own project](migrate-your-own-project.md) +* [Recipe development](recipe-development.md) diff --git a/workshops/spring-boot-migration-workshop/gradle-plugin-exercise.md b/workshops/spring-boot-migration-workshop/gradle-plugin-exercise.md new file mode 100644 index 00000000..bb971521 --- /dev/null +++ b/workshops/spring-boot-migration-workshop/gradle-plugin-exercise.md @@ -0,0 +1,1876 @@ +# Gradle plugin exercise + +In this exercise, you will migrate an old version of the [SpringPetClinic repository](https://github.com/spring-projects/spring-petclinic/) (that uses Spring Boot 2) to Spring Boot 3. + +If you were migrating this by hand, you would need to do a variety of things, such as: + +* Migrating to Java 17 +* Migrating to Spring Boot 2.7 +* Migrating to Spring Security 5.8 +* Migrating to Spring Cloud 2022 +* Migrating to Jakarta EE 9 +* Migrating to Spring Boot 3.0 +* Migrating to Spring Security 6.0 +* Migrating to Spring Boot 3.1 +* ... + +Fortunately, [OpenRewrite](https://docs.openrewrite.org/) has a [recipe](https://docs.openrewrite.org/concepts-explanations/recipes) that takes care of all of these pieces for you. Because of that, you only need to add the OpenRewrite plugin to your project and run a single [Migrate to Spring Boot 3.1 recipe](https://docs.openrewrite.org/recipes/java/spring/boot3/upgradespringboot\_3\_1). + +Let's walk through how to do that. + +### Prepare your environment + +Switch to Java 11 so that you can build this repository. Please notice that we need Java 11 and not Java 8 like in the [Maven plugin exercise](maven-plugin-exercise.md). This is because the first commit that supports Gradle build already uses Java 11. + +You might need to download Java 11 and update your `JAVA_HOME` environment variable. If you are on a Unix-based system, we recommend using [SDKMan](https://sdkman.io/): + +```bash +sdk install java 11.0.21-tem +sdk use java 11.0.21-tem +``` + +{% hint style="info" %} +If you aren't on a Unix-based system or you don't want to install SDKMan, you'll need to install Java 8 and run something like: + +```bash +export JAVA_HOME=REPLACE_WITH_LOCATION_OF_JAVA_11 +``` +{% endhint %} + +1. Clone the [Spring PetClinic repository](https://github.com/spring-projects/spring-petclinic): + +```bash +git clone https://github.com/spring-projects/spring-petclinic +``` + +2. Check out the first Gradle build commit: + +```bash +cd spring-petclinic +git checkout 4df621b41ed3013e527d4037d83a6cf756efd784 +``` + +{% hint style="warning" %} +This commit already has some of the potential migration recipes applied, but it's the first one with Gradle support. + +Because of that, if you compare it to the [Maven plugin exercise](maven-plugin-exercise.md), you will see less changes being made. + +For example, JUnit has already been migrated to version 5, and we already have Java 11 instead of Java 8. +{% endhint %} + +3. Make sure it runs on your machine: + +```bash +./gradlew assemble +``` + +### Migrate to SpringBoot3 with OpenRewrite + +OpenRewrite can be configured in your `build.gradle` file or as an additional `init.gradle` script without having to edit any previous build configurations ([see how here](https://docs.openrewrite.org/running-recipes/running-rewrite-on-a-gradle-project-without-modifying-the-build)). + +1. For simplicity, we will provide you with an `init.gradle` file that contains the Spring Boot migration recipe as well as the OpenRewrite dependencies. Please copy this file to the Spring PetClinic repository you have checked out locally. + +{% file src="../../.gitbook/assets/init.gradle" %} + +
+ +init.gradle + +{% code title="init.gradle" %} +```groovy +initscript { + repositories { + maven { url "https://plugins.gradle.org/m2" } + } + + dependencies { + classpath("org.openrewrite:plugin:latest.release") + } +} + +rootProject { + plugins.apply(org.openrewrite.gradle.RewritePlugin) + dependencies { + rewrite("org.openrewrite.recipe:rewrite-spring:latest.release") + } + rewrite { + activeRecipe("org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1") + } + afterEvaluate { + if (repositories.isEmpty()) { + repositories { + mavenCentral() + } + } + } +} +``` +{% endcode %} + +
+ +2. Due to some [Guava incompatibility issues with Gradle 6](https://github.com/google/guava/releases/tag/v32.1.0) and Wro4j being incompatible with Gradle 7, we have to first awkwardly downgrade to Gradle 5. + +```bash +./gradlew wrapper --gradle-version 5.6.4 +``` + +Don't worry; we will upgrade Gradle automatically as part of the recipe run so that it's compatible with Java 17. + +3. With `init.gradle` copied over, if you run `rewriteRun`, you will apply the migration recipe: + +```bash +./gradlew --info --init-script init.gradle rewriteRun +``` + +{% hint style="info" %} +Running OpenRewrite [can take a while](../../introduction.md) as we analyze the project and run recipes to make code changes. You should see results within a couple of minutes, depending on the size of your project and your project. +{% endhint %} + +
+ +You should see output similar to the following. + +```bash +Initialized native services in: /home/tim/.gradle/native +Found daemon DaemonInfo{pid=800284, address=[d894bba7-7c4e-4feb-8997-04fc66a50868 port:36395, addresses:[/0:0:0:0:0:0:0:1, /127.0.0.1]], state=Idle, lastBusy=1693566067810, context=DefaultDaemonContext[uid=03d2313d-ee70-418f-9038-e2ce17dde7e5,javaHome=/home/tim/.sdkman/candidates/java/8.0.392-zulu,daemonRegistryDir=/home/tim/.gradle/daemon,pid=800284,idleTimeout=10800000,priority=NORMAL,daemonOpts=-XX:MaxMetaspaceSize=256m,-XX:+HeapDumpOnOutOfMemoryError,-Xms256m,-Xmx512m,-Dfile.encoding=UTF-8,-Duser.country=US,-Duser.language=en,-Duser.variant]} however its context does not match the desired criteria. +Java home is different. +Wanted: DefaultDaemonContext[uid=null,javaHome=/home/tim/.sdkman/candidates/java/11.0.21-tem,daemonRegistryDir=/home/tim/.gradle/daemon,pid=800425,idleTimeout=null,priority=NORMAL,daemonOpts=--add-opens,java.base/java.util=ALL-UNNAMED,--add-opens,java.base/java.lang=ALL-UNNAMED,--add-opens,java.base/java.lang.invoke=ALL-UNNAMED,--add-opens,java.prefs/java.util.prefs=ALL-UNNAMED,-XX:MaxMetaspaceSize=256m,-XX:+HeapDumpOnOutOfMemoryError,-Xms256m,-Xmx512m,-Dfile.encoding=UTF-8,-Duser.country=US,-Duser.language=en,-Duser.variant] +Actual: DefaultDaemonContext[uid=03d2313d-ee70-418f-9038-e2ce17dde7e5,javaHome=/home/tim/.sdkman/candidates/java/8.0.392-zulu,daemonRegistryDir=/home/tim/.gradle/daemon,pid=800284,idleTimeout=10800000,priority=NORMAL,daemonOpts=-XX:MaxMetaspaceSize=256m,-XX:+HeapDumpOnOutOfMemoryError,-Xms256m,-Xmx512m,-Dfile.encoding=UTF-8,-Duser.country=US,-Duser.language=en,-Duser.variant] + +Looking for a different daemon... +Removing daemon from the registry due to communication failure. Daemon information: DaemonInfo{pid=11773, address=[075a4d1f-8528-42e4-8b46-a41fe2b4aad8 port:42229, addresses:[/0:0:0:0:0:0:0:1, /127.0.0.1]], state=Idle, lastBusy=1693515175555, context=DefaultDaemonContext[uid=de62defa-2384-46c4-b07b-b9480989c003,javaHome=/home/tim/.sdkman/candidates/java/11.0.21-tem,daemonRegistryDir=/home/tim/.gradle/daemon,pid=11773,idleTimeout=10800000,priority=NORMAL,daemonOpts=--add-opens,java.base/java.util=ALL-UNNAMED,--add-opens,java.base/java.lang=ALL-UNNAMED,--add-opens,java.base/java.lang.invoke=ALL-UNNAMED,--add-opens,java.prefs/java.util.prefs=ALL-UNNAMED,-XX:MaxMetaspaceSize=256m,-XX:+HeapDumpOnOutOfMemoryError,-Xms256m,-Xmx512m,-Dfile.encoding=UTF-8,-Duser.country=US,-Duser.language=en,-Duser.variant]} +Removing 0 daemon stop events from registry +Previous Daemon (11773) stopped at Fri Sep 01 13:01:25 CEST 2023 by user or operating system +Starting a Gradle Daemon, 2 incompatible and 1 stopped Daemons could not be reused, use --status for details +Starting process 'Gradle build daemon'. Working directory: /home/tim/.gradle/daemon/5.6.4 Command: /home/tim/.sdkman/candidates/java/11.0.21-tem/bin/java --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.lang.invoke=ALL-UNNAMED --add-opens java.prefs/java.util.prefs=ALL-UNNAMED -XX:MaxMetaspaceSize=256m -XX:+HeapDumpOnOutOfMemoryError -Xms256m -Xmx512m -Dfile.encoding=UTF-8 -Duser.country=US -Duser.language=en -Duser.variant -cp /home/tim/.gradle/wrapper/dists/gradle-5.6.4-bin/bxirm19lnfz6nurbatndyydux/gradle-5.6.4/lib/gradle-launcher-5.6.4.jar org.gradle.launcher.daemon.bootstrap.GradleDaemon 5.6.4 +Successfully started process 'Gradle build daemon' +An attempt to start the daemon took 0.413 secs. +The client will now receive all logging from the daemon (pid: 800467). The daemon log file: /home/tim/.gradle/daemon/5.6.4/daemon-800467.out.log +Starting build in new daemon [memory: 536.9 MB] +Using 20 worker leases. +Starting Build +Settings evaluated using settings file '/tmp/cli/spring-petclinic/settings.gradle'. +Projects loaded. Root project using build file '/tmp/cli/spring-petclinic/build.gradle'. +Included projects: [root project 'spring-petclinic'] + +> Configure project : +Evaluating root project 'spring-petclinic' using build file '/tmp/cli/spring-petclinic/build.gradle'. +Applying dependency management to configuration 'bootArchives' in project 'spring-petclinic' +Applying dependency management to configuration 'rewrite' in project 'spring-petclinic' +Applying dependency management to configuration 'archives' in project 'spring-petclinic' +Applying dependency management to configuration 'default' in project 'spring-petclinic' +Applying dependency management to configuration 'compile' in project 'spring-petclinic' +Applying dependency management to configuration 'implementation' in project 'spring-petclinic' +Applying dependency management to configuration 'runtime' in project 'spring-petclinic' +Applying dependency management to configuration 'compileOnly' in project 'spring-petclinic' +Applying dependency management to configuration 'compileClasspath' in project 'spring-petclinic' +Applying dependency management to configuration 'annotationProcessor' in project 'spring-petclinic' +Applying dependency management to configuration 'runtimeOnly' in project 'spring-petclinic' +Applying dependency management to configuration 'runtimeClasspath' in project 'spring-petclinic' +Applying dependency management to configuration 'testCompile' in project 'spring-petclinic' +Applying dependency management to configuration 'testImplementation' in project 'spring-petclinic' +Applying dependency management to configuration 'testRuntime' in project 'spring-petclinic' +Applying dependency management to configuration 'testCompileOnly' in project 'spring-petclinic' +Applying dependency management to configuration 'testCompileClasspath' in project 'spring-petclinic' +Applying dependency management to configuration 'testAnnotationProcessor' in project 'spring-petclinic' +Applying dependency management to configuration 'testRuntimeOnly' in project 'spring-petclinic' +Applying dependency management to configuration 'testRuntimeClasspath' in project 'spring-petclinic' +Applying dependency management to configuration 'apiElements' in project 'spring-petclinic' +Applying dependency management to configuration 'runtimeElements' in project 'spring-petclinic' +Applying dependency management to configuration 'developmentOnly' in project 'spring-petclinic' +Applying dependency management to configuration 'productionRuntimeClasspath' in project 'spring-petclinic' +Applying dependency management to configuration 'webjarsRuntime' in project 'spring-petclinic' +Applying dependency management to configuration 'webjars' in project 'spring-petclinic' +Applying dependency management to configuration 'webjarsTest' in project 'spring-petclinic' +Resolving global dependency management for project 'spring-petclinic' +Excluding [] +Excluding [] +All projects evaluated. +Selected primary task 'rewriteRun' from project : +Tasks to be executed: [task ':compileJava', task ':processResources', task ':prepareAssets', task ':prepareWebjars', task ':compileWebPetclinic', task ':processWebResources', task ':classes', task ':compileTestJava', task ':rewriteResolveDependencies', task ':rewriteRun'] +:compileJava (Thread[Execution worker for ':' Thread 4,5,main]) started. + +> Task :compileJava +Excluding [ognl:ognl] +Excluding [] +Caching disabled for task ':compileJava' because: +Build cache is disabled +Task ':compileJava' is not up-to-date because: +Task has failed previously. +All input files are considered out-of-date for incremental task ':compileJava'. +Full recompilation is required because no incremental change information is available. This is usually caused by clean builds or changing compiler arguments. +Compiling with JDK Java compiler API. +Created classpath snapshot for incremental compilation in 0.068 secs. 1 duplicate classes found in classpath (see all with --debug). +:compileJava (Thread[Execution worker for ':' Thread 4,5,main]) completed. Took 0.939 secs. +:processResources (Thread[Execution worker for ':' Thread 4,5,main]) started. + +> Task :processResources +Caching disabled for task ':processResources' because: +Build cache is disabled +Task ':processResources' is not up-to-date because: +No history is available. +:processResources (Thread[Execution worker for ':' Thread 4,5,main]) completed. Took 0.036 secs. +:prepareAssets (Thread[Execution worker for ':' Thread 4,5,main]) started. + +> Task :prepareAssets +Deleting stale output file: /tmp/cli/spring-petclinic/build/wro +Caching disabled for task ':prepareAssets' because: +Build cache is disabled +Task ':prepareAssets' is not up-to-date because: +No history is available. +:prepareAssets (Thread[Execution worker for ':' Thread 4,5,main]) completed. Took 0.018 secs. +:prepareWebjars (Thread[Execution worker for ':' Thread 4,5,main]) started. + +> Task :prepareWebjars +Caching disabled for task ':prepareWebjars' because: +Build cache is disabled +Task ':prepareWebjars' is not up-to-date because: +No history is available. +:prepareWebjars (Thread[Execution worker for ':' Thread 4,5,main]) completed. Took 0.177 secs. +:compileWebPetclinic (Thread[Execution worker for ':' Thread 4,5,main]) started. + +> Task :compileWebPetclinic +Caching disabled for task ':compileWebPetclinic' because: +Build cache is disabled +Task ':compileWebPetclinic' is not up-to-date because: +No history is available. +compileWebPetclinic.WroModel 'petclinic' { +/webjars/bootstrap/3.3.6/less/bootstrap.less +} +Processing group 'petclinic.css'... +Less warnings are: +10:1 Cannot link source map. Css result location is not know and could not be deduced from input less source.. +petclinic.css => /tmp/cli/spring-petclinic/build/resources/main/static/resources/css/petclinic.css / 145146B +:compileWebPetclinic (Thread[Execution worker for ':' Thread 4,5,main]) completed. Took 1.631 secs. +:processWebResources (Thread[Execution worker for ':' Thread 4,5,main]) started. + +> Task :processWebResources NO-SOURCE +Skipping task ':processWebResources' as it has no source files and no previous output files. +:processWebResources (Thread[Execution worker for ':' Thread 4,5,main]) completed. Took 0.001 secs. +:classes (Thread[Execution worker for ':' Thread 4,5,main]) started. + +> Task :classes +Skipping task ':classes' as it has no actions. +:classes (Thread[Execution worker for ':' Thread 4,5,main]) completed. Took 0.0 secs. +:compileTestJava (Thread[Execution worker for ':' Thread 4,5,main]) started. + +> Task :compileTestJava +Excluding [] +Excluding [] +Caching disabled for task ':compileTestJava' because: +Build cache is disabled +Task ':compileTestJava' is not up-to-date because: +No history is available. +All input files are considered out-of-date for incremental task ':compileTestJava'. +Full recompilation is required because no incremental change information is available. This is usually caused by clean builds or changing compiler arguments. +Compiling with JDK Java compiler API. +Created classpath snapshot for incremental compilation in 0.021 secs. 1 duplicate classes found in classpath (see all with --debug). +:compileTestJava (Thread[Execution worker for ':' Thread 4,5,main]) completed. Took 0.609 secs. +:rewriteResolveDependencies (Thread[Execution worker for ':' Thread 4,5,main]) started. + +> Task :rewriteResolveDependencies +Caching disabled for task ':rewriteResolveDependencies' because: +Build cache is disabled +Task ':rewriteResolveDependencies' is not up-to-date because: +Task has not declared any outputs despite executing actions. +Cache entries evicted. In-memory cache of /home/tim/.gradle/caches/journal-1/file-access.bin: Size{375} MaxSize{400}, CacheStats{hitCount=0, missCount=0, loadSuccessCount=0, loadExceptionCount=0, totalLoadTime=0, evictionCount=2} +Performance may suffer from in-memory cache misses. Increase max heap size of Gradle build process to reduce cache misses. +Cache entries evicted. In-memory cache of /home/tim/.gradle/caches/journal-1/file-access.bin: Size{372} MaxSize{400}, CacheStats{hitCount=0, missCount=0, loadSuccessCount=0, loadExceptionCount=0, totalLoadTime=0, evictionCount=1} +Performance may suffer from in-memory cache misses. Increase max heap size of Gradle build process to reduce cache misses. +Cache entries evicted. In-memory cache of /home/tim/.gradle/caches/journal-1/file-access.bin: Size{400} MaxSize{400}, CacheStats{hitCount=0, missCount=0, loadSuccessCount=0, loadExceptionCount=0, totalLoadTime=0, evictionCount=41} +Performance may suffer from in-memory cache misses. Increase max heap size of Gradle build process to reduce cache misses. +:rewriteResolveDependencies (Thread[Execution worker for ':' Thread 4,5,main]) completed. Took 0.095 secs. +:rewriteRun (Thread[Execution worker for ':' Thread 4,5,main]) started. + +> Task :rewriteRun +Caching disabled for task ':rewriteRun' because: +Build cache is disabled +Task ':rewriteRun' is not up-to-date because: +Task has not declared any outputs despite executing actions. +Validating active recipes +Scanning sources in project spring-petclinic +Applying dependency management to configuration 'rewriteimplementation' in project 'spring-petclinic' +Excluding [] +Scanned 25 Java sources in spring-petclinic/main +Applying dependency management to configuration 'rewritetestImplementation' in project 'spring-petclinic' +Excluding [] +Scanned 11 Java sources in spring-petclinic/test +Excluding [] +Excluding [] +Excluding [] +Excluding [com.google.protobuf:protobuf-java] +Excluding [] +Excluding [] +Cache entries evicted. In-memory cache of /home/tim/.gradle/caches/journal-1/file-access.bin: Size{400} MaxSize{400}, CacheStats{hitCount=0, missCount=0, loadSuccessCount=0, loadExceptionCount=0, totalLoadTime=0, evictionCount=81} +Performance may suffer from in-memory cache misses. Increase max heap size of Gradle build process to reduce cache misses. +Cache entries evicted. In-memory cache of /home/tim/.gradle/caches/journal-1/file-access.bin: Size{400} MaxSize{400}, CacheStats{hitCount=0, missCount=0, loadSuccessCount=0, loadExceptionCount=0, totalLoadTime=0, evictionCount=121} +Performance may suffer from in-memory cache misses. Increase max heap size of Gradle build process to reduce cache misses. +Cache entries evicted. In-memory cache of /home/tim/.gradle/caches/journal-1/file-access.bin: Size{400} MaxSize{400}, CacheStats{hitCount=0, missCount=0, loadSuccessCount=0, loadExceptionCount=0, totalLoadTime=0, evictionCount=161} +Performance may suffer from in-memory cache misses. Increase max heap size of Gradle build process to reduce cache misses. +Excluding [org.codehaus.groovy:groovy] +Excluding [] +Excluding [] +Excluding [] +Excluding [] +Excluding [] +Excluding [] +Excluding [] +All sources parsed, running active recipes: org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +Changes have been made to src/main/java/org/springframework/samples/petclinic/vet/Specialty.java by: +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_3 +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.3, addIfMissing=false} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.8, addIfMissing=false} +org.openrewrite.java.migrate.UpgradeToJava17 +org.openrewrite.java.migrate.JavaVersion17 +org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^7.4, addIfMissing=false} +org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta +org.openrewrite.java.migrate.jakarta.JavaxPersistenceToJakartaPersistence +org.openrewrite.java.ChangePackage: {oldPackageName=javax.persistence, newPackageName=jakarta.persistence, recursive=true} +Changes have been made to src/main/java/org/springframework/samples/petclinic/vet/Vet.java by: +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_3 +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.3, addIfMissing=false} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.8, addIfMissing=false} +org.openrewrite.java.migrate.UpgradeToJava17 +org.openrewrite.java.migrate.JavaVersion17 +org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^7.4, addIfMissing=false} +org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta +org.openrewrite.java.migrate.jakarta.JavaxPersistenceToJakartaPersistence +org.openrewrite.java.ChangePackage: {oldPackageName=javax.persistence, newPackageName=jakarta.persistence, recursive=true} +org.openrewrite.java.migrate.jakarta.JavaxXmlBindMigrationToJakartaXmlBind +org.openrewrite.java.ChangePackage: {oldPackageName=javax.xml.bind, newPackageName=jakarta.xml.bind, recursive=true} +Changes have been made to src/main/java/org/springframework/samples/petclinic/vet/Vets.java by: +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_3 +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.3, addIfMissing=false} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.8, addIfMissing=false} +org.openrewrite.java.migrate.UpgradeToJava17 +org.openrewrite.java.migrate.JavaVersion17 +org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^7.4, addIfMissing=false} +org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta +org.openrewrite.java.migrate.jakarta.JavaxXmlBindMigrationToJakartaXmlBind +org.openrewrite.java.ChangePackage: {oldPackageName=javax.xml.bind, newPackageName=jakarta.xml.bind, recursive=true} +Changes have been made to src/main/java/org/springframework/samples/petclinic/owner/OwnerController.java by: +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_3 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_2 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_1 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_0 +org.openrewrite.java.spring.boot2.SpringBoot2BestPractices +org.openrewrite.java.spring.ImplicitWebAnnotationNames +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.3, addIfMissing=false} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.8, addIfMissing=false} +org.openrewrite.java.migrate.UpgradeToJava17 +org.openrewrite.java.migrate.JavaVersion17 +org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^7.4, addIfMissing=false} +org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta +org.openrewrite.java.migrate.jakarta.JavaxValidationMigrationToJakartaValidation +org.openrewrite.java.ChangePackage: {oldPackageName=javax.validation, newPackageName=jakarta.validation, recursive=true} +Changes have been made to src/main/java/org/springframework/samples/petclinic/owner/Owner.java by: +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_3 +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.3, addIfMissing=false} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.8, addIfMissing=false} +org.openrewrite.java.migrate.UpgradeToJava17 +org.openrewrite.java.migrate.JavaVersion17 +org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^7.4, addIfMissing=false} +org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta +org.openrewrite.java.migrate.jakarta.JavaxPersistenceToJakartaPersistence +org.openrewrite.java.ChangePackage: {oldPackageName=javax.persistence, newPackageName=jakarta.persistence, recursive=true} +org.openrewrite.java.migrate.jakarta.JavaxValidationMigrationToJakartaValidation +org.openrewrite.java.ChangePackage: {oldPackageName=javax.validation, newPackageName=jakarta.validation, recursive=true} +Changes have been made to src/main/java/org/springframework/samples/petclinic/owner/PetType.java by: +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_3 +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.3, addIfMissing=false} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.8, addIfMissing=false} +org.openrewrite.java.migrate.UpgradeToJava17 +org.openrewrite.java.migrate.JavaVersion17 +org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^7.4, addIfMissing=false} +org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta +org.openrewrite.java.migrate.jakarta.JavaxPersistenceToJakartaPersistence +org.openrewrite.java.ChangePackage: {oldPackageName=javax.persistence, newPackageName=jakarta.persistence, recursive=true} +Changes have been made to src/main/java/org/springframework/samples/petclinic/owner/PetController.java by: +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_3 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_2 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_1 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_0 +org.openrewrite.java.spring.boot2.SpringBoot2BestPractices +org.openrewrite.java.spring.ImplicitWebAnnotationNames +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.3, addIfMissing=false} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.8, addIfMissing=false} +org.openrewrite.java.migrate.UpgradeToJava17 +org.openrewrite.java.migrate.JavaVersion17 +org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^7.4, addIfMissing=false} +org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta +org.openrewrite.java.migrate.jakarta.JavaxValidationMigrationToJakartaValidation +org.openrewrite.java.ChangePackage: {oldPackageName=javax.validation, newPackageName=jakarta.validation, recursive=true} +Changes have been made to src/main/java/org/springframework/samples/petclinic/owner/PetTypeFormatter.java by: +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_3 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_2 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_1 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_0 +org.openrewrite.java.spring.boot2.SpringBoot2BestPractices +org.openrewrite.java.spring.NoAutowiredOnConstructor +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.3, addIfMissing=false} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.8, addIfMissing=false} +org.openrewrite.java.migrate.UpgradeToJava17 +org.openrewrite.java.migrate.JavaVersion17 +org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^7.4, addIfMissing=false} +Changes have been made to src/main/java/org/springframework/samples/petclinic/owner/Pet.java by: +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_3 +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.3, addIfMissing=false} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.8, addIfMissing=false} +org.openrewrite.java.migrate.UpgradeToJava17 +org.openrewrite.java.migrate.JavaVersion17 +org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^7.4, addIfMissing=false} +org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta +org.openrewrite.java.migrate.jakarta.JavaxPersistenceToJakartaPersistence +org.openrewrite.java.ChangePackage: {oldPackageName=javax.persistence, newPackageName=jakarta.persistence, recursive=true} +Changes have been made to src/main/java/org/springframework/samples/petclinic/owner/VisitController.java by: +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_3 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_2 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_1 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_0 +org.openrewrite.java.spring.boot2.SpringBoot2BestPractices +org.openrewrite.java.spring.ImplicitWebAnnotationNames +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.3, addIfMissing=false} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.8, addIfMissing=false} +org.openrewrite.java.migrate.UpgradeToJava17 +org.openrewrite.java.migrate.JavaVersion17 +org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^7.4, addIfMissing=false} +org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta +org.openrewrite.java.migrate.jakarta.JavaxValidationMigrationToJakartaValidation +org.openrewrite.java.ChangePackage: {oldPackageName=javax.validation, newPackageName=jakarta.validation, recursive=true} +Changes have been made to src/main/java/org/springframework/samples/petclinic/model/Person.java by: +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_3 +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.3, addIfMissing=false} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.8, addIfMissing=false} +org.openrewrite.java.migrate.UpgradeToJava17 +org.openrewrite.java.migrate.JavaVersion17 +org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^7.4, addIfMissing=false} +org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta +org.openrewrite.java.migrate.jakarta.JavaxPersistenceToJakartaPersistence +org.openrewrite.java.ChangePackage: {oldPackageName=javax.persistence, newPackageName=jakarta.persistence, recursive=true} +org.openrewrite.java.migrate.jakarta.JavaxValidationMigrationToJakartaValidation +org.openrewrite.java.ChangePackage: {oldPackageName=javax.validation, newPackageName=jakarta.validation, recursive=true} +Changes have been made to src/main/java/org/springframework/samples/petclinic/model/NamedEntity.java by: +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_3 +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.3, addIfMissing=false} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.8, addIfMissing=false} +org.openrewrite.java.migrate.UpgradeToJava17 +org.openrewrite.java.migrate.JavaVersion17 +org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^7.4, addIfMissing=false} +org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta +org.openrewrite.java.migrate.jakarta.JavaxPersistenceToJakartaPersistence +org.openrewrite.java.ChangePackage: {oldPackageName=javax.persistence, newPackageName=jakarta.persistence, recursive=true} +Changes have been made to src/main/java/org/springframework/samples/petclinic/model/BaseEntity.java by: +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_3 +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.3, addIfMissing=false} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.8, addIfMissing=false} +org.openrewrite.java.migrate.UpgradeToJava17 +org.openrewrite.java.migrate.JavaVersion17 +org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^7.4, addIfMissing=false} +org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta +org.openrewrite.java.migrate.jakarta.JavaxPersistenceToJakartaPersistence +org.openrewrite.java.ChangePackage: {oldPackageName=javax.persistence, newPackageName=jakarta.persistence, recursive=true} +Changes have been made to src/main/java/org/springframework/samples/petclinic/visit/Visit.java by: +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_3 +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.3, addIfMissing=false} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.8, addIfMissing=false} +org.openrewrite.java.migrate.UpgradeToJava17 +org.openrewrite.java.migrate.JavaVersion17 +org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^7.4, addIfMissing=false} +org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta +org.openrewrite.java.migrate.jakarta.JavaxPersistenceToJakartaPersistence +org.openrewrite.java.ChangePackage: {oldPackageName=javax.persistence, newPackageName=jakarta.persistence, recursive=true} +org.openrewrite.java.migrate.jakarta.JavaxValidationMigrationToJakartaValidation +org.openrewrite.java.ChangePackage: {oldPackageName=javax.validation, newPackageName=jakarta.validation, recursive=true} +Changes have been made to src/main/java/org/springframework/samples/petclinic/system/CrashController.java by: +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_3 +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.3, addIfMissing=false} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.8, addIfMissing=false} +org.openrewrite.java.migrate.UpgradeToJava17 +org.openrewrite.java.migrate.JavaVersion17 +org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +org.openrewrite.java.migrate.lang.UseTextBlocks: {convertStringsWithoutNewlines=true} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^7.4, addIfMissing=false} +Changes have been made to application-postgres.properties by: +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_3 +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.3, addIfMissing=false} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.8, addIfMissing=false} +org.openrewrite.java.spring.boot2.SpringBootProperties_2_7 +org.openrewrite.java.spring.ChangeSpringPropertyKey: {oldPropertyKey=spring.datasource.initialization-mode, newPropertyKey=spring.sql.init.mode} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^7.4, addIfMissing=false} +Changes have been made to application-mysql.properties by: +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_3 +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.3, addIfMissing=false} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.8, addIfMissing=false} +org.openrewrite.java.spring.boot2.SpringBootProperties_2_7 +org.openrewrite.java.spring.ChangeSpringPropertyKey: {oldPropertyKey=spring.datasource.initialization-mode, newPropertyKey=spring.sql.init.mode} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^7.4, addIfMissing=false} +Changes have been made to application.properties by: +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_3 +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.3, addIfMissing=false} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.8, addIfMissing=false} +org.openrewrite.java.spring.boot2.SpringBootProperties_2_6 +org.openrewrite.java.spring.ChangeSpringPropertyKey: {oldPropertyKey=spring.resources.cache.cachecontrol.max-age, newPropertyKey=spring.web.resources.cache.cachecontrol.max-age} +org.openrewrite.java.spring.boot2.SpringBootProperties_2_7 +org.openrewrite.java.spring.ChangeSpringPropertyKey: {oldPropertyKey=spring.datasource.data, newPropertyKey=spring.sql.init.data-locations} +org.openrewrite.java.spring.ChangeSpringPropertyKey: {oldPropertyKey=spring.datasource.schema, newPropertyKey=spring.sql.init.schema-locations} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^7.4, addIfMissing=false} +Changes have been made to src/test/java/org/springframework/samples/petclinic/owner/PetTypeFormatterTests.java by: +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_3 +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.3, addIfMissing=false} +org.openrewrite.java.spring.boot2.SpringBoot2JUnit4to5Migration +org.openrewrite.java.spring.boot2.RemoveObsoleteSpringRunners +org.openrewrite.java.testing.junit5.JUnit5BestPractices +org.openrewrite.java.testing.junit5.StaticImports +org.openrewrite.java.UseStaticImport: {methodPattern=org.junit.jupiter.api.Assertions *(..)} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.8, addIfMissing=false} +org.openrewrite.java.migrate.UpgradeToJava17 +org.openrewrite.java.migrate.JavaVersion17 +org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^7.4, addIfMissing=false} +Changes have been made to src/test/java/org/springframework/samples/petclinic/model/ValidatorTests.java by: +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_3 +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.3, addIfMissing=false} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.8, addIfMissing=false} +org.openrewrite.java.migrate.UpgradeToJava17 +org.openrewrite.java.migrate.JavaVersion17 +org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^7.4, addIfMissing=false} +org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta +org.openrewrite.java.migrate.jakarta.JavaxValidationMigrationToJakartaValidation +org.openrewrite.java.ChangePackage: {oldPackageName=javax.validation, newPackageName=jakarta.validation, recursive=true} +Changes have been made to build.gradle by: +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +org.openrewrite.gradle.plugins.UpgradePluginVersion: {pluginIdPattern=org.springframework.boot, newVersion=2.4.x} +org.openrewrite.gradle.plugins.UpgradePluginVersion: {pluginIdPattern=org.springframework.boot, newVersion=2.5.x} +org.openrewrite.gradle.plugins.UpgradePluginVersion: {pluginIdPattern=io.spring.dependency-management, newVersion=1.0.x} +org.openrewrite.gradle.plugins.UpgradePluginVersion: {pluginIdPattern=org.springframework.boot, newVersion=2.6.x} +org.openrewrite.gradle.plugins.UpgradePluginVersion: {pluginIdPattern=org.springframework.boot, newVersion=2.7.x} +org.openrewrite.java.dependencies.ChangeDependency: {oldGroupId=mysql, oldArtifactId=mysql-connector-java, newGroupId=com.mysql, newArtifactId=mysql-connector-j, newVersion=8.0.x} +org.openrewrite.gradle.ChangeDependency: {oldGroupId=mysql, oldArtifactId=mysql-connector-java, newGroupId=com.mysql, newArtifactId=mysql-connector-j, newVersion=8.0.x} +org.openrewrite.java.migrate.UpgradeToJava17 +org.openrewrite.java.migrate.Java8toJava11 +org.openrewrite.java.migrate.javax.AddJaxwsDependencies +org.openrewrite.java.migrate.javax.AddJaxwsRuntime +org.openrewrite.java.migrate.javax.AddJaxwsRuntime$AddJaxwsRuntimeGradle +org.openrewrite.java.migrate.JavaVersion11 +org.openrewrite.java.migrate.UpgradeJavaVersion: {version=11} +org.openrewrite.java.migrate.JavaVersion17 +org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +org.openrewrite.gradle.plugins.UpgradePluginVersion: {pluginIdPattern=org.springframework.boot, newVersion=3.0.x} +org.openrewrite.gradle.plugins.UpgradePluginVersion: {pluginIdPattern=io.spring.dependency-management, newVersion=1.1.x} +org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta +org.openrewrite.java.migrate.jakarta.JavaxXmlWsMigrationToJakartaXmlWs +org.openrewrite.java.dependencies.UpgradeDependencyVersion: {groupId=com.sun.xml.ws, artifactId=jaxws-rt, newVersion=latest.release} +org.openrewrite.gradle.UpgradeDependencyVersion: {groupId=com.sun.xml.ws, artifactId=jaxws-rt, newVersion=latest.release} +org.openrewrite.gradle.plugins.UpgradePluginVersion: {pluginIdPattern=org.springframework.boot, newVersion=3.1.x} +Changes have been made to .github/workflows/maven-build.yml by: +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_3 +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.3, addIfMissing=false} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.8, addIfMissing=false} +org.openrewrite.java.migrate.UpgradeToJava17 +org.openrewrite.github.SetupJavaUpgradeJavaVersion +org.openrewrite.gradle.UpdateGradleWrapper: {version=^7.4, addIfMissing=false} +Changes have been made to src/main/resources/application-postgres.properties by: +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_3 +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.3, addIfMissing=false} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.8, addIfMissing=false} +org.openrewrite.java.spring.boot2.SpringBootProperties_2_7 +org.openrewrite.java.spring.ChangeSpringPropertyKey: {oldPropertyKey=spring.datasource.initialization-mode, newPropertyKey=spring.sql.init.mode} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^7.4, addIfMissing=false} +Changes have been made to src/main/resources/application-mysql.properties by: +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_3 +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.3, addIfMissing=false} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.8, addIfMissing=false} +org.openrewrite.java.spring.boot2.SpringBootProperties_2_7 +org.openrewrite.java.spring.ChangeSpringPropertyKey: {oldPropertyKey=spring.datasource.initialization-mode, newPropertyKey=spring.sql.init.mode} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^7.4, addIfMissing=false} +Changes have been made to src/main/resources/application.properties by: +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_3 +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.3, addIfMissing=false} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.8, addIfMissing=false} +org.openrewrite.java.spring.boot2.SpringBootProperties_2_6 +org.openrewrite.java.spring.ChangeSpringPropertyKey: {oldPropertyKey=spring.resources.cache.cachecontrol.max-age, newPropertyKey=spring.web.resources.cache.cachecontrol.max-age} +org.openrewrite.java.spring.boot2.SpringBootProperties_2_7 +org.openrewrite.java.spring.ChangeSpringPropertyKey: {oldPropertyKey=spring.datasource.data, newPropertyKey=spring.sql.init.data-locations} +org.openrewrite.java.spring.ChangeSpringPropertyKey: {oldPropertyKey=spring.datasource.schema, newPropertyKey=spring.sql.init.schema-locations} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^7.4, addIfMissing=false} +Changes have been made to gradlew by: +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_3 +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.3, addIfMissing=false} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.8, addIfMissing=false} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^7.4, addIfMissing=false} +Changes have been made to gradlew.bat by: +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_3 +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.3, addIfMissing=false} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.8, addIfMissing=false} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^7.4, addIfMissing=false} +Changes have been made to gradle/wrapper/gradle-wrapper.properties by: +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_3 +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.3, addIfMissing=false} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.8, addIfMissing=false} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^7.4, addIfMissing=false} +Changes have been made to gradle/wrapper/gradle-wrapper.jar by: +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_3 +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.3, addIfMissing=false} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^6.8, addIfMissing=false} +org.openrewrite.gradle.UpdateGradleWrapper: {version=^7.4, addIfMissing=false} +Please review and commit the results. +:rewriteRun (Thread[Execution worker for ':' Thread 4,5,main]) completed. Took 50.215 secs. + +BUILD SUCCESSFUL in 56s +8 actionable tasks: 8 executed +``` + +
+ +Notice how each change is listed in the output, along with the `org.openrewrite` recipe that made the change. + +### Explore the results + +You can compare the changes made through OpenRewrite in your favorite IDE or by running: + +```bash +git diff +``` + +
+ +You should see output similar to the following. + +```diff +diff --git a/.github/workflows/maven-build.yml b/.github/workflows/maven-build.yml +index f7ad114..fde5e28 100644 +--- a/.github/workflows/maven-build.yml ++++ b/.github/workflows/maven-build.yml +@@ -19,7 +19,7 @@ jobs: + - name: Set up JDK 11 + uses: actions/setup-java@v2 + with: +- java-version: '11' ++ java-version: '17' + distribution: 'adopt' + cache: maven + - name: Build with Maven Wrapper +diff --git a/build.gradle b/build.gradle +index c517cfc..3598ae2 100644 +--- a/build.gradle ++++ b/build.gradle +@@ -5,8 +5,8 @@ buildscript { + } + + plugins { +- id 'org.springframework.boot' version '2.4.5' +- id 'io.spring.dependency-management' version '1.0.11.RELEASE' ++ id 'org.springframework.boot' version '3.1.5' ++ id 'io.spring.dependency-management' version '1.1.3' + id 'java' + } + +@@ -15,7 +15,7 @@ apply plugin: 'wro4j' + + group = 'org.springframework.samples' + version = '2.4.5' +-sourceCompatibility = '11' ++sourceCompatibility = '17' + + repositories { + mavenCentral() +@@ -26,6 +26,8 @@ ext.webjarsJqueryUiVersion = "1.11.4" + ext.webjarsBootstrapVersion = "3.3.6" + + dependencies { ++ compileOnly "com.sun.xml.ws:jaxws-rt:4.0.1" ++ + implementation 'org.springframework.boot:spring-boot-starter-cache' + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' +@@ -38,8 +40,9 @@ dependencies { + webjarsRuntime "org.webjars:bootstrap:${webjarsBootstrapVersion}" + webjarsRuntime "org.webjars:bootstrap:${webjarsBootstrapVersion}" + runtimeOnly 'org.ehcache:ehcache' +- runtimeOnly 'com.h2database:h2' +- runtimeOnly 'mysql:mysql-connector-java' ++ testImplementation "com.sun.xml.ws:jaxws-rt:4.0.1" ++ runtimeOnly 'com.h2database:h2' ++ runtimeOnly 'com.mysql:mysql-connector-j' + developmentOnly 'org.springframework.boot:spring-boot-devtools' + testImplementation 'org.springframework.boot:spring-boot-starter-test' + } +diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar +index e708b1c..afba109 100644 +Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ +diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties +index 442d913..8fd50d7 100644 +--- a/gradle/wrapper/gradle-wrapper.properties ++++ b/gradle/wrapper/gradle-wrapper.properties +@@ -1,5 +1,6 @@ + distributionBase=GRADLE_USER_HOME + distributionPath=wrapper/dists +-distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip ++distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.2-bin.zip + zipStoreBase=GRADLE_USER_HOME + zipStorePath=wrapper/dists ++distributionSha256Sum=a01b6587e15fe7ed120a0ee299c25982a1eee045abd6a9dd5e216b2f628ef9ac +diff --git a/gradlew b/gradlew +index 4f906e0..65dcd68 100755 +--- a/gradlew ++++ b/gradlew +@@ -1,7 +1,7 @@ +-#!/usr/bin/env sh ++#!/bin/sh + + # +-# Copyright 2015 the original author or authors. ++# Copyright © 2015-2021 the original authors. + # + # Licensed under the Apache License, Version 2.0 (the "License"); + # you may not use this file except in compliance with the License. +@@ -17,67 +17,101 @@ + # + + ############################################################################## +-## +-## Gradle start up script for UN*X +-## ++# ++# Gradle start up script for POSIX generated by Gradle. ++# ++# Important for running: ++# ++# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is ++# noncompliant, but you have some other compliant shell such as ksh or ++# bash, then to run this script, type that shell name before the whole ++# command line, like: ++# ++# ksh Gradle ++# ++# Busybox and similar reduced shells will NOT work, because this script ++# requires all of these POSIX shell features: ++# * functions; ++# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», ++# «${var#prefix}», «${var%suffix}», and «$( cmd )»; ++# * compound commands having a testable exit status, especially «case»; ++# * various built-in commands including «command», «set», and «ulimit». ++# ++# Important for patching: ++# ++# (2) This script targets any POSIX shell, so it avoids extensions provided ++# by Bash, Ksh, etc; in particular arrays are avoided. ++# ++# The "traditional" practice of packing multiple parameters into a ++# space-separated string is a well documented source of bugs and security ++# problems, so this is (mostly) avoided, by progressively accumulating ++# options in "$@", and eventually passing that to Java. ++# ++# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, ++# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; ++# see the in-line comments for details. ++# ++# There are tweaks for specific operating systems such as AIX, CygWin, ++# Darwin, MinGW, and NonStop. ++# ++# (3) This script is generated from the Groovy template ++# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt ++# within the Gradle project. ++# ++# You can find Gradle at https://github.com/gradle/gradle/. ++# + ############################################################################## + + # Attempt to set APP_HOME ++ + # Resolve links: $0 may be a link +-PRG="$0" +-# Need this for relative symlinks. +-while [ -h "$PRG" ] ; do +- ls=`ls -ld "$PRG"` +- link=`expr "$ls" : '.*-> \(.*\)$'` +- if expr "$link" : '/.*' > /dev/null; then +- PRG="$link" +- else +- PRG=`dirname "$PRG"`"/$link" +- fi ++app_path=$0 ++ ++# Need this for daisy-chained symlinks. ++while ++ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path ++ [ -h "$app_path" ] ++do ++ ls=$( ls -ld "$app_path" ) ++ link=${ls#*' -> '} ++ case $link in #( ++ /*) app_path=$link ;; #( ++ *) app_path=$APP_HOME$link ;; ++ esac + done +-SAVED="`pwd`" +-cd "`dirname \"$PRG\"`/" >/dev/null +-APP_HOME="`pwd -P`" +-cd "$SAVED" >/dev/null + +-APP_NAME="Gradle" +-APP_BASE_NAME=`basename "$0"` ++# This is normally unused ++# shellcheck disable=SC2034 ++APP_BASE_NAME=${0##*/} ++APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + + # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. + DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + + # Use the maximum available, or set MAX_FD != -1 to use that value. +-MAX_FD="maximum" ++MAX_FD=maximum + + warn () { + echo "$*" +-} ++} >&2 + + die () { + echo + echo "$*" + echo + exit 1 +-} ++} >&2 + + # OS specific support (must be 'true' or 'false'). + cygwin=false + msys=false + darwin=false + nonstop=false +-case "`uname`" in +- CYGWIN* ) +- cygwin=true +- ;; +- Darwin* ) +- darwin=true +- ;; +- MINGW* ) +- msys=true +- ;; +- NONSTOP* ) +- nonstop=true +- ;; ++case "$( uname )" in #( ++ CYGWIN* ) cygwin=true ;; #( ++ Darwin* ) darwin=true ;; #( ++ MSYS* | MINGW* ) msys=true ;; #( ++ NONSTOP* ) nonstop=true ;; + esac + + CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar +@@ -87,9 +121,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables +- JAVACMD="$JAVA_HOME/jre/sh/java" ++ JAVACMD=$JAVA_HOME/jre/sh/java + else +- JAVACMD="$JAVA_HOME/bin/java" ++ JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME +@@ -98,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the + location of your Java installation." + fi + else +- JAVACMD="java" ++ JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + + Please set the JAVA_HOME variable in your environment to match the +@@ -106,80 +140,105 @@ location of your Java installation." + fi + + # Increase the maximum file descriptors if we can. +-if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then +- MAX_FD_LIMIT=`ulimit -H -n` +- if [ $? -eq 0 ] ; then +- if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then +- MAX_FD="$MAX_FD_LIMIT" +- fi +- ulimit -n $MAX_FD +- if [ $? -ne 0 ] ; then +- warn "Could not set maximum file descriptor limit: $MAX_FD" +- fi +- else +- warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" +- fi ++if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then ++ case $MAX_FD in #( ++ max*) ++ # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. ++ # shellcheck disable=SC3045 ++ MAX_FD=$( ulimit -H -n ) || ++ warn "Could not query maximum file descriptor limit" ++ esac ++ case $MAX_FD in #( ++ '' | soft) :;; #( ++ *) ++ # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. ++ # shellcheck disable=SC3045 ++ ulimit -n "$MAX_FD" || ++ warn "Could not set maximum file descriptor limit to $MAX_FD" ++ esac + fi + +-# For Darwin, add options to specify how the application appears in the dock +-if $darwin; then +- GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +-fi ++# Collect all arguments for the java command, stacking in reverse order: ++# * args from the command line ++# * the main class name ++# * -classpath ++# * -D...appname settings ++# * --module-path (only if needed) ++# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + + # For Cygwin or MSYS, switch paths to Windows format before running java +-if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then +- APP_HOME=`cygpath --path --mixed "$APP_HOME"` +- CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` +- +- JAVACMD=`cygpath --unix "$JAVACMD"` +- +- # We build the pattern for arguments to be converted via cygpath +- ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` +- SEP="" +- for dir in $ROOTDIRSRAW ; do +- ROOTDIRS="$ROOTDIRS$SEP$dir" +- SEP="|" +- done +- OURCYGPATTERN="(^($ROOTDIRS))" +- # Add a user-defined pattern to the cygpath arguments +- if [ "$GRADLE_CYGPATTERN" != "" ] ; then +- OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" +- fi ++if "$cygwin" || "$msys" ; then ++ APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) ++ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) ++ ++ JAVACMD=$( cygpath --unix "$JAVACMD" ) ++ + # Now convert the arguments - kludge to limit ourselves to /bin/sh +- i=0 +- for arg in "$@" ; do +- CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` +- CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option +- +- if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition +- eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` +- else +- eval `echo args$i`="\"$arg\"" ++ for arg do ++ if ++ case $arg in #( ++ -*) false ;; # don't mess with options #( ++ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath ++ [ -e "$t" ] ;; #( ++ *) false ;; ++ esac ++ then ++ arg=$( cygpath --path --ignore --mixed "$arg" ) + fi +- i=`expr $i + 1` ++ # Roll the args list around exactly as many times as the number of ++ # args, so each arg winds up back in the position where it started, but ++ # possibly modified. ++ # ++ # NB: a `for` loop captures its iteration list before it begins, so ++ # changing the positional parameters here affects neither the number of ++ # iterations, nor the values presented in `arg`. ++ shift # remove old arg ++ set -- "$@" "$arg" # push replacement arg + done +- case $i in +- 0) set -- ;; +- 1) set -- "$args0" ;; +- 2) set -- "$args0" "$args1" ;; +- 3) set -- "$args0" "$args1" "$args2" ;; +- 4) set -- "$args0" "$args1" "$args2" "$args3" ;; +- 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; +- 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; +- 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; +- 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; +- 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; +- esac + fi + +-# Escape application args +-save () { +- for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done +- echo " " +-} +-APP_ARGS=`save "$@"` ++# Collect all arguments for the java command; ++# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of ++# shell script including quotes and variable substitutions, so put them in ++# double quotes to make sure that they get re-expanded; and ++# * put everything else in single quotes, so that it's not re-expanded. ++ ++set -- \ ++ "-Dorg.gradle.appname=$APP_BASE_NAME" \ ++ -classpath "$CLASSPATH" \ ++ org.gradle.wrapper.GradleWrapperMain \ ++ "$@" ++ ++# Stop when "xargs" is not available. ++if ! command -v xargs >/dev/null 2>&1 ++then ++ die "xargs is not available" ++fi ++ ++# Use "xargs" to parse quoted args. ++# ++# With -n1 it outputs one arg per line, with the quotes and backslashes removed. ++# ++# In Bash we could simply go: ++# ++# readarray ARGS < <( xargs -n1 <<<"$var" ) && ++# set -- "${ARGS[@]}" "$@" ++# ++# but POSIX shell has neither arrays nor command substitution, so instead we ++# post-process each arg (as a line of input to sed) to backslash-escape any ++# character that might be a shell metacharacter, then use eval to reverse ++# that process (while maintaining the separation between arguments), and wrap ++# the whole thing up as a single "set" statement. ++# ++# This will of course break if any of these variables contains a newline or ++# an unmatched quote. ++# + +-# Collect all arguments for the java command, following the shell quoting and substitution rules +-eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" ++eval "set -- $( ++ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | ++ xargs -n1 | ++ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | ++ tr '\n' ' ' ++ )" '"$@"' + + exec "$JAVACMD" "$@" +diff --git a/gradlew.bat b/gradlew.bat +old mode 100644 +new mode 100755 +index ac1b06f..6689b85 +--- a/gradlew.bat ++++ b/gradlew.bat +@@ -14,7 +14,7 @@ + @rem limitations under the License. + @rem + +-@if "%DEBUG%" == "" @echo off ++@if "%DEBUG%"=="" @echo off + @rem ########################################################################## + @rem + @rem Gradle startup script for Windows +@@ -25,7 +25,8 @@ + if "%OS%"=="Windows_NT" setlocal + + set DIRNAME=%~dp0 +-if "%DIRNAME%" == "" set DIRNAME=. ++if "%DIRNAME%"=="" set DIRNAME=. ++@rem This is normally unused + set APP_BASE_NAME=%~n0 + set APP_HOME=%DIRNAME% + +@@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome + + set JAVA_EXE=java.exe + %JAVA_EXE% -version >NUL 2>&1 +-if "%ERRORLEVEL%" == "0" goto execute ++if %ERRORLEVEL% equ 0 goto execute + + echo. + echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +@@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + :end + @rem End local scope for the variables with windows NT shell +-if "%ERRORLEVEL%"=="0" goto mainEnd ++if %ERRORLEVEL% equ 0 goto mainEnd + + :fail + rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of + rem the _cmd.exe /c_ return code! +-if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +-exit /b 1 ++set EXIT_CODE=%ERRORLEVEL% ++if %EXIT_CODE% equ 0 set EXIT_CODE=1 ++if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% ++exit /b %EXIT_CODE% + + :mainEnd + if "%OS%"=="Windows_NT" endlocal +diff --git a/src/main/java/org/springframework/samples/petclinic/model/BaseEntity.java b/src/main/java/org/springframework/samples/petclinic/model/BaseEntity.java +index 3b47a95..5580bd4 100644 +--- a/src/main/java/org/springframework/samples/petclinic/model/BaseEntity.java ++++ b/src/main/java/org/springframework/samples/petclinic/model/BaseEntity.java +@@ -15,10 +15,10 @@ + */ + package org.springframework.samples.petclinic.model; + +-import javax.persistence.GeneratedValue; +-import javax.persistence.GenerationType; +-import javax.persistence.Id; +-import javax.persistence.MappedSuperclass; ++import jakarta.persistence.GeneratedValue; ++import jakarta.persistence.GenerationType; ++import jakarta.persistence.Id; ++import jakarta.persistence.MappedSuperclass; + import java.io.Serializable; + + /** +diff --git a/src/main/java/org/springframework/samples/petclinic/model/NamedEntity.java b/src/main/java/org/springframework/samples/petclinic/model/NamedEntity.java +index 088e52e..7c2ccb2 100644 +--- a/src/main/java/org/springframework/samples/petclinic/model/NamedEntity.java ++++ b/src/main/java/org/springframework/samples/petclinic/model/NamedEntity.java +@@ -15,8 +15,8 @@ + */ + package org.springframework.samples.petclinic.model; + +-import javax.persistence.Column; +-import javax.persistence.MappedSuperclass; ++import jakarta.persistence.Column; ++import jakarta.persistence.MappedSuperclass; + + /** + * Simple JavaBean domain object adds a name property to BaseEntity. Used as +diff --git a/src/main/java/org/springframework/samples/petclinic/model/Person.java b/src/main/java/org/springframework/samples/petclinic/model/Person.java +index 15fabac..e41b6ba 100644 +--- a/src/main/java/org/springframework/samples/petclinic/model/Person.java ++++ b/src/main/java/org/springframework/samples/petclinic/model/Person.java +@@ -15,9 +15,9 @@ + */ + package org.springframework.samples.petclinic.model; + +-import javax.persistence.Column; +-import javax.persistence.MappedSuperclass; +-import javax.validation.constraints.NotEmpty; ++import jakarta.persistence.Column; ++import jakarta.persistence.MappedSuperclass; ++import jakarta.validation.constraints.NotEmpty; + + /** + * Simple JavaBean domain object representing an person. +diff --git a/src/main/java/org/springframework/samples/petclinic/owner/Owner.java b/src/main/java/org/springframework/samples/petclinic/owner/Owner.java +index 7f2ef90..9f5411e 100644 +--- a/src/main/java/org/springframework/samples/petclinic/owner/Owner.java ++++ b/src/main/java/org/springframework/samples/petclinic/owner/Owner.java +@@ -21,14 +21,14 @@ import java.util.HashSet; + import java.util.List; + import java.util.Set; + +-import javax.persistence.CascadeType; +-import javax.persistence.Column; +-import javax.persistence.Entity; +-import javax.persistence.FetchType; +-import javax.persistence.OneToMany; +-import javax.persistence.Table; +-import javax.validation.constraints.Digits; +-import javax.validation.constraints.NotEmpty; ++import jakarta.persistence.CascadeType; ++import jakarta.persistence.Column; ++import jakarta.persistence.Entity; ++import jakarta.persistence.FetchType; ++import jakarta.persistence.OneToMany; ++import jakarta.persistence.Table; ++import jakarta.validation.constraints.Digits; ++import jakarta.validation.constraints.NotEmpty; + + import org.springframework.beans.support.MutableSortDefinition; + import org.springframework.beans.support.PropertyComparator; +diff --git a/src/main/java/org/springframework/samples/petclinic/owner/OwnerController.java b/src/main/java/org/springframework/samples/petclinic/owner/OwnerController.java +index 781184a..a43aacf 100644 +--- a/src/main/java/org/springframework/samples/petclinic/owner/OwnerController.java ++++ b/src/main/java/org/springframework/samples/petclinic/owner/OwnerController.java +@@ -18,7 +18,7 @@ package org.springframework.samples.petclinic.owner; + import java.util.List; + import java.util.Map; + +-import javax.validation.Valid; ++import jakarta.validation.Valid; + + import org.springframework.data.domain.Page; + import org.springframework.data.domain.PageRequest; +@@ -132,7 +132,7 @@ class OwnerController { + } + + @GetMapping("/owners/{ownerId}/edit") +- public String initUpdateOwnerForm(@PathVariable("ownerId") int ownerId, Model model) { ++ public String initUpdateOwnerForm(@PathVariable int ownerId, Model model) { + Owner owner = this.owners.findById(ownerId); + model.addAttribute(owner); + return VIEWS_OWNER_CREATE_OR_UPDATE_FORM; +@@ -140,7 +140,7 @@ class OwnerController { + + @PostMapping("/owners/{ownerId}/edit") + public String processUpdateOwnerForm(@Valid Owner owner, BindingResult result, +- @PathVariable("ownerId") int ownerId) { ++ @PathVariable int ownerId) { + if (result.hasErrors()) { + return VIEWS_OWNER_CREATE_OR_UPDATE_FORM; + } +@@ -157,7 +157,7 @@ class OwnerController { + * @return a ModelMap with the model attributes for the view + */ + @GetMapping("/owners/{ownerId}") +- public ModelAndView showOwner(@PathVariable("ownerId") int ownerId) { ++ public ModelAndView showOwner(@PathVariable int ownerId) { + ModelAndView mav = new ModelAndView("owners/ownerDetails"); + Owner owner = this.owners.findById(ownerId); + for (Pet pet : owner.getPets()) { +diff --git a/src/main/java/org/springframework/samples/petclinic/owner/Pet.java b/src/main/java/org/springframework/samples/petclinic/owner/Pet.java +index 2b68005..4042030 100755 +--- a/src/main/java/org/springframework/samples/petclinic/owner/Pet.java ++++ b/src/main/java/org/springframework/samples/petclinic/owner/Pet.java +@@ -24,12 +24,12 @@ import java.util.LinkedHashSet; + import java.util.List; + import java.util.Set; + +-import javax.persistence.Column; +-import javax.persistence.Entity; +-import javax.persistence.JoinColumn; +-import javax.persistence.ManyToOne; +-import javax.persistence.Table; +-import javax.persistence.Transient; ++import jakarta.persistence.Column; ++import jakarta.persistence.Entity; ++import jakarta.persistence.JoinColumn; ++import jakarta.persistence.ManyToOne; ++import jakarta.persistence.Table; ++import jakarta.persistence.Transient; + + import org.springframework.beans.support.MutableSortDefinition; + import org.springframework.beans.support.PropertyComparator; +diff --git a/src/main/java/org/springframework/samples/petclinic/owner/PetController.java b/src/main/java/org/springframework/samples/petclinic/owner/PetController.java +index a55e599..2eebf02 100644 +--- a/src/main/java/org/springframework/samples/petclinic/owner/PetController.java ++++ b/src/main/java/org/springframework/samples/petclinic/owner/PetController.java +@@ -22,7 +22,7 @@ import org.springframework.validation.BindingResult; + import org.springframework.web.bind.WebDataBinder; + import org.springframework.web.bind.annotation.*; + +-import javax.validation.Valid; ++import jakarta.validation.Valid; + import java.util.Collection; + + /** +@@ -51,7 +51,7 @@ class PetController { + } + + @ModelAttribute("owner") +- public Owner findOwner(@PathVariable("ownerId") int ownerId) { ++ public Owner findOwner(@PathVariable int ownerId) { + return this.owners.findById(ownerId); + } + +@@ -90,7 +90,7 @@ class PetController { + } + + @GetMapping("/pets/{petId}/edit") +- public String initUpdateForm(@PathVariable("petId") int petId, ModelMap model) { ++ public String initUpdateForm(@PathVariable int petId, ModelMap model) { + Pet pet = this.pets.findById(petId); + model.put("pet", pet); + return VIEWS_PETS_CREATE_OR_UPDATE_FORM; +diff --git a/src/main/java/org/springframework/samples/petclinic/owner/PetType.java b/src/main/java/org/springframework/samples/petclinic/owner/PetType.java +index 3cb9fc1..eeea6a7 100644 +--- a/src/main/java/org/springframework/samples/petclinic/owner/PetType.java ++++ b/src/main/java/org/springframework/samples/petclinic/owner/PetType.java +@@ -17,8 +17,8 @@ package org.springframework.samples.petclinic.owner; + + import org.springframework.samples.petclinic.model.NamedEntity; + +-import javax.persistence.Entity; +-import javax.persistence.Table; ++import jakarta.persistence.Entity; ++import jakarta.persistence.Table; + + /** + * @author Juergen Hoeller Can be Cat, Dog, Hamster... +diff --git a/src/main/java/org/springframework/samples/petclinic/owner/PetTypeFormatter.java b/src/main/java/org/springframework/samples/petclinic/owner/PetTypeFormatter.java +index c97107f..e7ece3e 100644 +--- a/src/main/java/org/springframework/samples/petclinic/owner/PetTypeFormatter.java ++++ b/src/main/java/org/springframework/samples/petclinic/owner/PetTypeFormatter.java +@@ -15,7 +15,6 @@ + */ + package org.springframework.samples.petclinic.owner; + +-import org.springframework.beans.factory.annotation.Autowired; + import org.springframework.format.Formatter; + import org.springframework.stereotype.Component; + +@@ -38,7 +37,6 @@ public class PetTypeFormatter implements Formatter { + + private final PetRepository pets; + +- @Autowired + public PetTypeFormatter(PetRepository pets) { + this.pets = pets; + } +diff --git a/src/main/java/org/springframework/samples/petclinic/owner/VisitController.java b/src/main/java/org/springframework/samples/petclinic/owner/VisitController.java +index 135497f..79535ae 100644 +--- a/src/main/java/org/springframework/samples/petclinic/owner/VisitController.java ++++ b/src/main/java/org/springframework/samples/petclinic/owner/VisitController.java +@@ -22,7 +22,7 @@ import org.springframework.validation.BindingResult; + import org.springframework.web.bind.WebDataBinder; + import org.springframework.web.bind.annotation.*; + +-import javax.validation.Valid; ++import jakarta.validation.Valid; + import java.util.Map; + + /** +@@ -57,7 +57,7 @@ class VisitController { + * @return Pet + */ + @ModelAttribute("visit") +- public Visit loadPetWithVisit(@PathVariable("petId") int petId, Map model) { ++ public Visit loadPetWithVisit(@PathVariable int petId, Map model) { + Pet pet = this.pets.findById(petId); + pet.setVisitsInternal(this.visits.findByPetId(petId)); + model.put("pet", pet); +@@ -68,7 +68,7 @@ class VisitController { + + // Spring MVC calls method loadPetWithVisit(...) before initNewVisitForm is called + @GetMapping("/owners/*/pets/{petId}/visits/new") +- public String initNewVisitForm(@PathVariable("petId") int petId, Map model) { ++ public String initNewVisitForm(@PathVariable int petId, Map model) { + return "pets/createOrUpdateVisitForm"; + } + +diff --git a/src/main/java/org/springframework/samples/petclinic/system/CrashController.java b/src/main/java/org/springframework/samples/petclinic/system/CrashController.java +index 2b28600..8fc8758 100644 +--- a/src/main/java/org/springframework/samples/petclinic/system/CrashController.java ++++ b/src/main/java/org/springframework/samples/petclinic/system/CrashController.java +@@ -31,7 +31,10 @@ class CrashController { + @GetMapping("/oups") + public String triggerException() { + throw new RuntimeException( +- "Expected: controller used to showcase what " + "happens when an exception is thrown"); ++ """ ++ Expected: controller used to showcase what \ ++ happens when an exception is thrown\ ++ """); + } + + } +diff --git a/src/main/java/org/springframework/samples/petclinic/vet/Specialty.java b/src/main/java/org/springframework/samples/petclinic/vet/Specialty.java +index 3a7347f..21f38c3 100644 +--- a/src/main/java/org/springframework/samples/petclinic/vet/Specialty.java ++++ b/src/main/java/org/springframework/samples/petclinic/vet/Specialty.java +@@ -15,8 +15,8 @@ + */ + package org.springframework.samples.petclinic.vet; + +-import javax.persistence.Entity; +-import javax.persistence.Table; ++import jakarta.persistence.Entity; ++import jakarta.persistence.Table; + + import org.springframework.samples.petclinic.model.NamedEntity; + +diff --git a/src/main/java/org/springframework/samples/petclinic/vet/Vet.java b/src/main/java/org/springframework/samples/petclinic/vet/Vet.java +index 7f61931..92a8570 100644 +--- a/src/main/java/org/springframework/samples/petclinic/vet/Vet.java ++++ b/src/main/java/org/springframework/samples/petclinic/vet/Vet.java +@@ -19,8 +19,8 @@ import org.springframework.beans.support.MutableSortDefinition; + import org.springframework.beans.support.PropertyComparator; + import org.springframework.samples.petclinic.model.Person; + +-import javax.persistence.*; +-import javax.xml.bind.annotation.XmlElement; ++import jakarta.persistence.*; ++import jakarta.xml.bind.annotation.XmlElement; + import java.util.*; + + /** +diff --git a/src/main/java/org/springframework/samples/petclinic/vet/Vets.java b/src/main/java/org/springframework/samples/petclinic/vet/Vets.java +index 961e5c0..f85d30b 100644 +--- a/src/main/java/org/springframework/samples/petclinic/vet/Vets.java ++++ b/src/main/java/org/springframework/samples/petclinic/vet/Vets.java +@@ -15,8 +15,8 @@ + */ + package org.springframework.samples.petclinic.vet; + +-import javax.xml.bind.annotation.XmlElement; +-import javax.xml.bind.annotation.XmlRootElement; ++import jakarta.xml.bind.annotation.XmlElement; ++import jakarta.xml.bind.annotation.XmlRootElement; + import java.util.ArrayList; + import java.util.List; + +diff --git a/src/main/java/org/springframework/samples/petclinic/visit/Visit.java b/src/main/java/org/springframework/samples/petclinic/visit/Visit.java +index 239d605..7644fbe 100755 +--- a/src/main/java/org/springframework/samples/petclinic/visit/Visit.java ++++ b/src/main/java/org/springframework/samples/petclinic/visit/Visit.java +@@ -18,10 +18,10 @@ package org.springframework.samples.petclinic.visit; + import org.springframework.format.annotation.DateTimeFormat; + import org.springframework.samples.petclinic.model.BaseEntity; + +-import javax.persistence.Column; +-import javax.persistence.Entity; +-import javax.persistence.Table; +-import javax.validation.constraints.NotEmpty; ++import jakarta.persistence.Column; ++import jakarta.persistence.Entity; ++import jakarta.persistence.Table; ++import jakarta.validation.constraints.NotEmpty; + import java.time.LocalDate; + + /** +diff --git a/src/main/resources/application-mysql.properties b/src/main/resources/application-mysql.properties +index d388c9e..e23dfa6 100644 +--- a/src/main/resources/application-mysql.properties ++++ b/src/main/resources/application-mysql.properties +@@ -4,4 +4,4 @@ spring.datasource.url=${MYSQL_URL:jdbc:mysql://localhost/petclinic} + spring.datasource.username=${MYSQL_USER:petclinic} + spring.datasource.password=${MYSQL_PASS:petclinic} + # SQL is written to be idempotent so this is safe +-spring.datasource.initialization-mode=always ++spring.sql.init.mode=always +diff --git a/src/main/resources/application-postgres.properties b/src/main/resources/application-postgres.properties +index 80bd3e1..60889b4 100644 +--- a/src/main/resources/application-postgres.properties ++++ b/src/main/resources/application-postgres.properties +@@ -3,4 +3,4 @@ spring.datasource.url=${POSTGRES_URL:jdbc:postgresql://localhost/petclinic} + spring.datasource.username=${POSTGRES_USER:petclinic} + spring.datasource.password=${POSTGRES_PASS:petclinic} + # SQL is written to be idempotent so this is safe +-spring.datasource.initialization-mode=always ++spring.sql.init.mode=always +diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties +index 4d4784e..6ed9856 100644 +--- a/src/main/resources/application.properties ++++ b/src/main/resources/application.properties +@@ -1,7 +1,7 @@ + # database init, supports mysql too + database=h2 +-spring.datasource.schema=classpath*:db/${database}/schema.sql +-spring.datasource.data=classpath*:db/${database}/data.sql ++spring.sql.init.schema-locations=classpath*:db/${database}/schema.sql ++spring.sql.init.data-locations=classpath*:db/${database}/data.sql + + # Web + spring.thymeleaf.mode=HTML +@@ -22,4 +22,4 @@ logging.level.org.springframework=INFO + # logging.level.org.springframework.context.annotation=TRACE + + # Maximum time static resources should be cached +-spring.resources.cache.cachecontrol.max-age=12h ++spring.web.resources.cache.cachecontrol.max-age=12h +diff --git a/src/test/java/org/springframework/samples/petclinic/model/ValidatorTests.java b/src/test/java/org/springframework/samples/petclinic/model/ValidatorTests.java +index 5fee819..7d3453d 100644 +--- a/src/test/java/org/springframework/samples/petclinic/model/ValidatorTests.java ++++ b/src/test/java/org/springframework/samples/petclinic/model/ValidatorTests.java +@@ -20,8 +20,8 @@ import org.junit.jupiter.api.Test; + import org.springframework.context.i18n.LocaleContextHolder; + import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; + +-import javax.validation.ConstraintViolation; +-import javax.validation.Validator; ++import jakarta.validation.ConstraintViolation; ++import jakarta.validation.Validator; + import java.util.Locale; + import java.util.Set; + +diff --git a/src/test/java/org/springframework/samples/petclinic/owner/PetTypeFormatterTests.java b/src/test/java/org/springframework/samples/petclinic/owner/PetTypeFormatterTests.java +index 1c0c01b..9cb2e1f 100644 +--- a/src/test/java/org/springframework/samples/petclinic/owner/PetTypeFormatterTests.java ++++ b/src/test/java/org/springframework/samples/petclinic/owner/PetTypeFormatterTests.java +@@ -16,7 +16,6 @@ + + package org.springframework.samples.petclinic.owner; + +-import org.junit.jupiter.api.Assertions; + import org.junit.jupiter.api.BeforeEach; + import org.junit.jupiter.api.Test; + import org.junit.jupiter.api.extension.ExtendWith; +@@ -30,6 +29,7 @@ import java.util.List; + import java.util.Locale; + + import static org.assertj.core.api.Assertions.assertThat; ++import static org.junit.jupiter.api.Assertions.assertThrows; + import static org.mockito.BDDMockito.given; + + /** +@@ -68,7 +68,7 @@ class PetTypeFormatterTests { + @Test + void shouldThrowParseException() throws ParseException { + given(this.pets.findPetTypes()).willReturn(makePetTypes()); +- Assertions.assertThrows(ParseException.class, () -> { ++ assertThrows(ParseException.class, () -> { + petTypeFormatter.parse("Fish", Locale.ENGLISH); + }); + } +``` + +
+ +If you look at the results, you should see that: + +* The `@Autowired` annotation was removed +* JUnit 4 has been replaced with JUnit 5 +* `javax` has been replaced with `jakarta` +* The code has been migrated to Java 17, and text blocks are used +* Some best practices are applied (such as adding the `public` test method modifier) + +After all of that, unfortunately, the build for this repository is broken as the commit we started from is using `Wro4j` - which has some [slight dependency conflicts](https://github.com/wro4j/wro4j/issues/1129). We've decided not to cover `Wro4j` with recipes for now, as [Spring PetClinic has dropped Wro4J as well](https://github.com/spring-projects/spring-petclinic/pull/868). + +### (Optional) Fix static code analysis issues + +If you have time, we recommend trying out one of the showcase recipes in OpenRewrite: [common static analysis](https://docs.openrewrite.org/recipes/staticanalysis/commonstaticanalysis). This recipe is composed of 50+ recipes that find and fix common mistakes people make. + +To demonstrate this recipe, we'll revert the Spring Boot migration changes to show a variety of errors that need to be fixed. + +1. Revert the Spring Boot migration changes: + +```bash +cd spring-petclinic +git reset --hard +git checkout 4df621b41ed3013e527d4037d83a6cf756efd784 +``` + +2. We'll change things up a bit by modifying the build file rather than using an `init.gradle` file. Download the `configure-build.patch` file to the root of the Spring PetClinic repository. + +{% file src="../../.gitbook/assets/configure-build.patch" %} + +
+ +configure-build.patch + +```diff +diff --git a/build.gradle b/build.gradle +index c517cfc..c040d7d 100644 +--- a/build.gradle ++++ b/build.gradle +@@ -1,17 +1,18 @@ +-buildscript { +- dependencies { +- classpath 'ro.isdc.wro4j.gradle:wro4j-gradle-plugin:1.8.0.Beta4' +- } +-} ++//buildscript { ++// dependencies { ++// classpath 'ro.isdc.wro4j.gradle:wro4j-gradle-plugin:1.8.0.Beta4' ++// } ++//} + + plugins { + id 'org.springframework.boot' version '2.4.5' + id 'io.spring.dependency-management' version '1.0.11.RELEASE' + id 'java' ++ id 'org.openrewrite.rewrite' version '6.4.3' + } + + apply plugin: 'java' +-apply plugin: 'wro4j' ++//apply plugin: 'wro4j' + + group = 'org.springframework.samples' + version = '2.4.5' +@@ -32,29 +33,35 @@ dependencies { + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-validation' + implementation 'javax.cache:cache-api' +- webjarsRuntime 'org.webjars:webjars-locator-core' +- webjarsRuntime "org.webjars:jquery:${webjarsJqueryVersion}" +- webjarsRuntime "org.webjars:jquery-ui:${webjarsJqueryUiVersion}" +- webjarsRuntime "org.webjars:bootstrap:${webjarsBootstrapVersion}" +- webjarsRuntime "org.webjars:bootstrap:${webjarsBootstrapVersion}" ++// webjarsRuntime 'org.webjars:webjars-locator-core' ++// webjarsRuntime "org.webjars:jquery:${webjarsJqueryVersion}" ++// webjarsRuntime "org.webjars:jquery-ui:${webjarsJqueryUiVersion}" ++// webjarsRuntime "org.webjars:bootstrap:${webjarsBootstrapVersion}" ++// webjarsRuntime "org.webjars:bootstrap:${webjarsBootstrapVersion}" + runtimeOnly 'org.ehcache:ehcache' + runtimeOnly 'com.h2database:h2' + runtimeOnly 'mysql:mysql-connector-java' + developmentOnly 'org.springframework.boot:spring-boot-devtools' + testImplementation 'org.springframework.boot:spring-boot-starter-test' ++ ++ rewrite 'org.openrewrite.recipe:rewrite-static-analysis:latest.release' ++} ++ ++rewrite { ++ activeRecipe 'org.openrewrite.staticanalysis.CommonStaticAnalysis' + } + + test { + useJUnitPlatform() + } + +-webResources { +- srcMainDir = layout.projectDirectory.dir('src/main').asFile +- dstStaticFolder = 'static/resources/css' +- bundle ('petclinic') { +- css 'webjars/bootstrap/3.3.6/less/bootstrap.less' +- css 'less/petclinic.less' +- preProcessor 'lessCssImport' +- postProcessor 'less4j' +- } +-} ++//webResources { ++// srcMainDir = layout.projectDirectory.dir('src/main').asFile ++// dstStaticFolder = 'static/resources/css' ++// bundle ('petclinic') { ++// css 'webjars/bootstrap/3.3.6/less/bootstrap.less' ++// css 'less/petclinic.less' ++// preProcessor 'lessCssImport' ++// postProcessor 'less4j' ++// } ++//} +diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties +index 442d913..98debb8 100644 +--- a/gradle/wrapper/gradle-wrapper.properties ++++ b/gradle/wrapper/gradle-wrapper.properties +@@ -1,5 +1,5 @@ + distributionBase=GRADLE_USER_HOME + distributionPath=wrapper/dists +-distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip ++distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.2-bin.zip + zipStoreBase=GRADLE_USER_HOME + zipStorePath=wrapper/dists + +``` + +
+ +3. Apply the patch file to automatically configure the rewrite Gradle plugin. We recommend that you look at the differences to understand how it is configured: + +```bash +git apply configure-build.patch +``` + +You'll notice that we both upgrade Gradle and disable Wro4j, again due to the issue we mentioned above. + +4. With the patch applied, you can now run OpenRewrite: + +```bash +./gradlew rewriteRun +``` + +
+ +You should see output similar to the following. + +```bash +> Task :rewriteRun +Validating active recipes +Scanning sources in project spring-petclinic +All sources parsed, running active recipes: org.openrewrite.staticanalysis.CommonStaticAnalysis +Changes have been made to src/test/java/org/springframework/samples/petclinic/vet/VetControllerTests.java by: + org.openrewrite.staticanalysis.CommonStaticAnalysis + org.openrewrite.staticanalysis.UseDiamondOperator +Changes have been made to src/test/java/org/springframework/samples/petclinic/owner/OwnerControllerTests.java by: + org.openrewrite.staticanalysis.CommonStaticAnalysis + org.openrewrite.staticanalysis.SimplifyBooleanReturn + org.openrewrite.staticanalysis.UseDiamondOperator +Please review and commit the results. +``` + +
+ +5. Check out all of the changes that were made by running: + +```bash +git checkout build.gradle +git checkout gradle/wrapper/gradle-wrapper.properties +git diff +``` + +While this recipe only shows limited results for the Spring PetClinic repository, at scale, this immediately resolves a lot of technical debt. diff --git a/workshops/spring-boot-migration-workshop/maven-plugin-exercise.md b/workshops/spring-boot-migration-workshop/maven-plugin-exercise.md new file mode 100644 index 00000000..318c2b32 --- /dev/null +++ b/workshops/spring-boot-migration-workshop/maven-plugin-exercise.md @@ -0,0 +1,1609 @@ +# Maven plugin exercise + +In this exercise, you will migrate an old version of the [Spring PetClinic repository](https://github.com/spring-projects/spring-petclinic/) (that uses Spring Boot 2) to Spring Boot 3 using Maven. + +If you were migrating this by hand, you would need to do a variety of things, such as: + +* Migrating to Java 17 +* Migrating to Spring Boot 2.7 +* Migrating to Spring Security 5.8 +* Migrating to Spring Cloud 2022 +* Migrating to Jakarta EE 9 +* Migrating to Spring Boot 3.0 +* Migrating to Spring Security 6.0 +* Migrating to Spring Boot 3.1 +* ... + +Fortunately, [OpenRewrite](https://docs.openrewrite.org/) has a [recipe](https://docs.openrewrite.org/concepts-explanations/recipes) that takes care of all of these pieces for you. Because of that, you only need to add the OpenRewrite plugin to your project and run a single [Migrate to Spring Boot 3.1 recipe](https://docs.openrewrite.org/recipes/java/spring/boot3/upgradespringboot\_3\_1). + +Let's walk through how to do that. + +### Prepare your environment + +You will need to switch to Java 8 in order to build the Spring PetClinic repository. You might need to download Java 8 and update your `JAVA_HOME` environment variable. If you are on a Unix-based system, we recommend using [SDKMan](https://sdkman.io/): + +```sh +sdk install java 8.0.392-zulu +sdk use java 8.0.392-zulu +``` + +{% hint style="info" %} +If you aren't on a Unix-based system or you don't want to install SDKMan, you'll need to install Java 8 and run something like: + +```bash +export JAVA_HOME=REPLACE_WITH_LOCATION_OF_JAVA_8 +``` +{% endhint %} + +1. Clone the [Spring PetClinic repository](https://github.com/spring-projects/spring-petclinic): + +```sh +git clone https://github.com/spring-projects/spring-petclinic +``` + +2. Check out the last Spring Boot 2.0 commit: + +```bash +cd spring-petclinic +git checkout b527de52f5fd19f9fe550372c017d145a3b2a809 +``` + +3. Make sure it runs on your machine: + +```bash +./mvnw verify -DskipTests +``` + +### Migrate to SpringBoot 3 with OpenRewrite + +For Maven projects, you can choose to update the `pom.xml` to add the OpenRewrite dependencies, or you can run a more complex command in the command line that includes all of the information needed to run the recipe. + +#### Option 1: Update the pom.xml + +Modify the `pom.xml` file and add the following information: + +```xml + + + ... + + + + org.openrewrite.maven + rewrite-maven-plugin + 5.10.0 + + + org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 + + + + + org.openrewrite.recipe + rewrite-spring + 5.0.12 + + + + + + +``` + +Once you've done that, you can run the Migrate to [Spring Boot 3.1 recipe](https://docs.openrewrite.org/recipes/java/spring/boot3/upgradespringboot\_3\_1) by running the following command: + +```bash +./mvnw -U org.openrewrite.maven:rewrite-maven-plugin:run +``` + +{% hint style="info" %} +Running OpenRewrite [can take a while](../../introduction.md) as we analyze the project and run recipes to make code changes. You should see results within a couple of minutes, depending on the size of your project and your project. +{% endhint %} + +### Option 2: Use the command line + +You can run a recipe without editing the `pom.xml` file by including all of the details in the command line. Below is the command for running the `UpgradeSpringBoot_3_1` recipe: + +```bash +./mvnw -U org.openrewrite.maven:rewrite-maven-plugin:run -Drewrite.activeRecipes=org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-spring:RELEASE +``` + +
+ +You should see output similar to the following. + +```bash +[INFO] Scanning for projects... +Downloading: https://repo.maven.apache.org/maven2/org/openrewrite/maven/rewrite-maven-plugin/maven-metadata.xml +Downloaded: https://repo.maven.apache.org/maven2/org/openrewrite/maven/rewrite-maven-plugin/maven-metadata.xml (5 KB at 19.1 KB/sec) +[INFO] +[INFO] ------------------------------------------------------------------------ +[INFO] Building petclinic 2.0.0.BUILD-SNAPSHOT +[INFO] ------------------------------------------------------------------------ +[INFO] +[INFO] >>> rewrite-maven-plugin:5.5.0:run (default-cli) > process-test-classes @ spring-petclinic >>> +[INFO] +[INFO] --- git-commit-id-plugin:2.2.3:revision (default) @ spring-petclinic --- +[INFO] dotGitDirectory /tmp/cli/spring-petclinic/.git +[INFO] git.build.user.name Tim te Beek +[INFO] git.build.user.email tim@moderne.io +[INFO] git.branch b527de52f5fd19f9fe550372c017d145a3b2a809 +[INFO] --always = true +[INFO] --dirty = -dirty +[INFO] --abbrev = 7 +[INFO] Tag refs [[Ref[refs/tags/1.5.x=c36452a2c34443ae26b4ecbba4f149906af14717]]] +[INFO] Created map: [{}] +[INFO] HEAD is [b527de52f5fd19f9fe550372c017d145a3b2a809] +[INFO] git.commit.id.describe b527de5 +[INFO] git.commit.id b527de52f5fd19f9fe550372c017d145a3b2a809 +[INFO] git.commit.id.abbrev b527de5 +[INFO] git.dirty false +[INFO] git.commit.user.name Stephane Nicoll +[INFO] git.commit.user.email snicoll@pivotal.io +[INFO] git.commit.message.full Upgrade to Spring Boot 2.0.0.RELEASE +[INFO] git.commit.message.short Upgrade to Spring Boot 2.0.0.RELEASE +[INFO] git.commit.time 2018-03-14T21:32:27+0100 +[INFO] git.remote.origin.url https://github.com/spring-projects/spring-petclinic +[INFO] git.tags +[INFO] Tag refs [[Ref[refs/tags/1.5.x=c36452a2c34443ae26b4ecbba4f149906af14717]]] +[INFO] Including lightweight tag [refs/tags/1.5.x] +[INFO] key [AnyObjectId[c36452a2c34443ae26b4ecbba4f149906af14717]], tags => [[DatedRevTag{id=c36452a2c34443ae26b4ecbba4f149906af14717, tagName='refs/tags/1.5.x', date=September 1, 0023 12:48:47 PM CET}]] +[INFO] git.closest.tag.name 1.5.x +[INFO] Tag refs [[Ref[refs/tags/1.5.x=c36452a2c34443ae26b4ecbba4f149906af14717]]] +[INFO] Including lightweight tag [refs/tags/1.5.x] +[INFO] key [AnyObjectId[c36452a2c34443ae26b4ecbba4f149906af14717]], tags => [[DatedRevTag{id=c36452a2c34443ae26b4ecbba4f149906af14717, tagName='refs/tags/1.5.x', date=September 1, 0023 12:48:47 PM CET}]] +[INFO] git.closest.tag.commit.count 15 +[INFO] git.build.time 2023-09-01T12:48:47+0200 +[INFO] git.build.version 2.0.0.BUILD-SNAPSHOT +[INFO] git.build.host tim-xps-15-9520 +[INFO] git.commit.id.describe-short b527de5 +[INFO] found property git.build.user.email +[INFO] found property git.build.host +[INFO] found property git.dirty +[INFO] found property git.remote.origin.url +[INFO] found property git.closest.tag.name +[INFO] found property git.commit.id.describe-short +[INFO] found property git.commit.user.email +[INFO] found property git.commit.time +[INFO] found property git.commit.message.full +[INFO] found property git.build.version +[INFO] found property git.commit.message.short +[INFO] found property git.commit.id.abbrev +[INFO] found property git.branch +[INFO] found property git.build.user.name +[INFO] found property git.closest.tag.commit.count +[INFO] found property git.commit.id.describe +[INFO] found property git.commit.id +[INFO] found property git.tags +[INFO] found property git.build.time +[INFO] found property git.commit.user.name +[INFO] Reading existing properties file [/tmp/cli/spring-petclinic/target/classes/git.properties] (for module petclinic)... +[INFO] Properties file [/tmp/cli/spring-petclinic/target/classes/git.properties] is up-to-date (for module petclinic)... +[INFO] +[INFO] --- spring-boot-maven-plugin:2.0.0.RELEASE:build-info (default) @ spring-petclinic --- +[INFO] +[INFO] --- wro4j-maven-plugin:1.8.0:run (default) @ spring-petclinic --- +Downloading: https://repo.maven.apache.org/maven2/me/n4u/sass/sass-gems/maven-metadata.xml +Downloading: https://oss.sonatype.org/content/repositories/snapshots/me/n4u/sass/sass-gems/maven-metadata.xml +Downloaded: https://repo.maven.apache.org/maven2/me/n4u/sass/sass-gems/maven-metadata.xml (518 B at 15.3 KB/sec) +[INFO] /tmp/cli/spring-petclinic/src/main/less +[INFO] Executing the mojo: +[INFO] Wro4j Model path: /tmp/cli/spring-petclinic/src/main/wro/wro.xml +[INFO] targetGroups: null +[INFO] minimize: true +[INFO] ignoreMissingResources: null +[INFO] parallelProcessing: false +[INFO] buildDirectory: /tmp/cli/spring-petclinic/target +[INFO] destinationFolder: /tmp/cli/spring-petclinic/target +[INFO] cssDestinationFolder: /tmp/cli/spring-petclinic/target/classes/static/resources/css +[INFO] The following groups will be processed: [petclinic] +[INFO] folder: /tmp/cli/spring-petclinic/target/classes/static/resources/css +[INFO] processing group: petclinic.css +[WARNING] Less warnings are: +[WARNING] 10:1 Cannot link source map. Css result location is not know and could not be deduced from input less source.. +[INFO] file size: petclinic.css -> 152399 bytes +[INFO] /tmp/cli/spring-petclinic/target/classes/static/resources/css/petclinic.css (152399 bytes) +[INFO] folder: /tmp/cli/spring-petclinic/target +[INFO] processing group: petclinic.js +[INFO] +[INFO] --- maven-resources-plugin:3.0.1:resources (default-resources) @ spring-petclinic --- +[INFO] Using 'UTF-8' encoding to copy filtered resources. +[INFO] Copying 2 resources +[INFO] Copying 35 resources +[INFO] +[INFO] --- maven-compiler-plugin:3.7.0:compile (default-compile) @ spring-petclinic --- +[INFO] Changes detected - recompiling the module! +[INFO] Compiling 25 source files to /tmp/cli/spring-petclinic/target/classes +[INFO] +[INFO] --- maven-resources-plugin:3.0.1:testResources (default-testResources) @ spring-petclinic --- +[INFO] Using 'UTF-8' encoding to copy filtered resources. +[INFO] skip non existing resourceDirectory /tmp/cli/spring-petclinic/src/test/resources +[INFO] +[INFO] --- maven-compiler-plugin:3.7.0:testCompile (default-testCompile) @ spring-petclinic --- +[INFO] Changes detected - recompiling the module! +[INFO] Compiling 11 source files to /tmp/cli/spring-petclinic/target/test-classes +[INFO] +[INFO] <<< rewrite-maven-plugin:5.5.0:run (default-cli) < process-test-classes @ spring-petclinic <<< +[INFO] +[INFO] --- rewrite-maven-plugin:5.5.0:run (default-cli) @ spring-petclinic --- +[INFO] Using active recipe(s) [org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1] +[INFO] Using active styles(s) [] +Downloading: https://dl.bintray.com/rabbitmq/maven-milestones/org/openrewrite/recipe/rewrite-spring/maven-metadata.xml +Downloading: https://repo.spring.io/milestone/org/openrewrite/recipe/rewrite-spring/maven-metadata.xml +Downloading: https://repo.maven.apache.org/maven2/org/openrewrite/recipe/rewrite-spring/maven-metadata.xml +Downloading: https://repo.spring.io/snapshot/org/openrewrite/recipe/rewrite-spring/maven-metadata.xml +Downloaded: https://repo.maven.apache.org/maven2/org/openrewrite/recipe/rewrite-spring/maven-metadata.xml (3 KB at 64.5 KB/sec) +[INFO] Validating active recipes... +[INFO] Project [petclinic] Resolving Poms... +[INFO] Project [petclinic] Parsing source files +[INFO] Running recipe(s)... +[WARNING] Changes have been made to pom.xml by: +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_3 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_2 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_1 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_0 +[WARNING] org.openrewrite.maven.UpgradeParentVersion: {groupId=org.springframework.boot, artifactId=spring-boot-starter-parent, newVersion=2.0.x} +[WARNING] org.openrewrite.java.spring.boot2.MigrateHibernateConstraintsToJavax +[WARNING] org.openrewrite.java.dependencies.AddDependency: {groupId=javax.validation, artifactId=validation-api, version=2.x, onlyIfUsing=javax.validation.constraints.*} +[WARNING] org.openrewrite.maven.AddDependency: {groupId=javax.validation, artifactId=validation-api, version=2.x, onlyIfUsing=javax.validation.constraints.*} +[WARNING] org.openrewrite.maven.UpgradeParentVersion: {groupId=org.springframework.boot, artifactId=spring-boot-starter-parent, newVersion=2.1.x} +[WARNING] org.openrewrite.maven.UpgradeParentVersion: {groupId=org.springframework.boot, artifactId=spring-boot-starter-parent, newVersion=2.2.x} +[WARNING] org.openrewrite.maven.UpgradeParentVersion: {groupId=org.springframework.boot, artifactId=spring-boot-starter-parent, newVersion=2.3.x} +[WARNING] org.openrewrite.java.dependencies.AddDependency: {groupId=org.springframework.boot, artifactId=spring-boot-starter-validation, version=2.3.x, onlyIfUsing=javax.validation.constraints.*, acceptTransitive=true} +[WARNING] org.openrewrite.maven.AddDependency: {groupId=org.springframework.boot, artifactId=spring-boot-starter-validation, version=2.3.x, onlyIfUsing=javax.validation.constraints.*, acceptTransitive=true} +[WARNING] org.openrewrite.java.spring.boot2.SpringBoot2JUnit4to5Migration +[WARNING] org.openrewrite.java.testing.junit5.JUnit4to5Migration +[WARNING] org.openrewrite.maven.ExcludeDependency: {groupId=junit, artifactId=junit} +[WARNING] org.openrewrite.maven.ExcludeDependency: {groupId=org.junit.vintage, artifactId=junit-vintage-engine} +[WARNING] org.openrewrite.maven.UpgradeParentVersion: {groupId=org.springframework.boot, artifactId=spring-boot-starter-parent, newVersion=2.4.x} +[WARNING] org.openrewrite.maven.RemoveExclusion: {groupId=org.springframework.boot, artifactId=spring-boot-starter-test, exclusionGroupId=org.junit.vintage, exclusionArtifactId=junit-vintage-engine} +[WARNING] org.openrewrite.maven.RemoveExclusion: {groupId=org.springframework.boot, artifactId=spring-boot-starter-test, exclusionGroupId=junit, exclusionArtifactId=junit} +[WARNING] org.openrewrite.maven.UpgradeParentVersion: {groupId=org.springframework.boot, artifactId=spring-boot-starter-parent, newVersion=2.5.x} +[WARNING] org.openrewrite.maven.UpgradeParentVersion: {groupId=org.springframework.boot, artifactId=spring-boot-starter-parent, newVersion=2.6.x} +[WARNING] org.openrewrite.maven.UpgradeParentVersion: {groupId=org.springframework.boot, artifactId=spring-boot-starter-parent, newVersion=2.7.x, retainVersions=[mysql:mysql-connector-java]} +[WARNING] org.openrewrite.java.dependencies.ChangeDependency: {oldGroupId=mysql, oldArtifactId=mysql-connector-java, newGroupId=com.mysql, newArtifactId=mysql-connector-j, newVersion=8.0.x} +[WARNING] org.openrewrite.maven.ChangeDependencyGroupIdAndArtifactId: {oldGroupId=mysql, oldArtifactId=mysql-connector-java, newGroupId=com.mysql, newArtifactId=mysql-connector-j, newVersion=8.0.x} +[WARNING] org.openrewrite.java.migrate.UpgradeToJava17 +[WARNING] org.openrewrite.java.migrate.Java8toJava11 +[WARNING] org.openrewrite.java.migrate.cobertura.RemoveCoberturaMavenPlugin +[WARNING] org.openrewrite.maven.RemovePlugin: {groupId=org.codehaus.mojo, artifactId=cobertura-maven-plugin} +[WARNING] org.openrewrite.java.migrate.wro4j.UpgradeWro4jMavenPluginVersion +[WARNING] org.openrewrite.maven.UpgradePluginVersion: {groupId=ro.isdc.wro4j, artifactId=wro4j-maven-plugin, newVersion=1.10.1} +[WARNING] org.openrewrite.java.migrate.JavaVersion11 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=11} +[WARNING] org.openrewrite.java.migrate.javax.AddJaxbDependencies +[WARNING] org.openrewrite.java.migrate.javax.AddJaxbRuntime: {runtime=glassfish} +[WARNING] org.openrewrite.java.migrate.javax.AddJaxbRuntime$AddJaxbRuntimeMaven +[WARNING] org.openrewrite.java.migrate.JavaVersion17 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +[WARNING] org.openrewrite.maven.UpgradeParentVersion: {groupId=org.springframework.boot, artifactId=spring-boot-starter-parent, newVersion=3.0.x, retainVersions=[org.thymeleaf:thymeleaf-spring5, org.thymeleaf.extras:thymeleaf-extras-springsecurity5]} +[WARNING] org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta +[WARNING] org.openrewrite.java.migrate.jakarta.JavaxValidationMigrationToJakartaValidation +[WARNING] org.openrewrite.java.dependencies.RemoveDependency: {groupId=javax.validation, artifactId=validation-api} +[WARNING] org.openrewrite.maven.RemoveDependency: {groupId=javax.validation, artifactId=validation-api} +[WARNING] org.openrewrite.java.migrate.jakarta.EhcacheJavaxToJakarta +[WARNING] org.openrewrite.maven.ChangeDependencyClassifier: {groupId=org.ehcache, artifactId=ehcache, newClassifier=jakarta} +[WARNING] org.openrewrite.maven.UpgradeParentVersion: {groupId=org.springframework.boot, artifactId=spring-boot-starter-parent, newVersion=3.1.x} +[WARNING] Changes have been made to src/main/java/org/springframework/samples/petclinic/vet/Specialty.java by: +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +[WARNING] org.openrewrite.java.migrate.UpgradeToJava17 +[WARNING] org.openrewrite.java.migrate.Java8toJava11 +[WARNING] org.openrewrite.java.migrate.JavaVersion11 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=11} +[WARNING] org.openrewrite.java.migrate.JavaVersion17 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +[WARNING] org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta +[WARNING] org.openrewrite.java.migrate.jakarta.JavaxPersistenceToJakartaPersistence +[WARNING] org.openrewrite.java.ChangePackage: {oldPackageName=javax.persistence, newPackageName=jakarta.persistence, recursive=true} +[WARNING] Changes have been made to src/main/java/org/springframework/samples/petclinic/vet/Vet.java by: +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +[WARNING] org.openrewrite.java.migrate.UpgradeToJava17 +[WARNING] org.openrewrite.java.migrate.Java8toJava11 +[WARNING] org.openrewrite.java.migrate.JavaVersion11 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=11} +[WARNING] org.openrewrite.java.migrate.JavaVersion17 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +[WARNING] org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta +[WARNING] org.openrewrite.java.migrate.jakarta.JavaxPersistenceToJakartaPersistence +[WARNING] org.openrewrite.java.ChangePackage: {oldPackageName=javax.persistence, newPackageName=jakarta.persistence, recursive=true} +[WARNING] org.openrewrite.java.migrate.jakarta.JavaxXmlBindMigrationToJakartaXmlBind +[WARNING] org.openrewrite.java.ChangePackage: {oldPackageName=javax.xml.bind, newPackageName=jakarta.xml.bind, recursive=true} +[WARNING] Changes have been made to src/main/java/org/springframework/samples/petclinic/vet/VetController.java by: +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_3 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_2 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_1 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_0 +[WARNING] org.openrewrite.java.spring.boot2.SpringBoot2BestPractices +[WARNING] org.openrewrite.java.spring.NoAutowiredOnConstructor +[WARNING] org.openrewrite.java.migrate.UpgradeToJava17 +[WARNING] org.openrewrite.java.migrate.Java8toJava11 +[WARNING] org.openrewrite.java.migrate.JavaVersion11 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=11} +[WARNING] org.openrewrite.java.migrate.JavaVersion17 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +[WARNING] Changes have been made to src/main/java/org/springframework/samples/petclinic/vet/Vets.java by: +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +[WARNING] org.openrewrite.java.migrate.UpgradeToJava17 +[WARNING] org.openrewrite.java.migrate.Java8toJava11 +[WARNING] org.openrewrite.java.migrate.JavaVersion11 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=11} +[WARNING] org.openrewrite.java.migrate.JavaVersion17 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +[WARNING] org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta +[WARNING] org.openrewrite.java.migrate.jakarta.JavaxXmlBindMigrationToJakartaXmlBind +[WARNING] org.openrewrite.java.ChangePackage: {oldPackageName=javax.xml.bind, newPackageName=jakarta.xml.bind, recursive=true} +[WARNING] Changes have been made to src/main/java/org/springframework/samples/petclinic/owner/OwnerController.java by: +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_3 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_2 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_1 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_0 +[WARNING] org.openrewrite.java.spring.boot2.SpringBoot2BestPractices +[WARNING] org.openrewrite.java.spring.ImplicitWebAnnotationNames +[WARNING] org.openrewrite.java.spring.NoAutowiredOnConstructor +[WARNING] org.openrewrite.java.migrate.UpgradeToJava17 +[WARNING] org.openrewrite.java.migrate.Java8toJava11 +[WARNING] org.openrewrite.java.migrate.JavaVersion11 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=11} +[WARNING] org.openrewrite.java.migrate.JavaVersion17 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +[WARNING] org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta +[WARNING] org.openrewrite.java.migrate.jakarta.JavaxValidationMigrationToJakartaValidation +[WARNING] org.openrewrite.java.ChangePackage: {oldPackageName=javax.validation, newPackageName=jakarta.validation, recursive=true} +[WARNING] Changes have been made to src/main/java/org/springframework/samples/petclinic/owner/Owner.java by: +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +[WARNING] org.openrewrite.java.migrate.UpgradeToJava17 +[WARNING] org.openrewrite.java.migrate.Java8toJava11 +[WARNING] org.openrewrite.java.migrate.JavaVersion11 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=11} +[WARNING] org.openrewrite.java.migrate.JavaVersion17 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +[WARNING] org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta +[WARNING] org.openrewrite.java.migrate.jakarta.JavaxPersistenceToJakartaPersistence +[WARNING] org.openrewrite.java.ChangePackage: {oldPackageName=javax.persistence, newPackageName=jakarta.persistence, recursive=true} +[WARNING] org.openrewrite.java.migrate.jakarta.JavaxValidationMigrationToJakartaValidation +[WARNING] org.openrewrite.java.ChangePackage: {oldPackageName=javax.validation, newPackageName=jakarta.validation, recursive=true} +[WARNING] Changes have been made to src/main/java/org/springframework/samples/petclinic/owner/PetType.java by: +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +[WARNING] org.openrewrite.java.migrate.UpgradeToJava17 +[WARNING] org.openrewrite.java.migrate.Java8toJava11 +[WARNING] org.openrewrite.java.migrate.JavaVersion11 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=11} +[WARNING] org.openrewrite.java.migrate.JavaVersion17 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +[WARNING] org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta +[WARNING] org.openrewrite.java.migrate.jakarta.JavaxPersistenceToJakartaPersistence +[WARNING] org.openrewrite.java.ChangePackage: {oldPackageName=javax.persistence, newPackageName=jakarta.persistence, recursive=true} +[WARNING] Changes have been made to src/main/java/org/springframework/samples/petclinic/owner/PetController.java by: +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_3 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_2 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_1 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_0 +[WARNING] org.openrewrite.java.spring.boot2.SpringBoot2BestPractices +[WARNING] org.openrewrite.java.spring.ImplicitWebAnnotationNames +[WARNING] org.openrewrite.java.spring.NoAutowiredOnConstructor +[WARNING] org.openrewrite.java.migrate.UpgradeToJava17 +[WARNING] org.openrewrite.java.migrate.Java8toJava11 +[WARNING] org.openrewrite.java.migrate.JavaVersion11 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=11} +[WARNING] org.openrewrite.java.migrate.JavaVersion17 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +[WARNING] org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta +[WARNING] org.openrewrite.java.migrate.jakarta.JavaxValidationMigrationToJakartaValidation +[WARNING] org.openrewrite.java.ChangePackage: {oldPackageName=javax.validation, newPackageName=jakarta.validation, recursive=true} +[WARNING] Changes have been made to src/main/java/org/springframework/samples/petclinic/owner/PetTypeFormatter.java by: +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_3 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_2 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_1 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_0 +[WARNING] org.openrewrite.java.spring.boot2.SpringBoot2BestPractices +[WARNING] org.openrewrite.java.spring.NoAutowiredOnConstructor +[WARNING] org.openrewrite.java.migrate.UpgradeToJava17 +[WARNING] org.openrewrite.java.migrate.Java8toJava11 +[WARNING] org.openrewrite.java.migrate.JavaVersion11 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=11} +[WARNING] org.openrewrite.java.migrate.JavaVersion17 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +[WARNING] Changes have been made to src/main/java/org/springframework/samples/petclinic/owner/Pet.java by: +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +[WARNING] org.openrewrite.java.migrate.UpgradeToJava17 +[WARNING] org.openrewrite.java.migrate.Java8toJava11 +[WARNING] org.openrewrite.java.migrate.JavaVersion11 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=11} +[WARNING] org.openrewrite.java.migrate.JavaVersion17 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +[WARNING] org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta +[WARNING] org.openrewrite.java.migrate.jakarta.JavaxPersistenceToJakartaPersistence +[WARNING] org.openrewrite.java.ChangePackage: {oldPackageName=javax.persistence, newPackageName=jakarta.persistence, recursive=true} +[WARNING] Changes have been made to src/main/java/org/springframework/samples/petclinic/owner/VisitController.java by: +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_3 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_2 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_1 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_0 +[WARNING] org.openrewrite.java.spring.boot2.SpringBoot2BestPractices +[WARNING] org.openrewrite.java.spring.ImplicitWebAnnotationNames +[WARNING] org.openrewrite.java.spring.NoAutowiredOnConstructor +[WARNING] org.openrewrite.java.migrate.UpgradeToJava17 +[WARNING] org.openrewrite.java.migrate.Java8toJava11 +[WARNING] org.openrewrite.java.migrate.JavaVersion11 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=11} +[WARNING] org.openrewrite.java.migrate.JavaVersion17 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +[WARNING] org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta +[WARNING] org.openrewrite.java.migrate.jakarta.JavaxValidationMigrationToJakartaValidation +[WARNING] org.openrewrite.java.ChangePackage: {oldPackageName=javax.validation, newPackageName=jakarta.validation, recursive=true} +[WARNING] Changes have been made to src/main/java/org/springframework/samples/petclinic/model/Person.java by: +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +[WARNING] org.openrewrite.java.migrate.UpgradeToJava17 +[WARNING] org.openrewrite.java.migrate.Java8toJava11 +[WARNING] org.openrewrite.java.migrate.JavaVersion11 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=11} +[WARNING] org.openrewrite.java.migrate.JavaVersion17 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +[WARNING] org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta +[WARNING] org.openrewrite.java.migrate.jakarta.JavaxPersistenceToJakartaPersistence +[WARNING] org.openrewrite.java.ChangePackage: {oldPackageName=javax.persistence, newPackageName=jakarta.persistence, recursive=true} +[WARNING] org.openrewrite.java.migrate.jakarta.JavaxValidationMigrationToJakartaValidation +[WARNING] org.openrewrite.java.ChangePackage: {oldPackageName=javax.validation, newPackageName=jakarta.validation, recursive=true} +[WARNING] Changes have been made to src/main/java/org/springframework/samples/petclinic/model/NamedEntity.java by: +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +[WARNING] org.openrewrite.java.migrate.UpgradeToJava17 +[WARNING] org.openrewrite.java.migrate.Java8toJava11 +[WARNING] org.openrewrite.java.migrate.JavaVersion11 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=11} +[WARNING] org.openrewrite.java.migrate.JavaVersion17 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +[WARNING] org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta +[WARNING] org.openrewrite.java.migrate.jakarta.JavaxPersistenceToJakartaPersistence +[WARNING] org.openrewrite.java.ChangePackage: {oldPackageName=javax.persistence, newPackageName=jakarta.persistence, recursive=true} +[WARNING] Changes have been made to src/main/java/org/springframework/samples/petclinic/model/BaseEntity.java by: +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +[WARNING] org.openrewrite.java.migrate.UpgradeToJava17 +[WARNING] org.openrewrite.java.migrate.Java8toJava11 +[WARNING] org.openrewrite.java.migrate.JavaVersion11 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=11} +[WARNING] org.openrewrite.java.migrate.JavaVersion17 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +[WARNING] org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta +[WARNING] org.openrewrite.java.migrate.jakarta.JavaxPersistenceToJakartaPersistence +[WARNING] org.openrewrite.java.ChangePackage: {oldPackageName=javax.persistence, newPackageName=jakarta.persistence, recursive=true} +[WARNING] Changes have been made to src/main/java/org/springframework/samples/petclinic/visit/Visit.java by: +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +[WARNING] org.openrewrite.java.migrate.UpgradeToJava17 +[WARNING] org.openrewrite.java.migrate.Java8toJava11 +[WARNING] org.openrewrite.java.migrate.JavaVersion11 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=11} +[WARNING] org.openrewrite.java.migrate.JavaVersion17 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +[WARNING] org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta +[WARNING] org.openrewrite.java.migrate.jakarta.JavaxPersistenceToJakartaPersistence +[WARNING] org.openrewrite.java.ChangePackage: {oldPackageName=javax.persistence, newPackageName=jakarta.persistence, recursive=true} +[WARNING] org.openrewrite.java.migrate.jakarta.JavaxValidationMigrationToJakartaValidation +[WARNING] org.openrewrite.java.ChangePackage: {oldPackageName=javax.validation, newPackageName=jakarta.validation, recursive=true} +[WARNING] Changes have been made to src/main/java/org/springframework/samples/petclinic/system/CrashController.java by: +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +[WARNING] org.openrewrite.java.migrate.UpgradeToJava17 +[WARNING] org.openrewrite.java.migrate.Java8toJava11 +[WARNING] org.openrewrite.java.migrate.JavaVersion11 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=11} +[WARNING] org.openrewrite.java.migrate.JavaVersion17 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +[WARNING] org.openrewrite.java.migrate.lang.UseTextBlocks: {convertStringsWithoutNewlines=true} +[WARNING] Changes have been made to src/main/resources/application.properties by: +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +[WARNING] org.openrewrite.java.spring.boot2.SpringBootProperties_2_7 +[WARNING] org.openrewrite.java.spring.ChangeSpringPropertyKey: {oldPropertyKey=spring.datasource.data, newPropertyKey=spring.sql.init.data-locations} +[WARNING] org.openrewrite.java.spring.ChangeSpringPropertyKey: {oldPropertyKey=spring.datasource.schema, newPropertyKey=spring.sql.init.schema-locations} +[WARNING] org.openrewrite.java.migrate.UpgradeToJava17 +[WARNING] org.openrewrite.java.migrate.Java8toJava11 +[WARNING] org.openrewrite.java.migrate.JavaVersion11 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=11} +[WARNING] org.openrewrite.java.migrate.JavaVersion17 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +[WARNING] Changes have been made to src/test/java/org/springframework/samples/petclinic/vet/VetControllerTests.java by: +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +[WARNING] org.openrewrite.java.spring.boot2.SpringBoot2JUnit4to5Migration +[WARNING] org.openrewrite.java.testing.junit5.JUnit4to5Migration +[WARNING] org.openrewrite.java.testing.junit5.UpdateBeforeAfterAnnotations +[WARNING] org.openrewrite.java.testing.junit5.UpdateTestAnnotation +[WARNING] org.openrewrite.java.spring.boot2.UnnecessarySpringRunWith +[WARNING] org.openrewrite.java.testing.junit5.RunnerToExtension: {runners=[org.springframework.test.context.junit4.SpringRunner, org.springframework.test.context.junit4.SpringJUnit4ClassRunner], extension=org.springframework.test.context.junit.jupiter.SpringExtension} +[WARNING] org.openrewrite.java.spring.boot2.UnnecessarySpringExtension +[WARNING] org.openrewrite.java.spring.boot2.RemoveObsoleteSpringRunners +[WARNING] org.openrewrite.java.testing.junit5.JUnit5BestPractices +[WARNING] org.openrewrite.java.testing.cleanup.TestsShouldNotBePublic +[WARNING] org.openrewrite.java.migrate.UpgradeToJava17 +[WARNING] org.openrewrite.java.migrate.Java8toJava11 +[WARNING] org.openrewrite.java.migrate.JavaVersion11 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=11} +[WARNING] org.openrewrite.java.migrate.JavaVersion17 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +[WARNING] Changes have been made to src/test/java/org/springframework/samples/petclinic/vet/VetTests.java by: +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +[WARNING] org.openrewrite.java.spring.boot2.SpringBoot2JUnit4to5Migration +[WARNING] org.openrewrite.java.testing.junit5.JUnit4to5Migration +[WARNING] org.openrewrite.java.testing.junit5.UpdateTestAnnotation +[WARNING] org.openrewrite.java.spring.boot2.RemoveObsoleteSpringRunners +[WARNING] org.openrewrite.java.testing.junit5.JUnit5BestPractices +[WARNING] org.openrewrite.java.testing.cleanup.TestsShouldNotBePublic +[WARNING] org.openrewrite.java.migrate.UpgradeToJava17 +[WARNING] org.openrewrite.java.migrate.Java8toJava11 +[WARNING] org.openrewrite.java.migrate.JavaVersion11 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=11} +[WARNING] org.openrewrite.java.migrate.JavaVersion17 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +[WARNING] Changes have been made to src/test/java/org/springframework/samples/petclinic/owner/VisitControllerTests.java by: +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +[WARNING] org.openrewrite.java.spring.boot2.SpringBoot2JUnit4to5Migration +[WARNING] org.openrewrite.java.testing.junit5.JUnit4to5Migration +[WARNING] org.openrewrite.java.testing.junit5.UpdateBeforeAfterAnnotations +[WARNING] org.openrewrite.java.testing.junit5.UpdateTestAnnotation +[WARNING] org.openrewrite.java.spring.boot2.UnnecessarySpringRunWith +[WARNING] org.openrewrite.java.testing.junit5.RunnerToExtension: {runners=[org.springframework.test.context.junit4.SpringRunner, org.springframework.test.context.junit4.SpringJUnit4ClassRunner], extension=org.springframework.test.context.junit.jupiter.SpringExtension} +[WARNING] org.openrewrite.java.spring.boot2.UnnecessarySpringExtension +[WARNING] org.openrewrite.java.spring.boot2.RemoveObsoleteSpringRunners +[WARNING] org.openrewrite.java.testing.junit5.JUnit5BestPractices +[WARNING] org.openrewrite.java.testing.cleanup.TestsShouldNotBePublic +[WARNING] org.openrewrite.java.migrate.UpgradeToJava17 +[WARNING] org.openrewrite.java.migrate.Java8toJava11 +[WARNING] org.openrewrite.java.migrate.JavaVersion11 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=11} +[WARNING] org.openrewrite.java.migrate.JavaVersion17 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +[WARNING] Changes have been made to src/test/java/org/springframework/samples/petclinic/owner/PetTypeFormatterTests.java by: +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +[WARNING] org.openrewrite.java.spring.boot2.SpringBoot2JUnit4to5Migration +[WARNING] org.openrewrite.java.testing.junit5.JUnit4to5Migration +[WARNING] org.openrewrite.java.testing.junit5.UseMockitoExtension +[WARNING] org.openrewrite.java.testing.junit5.RunnerToExtension: {runners=[org.mockito.runners.MockitoJUnitRunner, org.mockito.junit.MockitoJUnitRunner, org.mockito.runners.MockitoJUnit44Runner, org.mockito.junit.MockitoJUnit44Runner], extension=org.mockito.junit.jupiter.MockitoExtension} +[WARNING] org.openrewrite.java.testing.junit5.AssertToAssertions +[WARNING] org.openrewrite.java.testing.junit5.UpdateBeforeAfterAnnotations +[WARNING] org.openrewrite.java.testing.junit5.UpdateTestAnnotation +[WARNING] org.openrewrite.java.spring.boot2.RemoveObsoleteSpringRunners +[WARNING] org.openrewrite.java.testing.junit5.JUnit5BestPractices +[WARNING] org.openrewrite.java.testing.cleanup.TestsShouldNotBePublic +[WARNING] org.openrewrite.java.migrate.UpgradeToJava17 +[WARNING] org.openrewrite.java.migrate.Java8toJava11 +[WARNING] org.openrewrite.java.migrate.JavaVersion11 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=11} +[WARNING] org.openrewrite.java.migrate.JavaVersion17 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +[WARNING] Changes have been made to src/test/java/org/springframework/samples/petclinic/owner/OwnerControllerTests.java by: +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +[WARNING] org.openrewrite.java.spring.boot2.SpringBoot2JUnit4to5Migration +[WARNING] org.openrewrite.java.testing.junit5.JUnit4to5Migration +[WARNING] org.openrewrite.java.testing.junit5.UpdateBeforeAfterAnnotations +[WARNING] org.openrewrite.java.testing.junit5.UpdateTestAnnotation +[WARNING] org.openrewrite.java.spring.boot2.UnnecessarySpringRunWith +[WARNING] org.openrewrite.java.testing.junit5.RunnerToExtension: {runners=[org.springframework.test.context.junit4.SpringRunner, org.springframework.test.context.junit4.SpringJUnit4ClassRunner], extension=org.springframework.test.context.junit.jupiter.SpringExtension} +[WARNING] org.openrewrite.java.spring.boot2.UnnecessarySpringExtension +[WARNING] org.openrewrite.java.spring.boot2.RemoveObsoleteSpringRunners +[WARNING] org.openrewrite.java.testing.junit5.JUnit5BestPractices +[WARNING] org.openrewrite.java.testing.cleanup.TestsShouldNotBePublic +[WARNING] org.openrewrite.java.migrate.UpgradeToJava17 +[WARNING] org.openrewrite.java.migrate.Java8toJava11 +[WARNING] org.openrewrite.java.migrate.JavaVersion11 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=11} +[WARNING] org.openrewrite.java.migrate.JavaVersion17 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +[WARNING] Changes have been made to src/test/java/org/springframework/samples/petclinic/owner/PetControllerTests.java by: +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +[WARNING] org.openrewrite.java.spring.boot2.SpringBoot2JUnit4to5Migration +[WARNING] org.openrewrite.java.testing.junit5.JUnit4to5Migration +[WARNING] org.openrewrite.java.testing.junit5.UpdateBeforeAfterAnnotations +[WARNING] org.openrewrite.java.testing.junit5.UpdateTestAnnotation +[WARNING] org.openrewrite.java.spring.boot2.UnnecessarySpringRunWith +[WARNING] org.openrewrite.java.testing.junit5.RunnerToExtension: {runners=[org.springframework.test.context.junit4.SpringRunner, org.springframework.test.context.junit4.SpringJUnit4ClassRunner], extension=org.springframework.test.context.junit.jupiter.SpringExtension} +[WARNING] org.openrewrite.java.spring.boot2.UnnecessarySpringExtension +[WARNING] org.openrewrite.java.spring.boot2.RemoveObsoleteSpringRunners +[WARNING] org.openrewrite.java.testing.junit5.JUnit5BestPractices +[WARNING] org.openrewrite.java.testing.cleanup.TestsShouldNotBePublic +[WARNING] org.openrewrite.java.migrate.UpgradeToJava17 +[WARNING] org.openrewrite.java.migrate.Java8toJava11 +[WARNING] org.openrewrite.java.migrate.JavaVersion11 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=11} +[WARNING] org.openrewrite.java.migrate.JavaVersion17 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +[WARNING] Changes have been made to src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java by: +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +[WARNING] org.openrewrite.java.spring.boot2.SpringBoot2JUnit4to5Migration +[WARNING] org.openrewrite.java.testing.junit5.JUnit4to5Migration +[WARNING] org.openrewrite.java.testing.junit5.UpdateTestAnnotation +[WARNING] org.openrewrite.java.spring.boot2.UnnecessarySpringRunWith +[WARNING] org.openrewrite.java.testing.junit5.RunnerToExtension: {runners=[org.springframework.test.context.junit4.SpringRunner, org.springframework.test.context.junit4.SpringJUnit4ClassRunner], extension=org.springframework.test.context.junit.jupiter.SpringExtension} +[WARNING] org.openrewrite.java.spring.boot2.UnnecessarySpringExtension +[WARNING] org.openrewrite.java.spring.boot2.RemoveObsoleteSpringRunners +[WARNING] org.openrewrite.java.testing.junit5.JUnit5BestPractices +[WARNING] org.openrewrite.java.testing.cleanup.TestsShouldNotBePublic +[WARNING] org.openrewrite.java.migrate.UpgradeToJava17 +[WARNING] org.openrewrite.java.migrate.Java8toJava11 +[WARNING] org.openrewrite.java.migrate.JavaVersion11 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=11} +[WARNING] org.openrewrite.java.migrate.JavaVersion17 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +[WARNING] Changes have been made to src/test/java/org/springframework/samples/petclinic/model/ValidatorTests.java by: +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +[WARNING] org.openrewrite.java.spring.boot2.SpringBoot2JUnit4to5Migration +[WARNING] org.openrewrite.java.testing.junit5.JUnit4to5Migration +[WARNING] org.openrewrite.java.testing.junit5.UpdateTestAnnotation +[WARNING] org.openrewrite.java.spring.boot2.RemoveObsoleteSpringRunners +[WARNING] org.openrewrite.java.testing.junit5.JUnit5BestPractices +[WARNING] org.openrewrite.java.testing.cleanup.TestsShouldNotBePublic +[WARNING] org.openrewrite.java.migrate.UpgradeToJava17 +[WARNING] org.openrewrite.java.migrate.Java8toJava11 +[WARNING] org.openrewrite.java.migrate.JavaVersion11 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=11} +[WARNING] org.openrewrite.java.migrate.JavaVersion17 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +[WARNING] org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta +[WARNING] org.openrewrite.java.migrate.jakarta.JavaxValidationMigrationToJakartaValidation +[WARNING] org.openrewrite.java.ChangePackage: {oldPackageName=javax.validation, newPackageName=jakarta.validation, recursive=true} +[WARNING] Changes have been made to src/test/java/org/springframework/samples/petclinic/system/ProductionConfigurationTests.java by: +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +[WARNING] org.openrewrite.java.spring.boot2.SpringBoot2JUnit4to5Migration +[WARNING] org.openrewrite.java.testing.junit5.JUnit4to5Migration +[WARNING] org.openrewrite.java.testing.junit5.UpdateTestAnnotation +[WARNING] org.openrewrite.java.spring.boot2.UnnecessarySpringRunWith +[WARNING] org.openrewrite.java.testing.junit5.RunnerToExtension: {runners=[org.springframework.test.context.junit4.SpringRunner, org.springframework.test.context.junit4.SpringJUnit4ClassRunner], extension=org.springframework.test.context.junit.jupiter.SpringExtension} +[WARNING] org.openrewrite.java.spring.boot2.UnnecessarySpringExtension +[WARNING] org.openrewrite.java.spring.boot2.RemoveObsoleteSpringRunners +[WARNING] org.openrewrite.java.testing.junit5.JUnit5BestPractices +[WARNING] org.openrewrite.java.testing.cleanup.TestsShouldNotBePublic +[WARNING] org.openrewrite.java.migrate.UpgradeToJava17 +[WARNING] org.openrewrite.java.migrate.Java8toJava11 +[WARNING] org.openrewrite.java.migrate.JavaVersion11 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=11} +[WARNING] org.openrewrite.java.migrate.JavaVersion17 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +[WARNING] Changes have been made to src/test/java/org/springframework/samples/petclinic/system/CrashControllerTests.java by: +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 +[WARNING] org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_6 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_5 +[WARNING] org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_4 +[WARNING] org.openrewrite.java.spring.boot2.SpringBoot2JUnit4to5Migration +[WARNING] org.openrewrite.java.testing.junit5.JUnit4to5Migration +[WARNING] org.openrewrite.java.testing.junit5.IgnoreToDisabled +[WARNING] org.openrewrite.java.ChangeType: {oldFullyQualifiedTypeName=org.junit.Ignore, newFullyQualifiedTypeName=org.junit.jupiter.api.Disabled} +[WARNING] org.openrewrite.java.testing.junit5.UpdateTestAnnotation +[WARNING] org.openrewrite.java.spring.boot2.UnnecessarySpringRunWith +[WARNING] org.openrewrite.java.testing.junit5.RunnerToExtension: {runners=[org.springframework.test.context.junit4.SpringRunner, org.springframework.test.context.junit4.SpringJUnit4ClassRunner], extension=org.springframework.test.context.junit.jupiter.SpringExtension} +[WARNING] org.openrewrite.java.spring.boot2.UnnecessarySpringExtension +[WARNING] org.openrewrite.java.spring.boot2.RemoveObsoleteSpringRunners +[WARNING] org.openrewrite.java.testing.junit5.JUnit5BestPractices +[WARNING] org.openrewrite.java.testing.cleanup.TestsShouldNotBePublic +[WARNING] org.openrewrite.java.migrate.UpgradeToJava17 +[WARNING] org.openrewrite.java.migrate.Java8toJava11 +[WARNING] org.openrewrite.java.migrate.JavaVersion11 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=11} +[WARNING] org.openrewrite.java.migrate.JavaVersion17 +[WARNING] org.openrewrite.java.migrate.UpgradeJavaVersion: {version=17} +[WARNING] Please review and commit the results. +[INFO] ------------------------------------------------------------------------ +[INFO] BUILD SUCCESS +[INFO] ------------------------------------------------------------------------ +[INFO] Total time: 01:14 min +[INFO] Finished at: 2023-09-01T12:50:00+02:00 +[INFO] Final Memory: 194M/3278M +[INFO] ------------------------------------------------------------------------ +``` + +
+ +Notice how each change is listed in the output, along with the `org.openrewrite` recipe that made the change. + +### Explore the results + +You can compare the changes made through OpenRewrite in your favorite IDE, or by running: + +```bash +git diff +``` + +
+ +You should see output similar to the following. + +```diff +diff --git a/pom.xml b/pom.xml +index 0b8f9c2..738ff94 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -10,14 +10,14 @@ + + org.springframework.boot + spring-boot-starter-parent +- 2.0.0.RELEASE ++ 3.1.5 + + petclinic + + + + +- 1.8 ++ 17 + UTF-8 + UTF-8 + +@@ -25,7 +25,7 @@ + 3.3.6 + 1.11.4 + 2.2.4 +- 1.8.0 ++ 1.10.1 + + 2.7 + +@@ -53,6 +53,10 @@ + org.springframework.boot + spring-boot-starter-thymeleaf + ++ ++ org.springframework.boot ++ spring-boot-starter-validation ++ + + org.springframework.boot + spring-boot-starter-test +@@ -66,8 +70,8 @@ + runtime + + +- mysql +- mysql-connector-java ++ com.mysql ++ mysql-connector-j + runtime + + +@@ -79,6 +83,7 @@ + + org.ehcache + ehcache ++ jakarta + + + +@@ -133,22 +138,6 @@ + + + +- +- org.codehaus.mojo +- cobertura-maven-plugin +- ${cobertura.version} +- +- +- +- +- +- +- clean +- check +- +- +- +- + + +@@ -204,17 +193,6 @@ + + + +- +- org.codehaus.mojo +- cobertura-maven-plugin +- ${cobertura.version} +- +- +- html +- +- +- +- + + + +diff --git a/src/main/java/org/springframework/samples/petclinic/model/BaseEntity.java b/src/main/java/org/springframework/samples/petclinic/model/BaseEntity.java +index 86cc210..d45134c 100644 +--- a/src/main/java/org/springframework/samples/petclinic/model/BaseEntity.java ++++ b/src/main/java/org/springframework/samples/petclinic/model/BaseEntity.java +@@ -17,10 +17,10 @@ package org.springframework.samples.petclinic.model; + + import java.io.Serializable; + +-import javax.persistence.GeneratedValue; +-import javax.persistence.GenerationType; +-import javax.persistence.Id; +-import javax.persistence.MappedSuperclass; ++import jakarta.persistence.GeneratedValue; ++import jakarta.persistence.GenerationType; ++import jakarta.persistence.Id; ++import jakarta.persistence.MappedSuperclass; + + /** + * Simple JavaBean domain object with an id property. Used as a base class for objects +diff --git a/src/main/java/org/springframework/samples/petclinic/model/NamedEntity.java b/src/main/java/org/springframework/samples/petclinic/model/NamedEntity.java +index d66c97a..83bb717 100644 +--- a/src/main/java/org/springframework/samples/petclinic/model/NamedEntity.java ++++ b/src/main/java/org/springframework/samples/petclinic/model/NamedEntity.java +@@ -15,8 +15,8 @@ + */ + package org.springframework.samples.petclinic.model; + +-import javax.persistence.Column; +-import javax.persistence.MappedSuperclass; ++import jakarta.persistence.Column; ++import jakarta.persistence.MappedSuperclass; + + + /** +diff --git a/src/main/java/org/springframework/samples/petclinic/model/Person.java b/src/main/java/org/springframework/samples/petclinic/model/Person.java +index 5d23523..7294998 100644 +--- a/src/main/java/org/springframework/samples/petclinic/model/Person.java ++++ b/src/main/java/org/springframework/samples/petclinic/model/Person.java +@@ -15,9 +15,9 @@ + */ + package org.springframework.samples.petclinic.model; + +-import javax.persistence.Column; +-import javax.persistence.MappedSuperclass; +-import javax.validation.constraints.NotEmpty; ++import jakarta.persistence.Column; ++import jakarta.persistence.MappedSuperclass; ++import jakarta.validation.constraints.NotEmpty; + + /** + * Simple JavaBean domain object representing an person. +diff --git a/src/main/java/org/springframework/samples/petclinic/owner/Owner.java b/src/main/java/org/springframework/samples/petclinic/owner/Owner.java +index 89aad2c..063c750 100644 +--- a/src/main/java/org/springframework/samples/petclinic/owner/Owner.java ++++ b/src/main/java/org/springframework/samples/petclinic/owner/Owner.java +@@ -21,13 +21,13 @@ import java.util.HashSet; + import java.util.List; + import java.util.Set; + +-import javax.persistence.CascadeType; +-import javax.persistence.Column; +-import javax.persistence.Entity; +-import javax.persistence.OneToMany; +-import javax.persistence.Table; +-import javax.validation.constraints.Digits; +-import javax.validation.constraints.NotEmpty; ++import jakarta.persistence.CascadeType; ++import jakarta.persistence.Column; ++import jakarta.persistence.Entity; ++import jakarta.persistence.OneToMany; ++import jakarta.persistence.Table; ++import jakarta.validation.constraints.Digits; ++import jakarta.validation.constraints.NotEmpty; + + import org.springframework.beans.support.MutableSortDefinition; + import org.springframework.beans.support.PropertyComparator; +diff --git a/src/main/java/org/springframework/samples/petclinic/owner/OwnerController.java b/src/main/java/org/springframework/samples/petclinic/owner/OwnerController.java +index d914ed7..a25870b 100644 +--- a/src/main/java/org/springframework/samples/petclinic/owner/OwnerController.java ++++ b/src/main/java/org/springframework/samples/petclinic/owner/OwnerController.java +@@ -15,7 +15,6 @@ + */ + package org.springframework.samples.petclinic.owner; + +-import org.springframework.beans.factory.annotation.Autowired; + import org.springframework.stereotype.Controller; + import org.springframework.ui.Model; + import org.springframework.validation.BindingResult; +@@ -26,7 +25,7 @@ import org.springframework.web.bind.annotation.PathVariable; + import org.springframework.web.bind.annotation.PostMapping; + import org.springframework.web.servlet.ModelAndView; + +-import javax.validation.Valid; ++import jakarta.validation.Valid; + import java.util.Collection; + import java.util.Map; + +@@ -43,7 +42,6 @@ class OwnerController { + private final OwnerRepository owners; + + +- @Autowired + public OwnerController(OwnerRepository clinicService) { + this.owners = clinicService; + } +@@ -102,14 +100,14 @@ class OwnerController { + } + + @GetMapping("/owners/{ownerId}/edit") +- public String initUpdateOwnerForm(@PathVariable("ownerId") int ownerId, Model model) { ++ public String initUpdateOwnerForm(@PathVariable int ownerId, Model model) { + Owner owner = this.owners.findById(ownerId); + model.addAttribute(owner); + return VIEWS_OWNER_CREATE_OR_UPDATE_FORM; + } + + @PostMapping("/owners/{ownerId}/edit") +- public String processUpdateOwnerForm(@Valid Owner owner, BindingResult result, @PathVariable("ownerId") int ownerId) { ++ public String processUpdateOwnerForm(@Valid Owner owner, BindingResult result, @PathVariable int ownerId) { + if (result.hasErrors()) { + return VIEWS_OWNER_CREATE_OR_UPDATE_FORM; + } else { +@@ -126,7 +124,7 @@ class OwnerController { + * @return a ModelMap with the model attributes for the view + */ + @GetMapping("/owners/{ownerId}") +- public ModelAndView showOwner(@PathVariable("ownerId") int ownerId) { ++ public ModelAndView showOwner(@PathVariable int ownerId) { + ModelAndView mav = new ModelAndView("owners/ownerDetails"); + mav.addObject(this.owners.findById(ownerId)); + return mav; +diff --git a/src/main/java/org/springframework/samples/petclinic/owner/Pet.java b/src/main/java/org/springframework/samples/petclinic/owner/Pet.java +index 5e226a1..106934b 100755 +--- a/src/main/java/org/springframework/samples/petclinic/owner/Pet.java ++++ b/src/main/java/org/springframework/samples/petclinic/owner/Pet.java +@@ -23,16 +23,16 @@ import java.util.LinkedHashSet; + import java.util.List; + import java.util.Set; + +-import javax.persistence.CascadeType; +-import javax.persistence.Column; +-import javax.persistence.Entity; +-import javax.persistence.FetchType; +-import javax.persistence.JoinColumn; +-import javax.persistence.ManyToOne; +-import javax.persistence.OneToMany; +-import javax.persistence.Table; +-import javax.persistence.Temporal; +-import javax.persistence.TemporalType; ++import jakarta.persistence.CascadeType; ++import jakarta.persistence.Column; ++import jakarta.persistence.Entity; ++import jakarta.persistence.FetchType; ++import jakarta.persistence.JoinColumn; ++import jakarta.persistence.ManyToOne; ++import jakarta.persistence.OneToMany; ++import jakarta.persistence.Table; ++import jakarta.persistence.Temporal; ++import jakarta.persistence.TemporalType; + + import org.springframework.beans.support.MutableSortDefinition; + import org.springframework.beans.support.PropertyComparator; +diff --git a/src/main/java/org/springframework/samples/petclinic/owner/PetController.java b/src/main/java/org/springframework/samples/petclinic/owner/PetController.java +index 9c52e03..8694be1 100644 +--- a/src/main/java/org/springframework/samples/petclinic/owner/PetController.java ++++ b/src/main/java/org/springframework/samples/petclinic/owner/PetController.java +@@ -15,7 +15,6 @@ + */ + package org.springframework.samples.petclinic.owner; + +-import org.springframework.beans.factory.annotation.Autowired; + import org.springframework.stereotype.Controller; + import org.springframework.ui.ModelMap; + import org.springframework.util.StringUtils; +@@ -23,7 +22,7 @@ import org.springframework.validation.BindingResult; + import org.springframework.web.bind.WebDataBinder; + import org.springframework.web.bind.annotation.*; + +-import javax.validation.Valid; ++import jakarta.validation.Valid; + import java.util.Collection; + + /** +@@ -39,7 +38,6 @@ class PetController { + private final PetRepository pets; + private final OwnerRepository owners; + +- @Autowired + public PetController(PetRepository pets, OwnerRepository owners) { + this.pets = pets; + this.owners = owners; +@@ -51,7 +49,7 @@ class PetController { + } + + @ModelAttribute("owner") +- public Owner findOwner(@PathVariable("ownerId") int ownerId) { ++ public Owner findOwner(@PathVariable int ownerId) { + return this.owners.findById(ownerId); + } + +@@ -89,7 +87,7 @@ class PetController { + } + + @GetMapping("/pets/{petId}/edit") +- public String initUpdateForm(@PathVariable("petId") int petId, ModelMap model) { ++ public String initUpdateForm(@PathVariable int petId, ModelMap model) { + Pet pet = this.pets.findById(petId); + model.put("pet", pet); + return VIEWS_PETS_CREATE_OR_UPDATE_FORM; +diff --git a/src/main/java/org/springframework/samples/petclinic/owner/PetType.java b/src/main/java/org/springframework/samples/petclinic/owner/PetType.java +index ac827b3..e6a7271 100644 +--- a/src/main/java/org/springframework/samples/petclinic/owner/PetType.java ++++ b/src/main/java/org/springframework/samples/petclinic/owner/PetType.java +@@ -15,8 +15,8 @@ + */ + package org.springframework.samples.petclinic.owner; + +-import javax.persistence.Entity; +-import javax.persistence.Table; ++import jakarta.persistence.Entity; ++import jakarta.persistence.Table; + + import org.springframework.samples.petclinic.model.NamedEntity; + +diff --git a/src/main/java/org/springframework/samples/petclinic/owner/PetTypeFormatter.java b/src/main/java/org/springframework/samples/petclinic/owner/PetTypeFormatter.java +index 78451ca..8ad364f 100644 +--- a/src/main/java/org/springframework/samples/petclinic/owner/PetTypeFormatter.java ++++ b/src/main/java/org/springframework/samples/petclinic/owner/PetTypeFormatter.java +@@ -20,7 +20,6 @@ import java.text.ParseException; + import java.util.Collection; + import java.util.Locale; + +-import org.springframework.beans.factory.annotation.Autowired; + import org.springframework.format.Formatter; + import org.springframework.stereotype.Component; + +@@ -41,7 +40,6 @@ public class PetTypeFormatter implements Formatter { + private final PetRepository pets; + + +- @Autowired + public PetTypeFormatter(PetRepository pets) { + this.pets = pets; + } +diff --git a/src/main/java/org/springframework/samples/petclinic/owner/VisitController.java b/src/main/java/org/springframework/samples/petclinic/owner/VisitController.java +index d7afed1..c7e6109 100644 +--- a/src/main/java/org/springframework/samples/petclinic/owner/VisitController.java ++++ b/src/main/java/org/springframework/samples/petclinic/owner/VisitController.java +@@ -15,7 +15,6 @@ + */ + package org.springframework.samples.petclinic.owner; + +-import org.springframework.beans.factory.annotation.Autowired; + import org.springframework.samples.petclinic.visit.Visit; + import org.springframework.samples.petclinic.visit.VisitRepository; + import org.springframework.stereotype.Controller; +@@ -23,7 +22,7 @@ import org.springframework.validation.BindingResult; + import org.springframework.web.bind.WebDataBinder; + import org.springframework.web.bind.annotation.*; + +-import javax.validation.Valid; ++import jakarta.validation.Valid; + import java.util.Map; + + /** +@@ -40,7 +39,6 @@ class VisitController { + private final PetRepository pets; + + +- @Autowired + public VisitController(VisitRepository visits, PetRepository pets) { + this.visits = visits; + this.pets = pets; +@@ -62,7 +60,7 @@ class VisitController { + * @return Pet + */ + @ModelAttribute("visit") +- public Visit loadPetWithVisit(@PathVariable("petId") int petId, Map model) { ++ public Visit loadPetWithVisit(@PathVariable int petId, Map model) { + Pet pet = this.pets.findById(petId); + model.put("pet", pet); + Visit visit = new Visit(); +@@ -72,7 +70,7 @@ class VisitController { + + // Spring MVC calls method loadPetWithVisit(...) before initNewVisitForm is called + @GetMapping("/owners/*/pets/{petId}/visits/new") +- public String initNewVisitForm(@PathVariable("petId") int petId, Map model) { ++ public String initNewVisitForm(@PathVariable int petId, Map model) { + return "pets/createOrUpdateVisitForm"; + } + +diff --git a/src/main/java/org/springframework/samples/petclinic/system/CrashController.java b/src/main/java/org/springframework/samples/petclinic/system/CrashController.java +index 2f5e7a3..29f4fd5 100644 +--- a/src/main/java/org/springframework/samples/petclinic/system/CrashController.java ++++ b/src/main/java/org/springframework/samples/petclinic/system/CrashController.java +@@ -30,8 +30,10 @@ class CrashController { + + @GetMapping("/oups") + public String triggerException() { +- throw new RuntimeException("Expected: controller used to showcase what " +- + "happens when an exception is thrown"); ++ throw new RuntimeException(""" ++ Expected: controller used to showcase what \ ++ happens when an exception is thrown\ ++ """); + } + + } +diff --git a/src/main/java/org/springframework/samples/petclinic/vet/Specialty.java b/src/main/java/org/springframework/samples/petclinic/vet/Specialty.java +index 5691c24..7727e21 100644 +--- a/src/main/java/org/springframework/samples/petclinic/vet/Specialty.java ++++ b/src/main/java/org/springframework/samples/petclinic/vet/Specialty.java +@@ -17,8 +17,8 @@ package org.springframework.samples.petclinic.vet; + + import java.io.Serializable; + +-import javax.persistence.Entity; +-import javax.persistence.Table; ++import jakarta.persistence.Entity; ++import jakarta.persistence.Table; + + import org.springframework.samples.petclinic.model.NamedEntity; + +diff --git a/src/main/java/org/springframework/samples/petclinic/vet/Vet.java b/src/main/java/org/springframework/samples/petclinic/vet/Vet.java +index 43aecc4..d2841dd 100644 +--- a/src/main/java/org/springframework/samples/petclinic/vet/Vet.java ++++ b/src/main/java/org/springframework/samples/petclinic/vet/Vet.java +@@ -21,13 +21,13 @@ import java.util.HashSet; + import java.util.List; + import java.util.Set; + +-import javax.persistence.Entity; +-import javax.persistence.FetchType; +-import javax.persistence.JoinColumn; +-import javax.persistence.JoinTable; +-import javax.persistence.ManyToMany; +-import javax.persistence.Table; +-import javax.xml.bind.annotation.XmlElement; ++import jakarta.persistence.Entity; ++import jakarta.persistence.FetchType; ++import jakarta.persistence.JoinColumn; ++import jakarta.persistence.JoinTable; ++import jakarta.persistence.ManyToMany; ++import jakarta.persistence.Table; ++import jakarta.xml.bind.annotation.XmlElement; + + import org.springframework.beans.support.MutableSortDefinition; + import org.springframework.beans.support.PropertyComparator; +diff --git a/src/main/java/org/springframework/samples/petclinic/vet/VetController.java b/src/main/java/org/springframework/samples/petclinic/vet/VetController.java +index 7ce8374..ddaa364 100644 +--- a/src/main/java/org/springframework/samples/petclinic/vet/VetController.java ++++ b/src/main/java/org/springframework/samples/petclinic/vet/VetController.java +@@ -15,7 +15,6 @@ + */ + package org.springframework.samples.petclinic.vet; + +-import org.springframework.beans.factory.annotation.Autowired; + import org.springframework.stereotype.Controller; + import org.springframework.web.bind.annotation.GetMapping; + import org.springframework.web.bind.annotation.ResponseBody; +@@ -33,7 +32,6 @@ class VetController { + + private final VetRepository vets; + +- @Autowired + public VetController(VetRepository clinicService) { + this.vets = clinicService; + } +diff --git a/src/main/java/org/springframework/samples/petclinic/vet/Vets.java b/src/main/java/org/springframework/samples/petclinic/vet/Vets.java +index f5b24c3..c90b652 100644 +--- a/src/main/java/org/springframework/samples/petclinic/vet/Vets.java ++++ b/src/main/java/org/springframework/samples/petclinic/vet/Vets.java +@@ -18,8 +18,8 @@ package org.springframework.samples.petclinic.vet; + import java.util.ArrayList; + import java.util.List; + +-import javax.xml.bind.annotation.XmlElement; +-import javax.xml.bind.annotation.XmlRootElement; ++import jakarta.xml.bind.annotation.XmlElement; ++import jakarta.xml.bind.annotation.XmlRootElement; + + /** + * Simple domain object representing a list of veterinarians. Mostly here to be used for the 'vets' {@link +diff --git a/src/main/java/org/springframework/samples/petclinic/visit/Visit.java b/src/main/java/org/springframework/samples/petclinic/visit/Visit.java +index ce10d7b..2a5e854 100755 +--- a/src/main/java/org/springframework/samples/petclinic/visit/Visit.java ++++ b/src/main/java/org/springframework/samples/petclinic/visit/Visit.java +@@ -17,12 +17,12 @@ package org.springframework.samples.petclinic.visit; + + import java.util.Date; + +-import javax.persistence.Column; +-import javax.persistence.Entity; +-import javax.persistence.Table; +-import javax.persistence.Temporal; +-import javax.persistence.TemporalType; +-import javax.validation.constraints.NotEmpty; ++import jakarta.persistence.Column; ++import jakarta.persistence.Entity; ++import jakarta.persistence.Table; ++import jakarta.persistence.Temporal; ++import jakarta.persistence.TemporalType; ++import jakarta.validation.constraints.NotEmpty; + + import org.springframework.format.annotation.DateTimeFormat; + import org.springframework.samples.petclinic.model.BaseEntity; +diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties +index c8d5a5c..0616806 100644 +--- a/src/main/resources/application.properties ++++ b/src/main/resources/application.properties +@@ -1,7 +1,7 @@ + # database init, supports mysql too + database=hsqldb +-spring.datasource.schema=classpath*:db/${database}/schema.sql +-spring.datasource.data=classpath*:db/${database}/data.sql ++spring.sql.init.schema-locations=classpath*:db/${database}/schema.sql ++spring.sql.init.data-locations=classpath*:db/${database}/data.sql + + # Web + spring.thymeleaf.mode=HTML +diff --git a/src/test/java/org/springframework/samples/petclinic/model/ValidatorTests.java b/src/test/java/org/springframework/samples/petclinic/model/ValidatorTests.java +index 7da0d3d..cfafd31 100644 +--- a/src/test/java/org/springframework/samples/petclinic/model/ValidatorTests.java ++++ b/src/test/java/org/springframework/samples/petclinic/model/ValidatorTests.java +@@ -3,8 +3,8 @@ package org.springframework.samples.petclinic.model; + import java.util.Locale; + import java.util.Set; + +-import javax.validation.ConstraintViolation; +-import javax.validation.Validator; ++import jakarta.validation.ConstraintViolation; ++import jakarta.validation.Validator; + + import org.junit.Test; + +diff --git a/src/test/java/org/springframework/samples/petclinic/owner/OwnerControllerTests.java b/src/test/java/org/springframework/samples/petclinic/owner/OwnerControllerTests.java +index 7fccb3b..7b2edef 100644 +--- a/src/test/java/org/springframework/samples/petclinic/owner/OwnerControllerTests.java ++++ b/src/test/java/org/springframework/samples/petclinic/owner/OwnerControllerTests.java +@@ -12,14 +12,12 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. + import org.assertj.core.util.Lists; + import org.junit.Before; + import org.junit.Test; +-import org.junit.runner.RunWith; + import org.springframework.beans.factory.annotation.Autowired; + import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; + import org.springframework.boot.test.mock.mockito.MockBean; + import org.springframework.samples.petclinic.owner.Owner; + import org.springframework.samples.petclinic.owner.OwnerController; + import org.springframework.samples.petclinic.owner.OwnerRepository; +-import org.springframework.test.context.junit4.SpringRunner; + import org.springframework.test.web.servlet.MockMvc; + + /** +@@ -27,7 +25,6 @@ import org.springframework.test.web.servlet.MockMvc; + * + * @author Colin But + */ +-@RunWith(SpringRunner.class) + @WebMvcTest(OwnerController.class) + public class OwnerControllerTests { + +diff --git a/src/test/java/org/springframework/samples/petclinic/owner/PetControllerTests.java b/src/test/java/org/springframework/samples/petclinic/owner/PetControllerTests.java +index f95d7c8..19ea9c1 100755 +--- a/src/test/java/org/springframework/samples/petclinic/owner/PetControllerTests.java ++++ b/src/test/java/org/springframework/samples/petclinic/owner/PetControllerTests.java +@@ -10,7 +10,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. + import org.assertj.core.util.Lists; + import org.junit.Before; + import org.junit.Test; +-import org.junit.runner.RunWith; + import org.springframework.beans.factory.annotation.Autowired; + import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; + import org.springframework.boot.test.mock.mockito.MockBean; +@@ -23,7 +22,6 @@ import org.springframework.samples.petclinic.owner.PetController; + import org.springframework.samples.petclinic.owner.PetRepository; + import org.springframework.samples.petclinic.owner.PetType; + import org.springframework.samples.petclinic.owner.PetTypeFormatter; +-import org.springframework.test.context.junit4.SpringRunner; + import org.springframework.test.web.servlet.MockMvc; + + /** +@@ -31,7 +29,6 @@ import org.springframework.test.web.servlet.MockMvc; + * + * @author Colin But + */ +-@RunWith(SpringRunner.class) + @WebMvcTest(value = PetController.class, + includeFilters = @ComponentScan.Filter( + value = PetTypeFormatter.class, +diff --git a/src/test/java/org/springframework/samples/petclinic/owner/PetTypeFormatterTests.java b/src/test/java/org/springframework/samples/petclinic/owner/PetTypeFormatterTests.java +index 4e8e36c..387f918 100644 +--- a/src/test/java/org/springframework/samples/petclinic/owner/PetTypeFormatterTests.java ++++ b/src/test/java/org/springframework/samples/petclinic/owner/PetTypeFormatterTests.java +@@ -7,20 +7,20 @@ import java.util.List; + import java.util.Locale; + + import org.junit.Before; ++ ++import static org.junit.jupiter.api.Assertions.assertEquals; + import org.junit.Test; +-import org.junit.runner.RunWith; ++import org.junit.jupiter.api.extension.ExtendWith; + import org.mockito.Mock; + import org.mockito.Mockito; +-import org.mockito.junit.MockitoJUnitRunner; +- +-import static org.junit.Assert.assertEquals; ++import org.mockito.junit.jupiter.MockitoExtension; + + /** + * Test class for {@link PetTypeFormatter} + * + * @author Colin But + */ +-@RunWith(MockitoJUnitRunner.class) ++@ExtendWith(MockitoExtension.class) + public class PetTypeFormatterTests { + + @Mock +diff --git a/src/test/java/org/springframework/samples/petclinic/owner/VisitControllerTests.java b/src/test/java/org/springframework/samples/petclinic/owner/VisitControllerTests.java +index 08d6136..f77c9a7 100644 +--- a/src/test/java/org/springframework/samples/petclinic/owner/VisitControllerTests.java ++++ b/src/test/java/org/springframework/samples/petclinic/owner/VisitControllerTests.java +@@ -9,7 +9,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. + + import org.junit.Before; + import org.junit.Test; +-import org.junit.runner.RunWith; + import org.springframework.beans.factory.annotation.Autowired; + import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; + import org.springframework.boot.test.mock.mockito.MockBean; +@@ -17,7 +16,6 @@ import org.springframework.samples.petclinic.owner.Pet; + import org.springframework.samples.petclinic.owner.PetRepository; + import org.springframework.samples.petclinic.owner.VisitController; + import org.springframework.samples.petclinic.visit.VisitRepository; +-import org.springframework.test.context.junit4.SpringRunner; + import org.springframework.test.web.servlet.MockMvc; + + /** +@@ -25,7 +23,6 @@ import org.springframework.test.web.servlet.MockMvc; + * + * @author Colin But + */ +-@RunWith(SpringRunner.class) + @WebMvcTest(VisitController.class) + public class VisitControllerTests { + +diff --git a/src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java b/src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java +index 7ed5bf8..276ed65 100644 +--- a/src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java ++++ b/src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java +@@ -6,7 +6,6 @@ import java.util.Collection; + import java.util.Date; + + import org.junit.Test; +-import org.junit.runner.RunWith; + import org.springframework.beans.factory.annotation.Autowired; + import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; + import org.springframework.context.annotation.ComponentScan; +@@ -20,7 +19,6 @@ import org.springframework.samples.petclinic.vet.VetRepository; + import org.springframework.samples.petclinic.visit.Visit; + import org.springframework.samples.petclinic.visit.VisitRepository; + import org.springframework.stereotype.Service; +-import org.springframework.test.context.junit4.SpringRunner; + import org.springframework.transaction.annotation.Transactional; + + /** +@@ -44,7 +42,6 @@ import org.springframework.transaction.annotation.Transactional; + * @author Dave Syer + */ + +-@RunWith(SpringRunner.class) + @DataJpaTest(includeFilters = @ComponentScan.Filter(Service.class)) + public class ClinicServiceTests { + +diff --git a/src/test/java/org/springframework/samples/petclinic/system/CrashControllerTests.java b/src/test/java/org/springframework/samples/petclinic/system/CrashControllerTests.java +index 3f108bf..27701e9 100644 +--- a/src/test/java/org/springframework/samples/petclinic/system/CrashControllerTests.java ++++ b/src/test/java/org/springframework/samples/petclinic/system/CrashControllerTests.java +@@ -2,11 +2,9 @@ package org.springframework.samples.petclinic.system; + + import org.junit.Ignore; + import org.junit.Test; +-import org.junit.runner.RunWith; + + import org.springframework.beans.factory.annotation.Autowired; + import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +-import org.springframework.test.context.junit4.SpringRunner; + import org.springframework.test.web.servlet.MockMvc; + + import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +@@ -20,8 +18,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. + * + * @author Colin But + */ +-@RunWith(SpringRunner.class) +-// Waiting https://github.com/spring-projects/spring-boot/issues/5574 + @Ignore + @WebMvcTest(controllers = CrashController.class) + public class CrashControllerTests { +diff --git a/src/test/java/org/springframework/samples/petclinic/system/ProductionConfigurationTests.java b/src/test/java/org/springframework/samples/petclinic/system/ProductionConfigurationTests.java +index 9636e36..026635f 100644 +--- a/src/test/java/org/springframework/samples/petclinic/system/ProductionConfigurationTests.java ++++ b/src/test/java/org/springframework/samples/petclinic/system/ProductionConfigurationTests.java +@@ -1,14 +1,11 @@ + package org.springframework.samples.petclinic.system; + + import org.junit.Test; +-import org.junit.runner.RunWith; + + import org.springframework.beans.factory.annotation.Autowired; + import org.springframework.boot.test.context.SpringBootTest; + import org.springframework.samples.petclinic.vet.VetRepository; +-import org.springframework.test.context.junit4.SpringRunner; + +-@RunWith(SpringRunner.class) + @SpringBootTest + public class ProductionConfigurationTests { + +diff --git a/src/test/java/org/springframework/samples/petclinic/vet/VetControllerTests.java b/src/test/java/org/springframework/samples/petclinic/vet/VetControllerTests.java +index ce6adf8..0464dcb 100644 +--- a/src/test/java/org/springframework/samples/petclinic/vet/VetControllerTests.java ++++ b/src/test/java/org/springframework/samples/petclinic/vet/VetControllerTests.java +@@ -12,7 +12,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. + import org.assertj.core.util.Lists; + import org.junit.Before; + import org.junit.Test; +-import org.junit.runner.RunWith; + import org.springframework.beans.factory.annotation.Autowired; + import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; + import org.springframework.boot.test.mock.mockito.MockBean; +@@ -21,14 +20,12 @@ import org.springframework.samples.petclinic.vet.Specialty; + import org.springframework.samples.petclinic.vet.Vet; + import org.springframework.samples.petclinic.vet.VetController; + import org.springframework.samples.petclinic.vet.VetRepository; +-import org.springframework.test.context.junit4.SpringRunner; + import org.springframework.test.web.servlet.MockMvc; + import org.springframework.test.web.servlet.ResultActions; + + /** + * Test class for the {@link VetController} + */ +-@RunWith(SpringRunner.class) + @WebMvcTest(VetController.class) + public class VetControllerTests { +``` + +
+ +If you look at the results, you should see that: + +* The `@Autowired` annotation was removed +* JUnit 4 has been replaced with JUnit 5 +* `javax` has been replaced with `jakarta` +* The code has been migrated to Java 17 and text blocks are used +* Some best practices are applied (such as adding the `public` test method modifier) + +After all of that, unfortunately, the build for this repository is broken as the commit we started from is using `Wro4j` - which has some [slight dependency conflicts](https://github.com/wro4j/wro4j/issues/1129). We've decided not to cover `Wro4j` with recipes for now, as [Spring PetClinic has dropped Wro4J as well](https://github.com/spring-projects/spring-petclinic/pull/868). + +### (Optional) Fix static code analysis issues + +If you have time, we recommend trying out one of the showcase recipes in OpenRewrite: [common static analysis](https://docs.openrewrite.org/recipes/staticanalysis/commonstaticanalysis). This recipe is composed of 50+ recipes that find and fix common mistakes people make. + +To demonstrate this recipe, we'll use a different Maven repository that has a variety of errors that need to be fixed. + +1. Switch to Java 17: + +```bash + sdk install java 17.0.9-tem + sdk use java 17.0.9-tem +``` + +2. Clone the [Spring WS](https://github.com/spring-projects/spring-ws) repository: + +```bash +git clone https://github.com/spring-projects/spring-ws +``` + +3. Test that you can build it: + +```bash +cd spring-ws +./mvnw verify -DskipTests +``` + +4. Run the common static analysis recipe: + +```bash +./mvnw -U org.openrewrite.maven:rewrite-maven-plugin:run \ + -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-static-analysis:RELEASE \ + -Drewrite.activeRecipes=org.openrewrite.staticanalysis.CommonStaticAnalysis +``` + +5. Check out all of the changes that were made by running: + +```bash +git diff +``` + +6. Verify the project after the changes were made: + +```bash +./mvnw verify +``` + +You can probably imagine that this recipe resolves a lot of technical debt when run at scale throughout an organization. diff --git a/workshops/spring-boot-migration-workshop/migrate-your-own-project.md b/workshops/spring-boot-migration-workshop/migrate-your-own-project.md new file mode 100644 index 00000000..4ff8c48e --- /dev/null +++ b/workshops/spring-boot-migration-workshop/migrate-your-own-project.md @@ -0,0 +1,55 @@ +# Migrate your own project + +### Support timelines + +[OSS support for Spring Boot](https://spring.io/projects/spring-boot#support) 2.7 will end on November 18th, 2023, while support for Spring Boot 3.0 will end on November 24th, 2023. So if you haven't already, now's the time to migrate your project to Spring Boot 3.1! + +
+ +### Leap to Spring Boot 3.1 + +This guide will help you migrate your own project to Spring Boot 3.1. You've already seen various ways of running OpenRewrite recipes by now; pick the one that best suits your project for this migration. For a recap and detailed instructions see each of the indivual exercises: + +* [Maven plugin](maven-plugin-exercise.md) +* [Gradle plugin](gradle-plugin-exercise.md) +* [Moderne CLI](moderne-cli-exercise.md) + +You will want to [run the Migrate to Spring Boot 3.1 recipe](https://docs.openrewrite.org/recipes/java/spring/boot3/upgradespringboot\_3\_1), which runs you through all the steps of migrating to Spring Boot 3.1, no matter what version you're coming from. + +### Migrate in steps + +If you'd rather migrate in steps, you can also run recipes individually. This can be helpful if you'd like to review and build confidence in the changes, or need to troubleshoot a particular aspect. + +As you can see in [the Migrate to Spring Boot 3.1 recipe](https://docs.openrewrite.org/recipes/java/spring/boot3/upgradespringboot\_3\_1), that first takes you [to Spring Boot 3.0](https://docs.openrewrite.org/recipes/java/spring/boot3/upgradespringboot\_3\_0), which first takes you [to Spring Boot 2.7](https://docs.openrewrite.org/recipes/java/spring/boot2/upgradespringboot\_2\_7), which first takes you [to Spring Boot 2.6](https://docs.openrewrite.org/recipes/java/spring/boot2/upgradespringboot\_2\_6), ... You can run any of these intermediate recipes, to pick up the changes up to that point. + +You can also pick out specific migrations, for as much as you aren't up-to-date already, such as: + +* [Migrate Spring Boot 2.x projects to JUnit 5 from JUnit 4](https://docs.openrewrite.org/recipes/java/spring/boot2/springboot2junit4to5migration) +* [Migrate to Java 17](https://docs.openrewrite.org/recipes/java/migrate/upgradetojava17), which of course includes [Migrate to Java 11](https://docs.openrewrite.org/recipes/java/migrate/java8tojava11) +* [Migrate to Spring Security 5.8](https://docs.openrewrite.org/recipes/java/spring/security5/upgradespringsecurity\_5\_8) +* [Spring Boot 2.x best practices](https://docs.openrewrite.org/recipes/java/spring/boot2/springboot2bestpractices) + +### Best practices after you migrate + +After you've migrated to Spring Boot 3.1, you might want to consider some of the following best practices: + +* [Common static analysis issues](https://docs.openrewrite.org/recipes/staticanalysis/commonstaticanalysis) +* [JUnit Jupiter best practices](https://docs.openrewrite.org/recipes/java/testing/junit5/junit5bestpractices) +* [AssertJ best practices](https://docs.openrewrite.org/recipes/java/testing/assertj/assertj) +* [SLF4J best practices](https://docs.openrewrite.org/recipes/java/logging/slf4j/slf4jbestpractices) +* [Java security best practices](https://docs.openrewrite.org/recipes/java/security/javasecuritybestpractices) +* [Find and fix vulnerable dependencies](https://docs.openrewrite.org/recipes/java/dependencies/dependencyvulnerabilitycheck) + +You might even want to run some of these recipes periodically, to keep your projects up-to-date continuously. + +### Helpful resources + +Here's a number of links that might be helpful in case you encounter edge cases not yet covered: + +* [https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Migration-Guide](https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Migration-Guide) +* [https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.1-Release-Notes](https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.1-Release-Notes) +* [https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Release-Notes](https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Release-Notes) +* [https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.7-Release-Notes](https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.7-Release-Notes) +* [https://docs.spring.io/spring-security/reference/migration/index.html](https://docs.spring.io/spring-security/reference/migration/index.html) +* [https://github.com/spring-projects/spring-data-commons/wiki/](https://github.com/spring-projects/spring-data-commons/wiki/) +* [https://github.com/spring-cloud/spring-cloud-release/wiki/Spring-Cloud-2022.0-Release-Notes](https://github.com/spring-cloud/spring-cloud-release/wiki/Spring-Cloud-2022.0-Release-Notes) diff --git a/workshops/spring-boot-migration-workshop/moderne-cli-exercise.md b/workshops/spring-boot-migration-workshop/moderne-cli-exercise.md new file mode 100644 index 00000000..0f229965 --- /dev/null +++ b/workshops/spring-boot-migration-workshop/moderne-cli-exercise.md @@ -0,0 +1,1659 @@ +# Moderne CLI exercise + +In this exercise, you will use the [Moderne CLI](../../user-documentation/getting-started/cli-intro.md), a free tool that allows developer to run OpenRewrite recipes without configuring any build plugin, to migrate a repository from Spring Boot 2 to Spring Boot 3. + +### Prepare your environment + +#### Download and configure the Moderne CLI + +1. Go to the [Moderne platform](https://app.moderne.io) and sign in. If you don't have an account, you can sign up for free. +2. Download the CLI for your operating system: + +{% tabs %} +{% tab title="Mac" %} +[moderne-cli-v1.6.1](https://pkgs.dev.azure.com/moderneinc/moderne\_public/\_packaging/staging/maven/v1/io/moderne/moderne-cli-macos/v1.6.1/moderne-cli-macos-v1.6.1) + +{% hint style="success" %} +You can also use homebrew: + +
brew install moderneinc/moderne/mod
+
+ +and skip step 3. +{% endhint %} +{% endtab %} + +{% tab title="Linux" %} +[moderne-cli-v1.6.1](https://pkgs.dev.azure.com/moderneinc/moderne\_public/\_packaging/staging/maven/v1/io/moderne/moderne-cli-linux/v1.6.1/moderne-cli-linux-v1.6.1) +{% endtab %} + +{% tab title="Windows" %} +[moderne-cli-v1.6.1](https://pkgs.dev.azure.com/moderneinc/moderne\_public/\_packaging/staging/maven/v1/io/moderne/moderne-cli-windows/v1.6.1/moderne-cli-windows-v1.6.1) +{% endtab %} +{% endtabs %} + +3. Once you have it downloaded, save it somewhere that your terminal can access. If you want it available in each of your terminal windows, consider updating your `PATH` to point ot this location or aliasing `mod` to the location of the CLI. You could also save the file to a directory that's already on your `PATH` such as a `/usr/bin` directory. +4. Ensure you can run the CLI by typing `mod`. + +
+ +If everything is set up correctly, you should see output similar to the following: + +``` +➜ moderne-cli git:(main) mod + ▛▀▀▚▖ ▗▄▟▜ + ▌ ▜▄▟▀ ▐ + ▛▀▀█▀▛▀▀▀▀▜ + ▌▟▀ ▛▀▀▀▀▜ + ▀▀▀▀▀▀▀▀▀▀▀ + Moderne CLI v1.6.1 + Running in a local developer environment + + Usage: + + mod [-h] [COMMAND] + + Description: + + Automated code remediation. + + Options: + + -h, --help Display this help message. + + Commands: + + build Generates LST artifacts for one or more repositories. + clean Clean build and run artifacts produced by the CLI. + config Global configuration options that are required by some + CLI commands. + run Runs an OpenRewrite recipe locally. + list Lists the repository roots that can be built and + published. + publish Publishes the LST artifacts for a specific project. + study Produces studies from OpenRewrite recipe data tables + locally. + add Performs the equivalent of git add on multiple + repositories. + apply Performs the equivalent of git apply on multiple + repositories. + checkout Performs the equivalent of git checkout on multiple + repositories. + clone Performs the equivalent of git clone on multiple + repositories. + commit Performs the equivalent of git commit on multiple + repositories. + exec Execute an arbitrary shell command recursively on + selected repository roots. + pull Performs the equivalent of git pull on multiple + repositories. + push Performs the equivalent of git push on multiple + repositories. + reset Performs the equivalent of git reset on multiple + repositories. + rev-parse Performs the equivalent of git rev-parse on multiple + repositories. + stashset, atomicstash Performs the equivalent of git stash on multiple + repositories. + generate-completion Generate bash/zsh completion script for mod. + + MOD SUCCEEDED in (0.02s) +``` + +
+ +{% hint style="success" %} +Run `mod generate-completion --help` and follow the instructions to enable tab completion for the CLI. +{% endhint %} + +5. Before you can run any commands, you'll need to create a Moderne access token. Go to [https://app.moderne.io/settings/access-token](https://app.moderne.io/settings/access-token), enter a name for your token, and press `generate`. +6. Once created, copy the token and use it in the following command so that the CLI can communicate with Moderne: + +```bash +mod config moderne edit https://app.moderne.io --token mat-YOUR_TOKEN_HERE +``` + +7. With the Moderne connection established, install the Spring Boot recipe on your machine: + +```bash +mod config recipes moderne install UpgradeSpringBoot_3_1 +``` + +{% hint style="success" %} +Alternatively, you can sync all recipes available on Moderne with `mod config recipes moderne sync`, although this can take a while to complete. +{% endhint %} + +### Configure the Spring PetClinic repository + +With the CLI downloaded and configured, you're now ready to set up the repository. + +1. Clone the [Spring PetClinic repository](https://github.com/spring-projects/spring-petclinic): + +```bash +git clone https://github.com/spring-projects/spring-petclinic +``` + +2. Check out the last Spring Boot 2.0 commit: + +```bash +cd spring-petclinic +git checkout b527de52f5fd19f9fe550372c017d145a3b2a809 +``` + +3. If you tried building this repository right now, you would more than likely run into errors. This is because this version of the Spring PetClinic repo requires Java 8. To ensure that everything builds correctly, you may need to download Java 8 and update your `JAVA_HOME` environment variable. If you are on a Unix-based system, we recommend using [SDKMan](https://sdkman.io/): + +```bash +sdk install java 8.0.392-zulu +sdk use java 8.0.392-zulu +``` + +{% hint style="info" %} +If you want to use `sdk` and the `java 8.0.392-zulu` distribution is not available for you, select any distribution that represents a Java 8 version. +{% endhint %} + +{% hint style="info" %} +If you aren't on a Unix-based system or you don't want to install SDKMan, you'll need to install Java 8 and run something like: + +```bash +export JAVA_HOME=REPLACE_WITH_LOCATION_OF_JAVA_8 +``` +{% endhint %} + +4. With Java 8 configured, make sure that the Spring PetClinic repository builds on your machine: + +```bash +./mvnw verify -DskipTests +``` + +5. If everything has been set up correctly, you should see a `BUILD SUCCESS` message after the project is built and the tests passed. + +### Migrate to Spring Boot 3 using the Moderne CLI + +Now that the repository is configured, it's time to migrate it to Spring Boot 3 using the Moderne CLI. + +1. Run the build command to generate the LST for the PetClinic repo: + +```bash +mod build . +``` + +
+ +You should see output similar to the following. + +``` + ▛▀▀▚▖ ▗▄▟▜ + ▌ ▜▄▟▀ ▐ + ▛▀▀█▀▛▀▀▀▀▜ + ▌▟▀ ▛▀▀▀▀▜ + ▀▀▀▀▀▀▀▀▀▀▀ +Moderne CLI v1.6.1 + +> Selecting repositories + +> spring-projects/spring-petclinic@main +Selected 1 repositories +(0.54s) +> Building LST(s) + +> spring-projects/spring-petclinic@main + Build output will be written to file:///Users/mikesol/Desktop/code/spring-petclinic/.moderne/build/20230921094850-s8Qfa/build.log + 📶 Step 1 - build with Maven + Selected a Java 8 JDK + 📶 Step 2 - build resources using the native CLI + 📈 Reported build metrics to Moderne + ✅ Built LST file:///Users/mikesol/Desktop/code/spring-petclinic/.moderne/build/20230921094850-s8Qfa/spring-petclinic-20230921094920-ast.jar + 🧹 Cleaned 0 older builds. +Built 1 repositories (30s) + +* What to do next + > Run mod run . --recipe + +MOD SUCCEEDED in (30s) +``` + +
+ +2. Kick off the migration recipe by running the following command from the `spring-petclinic` repository: + +```bash +mod run . --recipe UpgradeSpringBoot_3_1 +``` + +
+ +You should see output similar to the following. + +``` + ▛▀▀▚▖ ▗▄▟▜ + ▌ ▜▄▟▀ ▐ + ▛▀▀█▀▛▀▀▀▀▜ + ▌▟▀ ▛▀▀▀▀▜ + ▀▀▀▀▀▀▀▀▀▀▀ + Moderne CLI v1.6.1 + + > Selecting repositories + + > spring-projects/spring-petclinic@main + Selected 1 repositories (0.48s) + + > Running recipe org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1 + + > spring-projects/spring-petclinic@main + ✅ Fix results at file:///Users/mikesol/Desktop/code/spring-petclinic/.moderne/run/20230925102039-NVf33/fix.patch + ✅ Search results at file:///Users/mikesol/Desktop/code/spring-petclinic/.moderne/run/20230925102039-NVf33/search.patch + Found results on 1 repositories (9m 37s) + + * What to do next + > Click on one of the patch links above to view the changes on a particular repository + > Run mod study . --last-recipe-run --data-table to examine data tables produced by this recipe + > Run npm install -g diff2html-cli to produce patch files on subsequent runs that are easier to view + > Run mod apply . --last-recipe-run to apply the changes + > Run mod apply . --recipe-run 20230925102039-NVf33 to apply the changes + + MOD SUCCEEDED in (9m 38s) +``` + +
+ +3. The previous command will generate a patch file (`fix.patch`) that contains the changes the recipe would make to your repository. You can examine the file with your favorite editor, or you can apply the changes to the code and use `git diff` to check out the changes. It's important to always double-check that the changes made match your expectations: + +```bash +mod apply . --last-recipe-run +git diff +``` + +
+ +You should see output similar to the following. + +```diff + diff --git a/pom.xml b/pom.xml + index 0b8f9c2..56693d7 100644 + --- a/pom.xml + +++ b/pom.xml + @@ -10,14 +10,14 @@ + + org.springframework.boot + spring-boot-starter-parent + - 2.0.0.RELEASE + + 3.1.4 + + petclinic + + + + + - 1.8 + + 17 + UTF-8 + UTF-8 + + @@ -25,7 +25,7 @@ + 3.3.6 + 1.11.4 + 2.2.4 + - 1.8.0 + + 1.10.1 + + 2.7 + + @@ -33,6 +33,10 @@ + + + + + + + jakarta.xml.bind + + jakarta.xml.bind-api + + + + org.springframework.boot + spring-boot-starter-actuator + @@ -53,6 +57,10 @@ + org.springframework.boot + spring-boot-starter-thymeleaf + + + + + org.springframework.boot + + spring-boot-starter-validation + + + + org.springframework.boot + spring-boot-starter-test + @@ -66,8 +74,13 @@ + runtime + + + - mysql + - mysql-connector-java + + com.mysql + + mysql-connector-j + + runtime + + + + + + org.glassfish.jaxb + + jaxb-runtime + runtime + + + @@ -79,6 +92,7 @@ + + org.ehcache + ehcache + + jakarta + + + + @@ -133,22 +147,6 @@ + + + + - + - org.codehaus.mojo + - cobertura-maven-plugin + - ${cobertura.version} + - + - + - + - + - + - + - clean + - check + - + - + - + - + + + @@ -204,17 +202,6 @@ + + + + - + - org.codehaus.mojo + - cobertura-maven-plugin + - ${cobertura.version} + - + - + - html + - + - + - + - + + + + diff --git a/src/main/java/org/springframework/samples/petclinic/model/BaseEntity.java b/src/main/java/org/springframework/samples/petclinic/model/BaseEntity.java + index 86cc210..d45134c 100644 + --- a/src/main/java/org/springframework/samples/petclinic/model/BaseEntity.java + +++ b/src/main/java/org/springframework/samples/petclinic/model/BaseEntity.java + @@ -17,10 +17,10 @@ package org.springframework.samples.petclinic.model; + + import java.io.Serializable; + + -import javax.persistence.GeneratedValue; + -import javax.persistence.GenerationType; + -import javax.persistence.Id; + -import javax.persistence.MappedSuperclass; + +import jakarta.persistence.GeneratedValue; + +import jakarta.persistence.GenerationType; + +import jakarta.persistence.Id; + +import jakarta.persistence.MappedSuperclass; + + /** + * Simple JavaBean domain object with an id property. Used as a base class for objects + diff --git a/src/main/java/org/springframework/samples/petclinic/model/NamedEntity.java b/src/main/java/org/springframework/samples/petclinic/model/NamedEntity.java + index d66c97a..83bb717 100644 + --- a/src/main/java/org/springframework/samples/petclinic/model/NamedEntity.java + +++ b/src/main/java/org/springframework/samples/petclinic/model/NamedEntity.java + @@ -15,8 +15,8 @@ + */ + package org.springframework.samples.petclinic.model; + + -import javax.persistence.Column; + -import javax.persistence.MappedSuperclass; + +import jakarta.persistence.Column; + +import jakarta.persistence.MappedSuperclass; + + + /** + diff --git a/src/main/java/org/springframework/samples/petclinic/model/Person.java b/src/main/java/org/springframework/samples/petclinic/model/Person.java + index 5d23523..7294998 100644 + --- a/src/main/java/org/springframework/samples/petclinic/model/Person.java + +++ b/src/main/java/org/springframework/samples/petclinic/model/Person.java + @@ -15,9 +15,9 @@ + */ + package org.springframework.samples.petclinic.model; + + -import javax.persistence.Column; + -import javax.persistence.MappedSuperclass; + -import javax.validation.constraints.NotEmpty; + +import jakarta.persistence.Column; + +import jakarta.persistence.MappedSuperclass; + +import jakarta.validation.constraints.NotEmpty; + + /** + * Simple JavaBean domain object representing an person. + diff --git a/src/main/java/org/springframework/samples/petclinic/owner/Owner.java b/src/main/java/org/springframework/samples/petclinic/owner/Owner.java + index 89aad2c..063c750 100644 + --- a/src/main/java/org/springframework/samples/petclinic/owner/Owner.java + +++ b/src/main/java/org/springframework/samples/petclinic/owner/Owner.java + @@ -21,13 +21,13 @@ import java.util.HashSet; + import java.util.List; + import java.util.Set; + + -import javax.persistence.CascadeType; + -import javax.persistence.Column; + -import javax.persistence.Entity; + -import javax.persistence.OneToMany; + -import javax.persistence.Table; + -import javax.validation.constraints.Digits; + -import javax.validation.constraints.NotEmpty; + +import jakarta.persistence.CascadeType; + +import jakarta.persistence.Column; + +import jakarta.persistence.Entity; + +import jakarta.persistence.OneToMany; + +import jakarta.persistence.Table; + +import jakarta.validation.constraints.Digits; + +import jakarta.validation.constraints.NotEmpty; + + import org.springframework.beans.support.MutableSortDefinition; + import org.springframework.beans.support.PropertyComparator; + diff --git a/src/main/java/org/springframework/samples/petclinic/owner/OwnerController.java b/src/main/java/org/springframework/samples/petclinic/owner/OwnerController.java + index d914ed7..a25870b 100644 + --- a/src/main/java/org/springframework/samples/petclinic/owner/OwnerController.java + +++ b/src/main/java/org/springframework/samples/petclinic/owner/OwnerController.java + @@ -15,7 +15,6 @@ + */ + package org.springframework.samples.petclinic.owner; + + -import org.springframework.beans.factory.annotation.Autowired; + import org.springframework.stereotype.Controller; + import org.springframework.ui.Model; + import org.springframework.validation.BindingResult; + @@ -26,7 +25,7 @@ import org.springframework.web.bind.annotation.PathVariable; + import org.springframework.web.bind.annotation.PostMapping; + import org.springframework.web.servlet.ModelAndView; + + -import javax.validation.Valid; + +import jakarta.validation.Valid; + import java.util.Collection; + import java.util.Map; + + @@ -43,7 +42,6 @@ class OwnerController { + private final OwnerRepository owners; + + + - @Autowired + public OwnerController(OwnerRepository clinicService) { + this.owners = clinicService; + } + @@ -102,14 +100,14 @@ class OwnerController { + } + + @GetMapping("/owners/{ownerId}/edit") + - public String initUpdateOwnerForm(@PathVariable("ownerId") int ownerId, Model model) { + + public String initUpdateOwnerForm(@PathVariable int ownerId, Model model) { + Owner owner = this.owners.findById(ownerId); + model.addAttribute(owner); + return VIEWS_OWNER_CREATE_OR_UPDATE_FORM; + } + + @PostMapping("/owners/{ownerId}/edit") + - public String processUpdateOwnerForm(@Valid Owner owner, BindingResult result, @PathVariable("ownerId") int ownerId) { + + public String processUpdateOwnerForm(@Valid Owner owner, BindingResult result, @PathVariable int ownerId) { + if (result.hasErrors()) { + return VIEWS_OWNER_CREATE_OR_UPDATE_FORM; + } else { + @@ -126,7 +124,7 @@ class OwnerController { + * @return a ModelMap with the model attributes for the view + */ + @GetMapping("/owners/{ownerId}") + - public ModelAndView showOwner(@PathVariable("ownerId") int ownerId) { + + public ModelAndView showOwner(@PathVariable int ownerId) { + ModelAndView mav = new ModelAndView("owners/ownerDetails"); + mav.addObject(this.owners.findById(ownerId)); + return mav; + diff --git a/src/main/java/org/springframework/samples/petclinic/owner/Pet.java b/src/main/java/org/springframework/samples/petclinic/owner/Pet.java + index 5e226a1..106934b 100755 + --- a/src/main/java/org/springframework/samples/petclinic/owner/Pet.java + +++ b/src/main/java/org/springframework/samples/petclinic/owner/Pet.java + @@ -23,16 +23,16 @@ import java.util.LinkedHashSet; + import java.util.List; + import java.util.Set; + + -import javax.persistence.CascadeType; + -import javax.persistence.Column; + -import javax.persistence.Entity; + -import javax.persistence.FetchType; + -import javax.persistence.JoinColumn; + -import javax.persistence.ManyToOne; + -import javax.persistence.OneToMany; + -import javax.persistence.Table; + -import javax.persistence.Temporal; + -import javax.persistence.TemporalType; + +import jakarta.persistence.CascadeType; + +import jakarta.persistence.Column; + +import jakarta.persistence.Entity; + +import jakarta.persistence.FetchType; + +import jakarta.persistence.JoinColumn; + +import jakarta.persistence.ManyToOne; + +import jakarta.persistence.OneToMany; + +import jakarta.persistence.Table; + +import jakarta.persistence.Temporal; + +import jakarta.persistence.TemporalType; + + import org.springframework.beans.support.MutableSortDefinition; + import org.springframework.beans.support.PropertyComparator; + diff --git a/src/main/java/org/springframework/samples/petclinic/owner/PetController.java b/src/main/java/org/springframework/samples/petclinic/owner/PetController.java + index 9c52e03..8694be1 100644 + --- a/src/main/java/org/springframework/samples/petclinic/owner/PetController.java + +++ b/src/main/java/org/springframework/samples/petclinic/owner/PetController.java + @@ -15,7 +15,6 @@ + */ + package org.springframework.samples.petclinic.owner; + + -import org.springframework.beans.factory.annotation.Autowired; + import org.springframework.stereotype.Controller; + import org.springframework.ui.ModelMap; + import org.springframework.util.StringUtils; + @@ -23,7 +22,7 @@ import org.springframework.validation.BindingResult; + import org.springframework.web.bind.WebDataBinder; + import org.springframework.web.bind.annotation.*; + + -import javax.validation.Valid; + +import jakarta.validation.Valid; + import java.util.Collection; + + /** + @@ -39,7 +38,6 @@ class PetController { + private final PetRepository pets; + private final OwnerRepository owners; + + - @Autowired + public PetController(PetRepository pets, OwnerRepository owners) { + this.pets = pets; + this.owners = owners; + @@ -51,7 +49,7 @@ class PetController { + } + + @ModelAttribute("owner") + - public Owner findOwner(@PathVariable("ownerId") int ownerId) { + + public Owner findOwner(@PathVariable int ownerId) { + return this.owners.findById(ownerId); + } + + @@ -89,7 +87,7 @@ class PetController { + } + + @GetMapping("/pets/{petId}/edit") + - public String initUpdateForm(@PathVariable("petId") int petId, ModelMap model) { + + public String initUpdateForm(@PathVariable int petId, ModelMap model) { + Pet pet = this.pets.findById(petId); + model.put("pet", pet); + return VIEWS_PETS_CREATE_OR_UPDATE_FORM; + diff --git a/src/main/java/org/springframework/samples/petclinic/owner/PetType.java b/src/main/java/org/springframework/samples/petclinic/owner/PetType.java + index ac827b3..e6a7271 100644 + --- a/src/main/java/org/springframework/samples/petclinic/owner/PetType.java + +++ b/src/main/java/org/springframework/samples/petclinic/owner/PetType.java + @@ -15,8 +15,8 @@ + */ + package org.springframework.samples.petclinic.owner; + + -import javax.persistence.Entity; + -import javax.persistence.Table; + +import jakarta.persistence.Entity; + +import jakarta.persistence.Table; + + import org.springframework.samples.petclinic.model.NamedEntity; + + diff --git a/src/main/java/org/springframework/samples/petclinic/owner/PetTypeFormatter.java b/src/main/java/org/springframework/samples/petclinic/owner/PetTypeFormatter.java + index 78451ca..8ad364f 100644 + --- a/src/main/java/org/springframework/samples/petclinic/owner/PetTypeFormatter.java + +++ b/src/main/java/org/springframework/samples/petclinic/owner/PetTypeFormatter.java + @@ -20,7 +20,6 @@ import java.text.ParseException; + import java.util.Collection; + import java.util.Locale; + + -import org.springframework.beans.factory.annotation.Autowired; + import org.springframework.format.Formatter; + import org.springframework.stereotype.Component; + + @@ -41,7 +40,6 @@ public class PetTypeFormatter implements Formatter { + private final PetRepository pets; + + + - @Autowired + public PetTypeFormatter(PetRepository pets) { + this.pets = pets; + } + diff --git a/src/main/java/org/springframework/samples/petclinic/owner/VisitController.java b/src/main/java/org/springframework/samples/petclinic/owner/VisitController.java + index d7afed1..c7e6109 100644 + --- a/src/main/java/org/springframework/samples/petclinic/owner/VisitController.java + +++ b/src/main/java/org/springframework/samples/petclinic/owner/VisitController.java + @@ -15,7 +15,6 @@ + */ + package org.springframework.samples.petclinic.owner; + + -import org.springframework.beans.factory.annotation.Autowired; + import org.springframework.samples.petclinic.visit.Visit; + import org.springframework.samples.petclinic.visit.VisitRepository; + import org.springframework.stereotype.Controller; + @@ -23,7 +22,7 @@ import org.springframework.validation.BindingResult; + import org.springframework.web.bind.WebDataBinder; + import org.springframework.web.bind.annotation.*; + + -import javax.validation.Valid; + +import jakarta.validation.Valid; + import java.util.Map; + + /** + @@ -40,7 +39,6 @@ class VisitController { + private final PetRepository pets; + + + - @Autowired + public VisitController(VisitRepository visits, PetRepository pets) { + this.visits = visits; + this.pets = pets; + @@ -62,7 +60,7 @@ class VisitController { + * @return Pet + */ + @ModelAttribute("visit") + - public Visit loadPetWithVisit(@PathVariable("petId") int petId, Map model) { + + public Visit loadPetWithVisit(@PathVariable int petId, Map model) { + Pet pet = this.pets.findById(petId); + model.put("pet", pet); + Visit visit = new Visit(); + @@ -72,7 +70,7 @@ class VisitController { + + // Spring MVC calls method loadPetWithVisit(...) before initNewVisitForm is called + @GetMapping("/owners/*/pets/{petId}/visits/new") + - public String initNewVisitForm(@PathVariable("petId") int petId, Map model) { + + public String initNewVisitForm(@PathVariable int petId, Map model) { + return "pets/createOrUpdateVisitForm"; + } + + diff --git a/src/main/java/org/springframework/samples/petclinic/system/CrashController.java b/src/main/java/org/springframework/samples/petclinic/system/CrashController.java + index 2f5e7a3..29f4fd5 100644 + --- a/src/main/java/org/springframework/samples/petclinic/system/CrashController.java + +++ b/src/main/java/org/springframework/samples/petclinic/system/CrashController.java + @@ -30,8 +30,10 @@ class CrashController { + + @GetMapping("/oups") + public String triggerException() { + - throw new RuntimeException("Expected: controller used to showcase what " + - + "happens when an exception is thrown"); + + throw new RuntimeException(""" + + Expected: controller used to showcase what \ + + happens when an exception is thrown\ + + """); + } + + } + diff --git a/src/main/java/org/springframework/samples/petclinic/vet/Specialty.java b/src/main/java/org/springframework/samples/petclinic/vet/Specialty.java + index 5691c24..7727e21 100644 + --- a/src/main/java/org/springframework/samples/petclinic/vet/Specialty.java + +++ b/src/main/java/org/springframework/samples/petclinic/vet/Specialty.java + @@ -17,8 +17,8 @@ package org.springframework.samples.petclinic.vet; + + import java.io.Serializable; + + -import javax.persistence.Entity; + -import javax.persistence.Table; + +import jakarta.persistence.Entity; + +import jakarta.persistence.Table; + + import org.springframework.samples.petclinic.model.NamedEntity; + + diff --git a/src/main/java/org/springframework/samples/petclinic/vet/Vet.java b/src/main/java/org/springframework/samples/petclinic/vet/Vet.java + index 43aecc4..d2841dd 100644 + --- a/src/main/java/org/springframework/samples/petclinic/vet/Vet.java + +++ b/src/main/java/org/springframework/samples/petclinic/vet/Vet.java + @@ -21,13 +21,13 @@ import java.util.HashSet; + import java.util.List; + import java.util.Set; + + -import javax.persistence.Entity; + -import javax.persistence.FetchType; + -import javax.persistence.JoinColumn; + -import javax.persistence.JoinTable; + -import javax.persistence.ManyToMany; + -import javax.persistence.Table; + -import javax.xml.bind.annotation.XmlElement; + +import jakarta.persistence.Entity; + +import jakarta.persistence.FetchType; + +import jakarta.persistence.JoinColumn; + +import jakarta.persistence.JoinTable; + +import jakarta.persistence.ManyToMany; + +import jakarta.persistence.Table; + +import jakarta.xml.bind.annotation.XmlElement; + + import org.springframework.beans.support.MutableSortDefinition; + import org.springframework.beans.support.PropertyComparator; + diff --git a/src/main/java/org/springframework/samples/petclinic/vet/VetController.java b/src/main/java/org/springframework/samples/petclinic/vet/VetController.java + index 7ce8374..ddaa364 100644 + --- a/src/main/java/org/springframework/samples/petclinic/vet/VetController.java + +++ b/src/main/java/org/springframework/samples/petclinic/vet/VetController.java + @@ -15,7 +15,6 @@ + */ + package org.springframework.samples.petclinic.vet; + + -import org.springframework.beans.factory.annotation.Autowired; + import org.springframework.stereotype.Controller; + import org.springframework.web.bind.annotation.GetMapping; + import org.springframework.web.bind.annotation.ResponseBody; + @@ -33,7 +32,6 @@ class VetController { + + private final VetRepository vets; + + - @Autowired + public VetController(VetRepository clinicService) { + this.vets = clinicService; + } + diff --git a/src/main/java/org/springframework/samples/petclinic/vet/Vets.java b/src/main/java/org/springframework/samples/petclinic/vet/Vets.java + index f5b24c3..c90b652 100644 + --- a/src/main/java/org/springframework/samples/petclinic/vet/Vets.java + +++ b/src/main/java/org/springframework/samples/petclinic/vet/Vets.java + @@ -18,8 +18,8 @@ package org.springframework.samples.petclinic.vet; + import java.util.ArrayList; + import java.util.List; + + -import javax.xml.bind.annotation.XmlElement; + -import javax.xml.bind.annotation.XmlRootElement; + +import jakarta.xml.bind.annotation.XmlElement; + +import jakarta.xml.bind.annotation.XmlRootElement; + + /** + * Simple domain object representing a list of veterinarians. Mostly here to be used for the 'vets' {@link + diff --git a/src/main/java/org/springframework/samples/petclinic/visit/Visit.java b/src/main/java/org/springframework/samples/petclinic/visit/Visit.java + index ce10d7b..2a5e854 100755 + --- a/src/main/java/org/springframework/samples/petclinic/visit/Visit.java + +++ b/src/main/java/org/springframework/samples/petclinic/visit/Visit.java + @@ -17,12 +17,12 @@ package org.springframework.samples.petclinic.visit; + + import java.util.Date; + + -import javax.persistence.Column; + -import javax.persistence.Entity; + -import javax.persistence.Table; + -import javax.persistence.Temporal; + -import javax.persistence.TemporalType; + -import javax.validation.constraints.NotEmpty; + +import jakarta.persistence.Column; + +import jakarta.persistence.Entity; + +import jakarta.persistence.Table; + +import jakarta.persistence.Temporal; + +import jakarta.persistence.TemporalType; + +import jakarta.validation.constraints.NotEmpty; + + import org.springframework.format.annotation.DateTimeFormat; + import org.springframework.samples.petclinic.model.BaseEntity; + diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties + index c8d5a5c..0616806 100644 + --- a/src/main/resources/application.properties + +++ b/src/main/resources/application.properties + @@ -1,7 +1,7 @@ + # database init, supports mysql too + database=hsqldb + -spring.datasource.schema=classpath*:db/${database}/schema.sql + -spring.datasource.data=classpath*:db/${database}/data.sql + +spring.sql.init.schema-locations=classpath*:db/${database}/schema.sql + +spring.sql.init.data-locations=classpath*:db/${database}/data.sql + + # Web + spring.thymeleaf.mode=HTML + diff --git a/src/test/java/org/springframework/samples/petclinic/model/ValidatorTests.java b/src/test/java/org/springframework/samples/petclinic/model/ValidatorTests.java + index 7da0d3d..3f4bfe9 100644 + --- a/src/test/java/org/springframework/samples/petclinic/model/ValidatorTests.java + +++ b/src/test/java/org/springframework/samples/petclinic/model/ValidatorTests.java + @@ -3,11 +3,10 @@ package org.springframework.samples.petclinic.model; + import java.util.Locale; + import java.util.Set; + + -import javax.validation.ConstraintViolation; + -import javax.validation.Validator; + - + -import org.junit.Test; + +import jakarta.validation.ConstraintViolation; + +import jakarta.validation.Validator; + + +import org.junit.jupiter.api.Test; + import org.springframework.context.i18n.LocaleContextHolder; + import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; + + @@ -17,7 +16,7 @@ import static org.assertj.core.api.Assertions.assertThat; + * @author Michael Isvy Simple test to make sure that Bean Validation is working (useful + * when upgrading to a new version of Hibernate Validator/ Bean Validation) + */ + -public class ValidatorTests { + +class ValidatorTests { + + private Validator createValidator() { + LocalValidatorFactoryBean localValidatorFactoryBean = new LocalValidatorFactoryBean(); + @@ -26,7 +25,7 @@ public class ValidatorTests { + } + + @Test + - public void shouldNotValidateWhenFirstNameEmpty() { + + void shouldNotValidateWhenFirstNameEmpty() { + + LocaleContextHolder.setLocale(Locale.ENGLISH); + Person person = new Person(); + diff --git a/src/test/java/org/springframework/samples/petclinic/owner/OwnerControllerTests.java b/src/test/java/org/springframework/samples/petclinic/owner/OwnerControllerTests.java + index 7fccb3b..1f1db70 100644 + --- a/src/test/java/org/springframework/samples/petclinic/owner/OwnerControllerTests.java + +++ b/src/test/java/org/springframework/samples/petclinic/owner/OwnerControllerTests.java + @@ -10,16 +10,14 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. + import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; + + import org.assertj.core.util.Lists; + -import org.junit.Before; + -import org.junit.Test; + -import org.junit.runner.RunWith; + +import org.junit.jupiter.api.BeforeEach; + +import org.junit.jupiter.api.Test; + import org.springframework.beans.factory.annotation.Autowired; + import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; + import org.springframework.boot.test.mock.mockito.MockBean; + import org.springframework.samples.petclinic.owner.Owner; + import org.springframework.samples.petclinic.owner.OwnerController; + import org.springframework.samples.petclinic.owner.OwnerRepository; + -import org.springframework.test.context.junit4.SpringRunner; + import org.springframework.test.web.servlet.MockMvc; + + /** + @@ -27,9 +25,8 @@ import org.springframework.test.web.servlet.MockMvc; + * + * @author Colin But + */ + -@RunWith(SpringRunner.class) + @WebMvcTest(OwnerController.class) + -public class OwnerControllerTests { + +class OwnerControllerTests { + + private static final int TEST_OWNER_ID = 1; + + @@ -41,8 +38,8 @@ public class OwnerControllerTests { + + private Owner george; + + - @Before + - public void setup() { + + @BeforeEach + + void setup() { + george = new Owner(); + george.setId(TEST_OWNER_ID); + george.setFirstName("George"); + @@ -54,7 +51,7 @@ public class OwnerControllerTests { + } + + @Test + - public void testInitCreationForm() throws Exception { + + void testInitCreationForm() throws Exception { + mockMvc.perform(get("/owners/new")) + .andExpect(status().isOk()) + .andExpect(model().attributeExists("owner")) + @@ -62,7 +59,7 @@ public class OwnerControllerTests { + } + + @Test + - public void testProcessCreationFormSuccess() throws Exception { + + void testProcessCreationFormSuccess() throws Exception { + mockMvc.perform(post("/owners/new") + .param("firstName", "Joe") + .param("lastName", "Bloggs") + @@ -74,7 +71,7 @@ public class OwnerControllerTests { + } + + @Test + - public void testProcessCreationFormHasErrors() throws Exception { + + void testProcessCreationFormHasErrors() throws Exception { + mockMvc.perform(post("/owners/new") + .param("firstName", "Joe") + .param("lastName", "Bloggs") + @@ -88,7 +85,7 @@ public class OwnerControllerTests { + } + + @Test + - public void testInitFindForm() throws Exception { + + void testInitFindForm() throws Exception { + mockMvc.perform(get("/owners/find")) + .andExpect(status().isOk()) + .andExpect(model().attributeExists("owner")) + @@ -96,7 +93,7 @@ public class OwnerControllerTests { + } + + @Test + - public void testProcessFindFormSuccess() throws Exception { + + void testProcessFindFormSuccess() throws Exception { + given(this.owners.findByLastName("")).willReturn(Lists.newArrayList(george, new Owner())); + mockMvc.perform(get("/owners")) + .andExpect(status().isOk()) + @@ -104,7 +101,7 @@ public class OwnerControllerTests { + } + + @Test + - public void testProcessFindFormByLastName() throws Exception { + + void testProcessFindFormByLastName() throws Exception { + given(this.owners.findByLastName(george.getLastName())).willReturn(Lists.newArrayList(george)); + mockMvc.perform(get("/owners") + .param("lastName", "Franklin") + @@ -114,7 +111,7 @@ public class OwnerControllerTests { + } + + @Test + - public void testProcessFindFormNoOwnersFound() throws Exception { + + void testProcessFindFormNoOwnersFound() throws Exception { + mockMvc.perform(get("/owners") + .param("lastName", "Unknown Surname") + ) + @@ -125,7 +122,7 @@ public class OwnerControllerTests { + } + + @Test + - public void testInitUpdateOwnerForm() throws Exception { + + void testInitUpdateOwnerForm() throws Exception { + mockMvc.perform(get("/owners/{ownerId}/edit", TEST_OWNER_ID)) + .andExpect(status().isOk()) + .andExpect(model().attributeExists("owner")) + @@ -138,7 +135,7 @@ public class OwnerControllerTests { + } + + @Test + - public void testProcessUpdateOwnerFormSuccess() throws Exception { + + void testProcessUpdateOwnerFormSuccess() throws Exception { + mockMvc.perform(post("/owners/{ownerId}/edit", TEST_OWNER_ID) + .param("firstName", "Joe") + .param("lastName", "Bloggs") + @@ -151,7 +148,7 @@ public class OwnerControllerTests { + } + + @Test + - public void testProcessUpdateOwnerFormHasErrors() throws Exception { + + void testProcessUpdateOwnerFormHasErrors() throws Exception { + mockMvc.perform(post("/owners/{ownerId}/edit", TEST_OWNER_ID) + .param("firstName", "Joe") + .param("lastName", "Bloggs") + @@ -165,7 +162,7 @@ public class OwnerControllerTests { + } + + @Test + - public void testShowOwner() throws Exception { + + void testShowOwner() throws Exception { + mockMvc.perform(get("/owners/{ownerId}", TEST_OWNER_ID)) + .andExpect(status().isOk()) + .andExpect(model().attribute("owner", hasProperty("lastName", is("Franklin")))) + diff --git a/src/test/java/org/springframework/samples/petclinic/owner/PetControllerTests.java b/src/test/java/org/springframework/samples/petclinic/owner/PetControllerTests.java + index f95d7c8..1d33b39 100755 + --- a/src/test/java/org/springframework/samples/petclinic/owner/PetControllerTests.java + +++ b/src/test/java/org/springframework/samples/petclinic/owner/PetControllerTests.java + @@ -8,9 +8,8 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. + import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; + + import org.assertj.core.util.Lists; + -import org.junit.Before; + -import org.junit.Test; + -import org.junit.runner.RunWith; + +import org.junit.jupiter.api.BeforeEach; + +import org.junit.jupiter.api.Test; + import org.springframework.beans.factory.annotation.Autowired; + import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; + import org.springframework.boot.test.mock.mockito.MockBean; + @@ -23,7 +22,6 @@ import org.springframework.samples.petclinic.owner.PetController; + import org.springframework.samples.petclinic.owner.PetRepository; + import org.springframework.samples.petclinic.owner.PetType; + import org.springframework.samples.petclinic.owner.PetTypeFormatter; + -import org.springframework.test.context.junit4.SpringRunner; + import org.springframework.test.web.servlet.MockMvc; + + /** + @@ -31,12 +29,11 @@ import org.springframework.test.web.servlet.MockMvc; + * + * @author Colin But + */ + -@RunWith(SpringRunner.class) + @WebMvcTest(value = PetController.class, + includeFilters = @ComponentScan.Filter( + - value = PetTypeFormatter.class, + - type = FilterType.ASSIGNABLE_TYPE)) + -public class PetControllerTests { + + value = PetTypeFormatter.class, + + type = FilterType.ASSIGNABLE_TYPE)) + +class PetControllerTests { + + private static final int TEST_OWNER_ID = 1; + private static final int TEST_PET_ID = 1; + @@ -51,8 +48,8 @@ public class PetControllerTests { + @MockBean + private OwnerRepository owners; + + - @Before + - public void setup() { + + @BeforeEach + + void setup() { + PetType cat = new PetType(); + cat.setId(3); + cat.setName("hamster"); + @@ -63,7 +60,7 @@ public class PetControllerTests { + } + + @Test + - public void testInitCreationForm() throws Exception { + + void testInitCreationForm() throws Exception { + mockMvc.perform(get("/owners/{ownerId}/pets/new", TEST_OWNER_ID)) + .andExpect(status().isOk()) + .andExpect(view().name("pets/createOrUpdatePetForm")) + @@ -71,7 +68,7 @@ public class PetControllerTests { + } + + @Test + - public void testProcessCreationFormSuccess() throws Exception { + + void testProcessCreationFormSuccess() throws Exception { + mockMvc.perform(post("/owners/{ownerId}/pets/new", TEST_OWNER_ID) + .param("name", "Betty") + .param("type", "hamster") + @@ -82,7 +79,7 @@ public class PetControllerTests { + } + + @Test + - public void testProcessCreationFormHasErrors() throws Exception { + + void testProcessCreationFormHasErrors() throws Exception { + mockMvc.perform(post("/owners/{ownerId}/pets/new", TEST_OWNER_ID) + .param("name", "Betty") + .param("birthDate", "2015-02-12") + @@ -96,7 +93,7 @@ public class PetControllerTests { + } + + @Test + - public void testInitUpdateForm() throws Exception { + + void testInitUpdateForm() throws Exception { + mockMvc.perform(get("/owners/{ownerId}/pets/{petId}/edit", TEST_OWNER_ID, TEST_PET_ID)) + .andExpect(status().isOk()) + .andExpect(model().attributeExists("pet")) + @@ -104,7 +101,7 @@ public class PetControllerTests { + } + + @Test + - public void testProcessUpdateFormSuccess() throws Exception { + + void testProcessUpdateFormSuccess() throws Exception { + mockMvc.perform(post("/owners/{ownerId}/pets/{petId}/edit", TEST_OWNER_ID, TEST_PET_ID) + .param("name", "Betty") + .param("type", "hamster") + @@ -115,7 +112,7 @@ public class PetControllerTests { + } + + @Test + - public void testProcessUpdateFormHasErrors() throws Exception { + + void testProcessUpdateFormHasErrors() throws Exception { + mockMvc.perform(post("/owners/{ownerId}/pets/{petId}/edit", TEST_OWNER_ID, TEST_PET_ID) + .param("name", "Betty") + .param("birthDate", "2015/02/12") + diff --git a/src/test/java/org/springframework/samples/petclinic/owner/PetTypeFormatterTests.java b/src/test/java/org/springframework/samples/petclinic/owner/PetTypeFormatterTests.java + index 4e8e36c..2c9f2b9 100644 + --- a/src/test/java/org/springframework/samples/petclinic/owner/PetTypeFormatterTests.java + +++ b/src/test/java/org/springframework/samples/petclinic/owner/PetTypeFormatterTests.java + @@ -6,35 +6,36 @@ import java.util.Collection; + import java.util.List; + import java.util.Locale; + + -import org.junit.Before; + -import org.junit.Test; + -import org.junit.runner.RunWith; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import static org.junit.jupiter.api.Assertions.assertThrows; + + + +import org.junit.jupiter.api.BeforeEach; + +import org.junit.jupiter.api.Test; + +import org.junit.jupiter.api.extension.ExtendWith; + import org.mockito.Mock; + import org.mockito.Mockito; + -import org.mockito.junit.MockitoJUnitRunner; + - + -import static org.junit.Assert.assertEquals; + +import org.mockito.junit.jupiter.MockitoExtension; + + /** + * Test class for {@link PetTypeFormatter} + * + * @author Colin But + */ + -@RunWith(MockitoJUnitRunner.class) + -public class PetTypeFormatterTests { + +@ExtendWith(MockitoExtension.class) + +class PetTypeFormatterTests { + + @Mock + private PetRepository pets; + + private PetTypeFormatter petTypeFormatter; + + - @Before + - public void setup() { + + @BeforeEach + + void setup() { + this.petTypeFormatter = new PetTypeFormatter(pets); + } + + @Test + - public void testPrint() { + + void testPrint() { + PetType petType = new PetType(); + petType.setName("Hamster"); + String petTypeName = this.petTypeFormatter.print(petType, Locale.ENGLISH); + @@ -42,16 +43,18 @@ public class PetTypeFormatterTests { + } + + @Test + - public void shouldParse() throws ParseException { + + void shouldParse() throws ParseException { + Mockito.when(this.pets.findPetTypes()).thenReturn(makePetTypes()); + PetType petType = petTypeFormatter.parse("Bird", Locale.ENGLISH); + assertEquals("Bird", petType.getName()); + } + + - @Test(expected = ParseException.class) + - public void shouldThrowParseException() throws ParseException { + - Mockito.when(this.pets.findPetTypes()).thenReturn(makePetTypes()); + - petTypeFormatter.parse("Fish", Locale.ENGLISH); + + @Test + + void shouldThrowParseException() throws ParseException { + + assertThrows(ParseException.class, () -> { + + Mockito.when(this.pets.findPetTypes()).thenReturn(makePetTypes()); + + petTypeFormatter.parse("Fish", Locale.ENGLISH); + + }); + } + + /** + diff --git a/src/test/java/org/springframework/samples/petclinic/owner/VisitControllerTests.java b/src/test/java/org/springframework/samples/petclinic/owner/VisitControllerTests.java + index 08d6136..3331750 100644 + --- a/src/test/java/org/springframework/samples/petclinic/owner/VisitControllerTests.java + +++ b/src/test/java/org/springframework/samples/petclinic/owner/VisitControllerTests.java + @@ -7,9 +7,8 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. + import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; + + -import org.junit.Before; + -import org.junit.Test; + -import org.junit.runner.RunWith; + +import org.junit.jupiter.api.BeforeEach; + +import org.junit.jupiter.api.Test; + import org.springframework.beans.factory.annotation.Autowired; + import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; + import org.springframework.boot.test.mock.mockito.MockBean; + @@ -17,7 +16,6 @@ import org.springframework.samples.petclinic.owner.Pet; + import org.springframework.samples.petclinic.owner.PetRepository; + import org.springframework.samples.petclinic.owner.VisitController; + import org.springframework.samples.petclinic.visit.VisitRepository; + -import org.springframework.test.context.junit4.SpringRunner; + import org.springframework.test.web.servlet.MockMvc; + + /** + @@ -25,9 +23,8 @@ import org.springframework.test.web.servlet.MockMvc; + * + * @author Colin But + */ + -@RunWith(SpringRunner.class) + @WebMvcTest(VisitController.class) + -public class VisitControllerTests { + +class VisitControllerTests { + + private static final int TEST_PET_ID = 1; + + @@ -40,20 +37,20 @@ public class VisitControllerTests { + @MockBean + private PetRepository pets; + + - @Before + - public void init() { + + @BeforeEach + + void init() { + given(this.pets.findById(TEST_PET_ID)).willReturn(new Pet()); + } + + @Test + - public void testInitNewVisitForm() throws Exception { + + void testInitNewVisitForm() throws Exception { + mockMvc.perform(get("/owners/*/pets/{petId}/visits/new", TEST_PET_ID)) + .andExpect(status().isOk()) + .andExpect(view().name("pets/createOrUpdateVisitForm")); + } + + @Test + - public void testProcessNewVisitFormSuccess() throws Exception { + + void testProcessNewVisitFormSuccess() throws Exception { + mockMvc.perform(post("/owners/*/pets/{petId}/visits/new", TEST_PET_ID) + .param("name", "George") + .param("description", "Visit Description") + @@ -63,7 +60,7 @@ public class VisitControllerTests { + } + + @Test + - public void testProcessNewVisitFormHasErrors() throws Exception { + + void testProcessNewVisitFormHasErrors() throws Exception { + mockMvc.perform(post("/owners/*/pets/{petId}/visits/new", TEST_PET_ID) + .param("name", "George") + ) + diff --git a/src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java b/src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java + index 7ed5bf8..aaa3c1d 100644 + --- a/src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java + +++ b/src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java + @@ -5,8 +5,7 @@ import static org.assertj.core.api.Assertions.assertThat; + import java.util.Collection; + import java.util.Date; + + -import org.junit.Test; + -import org.junit.runner.RunWith; + +import org.junit.jupiter.api.Test; + import org.springframework.beans.factory.annotation.Autowired; + import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; + import org.springframework.context.annotation.ComponentScan; + @@ -20,7 +19,6 @@ import org.springframework.samples.petclinic.vet.VetRepository; + import org.springframework.samples.petclinic.visit.Visit; + import org.springframework.samples.petclinic.visit.VisitRepository; + import org.springframework.stereotype.Service; + -import org.springframework.test.context.junit4.SpringRunner; + import org.springframework.transaction.annotation.Transactional; + + /** + @@ -44,9 +42,8 @@ import org.springframework.transaction.annotation.Transactional; + * @author Dave Syer + */ + + -@RunWith(SpringRunner.class) + @DataJpaTest(includeFilters = @ComponentScan.Filter(Service.class)) + -public class ClinicServiceTests { + +class ClinicServiceTests { + + @Autowired + protected OwnerRepository owners; + @@ -61,7 +58,7 @@ public class ClinicServiceTests { + protected VetRepository vets; + + @Test + - public void shouldFindOwnersByLastName() { + + void shouldFindOwnersByLastName() { + Collection owners = this.owners.findByLastName("Davis"); + assertThat(owners.size()).isEqualTo(2); + + @@ -70,7 +67,7 @@ public class ClinicServiceTests { + } + + @Test + - public void shouldFindSingleOwnerWithPet() { + + void shouldFindSingleOwnerWithPet() { + Owner owner = this.owners.findById(1); + assertThat(owner.getLastName()).startsWith("Franklin"); + assertThat(owner.getPets().size()).isEqualTo(1); + @@ -80,7 +77,7 @@ public class ClinicServiceTests { + + @Test + @Transactional + - public void shouldInsertOwner() { + + void shouldInsertOwner() { + Collection owners = this.owners.findByLastName("Schultz"); + int found = owners.size(); + + @@ -99,7 +96,7 @@ public class ClinicServiceTests { + + @Test + @Transactional + - public void shouldUpdateOwner() { + + void shouldUpdateOwner() { + Owner owner = this.owners.findById(1); + String oldLastName = owner.getLastName(); + String newLastName = oldLastName + "X"; + @@ -113,7 +110,7 @@ public class ClinicServiceTests { + } + + @Test + - public void shouldFindPetWithCorrectId() { + + void shouldFindPetWithCorrectId() { + Pet pet7 = this.pets.findById(7); + assertThat(pet7.getName()).startsWith("Samantha"); + assertThat(pet7.getOwner().getFirstName()).isEqualTo("Jean"); + @@ -121,7 +118,7 @@ public class ClinicServiceTests { + } + + @Test + - public void shouldFindAllPetTypes() { + + void shouldFindAllPetTypes() { + Collection petTypes = this.pets.findPetTypes(); + + PetType petType1 = EntityUtils.getById(petTypes, PetType.class, 1); + @@ -132,7 +129,7 @@ public class ClinicServiceTests { + + @Test + @Transactional + - public void shouldInsertPetIntoDatabaseAndGenerateId() { + + void shouldInsertPetIntoDatabaseAndGenerateId() { + Owner owner6 = this.owners.findById(6); + int found = owner6.getPets().size(); + + @@ -155,7 +152,7 @@ public class ClinicServiceTests { + + @Test + @Transactional + - public void shouldUpdatePetName() throws Exception { + + void shouldUpdatePetName() throws Exception { + Pet pet7 = this.pets.findById(7); + String oldName = pet7.getName(); + + @@ -168,7 +165,7 @@ public class ClinicServiceTests { + } + + @Test + - public void shouldFindVets() { + + void shouldFindVets() { + Collection vets = this.vets.findAll(); + + Vet vet = EntityUtils.getById(vets, Vet.class, 3); + @@ -180,7 +177,7 @@ public class ClinicServiceTests { + + @Test + @Transactional + - public void shouldAddNewVisitForPet() { + + void shouldAddNewVisitForPet() { + Pet pet7 = this.pets.findById(7); + int found = pet7.getVisits().size(); + Visit visit = new Visit(); + @@ -195,7 +192,7 @@ public class ClinicServiceTests { + } + + @Test + - public void shouldFindVisitsByPetId() throws Exception { + + void shouldFindVisitsByPetId() throws Exception { + Collection visits = this.visits.findByPetId(7); + assertThat(visits.size()).isEqualTo(2); + Visit[] visitArr = visits.toArray(new Visit[visits.size()]); + diff --git a/src/test/java/org/springframework/samples/petclinic/system/CrashControllerTests.java b/src/test/java/org/springframework/samples/petclinic/system/CrashControllerTests.java + index 3f108bf..0da16c5 100644 + --- a/src/test/java/org/springframework/samples/petclinic/system/CrashControllerTests.java + +++ b/src/test/java/org/springframework/samples/petclinic/system/CrashControllerTests.java + @@ -1,12 +1,10 @@ + package org.springframework.samples.petclinic.system; + + -import org.junit.Ignore; + -import org.junit.Test; + -import org.junit.runner.RunWith; + +import org.junit.jupiter.api.Disabled; + +import org.junit.jupiter.api.Test; + + import org.springframework.beans.factory.annotation.Autowired; + import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; + -import org.springframework.test.context.junit4.SpringRunner; + import org.springframework.test.web.servlet.MockMvc; + + import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; + @@ -20,17 +18,15 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. + * + * @author Colin But + */ + -@RunWith(SpringRunner.class) + -// Waiting https://github.com/spring-projects/spring-boot/issues/5574 + -@Ignore + +@Disabled + @WebMvcTest(controllers = CrashController.class) + -public class CrashControllerTests { + +class CrashControllerTests { + + @Autowired + private MockMvc mockMvc; + + @Test + - public void testTriggerException() throws Exception { + + void testTriggerException() throws Exception { + mockMvc.perform(get("/oups")).andExpect(view().name("exception")) + .andExpect(model().attributeExists("exception")) + .andExpect(forwardedUrl("exception")).andExpect(status().isOk()); + diff --git a/src/test/java/org/springframework/samples/petclinic/system/ProductionConfigurationTests.java b/src/test/java/org/springframework/samples/petclinic/system/ProductionConfigurationTests.java + index 9636e36..1f7ac94 100644 + --- a/src/test/java/org/springframework/samples/petclinic/system/ProductionConfigurationTests.java + +++ b/src/test/java/org/springframework/samples/petclinic/system/ProductionConfigurationTests.java + @@ -1,22 +1,19 @@ + package org.springframework.samples.petclinic.system; + + -import org.junit.Test; + -import org.junit.runner.RunWith; + +import org.junit.jupiter.api.Test; + + import org.springframework.beans.factory.annotation.Autowired; + import org.springframework.boot.test.context.SpringBootTest; + import org.springframework.samples.petclinic.vet.VetRepository; + -import org.springframework.test.context.junit4.SpringRunner; + + -@RunWith(SpringRunner.class) + @SpringBootTest + -public class ProductionConfigurationTests { + +class ProductionConfigurationTests { + + @Autowired + private VetRepository vets; + + @Test + - public void testFindAll() throws Exception { + + void testFindAll() throws Exception { + vets.findAll(); + vets.findAll(); // served from cache + } + diff --git a/src/test/java/org/springframework/samples/petclinic/vet/VetControllerTests.java b/src/test/java/org/springframework/samples/petclinic/vet/VetControllerTests.java + index ce6adf8..fd7490a 100644 + --- a/src/test/java/org/springframework/samples/petclinic/vet/VetControllerTests.java + +++ b/src/test/java/org/springframework/samples/petclinic/vet/VetControllerTests.java + @@ -10,9 +10,8 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. + import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; + + import org.assertj.core.util.Lists; + -import org.junit.Before; + -import org.junit.Test; + -import org.junit.runner.RunWith; + +import org.junit.jupiter.api.BeforeEach; + +import org.junit.jupiter.api.Test; + import org.springframework.beans.factory.annotation.Autowired; + import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; + import org.springframework.boot.test.mock.mockito.MockBean; + @@ -21,16 +20,14 @@ import org.springframework.samples.petclinic.vet.Specialty; + import org.springframework.samples.petclinic.vet.Vet; + import org.springframework.samples.petclinic.vet.VetController; + import org.springframework.samples.petclinic.vet.VetRepository; + -import org.springframework.test.context.junit4.SpringRunner; + import org.springframework.test.web.servlet.MockMvc; + import org.springframework.test.web.servlet.ResultActions; + + /** + * Test class for the {@link VetController} + */ + -@RunWith(SpringRunner.class) + @WebMvcTest(VetController.class) + -public class VetControllerTests { + +class VetControllerTests { + + @Autowired + private MockMvc mockMvc; + @@ -38,8 +35,8 @@ public class VetControllerTests { + @MockBean + private VetRepository vets; + + - @Before + - public void setup() { + + @BeforeEach + + void setup() { + Vet james = new Vet(); + james.setFirstName("James"); + james.setLastName("Carter"); + @@ -56,7 +53,7 @@ public class VetControllerTests { + } + + @Test + - public void testShowVetListHtml() throws Exception { + + void testShowVetListHtml() throws Exception { + mockMvc.perform(get("/vets.html")) + .andExpect(status().isOk()) + .andExpect(model().attributeExists("vets")) + @@ -64,7 +61,7 @@ public class VetControllerTests { + } + + @Test + - public void testShowResourcesVetList() throws Exception { + + void testShowResourcesVetList() throws Exception { + ResultActions actions = mockMvc.perform(get("/vets.json").accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()); + actions.andExpect(content().contentType("application/json;charset=UTF-8")) + @@ -72,7 +69,7 @@ public class VetControllerTests { + } + + @Test + - public void testShowVetListXml() throws Exception { + + void testShowVetListXml() throws Exception { + mockMvc.perform(get("/vets.xml").accept(MediaType.APPLICATION_XML)) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_XML_VALUE)) + diff --git a/src/test/java/org/springframework/samples/petclinic/vet/VetTests.java b/src/test/java/org/springframework/samples/petclinic/vet/VetTests.java + index de3a7b9..a2dacda 100644 + --- a/src/test/java/org/springframework/samples/petclinic/vet/VetTests.java + +++ b/src/test/java/org/springframework/samples/petclinic/vet/VetTests.java + @@ -15,8 +15,7 @@ + */ + package org.springframework.samples.petclinic.vet; + + -import org.junit.Test; + - + +import org.junit.jupiter.api.Test; + import org.springframework.util.SerializationUtils; + + import static org.assertj.core.api.Assertions.assertThat; + @@ -25,10 +24,10 @@ import static org.assertj.core.api.Assertions.assertThat; + * @author Dave Syer + * + */ + -public class VetTests { + +class VetTests { + + @Test + - public void testSerialization() { + + void testSerialization() { + Vet vet = new Vet(); + vet.setFirstName("Zaphod"); + vet.setLastName("Beeblebrox"); +``` + +
+ +If you look at the results, you should see that: + +* The `@Autowired` annotation was removed +* JUnit 4 has been replaced with JUnit 5 +* `javax` has been replaced with `jakarta` +* The code has been migrated to Java 17, and text blocks are used +* Some best practices are applied (such as adding the `public` test method modifier) + +Some of you might be tempted to run `./mvnw verify` to confirm that the build works. Unfortunately, this isn't the case as the commit we started from is using `Wro4j` -- which has some [slight dependency conflicts](../../introduction.md). We've decided not to cover `Wro4j` with recipes for now, as [Spring PetClinic has dropped Wro4J](../../introduction.md) as well. + +### Run a recipe on multiple local repositories + +In the previous example, we used the Moderne CLI to run a recipe against a repository on your local machine. This is fine when you only have one repository you're working with. However, what if you wanted to run a recipe against many repositories at once? Checking them out locally, building each of them, and then running a separate command for each would take a considerable amount of time. + +Fortunately, the Moderne CLI offers the ability to work on groups of repositories. This can be especially helpful when you're working on debugging a new recipe and want to test it against many repositories at once. + +For this exercise, we have prepared a list of Spring 2.x open-source repositories from the `spring-projects` GitHub organization that can be migrated. These repositories have been added to the Moderne platform and put inside the `Spring Projects 2.x` organization. + +To clone all of these repositories at once: + +```bash +mkdir -p $HOME/workshop +mod clone $HOME/workshop --moderne-organization "Spring Projects 2.x" +``` + +If you look in the `$HOME/workshop/spring-projects` directory, you should see 3 different repositories: + +```bash +ls -ltr $HOME/workshop/spring-projects/ +``` + +
+ +You should see output similar to the following. + +```bash +total 0 +drwxr-xr-x 13 mikesol staff 416 Sep 21 10:22 spring-data-release +drwxr-xr-x 21 mikesol staff 672 Sep 21 10:22 spring-hateoas-examples +drwxr-xr-x 14 mikesol staff 448 Sep 21 10:22 spring-session-data-mongodb-examples +``` + +
+ +Now that you have the repositories locally, you can run a recipe against all of them at once. Since all of these repositories have their LSTs published onto the Moderne platform, the build operation will download the LSTs without having to build the repositories locally. This will save you a lot of time! + +```bash +mod build $HOME/workshop +``` + +
+ +You should see output similar to the following. + +``` + ▛▀▀▚▖ ▗▄▟▜ + ▌ ▜▄▟▀ ▐ + ▛▀▀█▀▛▀▀▀▀▜ + ▌▟▀ ▛▀▀▀▀▜ + ▀▀▀▀▀▀▀▀▀▀▀ + Moderne CLI v1.6.1 + Running in a local developer environment + + > Selecting repositories + + > spring-projects/spring-data-release@main + > spring-projects/spring-hateoas-examples@main + > spring-projects/spring-session-data-mongodb-examples@main + Selected 3 repositories (0.36s) + + > Building LST(s) + + > spring-projects/spring-data-release@main + Build output will be written to file:///Users/mikesol/Desktop/code/workshop/spring-projects/spring-data-release/.moderne/build/20230921102317-1wuaH/build.log + 📶 Step 1 - download from Moderne + ✅ Downloaded LST file:///Users/mikesol/Desktop/code/workshop/spring-projects/spring-data-release/.moderne/build/20230921102317-1wuaH/0-spring-data-release-20230921034129-ast.jar + Cleaned 0 older builds. + > spring-projects/spring-hateoas-examples@main + Build output will be written to file:///Users/mikesol/Desktop/code/workshop/spring-projects/spring-hateoas-examples/.moderne/build/20230921102319-BBHxN/build.log + 📶 Step 1 - download from Moderne + ✅ Downloaded LST file:///Users/mikesol/Desktop/code/workshop/spring-projects/spring-hateoas-examples/.moderne/build/20230921102319-BBHxN/0-spring-hateoas-examples-20230921093801-ast.jar + Cleaned 0 older builds. + > spring-projects/spring-session-data-mongodb-examples@main + Build output will be written to file:///Users/mikesol/Desktop/code/workshop/spring-projects/spring-session-data-mongodb-examples/.moderne/build/20230921102320-A1sUV/build.log + 📶 Step 1 - download from Moderne + ✅ Downloaded LST file:///Users/mikesol/Desktop/code/workshop/spring-projects/spring-session-data-mongodb-examples/.moderne/build/20230921102320-A1sUV/0-spring-session-data-mongodb-examples-20230921125257-ast.jar + Cleaned 0 older builds. + Built 3 repositories (3s) + + * What to do next + > Run mod run . --recipe + + MOD SUCCEEDED in (4s) +``` + +
+ +You can apply the changes to all of these repositories at once with the following command: + +```bash +mod apply $HOME/workshop --last-recipe-run +``` + +You can preview the changes with git by going to each repository and running this command: + +```bash +git diff +``` + +Finally, you can commit the changes to all the repositories at once with the following command: + +```bash +mod commit $HOME/workshop -m "Migrate to spring boot 3" --last-recipe-run +``` + +If you'd rather make a branch for each repository and make changes in that, you can use the `mod checkout` command before running `mod commit` to commit the changes. This might be useful if you want to create a pull request for each repository. diff --git a/workshops/spring-boot-migration-workshop/moderne-platform-exercise.md b/workshops/spring-boot-migration-workshop/moderne-platform-exercise.md new file mode 100644 index 00000000..067ab69c --- /dev/null +++ b/workshops/spring-boot-migration-workshop/moderne-platform-exercise.md @@ -0,0 +1,52 @@ +# Moderne platform exercise + +In this exercise, you will utilize the [Moderne platform](https://app.moderne.io/) to: + +* Run static code analysis recipes across repositories from different GitHub organizations +* Fix security vulnerabilities across hundreds of open-source projects. + +### Prepare your environment + +Go to [https://app.moderne.io/](https://app.moderne.io/) and register with your GitHub account. Once you've signed in, you'll find more than 31,000 open-source repositories that can be used to test OpenRewrite recipes without you having to configure anything. + +### Running recipes with the Moderne platform + +1. Once you're logged in to [Moderne](https://app.moderne.io/), you will see that the `Default` organization (a grouping of repositories) is selected in the sidebar. + +
+ +2. With the organization selected, you can go to the[ repositories page](https://app.moderne.io/organizations) and see what repositories are included. There are a few repositories selected from the Netflix, spring-cloud, and spring-projects GitHub organizations. + +
+ +{% hint style="info" %} +The default group has a small set of repositories so recipes will run quickly. If you would rather see more results, you can choose to use the `Netflix + Spring` organization which consists of more than 100 repositories by clicking on `Default` and selecting the new organization. +{% endhint %} + +3. With the organization selected, please go to the [Moderne Marketplace](https://app.moderne.io/marketplace). From there, click on `Static analysis and remediation`, and finally select `Common static analysis issues`. +4. Click on the `More Details` link. You should now be on the [common static analysis issues recipe page](https://app.moderne.io/recipes/org.openrewrite.staticanalysis.CommonStaticAnalysis). From there, you can see that there are many different sonarqube rules under the recipe list. This is because common static analysis issues is a composition of other recipes. You can restrict the ones you want to apply to see the results of a particular recipe by using the [recipe builder](https://app.moderne.io/recipes/builder). + +
+ +5. To begin running the recipe, click on the `DRY RUN` button. +6. You will now be redirected to a page that shows all the relevant recipe run information. Once it's finished, you can click on each repository name to see the results. +7. If you look at the results, you might want to understand why a change has been introduced. Every single change has three dots you can click on in the top right corner of the change. From there, you can select `Why did this change?` to find out more information. + +
+ +{% hint style="warning" %} +Please, do not create pull requests with the results produced by the Moderne platform if you are not an active contributor of those repositories. +{% endhint %} + +### Fixing security vulnerabilities with the Moderne platform + +Another substantial use case for the Moderne platform is detecting and potentially resolving CVEs in your projects and their dependencies. Since the Moderne platform supports complex refactoring recipes (such as the Spring Boot 3 migration), the community can contribute and provide recipes for other major migrations that do more than bump a dependency version. + +In this part of the exercise, let's use the Moderne platform to get a list of vulnerabilities in open-source repositories. + +1. Begin by navigating to the [Check for dependency vulnerabilities recipe](https://app.moderne.io/recipes/org.openrewrite.java.dependencies.DependencyVulnerabilityCheck). +2. Select `compile` for the first option (`scope`), `true`, for the second option (`override managed version`), and leave the third option as blank (`add markers`). +3. Click on the `DRY RUN` button to begin executing this recipe. It should take a few minutes to run. +4. Once the recipe is done running, you can click on the individual repositories to see suggested changes that fix some vulnerabilities. +5. You can also click on the `Data Tables` tab to get taken to a page that allows you to download a CSV or Excel file that contains a list of CVEs that the repositories are vulnerable to. Download the CSV vulnerability report and open the CSV with your preferred CSV reader. You will see that the CSV contains an entry per vulnerability, dependency, and repository. Take special note of the column called `fixedVersion`. That tells you what version fixes that vulnerability. Also take note of the `depth` column, which lets you see how many dependencies away it is from your original dependency. +6. You can also click on the `Visualizations` tab to get a quick high over insight into the number of known vulnerabilities associated with dependencies in the projects. diff --git a/workshops/spring-boot-migration-workshop/recipe-development.md b/workshops/spring-boot-migration-workshop/recipe-development.md new file mode 100644 index 00000000..daca7b61 --- /dev/null +++ b/workshops/spring-boot-migration-workshop/recipe-development.md @@ -0,0 +1,15 @@ +# Recipe development + +The Java ecosystem is vast, and continuously evolving. As such, it's possible OpenRewrite does not yet cover some parts of your migration. We're always looking for help to expand the coverage of migration recipes, and we've made it as easy as possible to get started with recipe development. + +Should you find any parts of your migration are not yet covered, then the first thing to check is whether there is already a corresponding [issue on the backlog](https://github.com/orgs/openrewrite/projects/4/views/10), perhaps with some pointers on an implementation. If not, you can [create a new issue](https://github.com/openrewrite/rewrite-spring/issues/new/choose) to discuss the recipe you'd like to develop. Note that there are separate modules for Spring recipes, Java recipes, testing recipes, logging recipes, and many more. It helps to browse the existing modules for any related work that might be similar and start from there. + +### Types of recipes + +If there's no existing recipe that covers your use case, then you can write your own. There are three types of recipes you can write, each with their own tradeoffs. + +1. [Declarative recipes](https://docs.openrewrite.org/authoring-recipes/types-of-recipes#declarative-recipes) are the simplest to write, and are the most common type of recipe. They are written in YAML, and often tie together existing recipe building blocks with some light configuration. +2. [Refaster rules ](https://docs.openrewrite.org/authoring-recipes/types-of-recipes#refaster-templates)bring you the benefit of compiler support, and work best for straightforward replacements. They generate recipes that can also be used as a starting point for more complex recipe implementations. +3. [Imperative recipes](https://docs.openrewrite.org/authoring-recipes/types-of-recipes#imperative-recipes) are the most powerful, and allow you to write Java code to implement your recipe. By [using the `JavaTemplate` builder](https://docs.openrewrite.org/authoring-recipes/modifying-methods-with-javatemplate), you can keep complexity down, as you define arbitrary code changes. + +No matter which method of recipe development you choose, you can always [write unit tests for your recipe](https://docs.openrewrite.org/authoring-recipes/recipe-testing). Beyond that there are [best practices for writing recipes](https://docs.openrewrite.org/authoring-recipes/recipe-conventions-and-best-practices), such as ensuring idempotence, and avoiding harmful changes. In rare cases, such as with Spring, you might need to [use multiple versions of a dependency](https://docs.openrewrite.org/authoring-recipes/multiple-versions). When you get started, be sure to set up the recommended [recipe development environment](https://docs.openrewrite.org/authoring-recipes/recipe-development-environment).