diff --git a/module/spring-boot-rsocket/build.gradle b/module/spring-boot-rsocket/build.gradle index dcc0ed647fe..263a87aedc3 100644 --- a/module/spring-boot-rsocket/build.gradle +++ b/module/spring-boot-rsocket/build.gradle @@ -29,6 +29,8 @@ dependencies { api("io.rsocket:rsocket-core") api("org.springframework:spring-messaging") + compileOnly("com.google.code.findbugs:jsr305") + implementation("org.springframework:spring-web") optional(project(":core:spring-boot-autoconfigure")) diff --git a/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/autoconfigure/RSocketProperties.java b/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/autoconfigure/RSocketProperties.java index 14afad7af28..e57a3085104 100644 --- a/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/autoconfigure/RSocketProperties.java +++ b/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/autoconfigure/RSocketProperties.java @@ -18,6 +18,8 @@ package org.springframework.boot.rsocket.autoconfigure; import java.net.InetAddress; +import org.jspecify.annotations.Nullable; + import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.NestedConfigurationProperty; import org.springframework.boot.rsocket.server.RSocketServer; @@ -46,12 +48,12 @@ public class RSocketProperties { /** * Server port. */ - private Integer port; + private @Nullable Integer port; /** * Network address to which the server should bind. */ - private InetAddress address; + private @Nullable InetAddress address; /** * RSocket transport protocol. @@ -62,32 +64,32 @@ public class RSocketProperties { * Path under which RSocket handles requests (only works with websocket * transport). */ - private String mappingPath; + private @Nullable String mappingPath; /** * Maximum transmission unit. Frames larger than the specified value are * fragmented. */ - private DataSize fragmentSize; + private @Nullable DataSize fragmentSize; @NestedConfigurationProperty - private Ssl ssl; + private @Nullable Ssl ssl; private final Spec spec = new Spec(); - public Integer getPort() { + public @Nullable Integer getPort() { return this.port; } - public void setPort(Integer port) { + public void setPort(@Nullable Integer port) { this.port = port; } - public InetAddress getAddress() { + public @Nullable InetAddress getAddress() { return this.address; } - public void setAddress(InetAddress address) { + public void setAddress(@Nullable InetAddress address) { this.address = address; } @@ -99,27 +101,27 @@ public class RSocketProperties { this.transport = transport; } - public String getMappingPath() { + public @Nullable String getMappingPath() { return this.mappingPath; } - public void setMappingPath(String mappingPath) { + public void setMappingPath(@Nullable String mappingPath) { this.mappingPath = mappingPath; } - public DataSize getFragmentSize() { + public @Nullable DataSize getFragmentSize() { return this.fragmentSize; } - public void setFragmentSize(DataSize fragmentSize) { + public void setFragmentSize(@Nullable DataSize fragmentSize) { this.fragmentSize = fragmentSize; } - public Ssl getSsl() { + public @Nullable Ssl getSsl() { return this.ssl; } - public void setSsl(Ssl ssl) { + public void setSsl(@Nullable Ssl ssl) { this.ssl = ssl; } @@ -132,7 +134,7 @@ public class RSocketProperties { /** * Sub-protocols to use in websocket handshake signature. */ - private String protocols; + private @Nullable String protocols; /** * Maximum allowable frame payload length. @@ -149,11 +151,11 @@ public class RSocketProperties { */ private boolean compress; - public String getProtocols() { + public @Nullable String getProtocols() { return this.protocols; } - public void setProtocols(String protocols) { + public void setProtocols(@Nullable String protocols) { this.protocols = protocols; } diff --git a/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/autoconfigure/RSocketServerAutoConfiguration.java b/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/autoconfigure/RSocketServerAutoConfiguration.java index f1fd94fa1b6..973f1fef2e9 100644 --- a/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/autoconfigure/RSocketServerAutoConfiguration.java +++ b/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/autoconfigure/RSocketServerAutoConfiguration.java @@ -51,6 +51,7 @@ import org.springframework.core.io.buffer.NettyDataBufferFactory; import org.springframework.http.client.ReactorResourceFactory; import org.springframework.messaging.rsocket.RSocketStrategies; import org.springframework.messaging.rsocket.annotation.support.RSocketMessageHandler; +import org.springframework.util.Assert; import org.springframework.util.unit.DataSize; /** @@ -78,9 +79,10 @@ public final class RSocketServerAutoConfiguration { @ConditionalOnMissingBean RSocketWebSocketNettyRouteProvider rSocketWebsocketRouteProvider(RSocketProperties properties, RSocketMessageHandler messageHandler, ObjectProvider customizers) { - return new RSocketWebSocketNettyRouteProvider(properties.getServer().getMappingPath(), - messageHandler.responder(), customizeWebsocketServerSpec(properties.getServer().getSpec()), - customizers.orderedStream()); + String mappingPath = properties.getServer().getMappingPath(); + Assert.state(mappingPath != null, "'mappingPath' must not be null"); + return new RSocketWebSocketNettyRouteProvider(mappingPath, messageHandler.responder(), + customizeWebsocketServerSpec(properties.getServer().getSpec()), customizers.orderedStream()); } private Consumer customizeWebsocketServerSpec(Spec spec) { diff --git a/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/autoconfigure/package-info.java b/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/autoconfigure/package-info.java index 0a88c05f02e..cf284e64064 100644 --- a/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/autoconfigure/package-info.java +++ b/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/autoconfigure/package-info.java @@ -17,4 +17,7 @@ /** * Auto-configuration for RSocket. */ +@NullMarked package org.springframework.boot.rsocket.autoconfigure; + +import org.jspecify.annotations.NullMarked; diff --git a/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/context/RSocketServerBootstrap.java b/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/context/RSocketServerBootstrap.java index 93b82eaa49f..d3a45c8b150 100644 --- a/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/context/RSocketServerBootstrap.java +++ b/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/context/RSocketServerBootstrap.java @@ -35,6 +35,7 @@ public class RSocketServerBootstrap implements ApplicationEventPublisherAware, S private final RSocketServer server; + @SuppressWarnings("NullAway.Init") private ApplicationEventPublisher eventPublisher; public RSocketServerBootstrap(RSocketServerFactory serverFactory, SocketAcceptor socketAcceptor) { @@ -60,11 +61,7 @@ public class RSocketServerBootstrap implements ApplicationEventPublisherAware, S @Override public boolean isRunning() { - RSocketServer server = this.server; - if (server != null) { - return server.address() != null; - } - return false; + return this.server.address() != null; } } diff --git a/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/context/package-info.java b/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/context/package-info.java index 9f3e490878a..7a26eff0f32 100644 --- a/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/context/package-info.java +++ b/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/context/package-info.java @@ -18,4 +18,7 @@ * RSocket integrations with Spring Framework's * {@link org.springframework.context.ApplicationContext ApplicationContext}. */ +@NullMarked package org.springframework.boot.rsocket.context; + +import org.jspecify.annotations.NullMarked; diff --git a/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/messaging/package-info.java b/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/messaging/package-info.java index c41f4693924..5765a84e157 100644 --- a/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/messaging/package-info.java +++ b/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/messaging/package-info.java @@ -17,4 +17,7 @@ /** * Support for RSocket-based messaging. */ +@NullMarked package org.springframework.boot.rsocket.messaging; + +import org.jspecify.annotations.NullMarked; diff --git a/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/netty/NettyRSocketServer.java b/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/netty/NettyRSocketServer.java index 1d93582083b..529705e75bd 100644 --- a/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/netty/NettyRSocketServer.java +++ b/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/netty/NettyRSocketServer.java @@ -22,6 +22,7 @@ import java.time.Duration; import io.rsocket.transport.netty.server.CloseableChannel; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.jspecify.annotations.Nullable; import reactor.core.publisher.Mono; import org.springframework.boot.rsocket.server.RSocketServer; @@ -41,18 +42,18 @@ public class NettyRSocketServer implements RSocketServer { private final Mono starter; - private final Duration lifecycleTimeout; + private final @Nullable Duration lifecycleTimeout; - private CloseableChannel channel; + private @Nullable CloseableChannel channel; - public NettyRSocketServer(Mono starter, Duration lifecycleTimeout) { + public NettyRSocketServer(Mono starter, @Nullable Duration lifecycleTimeout) { Assert.notNull(starter, "'starter' must not be null"); this.starter = starter; this.lifecycleTimeout = lifecycleTimeout; } @Override - public InetSocketAddress address() { + public @Nullable InetSocketAddress address() { if (this.channel != null) { return this.channel.address(); } @@ -62,11 +63,16 @@ public class NettyRSocketServer implements RSocketServer { @Override public void start() throws RSocketServerException { this.channel = block(this.starter, this.lifecycleTimeout); - logger.info("Netty RSocket started on port " + address().getPort()); + InetSocketAddress address = address(); + Assert.state(address != null, "'address' must not be null"); + logger.info("Netty RSocket started on port " + address.getPort()); startDaemonAwaitThread(this.channel); } - private void startDaemonAwaitThread(CloseableChannel channel) { + private void startDaemonAwaitThread(@Nullable CloseableChannel channel) { + if (channel == null) { + return; + } Thread awaitThread = new Thread(() -> channel.onClose().block(), "rsocket"); awaitThread.setContextClassLoader(getClass().getClassLoader()); awaitThread.setDaemon(false); @@ -81,7 +87,7 @@ public class NettyRSocketServer implements RSocketServer { } } - private T block(Mono mono, Duration timeout) { + private @Nullable T block(Mono mono, @Nullable Duration timeout) { return (timeout != null) ? mono.block(timeout) : mono.block(); } diff --git a/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/netty/NettyRSocketServerFactory.java b/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/netty/NettyRSocketServerFactory.java index 02fb798570d..dfacc2e95b3 100644 --- a/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/netty/NettyRSocketServerFactory.java +++ b/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/netty/NettyRSocketServerFactory.java @@ -33,6 +33,7 @@ import io.rsocket.transport.ServerTransport; import io.rsocket.transport.netty.server.CloseableChannel; import io.rsocket.transport.netty.server.TcpServerTransport; import io.rsocket.transport.netty.server.WebsocketServerTransport; +import org.jspecify.annotations.Nullable; import reactor.core.publisher.Mono; import reactor.netty.http.Http11SslContextSpec; import reactor.netty.http.server.HttpServer; @@ -70,21 +71,21 @@ public class NettyRSocketServerFactory implements RSocketServerFactory, Configur private int port = 9898; - private DataSize fragmentSize; + private @Nullable DataSize fragmentSize; - private InetAddress address; + private @Nullable InetAddress address; private RSocketServer.Transport transport = RSocketServer.Transport.TCP; - private ReactorResourceFactory resourceFactory; + private @Nullable ReactorResourceFactory resourceFactory; - private Duration lifecycleTimeout; + private @Nullable Duration lifecycleTimeout; private List rSocketServerCustomizers = new ArrayList<>(); - private Ssl ssl; + private @Nullable Ssl ssl; - private SslBundles sslBundles; + private @Nullable SslBundles sslBundles; @Override public void setPort(int port) { @@ -92,12 +93,12 @@ public class NettyRSocketServerFactory implements RSocketServerFactory, Configur } @Override - public void setFragmentSize(DataSize fragmentSize) { + public void setFragmentSize(@Nullable DataSize fragmentSize) { this.fragmentSize = fragmentSize; } @Override - public void setAddress(InetAddress address) { + public void setAddress(@Nullable InetAddress address) { this.address = address; } @@ -107,12 +108,12 @@ public class NettyRSocketServerFactory implements RSocketServerFactory, Configur } @Override - public void setSsl(Ssl ssl) { + public void setSsl(@Nullable Ssl ssl) { this.ssl = ssl; } @Override - public void setSslBundles(SslBundles sslBundles) { + public void setSslBundles(@Nullable SslBundles sslBundles) { this.sslBundles = sslBundles; } @@ -120,7 +121,7 @@ public class NettyRSocketServerFactory implements RSocketServerFactory, Configur * Set the {@link ReactorResourceFactory} to get the shared resources from. * @param resourceFactory the server resources */ - public void setResourceFactory(ReactorResourceFactory resourceFactory) { + public void setResourceFactory(@Nullable ReactorResourceFactory resourceFactory) { this.resourceFactory = resourceFactory; } @@ -184,13 +185,13 @@ public class NettyRSocketServerFactory implements RSocketServerFactory, Configur httpServer = httpServer.runOn(this.resourceFactory.getLoopResources()); } if (Ssl.isEnabled(this.ssl)) { - httpServer = customizeSslConfiguration(httpServer); + httpServer = customizeSslConfiguration(httpServer, this.ssl); } return WebsocketServerTransport.create(httpServer.bindAddress(this::getListenAddress)); } - private HttpServer customizeSslConfiguration(HttpServer httpServer) { - return new HttpServerSslCustomizer(this.ssl.getClientAuth(), getSslBundle(), getServerNameSslBundles()) + private HttpServer customizeSslConfiguration(HttpServer httpServer, Ssl ssl) { + return new HttpServerSslCustomizer(ssl.getClientAuth(), getSslBundle(), getServerNameSslBundles()) .apply(httpServer); } @@ -211,12 +212,14 @@ public class NettyRSocketServerFactory implements RSocketServerFactory, Configur } protected final Map getServerNameSslBundles() { + Assert.state(this.ssl != null, "'ssl' must not be null"); return this.ssl.getServerNameBundles() .stream() .collect(Collectors.toMap(Ssl.ServerNameSslBundle::serverName, this::getBundle)); } private SslBundle getBundle(ServerNameSslBundle serverNameSslBundle) { + Assert.state(this.sslBundles != null, "'sslBundles' must not be null"); return this.sslBundles.getBundle(serverNameSslBundle.bundle()); } @@ -253,7 +256,7 @@ public class NettyRSocketServerFactory implements RSocketServerFactory, Configur private final SslBundle sslBundle; - private TcpServerSslCustomizer(Ssl.ClientAuth clientAuth, SslBundle sslBundle, + private TcpServerSslCustomizer(Ssl.@Nullable ClientAuth clientAuth, SslBundle sslBundle, Map serverNameSslBundles) { super(Ssl.ClientAuth.map(clientAuth, ClientAuth.NONE, ClientAuth.OPTIONAL, ClientAuth.REQUIRE)); this.sslBundle = sslBundle; @@ -272,7 +275,7 @@ public class NettyRSocketServerFactory implements RSocketServerFactory, Configur private final Map serverNameSslProviders; - private HttpServerSslCustomizer(Ssl.ClientAuth clientAuth, SslBundle sslBundle, + private HttpServerSslCustomizer(Ssl.@Nullable ClientAuth clientAuth, SslBundle sslBundle, Map serverNameSslBundles) { super(Ssl.ClientAuth.map(clientAuth, ClientAuth.NONE, ClientAuth.OPTIONAL, ClientAuth.REQUIRE)); this.sslProvider = createSslProvider(sslBundle); diff --git a/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/netty/package-info.java b/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/netty/package-info.java index 7567b7690e4..614288cf6c5 100644 --- a/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/netty/package-info.java +++ b/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/netty/package-info.java @@ -17,4 +17,7 @@ /** * Reactor Netty based RSocket server implementation. */ +@NullMarked package org.springframework.boot.rsocket.netty; + +import org.jspecify.annotations.NullMarked; diff --git a/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/server/ConfigurableRSocketServerFactory.java b/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/server/ConfigurableRSocketServerFactory.java index 053d7905a0d..d3ccd614ec7 100644 --- a/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/server/ConfigurableRSocketServerFactory.java +++ b/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/server/ConfigurableRSocketServerFactory.java @@ -18,6 +18,8 @@ package org.springframework.boot.rsocket.server; import java.net.InetAddress; +import org.jspecify.annotations.Nullable; + import org.springframework.boot.ssl.SslBundles; import org.springframework.boot.web.server.Ssl; import org.springframework.util.unit.DataSize; @@ -44,13 +46,13 @@ public interface ConfigurableRSocketServerFactory { * @param fragmentSize the fragment size * @since 2.4.0 */ - void setFragmentSize(DataSize fragmentSize); + void setFragmentSize(@Nullable DataSize fragmentSize); /** * Set the specific network address that the server should bind to. * @param address the address to set (defaults to {@code null}) */ - void setAddress(InetAddress address); + void setAddress(@Nullable InetAddress address); /** * Set the transport that the RSocket server should use. @@ -62,13 +64,13 @@ public interface ConfigurableRSocketServerFactory { * Sets the SSL configuration that will be applied to the server's default connector. * @param ssl the SSL configuration */ - void setSsl(Ssl ssl); + void setSsl(@Nullable Ssl ssl); /** * Sets an SSL bundle that can be used to get SSL configuration. * @param sslBundles the SSL bundles * @since 3.1.0 */ - void setSslBundles(SslBundles sslBundles); + void setSslBundles(@Nullable SslBundles sslBundles); } diff --git a/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/server/RSocketServer.java b/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/server/RSocketServer.java index e9c505667ef..5210e7c0709 100644 --- a/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/server/RSocketServer.java +++ b/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/server/RSocketServer.java @@ -18,6 +18,8 @@ package org.springframework.boot.rsocket.server; import java.net.InetSocketAddress; +import org.jspecify.annotations.Nullable; + /** * Simple interface that represents a fully configured RSocket server. Allows the server * to be {@link #start() started} and {@link #stop() stopped}. @@ -45,7 +47,7 @@ public interface RSocketServer { * Return the address this server is listening on. * @return the address */ - InetSocketAddress address(); + @Nullable InetSocketAddress address(); /** * Choice of transport protocol for the RSocket server. diff --git a/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/server/package-info.java b/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/server/package-info.java index e1604cd37c6..58b292c0da2 100644 --- a/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/server/package-info.java +++ b/module/spring-boot-rsocket/src/main/java/org/springframework/boot/rsocket/server/package-info.java @@ -17,4 +17,7 @@ /** * Support for RSocket servers. */ +@NullMarked package org.springframework.boot.rsocket.server; + +import org.jspecify.annotations.NullMarked;