From 24af0a4b05b8620028611bc1dfc15fa981a02eb7 Mon Sep 17 00:00:00 2001 From: Alex Boyko Date: Thu, 20 Jun 2024 14:58:02 -0400 Subject: [PATCH] Boot 3 upgrade doesn't add XML Bind dependency (#485) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Boot 3 upgrade doesn't add XML Bind dependency * Update src/testWithSpringBoot_2_7/java/org/openrewrite/java/spring/boot2/Boot3UpgradeTest.java Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update src/testWithSpringBoot_2_7/java/org/openrewrite/java/spring/boot2/Boot3UpgradeTest.java Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * refactor: Update Gradle wrapper (#534) Use this link to re-run the recipe: https://app.moderne.io/recipes/org.openrewrite.gradle.UpdateGradleWrapper?organizationId=T3BlblJld3JpdGU%3D Co-authored-by: Moderne * Drop AdditionalSpringBootProperties_3_0 As indicated on https://github.com/openrewrite/rewrite-spring/pull/517#issuecomment-2145818887 * refactor: Add a blank line around fields with annotations Use this link to re-run the recipe: https://app.moderne.io/recipes/org.openrewrite.java.recipes.BlankLinesAroundFieldsWithAnnotations?organizationId=T3BlblJld3JpdGU%3D Co-authored-by: Moderne * Relocate Launcher classes renamed in Spring Boot 3.2 (#538) * refactor: Only publish build scans if authenticated Use this link to re-run the recipe: https://app.moderne.io/recipes/builder/kLJjXlflM?organizationId=T3BlblJld3JpdGU%3D Co-authored-by: Moderne * Adopt test to the latest changes * Unit tests for spring petclinic missing `jakarta.xml.bind-api` dependency * Apply automated code review suggestion * Apply formatter and add link to issue for docs * Drop Environment.builder() * Adopt to the latest changes in `rewrite-migrate-java` --------- Co-authored-by: Tim te Beek Co-authored-by: Tim te Beek Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Shannon Pamperl Co-authored-by: Moderne Co-authored-by: Jonathan Schnéider --- build.gradle.kts | 4 + .../java/spring/boot2/Boot3UpgradeTest.java | 456 ++++++++++++++++++ 2 files changed, 460 insertions(+) create mode 100644 src/testWithSpringBoot_2_7/java/org/openrewrite/java/spring/boot2/Boot3UpgradeTest.java diff --git a/build.gradle.kts b/build.gradle.kts index f1fdf98c..f1824c5c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -201,11 +201,15 @@ dependencies { "testWithSpringBoot_2_7RuntimeOnly"("org.springframework:spring-web:5.3.+") "testWithSpringBoot_2_7RuntimeOnly"("org.springframework:spring-webmvc:5.3.+") "testWithSpringBoot_2_7RuntimeOnly"("org.springframework:spring-webflux:5.3.+") + "testWithSpringBoot_2_7RuntimeOnly"("org.springframework.data:spring-data-jpa:2.7.+") "testWithSpringBoot_2_7RuntimeOnly"("org.springframework.security:spring-security-core:5.7.+") "testWithSpringBoot_2_7RuntimeOnly"("org.springframework.security:spring-security-config:5.7.+") "testWithSpringBoot_2_7RuntimeOnly"("org.springframework.security:spring-security-web:5.7.+") "testWithSpringBoot_2_7RuntimeOnly"("org.springframework.security:spring-security-ldap:5.7.+") "testWithSpringBoot_2_7RuntimeOnly"("org.apache.tomcat.embed:tomcat-embed-core:9.0.+") + "testWithSpringBoot_2_7RuntimeOnly"("jakarta.persistence:jakarta.persistence-api:2.2.3") + "testWithSpringBoot_2_7RuntimeOnly"("jakarta.validation:jakarta.validation-api:2.0.2") + "testWithSpringBoot_2_7RuntimeOnly"("jakarta.xml.bind:jakarta.xml.bind-api:2.3.3") "testWithSpringBoot_3_0RuntimeOnly"("org.springframework.boot:spring-boot-starter:3.0.+") "testWithSpringBoot_3_0RuntimeOnly"("org.springframework.boot:spring-boot-starter-test:3.0.+") diff --git a/src/testWithSpringBoot_2_7/java/org/openrewrite/java/spring/boot2/Boot3UpgradeTest.java b/src/testWithSpringBoot_2_7/java/org/openrewrite/java/spring/boot2/Boot3UpgradeTest.java new file mode 100644 index 00000000..0fb91541 --- /dev/null +++ b/src/testWithSpringBoot_2_7/java/org/openrewrite/java/spring/boot2/Boot3UpgradeTest.java @@ -0,0 +1,456 @@ +/* + * Copyright 2024 the original author or authors. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.java.spring.boot2; + +import org.junit.jupiter.api.Test; +import org.openrewrite.DocumentExample; +import org.openrewrite.Issue; +import org.openrewrite.java.JavaParser; +import org.openrewrite.test.RecipeSpec; +import org.openrewrite.test.RewriteTest; + +import static org.openrewrite.java.Assertions.*; +import static org.openrewrite.maven.Assertions.pomXml; + +class Boot3UpgradeTest implements RewriteTest { + + @Override + public void defaults(RecipeSpec spec) { + spec + .recipeFromResources("org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0") + .parser(JavaParser.fromJavaVersion() + .classpath("spring-context", "spring-data-jpa", "spring-web", + "spring-boot", "spring-core", "persistence-api", "validation-api", "xml.bind-api")); + } + + @DocumentExample + @Test + @Issue("https://github.com/openrewrite/rewrite-spring/issues/486") + void xmlBindMissing() { + rewriteRun( + mavenProject("project", + //language=xml + pomXml( + """ + + 4.0.0 + org.springframework.samples + spring-petclinic + 2.7.3 + + + org.springframework.boot + spring-boot-starter-parent + 2.7.3 + + petclinic + + + 1.8 + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-validation + + + org.ehcache + ehcache + + + + """, + """ + + 4.0.0 + org.springframework.samples + spring-petclinic + 2.7.3 + + + org.springframework.boot + spring-boot-starter-parent + 3.0.13 + + petclinic + + + 17 + + + + + jakarta.validation + jakarta.validation-api + 3.1.0 + + + + + + + jakarta.validation + jakarta.validation-api + + + jakarta.xml.bind + jakarta.xml.bind-api + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-validation + + + org.ehcache + ehcache + jakarta + + + + """ + ), + //language=java + srcMainJava( + java( + """ + package org.springframework.samples.petclinic.vet; + + import java.io.Serializable; + + import javax.persistence.Column; + import javax.persistence.Entity; + import javax.persistence.GeneratedValue; + import javax.persistence.GenerationType; + import javax.persistence.Id; + import javax.persistence.Table; + + @Entity + @Table(name = "specialties") + public class Specialty implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @Column(name = "name") + private String name; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public boolean isNew() { + return this.id == null; + } + + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + + } + """, + """ + package org.springframework.samples.petclinic.vet; + + import java.io.Serializable; + + import jakarta.persistence.Column; + import jakarta.persistence.Entity; + import jakarta.persistence.GeneratedValue; + import jakarta.persistence.GenerationType; + import jakarta.persistence.Id; + import jakarta.persistence.Table; + + @Entity + @Table(name = "specialties") + public class Specialty implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @Column(name = "name") + private String name; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public boolean isNew() { + return this.id == null; + } + + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + + } + """ + ), + java( + """ + package org.springframework.samples.petclinic.vet; + + import java.io.Serializable; + import java.util.ArrayList; + import java.util.Collections; + import java.util.HashSet; + import java.util.List; + import java.util.Set; + + import javax.persistence.Column; + import javax.persistence.Entity; + import javax.persistence.FetchType; + import javax.persistence.GeneratedValue; + import javax.persistence.GenerationType; + import javax.persistence.Id; + import javax.persistence.JoinColumn; + import javax.persistence.JoinTable; + import javax.persistence.ManyToMany; + import javax.persistence.Table; + import javax.validation.constraints.NotEmpty; + import javax.xml.bind.annotation.XmlElement; + + @Entity + @Table(name = "vets") + public class Vet implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @Column(name = "name") + private String name; + + @Column(name = "first_name") + @NotEmpty + private String firstName; + + @Column(name = "last_name") + @NotEmpty + private String lastName; + + @ManyToMany(fetch = FetchType.EAGER) + @JoinTable(name = "vet_specialties", joinColumns = @JoinColumn(name = "vet_id"), + inverseJoinColumns = @JoinColumn(name = "specialty_id")) + private Set specialties; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public boolean isNew() { + return this.id == null; + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + protected Set getSpecialtiesInternal() { + if (this.specialties == null) { + this.specialties = new HashSet<>(); + } + return this.specialties; + } + + protected void setSpecialtiesInternal(Set specialties) { + this.specialties = specialties; + } + + @XmlElement + public List getSpecialties() { + List sortedSpecs = new ArrayList<>(getSpecialtiesInternal()); + return Collections.unmodifiableList(sortedSpecs); + } + + public int getNrOfSpecialties() { + return getSpecialtiesInternal().size(); + } + + public void addSpecialty(Specialty specialty) { + getSpecialtiesInternal().add(specialty); + } + + public String getFirstName() { + return this.firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return this.lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + } + """, + """ + package org.springframework.samples.petclinic.vet; + + import java.io.Serializable; + import java.util.ArrayList; + import java.util.Collections; + import java.util.HashSet; + import java.util.List; + import java.util.Set; + + import jakarta.persistence.Column; + import jakarta.persistence.Entity; + import jakarta.persistence.FetchType; + import jakarta.persistence.GeneratedValue; + import jakarta.persistence.GenerationType; + import jakarta.persistence.Id; + import jakarta.persistence.JoinColumn; + import jakarta.persistence.JoinTable; + import jakarta.persistence.ManyToMany; + import jakarta.persistence.Table; + import jakarta.validation.constraints.NotEmpty; + import jakarta.xml.bind.annotation.XmlElement; + + @Entity + @Table(name = "vets") + public class Vet implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @Column(name = "name") + private String name; + + @Column(name = "first_name") + @NotEmpty + private String firstName; + + @Column(name = "last_name") + @NotEmpty + private String lastName; + + @ManyToMany(fetch = FetchType.EAGER) + @JoinTable(name = "vet_specialties", joinColumns = @JoinColumn(name = "vet_id"), + inverseJoinColumns = @JoinColumn(name = "specialty_id")) + private Set specialties; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public boolean isNew() { + return this.id == null; + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + protected Set getSpecialtiesInternal() { + if (this.specialties == null) { + this.specialties = new HashSet<>(); + } + return this.specialties; + } + + protected void setSpecialtiesInternal(Set specialties) { + this.specialties = specialties; + } + + @XmlElement + public List getSpecialties() { + List sortedSpecs = new ArrayList<>(getSpecialtiesInternal()); + return Collections.unmodifiableList(sortedSpecs); + } + + public int getNrOfSpecialties() { + return getSpecialtiesInternal().size(); + } + + public void addSpecialty(Specialty specialty) { + getSpecialtiesInternal().add(specialty); + } + + public String getFirstName() { + return this.firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return this.lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + } + """ + ) + ) + ) + ); + } +}