Skip to content

Commit 7fcacb7

Browse files
refactor: Migrate to JSpecify annotations for nullability constraints. (#3016)
Replaces all deprecated Spring annotations with JSpecify annotations, and includes a full refactor so that the parent build profile `-Pnullaway` compiles and works proper. Closes #2987 Signed-off-by: Michael Simons <[email protected]>
1 parent a4efefa commit 7fcacb7

File tree

153 files changed

+1465
-1283
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

153 files changed

+1465
-1283
lines changed

pom.xml

Lines changed: 44 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,19 @@
8484
<java-module-name>spring.data.neo4j</java-module-name>
8585
<java.version>17</java.version>
8686
<jaxb.version>2.3.1</jaxb.version>
87+
<jna.version>5.8.0</jna.version>
88+
<jspecify.version>1.0.0</jspecify.version>
89+
<jsr305.version>3.0.2</jsr305.version>
8790
<junit-cc-testcontainer>2021.0.1</junit-cc-testcontainer>
91+
<junit-pioneer.version>2.2.0</junit-pioneer.version>
8892
<maven-install-plugin.version>3.1.4</maven-install-plugin.version>
8993
<maven-site-plugin.version>3.7.1</maven-site-plugin.version>
9094
<maven.compiler.release>${java.version}</maven.compiler.release>
9195
<neo4j-java-driver.version>5.28.5</neo4j-java-driver.version>
9296
<neo4j-migrations.version>2.17.3</neo4j-migrations.version>
9397
<neo4j.version>4.4.41</neo4j.version>
9498
<objenesis.version>3.0.1</objenesis.version>
99+
<org.osgi.core.version>6.0.0</org.osgi.core.version>
95100
<project.build.docs>${project.build.directory}/docs</project.build.docs>
96101
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
97102
<r2dbc.releasetrain>Arabba-SR11</r2dbc.releasetrain>
@@ -102,22 +107,14 @@
102107
<skipUnitTests>${skipTests}</skipUnitTests>
103108

104109
<springdata.commons>4.0.0-SNAPSHOT</springdata.commons>
105-
<junit-pioneer.version>2.2.0</junit-pioneer.version>
106110
</properties>
107111

108112
<dependencyManagement>
109113
<dependencies>
110-
<dependency>
111-
<groupId>org.neo4j</groupId>
112-
<artifactId>neo4j-cypher-dsl-bom</artifactId>
113-
<version>${cypher-dsl.version}</version>
114-
<type>pom</type>
115-
<scope>import</scope>
116-
</dependency>
117114
<dependency>
118115
<groupId>com.google.code.findbugs</groupId>
119116
<artifactId>jsr305</artifactId>
120-
<version>3.0.2</version>
117+
<version>${jsr305.version}</version>
121118
</dependency>
122119
<dependency>
123120
<groupId>com.tngtech.archunit</groupId>
@@ -131,9 +128,9 @@
131128
<scope>test</scope>
132129
</dependency>
133130
<dependency>
134-
<groupId>org.junit-pioneer</groupId>
135-
<artifactId>junit-pioneer</artifactId>
136-
<version>${junit-pioneer.version}</version>
131+
<groupId>io.projectreactor.tools</groupId>
132+
<artifactId>blockhound</artifactId>
133+
<version>${blockhound.version}</version>
137134
</dependency>
138135
<dependency>
139136
<groupId>io.r2dbc</groupId>
@@ -161,18 +158,35 @@
161158
<dependency>
162159
<groupId>net.java.dev.jna</groupId>
163160
<artifactId>jna</artifactId>
164-
<version>5.8.0</version>
161+
<version>${jna.version}</version>
165162
</dependency>
166163
<dependency>
167164
<groupId>org.apiguardian</groupId>
168165
<artifactId>apiguardian-api</artifactId>
169166
<version>${apiguardian.version}</version>
170167
</dependency>
168+
<dependency>
169+
<groupId>org.jspecify</groupId>
170+
<artifactId>jspecify</artifactId>
171+
<version>${jspecify.version}</version>
172+
</dependency>
173+
<dependency>
174+
<groupId>org.junit-pioneer</groupId>
175+
<artifactId>junit-pioneer</artifactId>
176+
<version>${junit-pioneer.version}</version>
177+
</dependency>
171178
<dependency>
172179
<groupId>org.neo4j</groupId>
173180
<artifactId>neo4j</artifactId>
174181
<version>${neo4j.version}</version>
175182
</dependency>
183+
<dependency>
184+
<groupId>org.neo4j</groupId>
185+
<artifactId>neo4j-cypher-dsl-bom</artifactId>
186+
<version>${cypher-dsl.version}</version>
187+
<type>pom</type>
188+
<scope>import</scope>
189+
</dependency>
176190
<dependency>
177191
<groupId>org.neo4j.driver</groupId>
178192
<artifactId>neo4j-java-driver</artifactId>
@@ -191,7 +205,7 @@
191205
<dependency>
192206
<groupId>org.osgi</groupId>
193207
<artifactId>org.osgi.core</artifactId>
194-
<version>6.0.0</version>
208+
<version>${org.osgi.core.version}</version>
195209
</dependency>
196210
<dependency>
197211
<groupId>org.slf4j</groupId>
@@ -210,11 +224,6 @@
210224
<type>pom</type>
211225
<scope>import</scope>
212226
</dependency>
213-
<dependency>
214-
<groupId>io.projectreactor.tools</groupId>
215-
<artifactId>blockhound</artifactId>
216-
<version>${blockhound.version}</version>
217-
</dependency>
218227
</dependencies>
219228
</dependencyManagement>
220229

@@ -279,6 +288,11 @@
279288
<scope>test</scope>
280289
<optional>true</optional>
281290
</dependency>
291+
<dependency>
292+
<groupId>io.projectreactor.tools</groupId>
293+
<artifactId>blockhound</artifactId>
294+
<scope>test</scope>
295+
</dependency>
282296
<dependency>
283297
<groupId>io.r2dbc</groupId>
284298
<artifactId>r2dbc-h2</artifactId>
@@ -341,6 +355,11 @@
341355
<artifactId>kotlinx-coroutines-reactor</artifactId>
342356
<optional>true</optional>
343357
</dependency>
358+
<dependency>
359+
<groupId>org.junit-pioneer</groupId>
360+
<artifactId>junit-pioneer</artifactId>
361+
<scope>test</scope>
362+
</dependency>
344363
<dependency>
345364
<groupId>org.neo4j</groupId>
346365
<artifactId>neo4j-cypher-dsl</artifactId>
@@ -415,28 +434,18 @@
415434
</exclusion>
416435
</exclusions>
417436
</dependency>
418-
<dependency>
419-
<groupId>io.projectreactor.tools</groupId>
420-
<artifactId>blockhound</artifactId>
421-
<scope>test</scope>
422-
</dependency>
423-
<dependency>
424-
<groupId>org.junit-pioneer</groupId>
425-
<artifactId>junit-pioneer</artifactId>
426-
<scope>test</scope>
427-
</dependency>
428437
</dependencies>
429438

430439
<repositories>
431440
<repository>
432-
<id>spring-snapshot</id>
433-
<url>https://repo.spring.io/snapshot</url>
434-
<snapshots>
435-
<enabled>true</enabled>
436-
</snapshots>
437441
<releases>
438442
<enabled>false</enabled>
439443
</releases>
444+
<snapshots>
445+
<enabled>true</enabled>
446+
</snapshots>
447+
<id>spring-snapshot</id>
448+
<url>https://repo.spring.io/snapshot</url>
440449
</repository>
441450
<repository>
442451
<id>spring-milestone</id>
@@ -643,31 +652,6 @@
643652
</archive>
644653
</configuration>
645654
</plugin>
646-
<plugin>
647-
<groupId>org.apache.maven.plugins</groupId>
648-
<artifactId>maven-compiler-plugin</artifactId>
649-
<executions>
650-
<execution>
651-
<id>java-compile</id>
652-
<configuration combine.self="append">
653-
<compilerArgs>
654-
<arg>-Xlint:all,-options,-path</arg>
655-
</compilerArgs>
656-
</configuration>
657-
</execution>
658-
<execution>
659-
<!-- You would think that applying above configuration to java-test-compile would have the same result.
660-
Alas, it doesn't. The build just fails, -e -X doesn't show anything sane.
661-
So, showDeprecation is just warnings, if set to errors, than it fails hard (which is nice for
662-
deprecation, but it also fails during missing When.MAYBE whateever Jakarta annotation
663-
and there's just no motiviation to deal with Spring Data Commons build setup in this project -->
664-
<id>java-test-compile</id>
665-
<configuration combine.self="append">
666-
<showDeprecation>true</showDeprecation>
667-
</configuration>
668-
</execution>
669-
</executions>
670-
</plugin>
671655
<plugin>
672656
<groupId>org.apache.maven.plugins</groupId>
673657
<artifactId>maven-resources-plugin</artifactId>
@@ -689,8 +673,8 @@
689673
<build>
690674
<resources>
691675
<resource>
692-
<directory>src/main/antora/resources/antora-resources</directory>
693676
<filtering>true</filtering>
677+
<directory>src/main/antora/resources/antora-resources</directory>
694678
</resource>
695679
</resources>
696680
</build>

src/main/java/org/springframework/data/neo4j/aot/Neo4jManagedTypesBeanRegistrationAotProcessor.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,17 @@
1515
*/
1616
package org.springframework.data.neo4j.aot;
1717

18+
import org.jspecify.annotations.Nullable;
1819
import org.springframework.aot.generate.GenerationContext;
1920
import org.springframework.core.ResolvableType;
2021
import org.springframework.data.aot.ManagedTypesBeanRegistrationAotProcessor;
21-
import org.springframework.lang.Nullable;
2222
import org.springframework.util.ClassUtils;
2323

2424
/**
2525
* @author Gerrit Meier
2626
* @since 7.0.0
2727
*/
28-
public class Neo4jManagedTypesBeanRegistrationAotProcessor extends ManagedTypesBeanRegistrationAotProcessor {
28+
public final class Neo4jManagedTypesBeanRegistrationAotProcessor extends ManagedTypesBeanRegistrationAotProcessor {
2929

3030
public Neo4jManagedTypesBeanRegistrationAotProcessor() {
3131
setModuleIdentifier("neo4j");
@@ -36,7 +36,7 @@ protected boolean isMatch(@Nullable Class<?> beanType, @Nullable String beanName
3636
return isNeo4jManagedTypes(beanType) || super.isMatch(beanType, beanName);
3737
}
3838

39-
protected boolean isNeo4jManagedTypes(@Nullable Class<?> beanType) {
39+
boolean isNeo4jManagedTypes(@Nullable Class<?> beanType) {
4040
return beanType != null && ClassUtils.isAssignable(Neo4jManagedTypes.class, beanType);
4141
}
4242

src/main/java/org/springframework/data/neo4j/aot/Neo4jRuntimeHints.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package org.springframework.data.neo4j.aot;
1717

18+
import org.jspecify.annotations.Nullable;
1819
import org.springframework.aot.hint.MemberCategory;
1920
import org.springframework.aot.hint.RuntimeHints;
2021
import org.springframework.aot.hint.RuntimeHintsRegistrar;
@@ -34,7 +35,6 @@
3435
import org.springframework.data.neo4j.repository.support.SimpleReactiveNeo4jRepository;
3536
import org.springframework.data.querydsl.QuerydslUtils;
3637
import org.springframework.data.util.ReactiveWrappers;
37-
import org.springframework.lang.Nullable;
3838

3939
import java.util.Arrays;
4040

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
@NullMarked
2+
package org.springframework.data.neo4j.aot;
3+
4+
import org.jspecify.annotations.NullMarked;

src/main/java/org/springframework/data/neo4j/config/AbstractNeo4jConfig.java

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package org.springframework.data.neo4j.config;
1717

1818
import org.apiguardian.api.API;
19+
import org.jspecify.annotations.Nullable;
1920
import org.neo4j.driver.Driver;
2021
import org.springframework.beans.factory.ObjectProvider;
2122
import org.springframework.beans.factory.annotation.Autowired;
@@ -30,7 +31,6 @@
3031
import org.springframework.data.neo4j.core.transaction.Neo4jBookmarkManager;
3132
import org.springframework.data.neo4j.core.transaction.Neo4jTransactionManager;
3233
import org.springframework.data.neo4j.repository.config.Neo4jRepositoryConfigurationExtension;
33-
import org.springframework.lang.Nullable;
3434
import org.springframework.transaction.PlatformTransactionManager;
3535

3636
/**
@@ -65,11 +65,11 @@ public abstract class AbstractNeo4jConfig extends Neo4jConfigurationSupport {
6565
* @return A imperative Neo4j client.
6666
*/
6767
@Bean(Neo4jRepositoryConfigurationExtension.DEFAULT_NEO4J_CLIENT_BEAN_NAME)
68-
public Neo4jClient neo4jClient(Driver driver, DatabaseSelectionProvider databaseSelectionProvider) {
68+
public Neo4jClient neo4jClient(Driver driver, @Nullable DatabaseSelectionProvider databaseSelectionProvider) {
6969

7070
return Neo4jClient.with(driver)
7171
.withDatabaseSelectionProvider(databaseSelectionProvider)
72-
.withUserSelectionProvider(getUserSelectionProvider())
72+
.withUserSelectionProvider(this.userSelectionProviders.getIfUnique())
7373
.withNeo4jBookmarkManager(getBootBookmarkManager())
7474
.build();
7575
}
@@ -78,11 +78,6 @@ private Neo4jBookmarkManager getBootBookmarkManager() {
7878
return this.bookmarkManagerProviders.getIfAvailable(Neo4jBookmarkManager::create);
7979
}
8080

81-
@Nullable
82-
private UserSelectionProvider getUserSelectionProvider() {
83-
return this.userSelectionProviders == null ? null : this.userSelectionProviders.getIfUnique();
84-
}
85-
8681
@Bean(Neo4jRepositoryConfigurationExtension.DEFAULT_NEO4J_TEMPLATE_BEAN_NAME)
8782
public Neo4jOperations neo4jTemplate(final Neo4jClient neo4jClient, final Neo4jMappingContext mappingContext) {
8883

@@ -97,12 +92,12 @@ public Neo4jOperations neo4jTemplate(final Neo4jClient neo4jClient, final Neo4jM
9792
* @return A platform transaction manager
9893
*/
9994
@Bean(Neo4jRepositoryConfigurationExtension.DEFAULT_TRANSACTION_MANAGER_BEAN_NAME)
100-
public PlatformTransactionManager transactionManager(Driver driver, DatabaseSelectionProvider databaseSelectionProvider) {
95+
public PlatformTransactionManager transactionManager(Driver driver, @Nullable DatabaseSelectionProvider databaseSelectionProvider) {
10196

10297
return Neo4jTransactionManager
10398
.with(driver)
10499
.withDatabaseSelectionProvider(databaseSelectionProvider)
105-
.withUserSelectionProvider(getUserSelectionProvider())
100+
.withUserSelectionProvider(this.userSelectionProviders.getIfUnique())
106101
.withBookmarkManager(getBootBookmarkManager())
107102
.build();
108103
}

src/main/java/org/springframework/data/neo4j/config/AbstractReactiveNeo4jConfig.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package org.springframework.data.neo4j.config;
1717

1818
import org.apiguardian.api.API;
19+
import org.jspecify.annotations.Nullable;
1920
import org.neo4j.driver.Driver;
2021
import org.springframework.beans.factory.ObjectProvider;
2122
import org.springframework.beans.factory.annotation.Autowired;
@@ -29,7 +30,6 @@
2930
import org.springframework.data.neo4j.core.transaction.Neo4jBookmarkManager;
3031
import org.springframework.data.neo4j.core.transaction.ReactiveNeo4jTransactionManager;
3132
import org.springframework.data.neo4j.repository.config.ReactiveNeo4jRepositoryConfigurationExtension;
32-
import org.springframework.lang.Nullable;
3333
import org.springframework.transaction.PlatformTransactionManager;
3434
import org.springframework.transaction.ReactiveTransactionManager;
3535

src/main/java/org/springframework/data/neo4j/config/Neo4jConfigurationSupport.java

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -90,18 +90,4 @@ protected final Set<Class<?>> getInitialEntitySet() throws ClassNotFoundExceptio
9090

9191
return Neo4jEntityScanner.get().scan(getMappingBasePackages());
9292
}
93-
94-
/**
95-
* Scans the given base package for entities, i.e. Neo4j specific types annotated with {@link Node}.
96-
*
97-
* @param basePackage must not be {@literal null}.
98-
* @return found entities in the package to scan.
99-
* @throws ClassNotFoundException if the given class cannot be loaded by the class loader.
100-
* @deprecated since 6.0.2 Use {@link Neo4jEntityScanner} instead.
101-
*/
102-
@Deprecated
103-
protected final Set<Class<?>> scanForEntities(String basePackage) throws ClassNotFoundException {
104-
105-
return Neo4jEntityScanner.get().scan(basePackage);
106-
}
10793
}

src/main/java/org/springframework/data/neo4j/config/Neo4jEntityScanner.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.util.stream.Collectors;
2424

2525
import org.apiguardian.api.API;
26+
import org.jspecify.annotations.Nullable;
2627
import org.springframework.beans.factory.config.BeanDefinition;
2728
import org.springframework.context.ApplicationContext;
2829
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
@@ -31,7 +32,6 @@
3132
import org.springframework.data.annotation.Persistent;
3233
import org.springframework.data.neo4j.core.schema.Node;
3334
import org.springframework.data.neo4j.core.schema.RelationshipProperties;
34-
import org.springframework.lang.Nullable;
3535
import org.springframework.util.ClassUtils;
3636
import org.springframework.util.StringUtils;
3737

@@ -55,7 +55,8 @@ public static Neo4jEntityScanner get(@Nullable ResourceLoader resourceLoader) {
5555
return new Neo4jEntityScanner(resourceLoader);
5656
}
5757

58-
private @Nullable final ResourceLoader resourceLoader;
58+
@Nullable
59+
private final ResourceLoader resourceLoader;
5960

6061
/**
6162
* Create a new {@link Neo4jEntityScanner} instance.
@@ -121,8 +122,7 @@ public Set<Class<?>> scan(Collection<String> packages) throws ClassNotFoundExcep
121122
* @param resourceLoader an optional {@link ResourceLoader} to use
122123
* @return a {@link ClassPathScanningCandidateComponentProvider} suitable to scan for Neo4j entities
123124
*/
124-
private static ClassPathScanningCandidateComponentProvider createClassPathScanningCandidateComponentProvider(
125-
@Nullable ResourceLoader resourceLoader) {
125+
private static ClassPathScanningCandidateComponentProvider createClassPathScanningCandidateComponentProvider(@Nullable ResourceLoader resourceLoader) {
126126

127127
ClassPathScanningCandidateComponentProvider delegate = new ClassPathScanningCandidateComponentProvider(false);
128128
if (resourceLoader != null) {

0 commit comments

Comments
 (0)