Skip to content

Commit 172a9d3

Browse files
committed
Add rule to prevent calls to Objects.requireNonNull()
1 parent 397f879 commit 172a9d3

File tree

4 files changed

+103
-1
lines changed

4 files changed

+103
-1
lines changed

buildSrc/src/main/java/org/springframework/boot/build/architecture/ArchitectureCheck.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.nio.file.Files;
2424
import java.nio.file.StandardOpenOption;
2525
import java.util.List;
26+
import java.util.Objects;
2627
import java.util.stream.Collectors;
2728

2829
import com.tngtech.archunit.base.DescribedPredicate;
@@ -83,7 +84,7 @@ public ArchitectureCheck() {
8384
noClassesShouldCallStepVerifierStepVerifyComplete(),
8485
noClassesShouldConfigureDefaultStepVerifierTimeout(), noClassesShouldCallCollectorsToList(),
8586
noClassesShouldCallURLEncoderWithStringEncoding(), noClassesShouldCallURLDecoderWithStringEncoding(),
86-
noClassesShouldLoadResourcesUsingResourceUtils());
87+
noClassesShouldLoadResourcesUsingResourceUtils(), noClassesShouldCallObjectsRequireNonNull());
8788
getRuleDescriptions().set(getRules().map((rules) -> rules.stream().map(ArchRule::getDescription).toList()));
8889
}
8990

@@ -228,6 +229,15 @@ private ArchRule noClassesShouldLoadResourcesUsingResourceUtils() {
228229
.because("org.springframework.boot.io.ApplicationResourceLoader should be used instead");
229230
}
230231

232+
private ArchRule noClassesShouldCallObjectsRequireNonNull() {
233+
return ArchRuleDefinition.noClasses()
234+
.should()
235+
.callMethod(Objects.class, "requireNonNull", Object.class)
236+
.orShould()
237+
.callMethod(Objects.class, "requireNonNull", Object.class, String.class)
238+
.because("org.springframework.utils.Assert.notNull() should be used instead");
239+
}
240+
231241
public void setClasses(FileCollection classes) {
232242
this.classes = classes;
233243
}

buildSrc/src/test/java/org/springframework/boot/build/architecture/ArchitectureCheckTests.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,22 @@ void whenClassUsesResourceUtilsWithoutLoadingResourcesTaskSucceedsAndWritesAnEmp
138138
});
139139
}
140140

141+
@Test
142+
void whenClassCallsObjectsRequireNonNullTaskFailsAndWritesReport() throws Exception {
143+
prepareTask("objects/requireNonNull", (architectureCheck) -> {
144+
assertThatExceptionOfType(GradleException.class).isThrownBy(architectureCheck::checkArchitecture);
145+
assertThat(failureReport(architectureCheck)).isNotEmpty();
146+
});
147+
}
148+
149+
@Test
150+
void whenClassDoesNotCallObjectsRequireNonNullTaskSucceedsAndWritesAnEmptyReport() throws Exception {
151+
prepareTask("objects/noRequireNonNull", (architectureCheck) -> {
152+
architectureCheck.checkArchitecture();
153+
assertThat(failureReport(architectureCheck)).isEmpty();
154+
});
155+
}
156+
141157
private void prepareTask(String classes, Callback<ArchitectureCheck> callback) throws Exception {
142158
File projectDir = new File(this.temp, "project");
143159
projectDir.mkdirs();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright 2012-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.build.architecture.objects.noRequireNonNull;
18+
19+
import org.springframework.util.Assert;
20+
21+
/**
22+
* This class is used to test the use of `Assert.notNull` for null-checking. It is
23+
* intended to demonstrate an acceptable approach according to the architecture check
24+
* rules.
25+
*
26+
* @author Ivan Malutin
27+
*/
28+
public class AssertNotNullUsage {
29+
30+
/**
31+
* Validates that the provided object is not null using `Assert.notNull`. This method
32+
* is compliant with the architecture check rules.
33+
*/
34+
public void ensureObjectNotNull() {
35+
Assert.notNull(new Object(), "The object must not be null");
36+
}
37+
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright 2012-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.build.architecture.objects.requireNonNull;
18+
19+
import java.util.Objects;
20+
21+
/**
22+
* This class is used to test the use of `Objects.requireNonNull` for null-checking. It is
23+
* intended to demonstrate a scenario that should trigger a failure in the architecture
24+
* check.
25+
*
26+
* @author Ivan Malutin
27+
*/
28+
public class RequireNonNullUsage {
29+
30+
/**
31+
* Validates that the provided object is not null using `Objects.requireNonNull`. This
32+
* method is expected to trigger a failure according to the architecture check rules.
33+
*/
34+
public void validateObject() {
35+
Objects.requireNonNull(new Object(), "The object cannot be null");
36+
}
37+
38+
}

0 commit comments

Comments
 (0)