From 413a7f20e29889ae77b9c296bb0c1963c7f66a6d Mon Sep 17 00:00:00 2001 From: sijun-yang Date: Wed, 9 Oct 2024 02:47:49 +0900 Subject: [PATCH 1/2] Add Configuration for Kotlin's All-Open Plugin for JPA Entities See gh-1576 --- .../spring/build/BuildMetadataResolver.java | 13 ++++++++ .../KotlinJpaGradleBuildCustomizer.java | 15 ++++++++- .../kotlin/KotlinJpaMavenBuildCustomizer.java | 12 +++++-- ...ationDefaultContributorsConfiguration.java | 14 +++++++-- .../KotlinJpaGradleBuildCustomizerTests.java | 31 ++++++++++++++++++- .../KotlinJpaMavenBuildCustomizerTests.java | 31 +++++++++++++++++++ 6 files changed, 109 insertions(+), 7 deletions(-) diff --git a/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/build/BuildMetadataResolver.java b/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/build/BuildMetadataResolver.java index 38660f6dfa..b9673d56f7 100644 --- a/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/build/BuildMetadataResolver.java +++ b/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/build/BuildMetadataResolver.java @@ -29,6 +29,7 @@ * * @author Stephane Nicoll * @author Moritz Halbritter + * @author Sijun Yang */ public class BuildMetadataResolver { @@ -65,4 +66,16 @@ public boolean hasFacet(Build build, String facet) { return dependencies(build).anyMatch((dependency) -> dependency.getFacets().contains(facet)); } + /** + * Checks if the given {@link Build} contains dependencies with the given + * {@code groupId}. + * @param build the build to query + * @param groupId the groupId to query + * @return {@code true} if this build defines at least a dependency with that groupId, + * {@code false} otherwise + */ + public boolean hasGroupId(Build build, String groupId) { + return dependencies(build).anyMatch((dependency) -> dependency.getGroupId().equals(groupId)); + } + } diff --git a/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/code/kotlin/KotlinJpaGradleBuildCustomizer.java b/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/code/kotlin/KotlinJpaGradleBuildCustomizer.java index db12fe04eb..959ebbba56 100644 --- a/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/code/kotlin/KotlinJpaGradleBuildCustomizer.java +++ b/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/code/kotlin/KotlinJpaGradleBuildCustomizer.java @@ -28,6 +28,7 @@ * related dependency is present. * * @author Madhura Bhave + * @author Sijun Yang */ public class KotlinJpaGradleBuildCustomizer implements BuildCustomizer { @@ -35,10 +36,13 @@ public class KotlinJpaGradleBuildCustomizer implements BuildCustomizer plugin.setVersion(this.settings.getVersion())); + build.extensions().customize("allOpen", (allOpen) -> { + allOpen.invoke("annotation", quote("jakarta.persistence.Entity")); + allOpen.invoke("annotation", quote("jakarta.persistence.MappedSuperclass")); + allOpen.invoke("annotation", quote("jakarta.persistence.Embeddable")); + }); } } + private String quote(String element) { + return this.quote + element + this.quote; + } + } diff --git a/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/code/kotlin/KotlinJpaMavenBuildCustomizer.java b/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/code/kotlin/KotlinJpaMavenBuildCustomizer.java index c57927c002..ea16771b1d 100644 --- a/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/code/kotlin/KotlinJpaMavenBuildCustomizer.java +++ b/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/code/kotlin/KotlinJpaMavenBuildCustomizer.java @@ -28,6 +28,7 @@ * * @author Madhura Bhave * @author Sebastien Deleuze + * @author Sijun Yang */ public class KotlinJpaMavenBuildCustomizer implements BuildCustomizer { @@ -41,8 +42,15 @@ public KotlinJpaMavenBuildCustomizer(InitializrMetadata metadata, ProjectDescrip public void customize(MavenBuild build) { if (this.buildMetadataResolver.hasFacet(build, "jpa")) { build.plugins().add("org.jetbrains.kotlin", "kotlin-maven-plugin", (kotlinPlugin) -> { - kotlinPlugin.configuration((configuration) -> configuration.configure("compilerPlugins", - (compilerPlugins) -> compilerPlugins.add("plugin", "jpa"))); + kotlinPlugin.configuration((configuration) -> { + configuration.configure("compilerPlugins", + (compilerPlugins) -> compilerPlugins.add("plugin", "jpa")); + configuration.configure("pluginOptions", (option) -> { + option.add("option", "all-open:annotation=jakarta.persistence.Entity"); + option.add("option", "all-open:annotation=jakarta.persistence.MappedSuperclass"); + option.add("option", "all-open:annotation=jakarta.persistence.Embeddable"); + }); + }); kotlinPlugin.dependency("org.jetbrains.kotlin", "kotlin-maven-noarg", "${kotlin.version}"); }); } diff --git a/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/code/kotlin/KotlinProjectGenerationDefaultContributorsConfiguration.java b/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/code/kotlin/KotlinProjectGenerationDefaultContributorsConfiguration.java index 4a933aeb24..6bb36e4a81 100644 --- a/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/code/kotlin/KotlinProjectGenerationDefaultContributorsConfiguration.java +++ b/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/code/kotlin/KotlinProjectGenerationDefaultContributorsConfiguration.java @@ -47,6 +47,7 @@ * @author Stephane Nicoll * @author Jean-Baptiste Nizet * @author Moritz Halbritter + * @author Sijun Yang */ @Configuration class KotlinProjectGenerationDefaultContributorsConfiguration { @@ -67,10 +68,17 @@ BuildCustomizer kotlinDependenciesConfigurer() { } @Bean - @ConditionalOnBuildSystem(GradleBuildSystem.ID) - KotlinJpaGradleBuildCustomizer kotlinJpaGradleBuildCustomizer(InitializrMetadata metadata, + @ConditionalOnBuildSystem(value = GradleBuildSystem.ID, dialect = GradleBuildSystem.DIALECT_KOTLIN) + KotlinJpaGradleBuildCustomizer kotlinJpaGradleBuildCustomizerKotlinDsl(InitializrMetadata metadata, + KotlinProjectSettings settings, ProjectDescription projectDescription) { + return new KotlinJpaGradleBuildCustomizer(metadata, settings, projectDescription, '\"'); + } + + @Bean + @ConditionalOnBuildSystem(value = GradleBuildSystem.ID, dialect = GradleBuildSystem.DIALECT_GROOVY) + KotlinJpaGradleBuildCustomizer kotlinJpaGradleBuildCustomizerGroovyDsl(InitializrMetadata metadata, KotlinProjectSettings settings, ProjectDescription projectDescription) { - return new KotlinJpaGradleBuildCustomizer(metadata, settings, projectDescription); + return new KotlinJpaGradleBuildCustomizer(metadata, settings, projectDescription, '\''); } @Bean diff --git a/initializr-generator-spring/src/test/java/io/spring/initializr/generator/spring/code/kotlin/KotlinJpaGradleBuildCustomizerTests.java b/initializr-generator-spring/src/test/java/io/spring/initializr/generator/spring/code/kotlin/KotlinJpaGradleBuildCustomizerTests.java index e36aa71a5a..666254153d 100644 --- a/initializr-generator-spring/src/test/java/io/spring/initializr/generator/spring/code/kotlin/KotlinJpaGradleBuildCustomizerTests.java +++ b/initializr-generator-spring/src/test/java/io/spring/initializr/generator/spring/code/kotlin/KotlinJpaGradleBuildCustomizerTests.java @@ -17,6 +17,8 @@ package io.spring.initializr.generator.spring.code.kotlin; import java.util.Collections; +import java.util.List; +import java.util.Objects; import io.spring.initializr.generator.buildsystem.gradle.GradleBuild; import io.spring.initializr.generator.buildsystem.gradle.GradlePlugin; @@ -35,6 +37,7 @@ * Tests for {@link KotlinJpaGradleBuildCustomizer}. * * @author Madhura Bhave + * @author Sijun Yang */ class KotlinJpaGradleBuildCustomizerTests { @@ -58,6 +61,32 @@ void customizeWhenJpaFacetAbsentShouldNotAddKotlinJpaPlugin() { assertThat(build.plugins().values()).isEmpty(); } + @Test + void customizeWhenJpaFacetPresentShouldCustomizeAllOpen() { + Dependency dependency = Dependency.withId("foo"); + dependency.setFacets(Collections.singletonList("jpa")); + GradleBuild build = getCustomizedBuild(dependency); + assertThat(build.extensions().values()).singleElement().satisfies((extension) -> { + assertThat(extension.getName()).isEqualTo("allOpen"); + assertThat(extension.getInvocations()) + .filteredOn((invocation) -> Objects.equals(invocation.getTarget(), "annotation")) + .extracting("arguments") + .containsExactlyInAnyOrder(List.of("\"jakarta.persistence.Entity\""), + List.of("\"jakarta.persistence.MappedSuperclass\""), + List.of("\"jakarta.persistence.Embeddable\"")); + }); + } + + @Test + void customizeWhenJpaFacetAbsentShouldNotCustomizeAllOpen() { + Dependency dependency = Dependency.withId("foo"); + GradleBuild build = getCustomizedBuild(dependency); + assertThat(build.extensions().values()) + .filteredOn((extension) -> Objects.equals(extension.getName(), "allOpen")) + .isEmpty(); + assertThat(build.extensions().values()).isEmpty(); + } + private GradleBuild getCustomizedBuild(Dependency dependency) { InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() .addDependencyGroup("test", dependency) @@ -66,7 +95,7 @@ private GradleBuild getCustomizedBuild(Dependency dependency) { MutableProjectDescription projectDescription = new MutableProjectDescription(); projectDescription.setPlatformVersion(Version.parse("1.0.0")); KotlinJpaGradleBuildCustomizer customizer = new KotlinJpaGradleBuildCustomizer(metadata, settings, - projectDescription); + projectDescription, '\"'); GradleBuild build = new GradleBuild(new MetadataBuildItemResolver(metadata, Version.parse("2.0.0.RELEASE"))); build.dependencies().add("foo"); customizer.customize(build); diff --git a/initializr-generator-spring/src/test/java/io/spring/initializr/generator/spring/code/kotlin/KotlinJpaMavenBuildCustomizerTests.java b/initializr-generator-spring/src/test/java/io/spring/initializr/generator/spring/code/kotlin/KotlinJpaMavenBuildCustomizerTests.java index a907b18526..0ef96c344c 100644 --- a/initializr-generator-spring/src/test/java/io/spring/initializr/generator/spring/code/kotlin/KotlinJpaMavenBuildCustomizerTests.java +++ b/initializr-generator-spring/src/test/java/io/spring/initializr/generator/spring/code/kotlin/KotlinJpaMavenBuildCustomizerTests.java @@ -17,6 +17,8 @@ package io.spring.initializr.generator.spring.code.kotlin; import java.util.Collections; +import java.util.List; +import java.util.Objects; import io.spring.initializr.generator.buildsystem.maven.MavenBuild; import io.spring.initializr.generator.buildsystem.maven.MavenPlugin; @@ -36,6 +38,7 @@ * * @author Madhura Bhave * @author Sebastien Deleuze + * @author Sijun Yang */ class KotlinJpaMavenBuildCustomizerTests { @@ -67,6 +70,34 @@ void customizeWhenJpaFacetAbsentShouldNotAddKotlinJpaPlugin() { assertThat(build.plugins().isEmpty()).isTrue(); } + @Test + void customizeWhenJpaFacetPresentShouldCustomizeAllOpen() { + Dependency dependency = Dependency.withId("foo"); + dependency.setFacets(Collections.singletonList("jpa")); + MavenBuild build = getCustomizedBuild(dependency); + + assertThat(build.plugins().values()).singleElement().satisfies((plugin) -> { + MavenPlugin.Configuration configuration = plugin.getConfiguration(); + + assertThat(configuration.getSettings()).filteredOn((setting) -> setting.getName().equals("pluginOptions")) + .isNotEmpty() + .first() + .satisfies((pluginOptions) -> assertThat(((List) pluginOptions.getValue())) + .filteredOn((option) -> Objects.equals(option.getName(), "option")) + .map(MavenPlugin.Setting::getValue) + .containsExactlyInAnyOrder("all-open:annotation=jakarta.persistence.Entity", + "all-open:annotation=jakarta.persistence.MappedSuperclass", + "all-open:annotation=jakarta.persistence.Embeddable")); + }); + } + + @Test + void customizeWhenJpaFacetAbsentShouldNotCustomizeAllOpen() { + Dependency dependency = Dependency.withId("foo"); + MavenBuild build = getCustomizedBuild(dependency); + assertThat(build.plugins().values()).isEmpty(); + } + private MavenBuild getCustomizedBuild(Dependency dependency) { InitializrMetadata metadata = InitializrMetadataTestBuilder.withDefaults() .addDependencyGroup("test", dependency) From 7460b7baa42e931d31f22ed114597c8cf0289e4e Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Fri, 11 Oct 2024 10:07:26 +0200 Subject: [PATCH 2/2] Polish "Add Configuration for Kotlin's All-Open Plugin for JPA Entities" See gh-1576 --- .../spring/build/BuildMetadataResolver.java | 13 ------------- ...tGenerationDefaultContributorsConfiguration.java | 8 ++++---- 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/build/BuildMetadataResolver.java b/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/build/BuildMetadataResolver.java index b9673d56f7..38660f6dfa 100644 --- a/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/build/BuildMetadataResolver.java +++ b/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/build/BuildMetadataResolver.java @@ -29,7 +29,6 @@ * * @author Stephane Nicoll * @author Moritz Halbritter - * @author Sijun Yang */ public class BuildMetadataResolver { @@ -66,16 +65,4 @@ public boolean hasFacet(Build build, String facet) { return dependencies(build).anyMatch((dependency) -> dependency.getFacets().contains(facet)); } - /** - * Checks if the given {@link Build} contains dependencies with the given - * {@code groupId}. - * @param build the build to query - * @param groupId the groupId to query - * @return {@code true} if this build defines at least a dependency with that groupId, - * {@code false} otherwise - */ - public boolean hasGroupId(Build build, String groupId) { - return dependencies(build).anyMatch((dependency) -> dependency.getGroupId().equals(groupId)); - } - } diff --git a/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/code/kotlin/KotlinProjectGenerationDefaultContributorsConfiguration.java b/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/code/kotlin/KotlinProjectGenerationDefaultContributorsConfiguration.java index 6bb36e4a81..aa2aa4d898 100644 --- a/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/code/kotlin/KotlinProjectGenerationDefaultContributorsConfiguration.java +++ b/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/code/kotlin/KotlinProjectGenerationDefaultContributorsConfiguration.java @@ -68,14 +68,14 @@ BuildCustomizer kotlinDependenciesConfigurer() { } @Bean - @ConditionalOnBuildSystem(value = GradleBuildSystem.ID, dialect = GradleBuildSystem.DIALECT_KOTLIN) + @ConditionalOnBuildSystem(id = GradleBuildSystem.ID, dialect = GradleBuildSystem.DIALECT_KOTLIN) KotlinJpaGradleBuildCustomizer kotlinJpaGradleBuildCustomizerKotlinDsl(InitializrMetadata metadata, KotlinProjectSettings settings, ProjectDescription projectDescription) { return new KotlinJpaGradleBuildCustomizer(metadata, settings, projectDescription, '\"'); } @Bean - @ConditionalOnBuildSystem(value = GradleBuildSystem.ID, dialect = GradleBuildSystem.DIALECT_GROOVY) + @ConditionalOnBuildSystem(id = GradleBuildSystem.ID, dialect = GradleBuildSystem.DIALECT_GROOVY) KotlinJpaGradleBuildCustomizer kotlinJpaGradleBuildCustomizerGroovyDsl(InitializrMetadata metadata, KotlinProjectSettings settings, ProjectDescription projectDescription) { return new KotlinJpaGradleBuildCustomizer(metadata, settings, projectDescription, '\''); @@ -89,13 +89,13 @@ KotlinJpaMavenBuildCustomizer kotlinJpaMavenBuildCustomizer(InitializrMetadata m } @Bean - @ConditionalOnBuildSystem(value = GradleBuildSystem.ID, dialect = GradleBuildSystem.DIALECT_KOTLIN) + @ConditionalOnBuildSystem(id = GradleBuildSystem.ID, dialect = GradleBuildSystem.DIALECT_KOTLIN) KotlinGradleBuildCustomizer kotlinBuildCustomizerKotlinDsl(KotlinProjectSettings kotlinProjectSettings) { return new KotlinGradleBuildCustomizer(kotlinProjectSettings, '\"'); } @Bean - @ConditionalOnBuildSystem(value = GradleBuildSystem.ID, dialect = GradleBuildSystem.DIALECT_GROOVY) + @ConditionalOnBuildSystem(id = GradleBuildSystem.ID, dialect = GradleBuildSystem.DIALECT_GROOVY) KotlinGradleBuildCustomizer kotlinBuildCustomizerGroovyDsl(KotlinProjectSettings kotlinProjectSettings) { return new KotlinGradleBuildCustomizer(kotlinProjectSettings, '\''); }