diff --git a/buildSrc/src/main/java/org/springframework/boot/build/architecture/ArchitectureCheck.java b/buildSrc/src/main/java/org/springframework/boot/build/architecture/ArchitectureCheck.java index c36d46a67502..7b79dfd71f91 100644 --- a/buildSrc/src/main/java/org/springframework/boot/build/architecture/ArchitectureCheck.java +++ b/buildSrc/src/main/java/org/springframework/boot/build/architecture/ArchitectureCheck.java @@ -23,6 +23,8 @@ import java.nio.file.Files; import java.nio.file.StandardOpenOption; import java.util.List; +import java.util.Objects; +import java.util.function.Supplier; import java.util.stream.Collectors; import com.tngtech.archunit.base.DescribedPredicate; @@ -83,7 +85,8 @@ public ArchitectureCheck() { noClassesShouldCallStepVerifierStepVerifyComplete(), noClassesShouldConfigureDefaultStepVerifierTimeout(), noClassesShouldCallCollectorsToList(), noClassesShouldCallURLEncoderWithStringEncoding(), noClassesShouldCallURLDecoderWithStringEncoding(), - noClassesShouldLoadResourcesUsingResourceUtils()); + noClassesShouldLoadResourcesUsingResourceUtils(), noClassesShouldCallObjectsRequireNonNullWithMessage(), + noClassesShouldCallObjectsRequireNonNullWithSupplier()); getRuleDescriptions().set(getRules().map((rules) -> rules.stream().map(ArchRule::getDescription).toList())); } @@ -228,6 +231,20 @@ private ArchRule noClassesShouldLoadResourcesUsingResourceUtils() { .because("org.springframework.boot.io.ApplicationResourceLoader should be used instead"); } + private ArchRule noClassesShouldCallObjectsRequireNonNullWithMessage() { + return ArchRuleDefinition.noClasses() + .should() + .callMethod(Objects.class, "requireNonNull", Object.class, String.class) + .because("Use org.springframework.utils.Assert.notNull(Object, String) should be used instead"); + } + + private ArchRule noClassesShouldCallObjectsRequireNonNullWithSupplier() { + return ArchRuleDefinition.noClasses() + .should() + .callMethod(Objects.class, "requireNonNull", Object.class, Supplier.class) + .because("Use org.springframework.utils.Assert.notNull(Object, Supplier) should be used instead"); + } + public void setClasses(FileCollection classes) { this.classes = classes; } diff --git a/buildSrc/src/test/java/org/springframework/boot/build/architecture/ArchitectureCheckTests.java b/buildSrc/src/test/java/org/springframework/boot/build/architecture/ArchitectureCheckTests.java index 11f15a8ade9c..1f7756934fc1 100644 --- a/buildSrc/src/test/java/org/springframework/boot/build/architecture/ArchitectureCheckTests.java +++ b/buildSrc/src/test/java/org/springframework/boot/build/architecture/ArchitectureCheckTests.java @@ -138,6 +138,38 @@ void whenClassUsesResourceUtilsWithoutLoadingResourcesTaskSucceedsAndWritesAnEmp }); } + @Test + void whenClassCallsObjectsRequireNonNullWithMessageTaskFailsAndWritesReport() throws Exception { + prepareTask("objects/requireNonNullWithMessage", (architectureCheck) -> { + assertThatExceptionOfType(GradleException.class).isThrownBy(architectureCheck::checkArchitecture); + assertThat(failureReport(architectureCheck)).isNotEmpty(); + }); + } + + @Test + void whenClassDoesNotCallObjectsRequireNonNullWithMessageTaskSucceedsAndWritesAnEmptyReport() throws Exception { + prepareTask("objects/noRequireNonNullWithMessage", (architectureCheck) -> { + architectureCheck.checkArchitecture(); + assertThat(failureReport(architectureCheck)).isEmpty(); + }); + } + + @Test + void whenClassCallsObjectsRequireNonNullWithSupplierTaskFailsAndWritesReport() throws Exception { + prepareTask("objects/requireNonNullWithSupplier", (architectureCheck) -> { + assertThatExceptionOfType(GradleException.class).isThrownBy(architectureCheck::checkArchitecture); + assertThat(failureReport(architectureCheck)).isNotEmpty(); + }); + } + + @Test + void whenClassDoesNotCallObjectsRequireNonNullWithSupplierTaskSucceedsAndWritesAnEmptyReport() throws Exception { + prepareTask("objects/noRequireNonNullWithSupplier", (architectureCheck) -> { + architectureCheck.checkArchitecture(); + assertThat(failureReport(architectureCheck)).isEmpty(); + }); + } + private void prepareTask(String classes, Callback callback) throws Exception { File projectDir = new File(this.temp, "project"); projectDir.mkdirs(); diff --git a/buildSrc/src/test/java/org/springframework/boot/build/architecture/objects/noRequireNonNullWithMessage/NoRequireNonNullWithMessageUsage.java b/buildSrc/src/test/java/org/springframework/boot/build/architecture/objects/noRequireNonNullWithMessage/NoRequireNonNullWithMessageUsage.java new file mode 100644 index 000000000000..066faa774656 --- /dev/null +++ b/buildSrc/src/test/java/org/springframework/boot/build/architecture/objects/noRequireNonNullWithMessage/NoRequireNonNullWithMessageUsage.java @@ -0,0 +1,37 @@ +/* + * Copyright 2012-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.springframework.boot.build.architecture.objects.noRequireNonNullWithMessage; + +import org.springframework.util.Assert; + +/** + * This class uses `Assert.notNull(Object, String)` instead of + * `Objects.requireNonNull(Object, String)`, and should pass the architecture check. + * + * @author Ivan Malutin + */ +public class NoRequireNonNullWithMessageUsage { + + /** + * Example method that uses `Assert.notNull(Object, String)`, which should not be + * flagged by the architecture check. + */ + public void exampleMethod() { + Assert.notNull(new Object(), "Object must not be null"); + } + +} diff --git a/buildSrc/src/test/java/org/springframework/boot/build/architecture/objects/noRequireNonNullWithSupplier/NoRequireNonNullWithSupplierUsage.java b/buildSrc/src/test/java/org/springframework/boot/build/architecture/objects/noRequireNonNullWithSupplier/NoRequireNonNullWithSupplierUsage.java new file mode 100644 index 000000000000..36ab315e410a --- /dev/null +++ b/buildSrc/src/test/java/org/springframework/boot/build/architecture/objects/noRequireNonNullWithSupplier/NoRequireNonNullWithSupplierUsage.java @@ -0,0 +1,37 @@ +/* + * Copyright 2012-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.springframework.boot.build.architecture.objects.noRequireNonNullWithSupplier; + +import org.springframework.util.Assert; + +/** + * This class uses `Assert.notNull(Object, Supplier)` instead of + * `Objects.requireNonNull(Object, Supplier)`, and should pass the architecture check. + * + * @author Ivan Malutin + */ +public class NoRequireNonNullWithSupplierUsage { + + /** + * Example method that uses `Assert.notNull(Object, Supplier)`, which should not be + * flagged by the architecture check. + */ + public void exampleMethod() { + Assert.notNull(new Object(), () -> "Object must not be null"); + } + +} diff --git a/buildSrc/src/test/java/org/springframework/boot/build/architecture/objects/requireNonNullWithMessage/RequireNonNullWithMessageUsage.java b/buildSrc/src/test/java/org/springframework/boot/build/architecture/objects/requireNonNullWithMessage/RequireNonNullWithMessageUsage.java new file mode 100644 index 000000000000..9e7ee8241f1b --- /dev/null +++ b/buildSrc/src/test/java/org/springframework/boot/build/architecture/objects/requireNonNullWithMessage/RequireNonNullWithMessageUsage.java @@ -0,0 +1,37 @@ +/* + * Copyright 2012-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.springframework.boot.build.architecture.objects.requireNonNullWithMessage; + +import java.util.Objects; + +/** + * This class is intentionally designed to test the use of `Objects.requireNonNull(Object, + * String)`, which should trigger a failure in the architecture check. + * + * @author Ivan Malutin + */ +public class RequireNonNullWithMessageUsage { + + /** + * Example method that uses `Objects.requireNonNull(Object, String)`, which should be + * flagged by the architecture check. + */ + public void exampleMethod() { + Objects.requireNonNull(new Object(), "Object cannot be null"); + } + +} diff --git a/buildSrc/src/test/java/org/springframework/boot/build/architecture/objects/requireNonNullWithSupplier/RequireNonNullWithSupplierUsage.java b/buildSrc/src/test/java/org/springframework/boot/build/architecture/objects/requireNonNullWithSupplier/RequireNonNullWithSupplierUsage.java new file mode 100644 index 000000000000..5f6529b22f16 --- /dev/null +++ b/buildSrc/src/test/java/org/springframework/boot/build/architecture/objects/requireNonNullWithSupplier/RequireNonNullWithSupplierUsage.java @@ -0,0 +1,37 @@ +/* + * Copyright 2012-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.springframework.boot.build.architecture.objects.requireNonNullWithSupplier; + +import java.util.Objects; + +/** + * This class is intentionally designed to test the use of `Objects.requireNonNull(Object, + * Supplier)`, which should trigger a failure in the architecture check. + * + * @author Ivan Malutin + */ +public class RequireNonNullWithSupplierUsage { + + /** + * Example method that uses `Objects.requireNonNull(Object, Supplier)`, which should + * be flagged by the architecture check. + */ + public void exampleMethod() { + Objects.requireNonNull(new Object(), () -> "Object cannot be null"); + } + +}