Skip to content

Commit 2f851e9

Browse files
97 implement null handling with jspecify (#120)
* - Added jspecify to pom.xml - @NullMarked to src/main/java/org/example - Checked all files in example for handling null return values. * - @NullMarked to src/main/java/org/example/config - Checked all files for handling null return values * - Added @NullMarked to src/main/java/org/example/filter package - Checked all files for handling null return values * - Added @NullMarked to src/main/java/org/example/http package - Checked all files for handling null return values * - Added @NullMarked to src/main/java/org/example/httpparser package - Checked all files for handling null return values * - Added @NullMarked to src/main/java/org/example/server package - Checked all files for handling null return values * - Added @NullMarked to src/test/java/org/example package - Checked all files for handling null return values * - Added @NullMarked to src/test/java/org/example/config package - Checked ConfigLoaderTest for null handling * - Added @NullMarked to src/test/java/org/example/filter package - Checked all tests for null handling - Marked body in HttpRequest parameters as nullable to satisfy tests in CompressionFilterTest. - Marked ip parameters for normalizeIp, addBlockedIp and addAllowedIp to be Nullable since they work as intended but warnings need to be suppressed. -Added @nullable to request parameter for doFilter in LocaleFilter since it is handled. * - Added @NullMarked to src/test/java/org/example/http package - Checked all tests for null handling - Marked filename parameter in detectMimeType as Nullable since it's handled. * - Added @NullMarked to src/test/java/org/example/httpparser package - Checked all tests for null handling - Marked "in" parameter for setReader in HttpParser as nullable since it is handled. * - Added @NullMarked to src/test/java/org/example/server package - Checked ConfigurableFilterPipelineTest for null handling - Marked the routePatterns parameter in the FilterRegistration record in FilterRegistration.java since it is safely null handled. * Applied suggested CodeRabbit fixes to Major Issues regarding null markings and null handling. * CodeRabbit test went against intended outcome of test. Rollbacked change to SetReader in HttpParser * - LocaleFilteR: Moved @nullable from doFilter request parameter to resolveLocale request parameter since resolveLocale does the actual null handling. - Removed testParserThrowErrorWhenNull test since it is made redundant by jspecify null marking. * - Fixed compilation errors. - Tests and compilation run without issue on my local setup now.
1 parent f9c69a4 commit 2f851e9

22 files changed

Lines changed: 74 additions & 24 deletions

pom.xml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@
1515
<assertj.core.version>3.27.7</assertj.core.version>
1616
<mockito.version>5.21.0</mockito.version>
1717
<bucket4j.version>8.14.0</bucket4j.version>
18-
1918
</properties>
20-
2119
<dependencies>
2220
<dependency>
2321
<groupId>com.bucket4j</groupId>
@@ -70,14 +68,17 @@
7068
<artifactId>brotli4j</artifactId>
7169
<version>1.20.0</version>
7270
</dependency>
73-
71+
<dependency>
72+
<groupId>org.jspecify</groupId>
73+
<artifactId>jspecify</artifactId>
74+
<version>1.0.0</version>
75+
</dependency>
7476
<dependency>
7577
<groupId>ch.qos.logback</groupId>
7678
<artifactId>logback-classic</artifactId>
7779
<version>1.5.32</version>
7880
<scope>compile</scope>
7981
</dependency>
80-
8182
</dependencies>
8283
<build>
8384
<plugins>

src/main/java/org/example/App.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
import org.example.config.AppConfig;
44
import org.example.config.ConfigLoader;
5+
import org.jspecify.annotations.Nullable;
56

6-
import java.net.Socket;
77
import java.nio.file.Path;
88

99
public class App {
@@ -30,7 +30,7 @@ static int resolvePort(String[] args, int configPort) {
3030
return validatePort(configPort, "configuration server.port");
3131
}
3232

33-
static Integer parsePortFromCli(String[] args) {
33+
static @Nullable Integer parsePortFromCli(String[] args) {
3434
if (args == null) return null;
3535

3636
for (int i = 0; i < args.length; i++) {
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
@NullMarked
2+
package org.example.config;
3+
4+
import org.jspecify.annotations.NullMarked;

src/main/java/org/example/filter/CompressionFilter.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import org.example.http.HttpResponseBuilder;
55
import org.example.httpparser.HttpRequest;
66
import com.aayushatharva.brotli4j.encoder.Encoder;
7+
import org.jspecify.annotations.Nullable;
78

89
import java.io.ByteArrayOutputStream;
910
import java.io.IOException;
@@ -186,7 +187,7 @@ private boolean shouldCompress(String contentType) {
186187
baseType.startsWith("text/");
187188
}
188189

189-
private String getHeader(HttpRequest request, String headerName) {
190+
private @Nullable String getHeader(HttpRequest request, String headerName) {
190191
Map<String, String> headers = request.getHeaders();
191192

192193
String value = headers.get(headerName);

src/main/java/org/example/filter/IpFilter.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import org.example.http.HttpResponseBuilder;
55
import org.example.httpparser.HttpRequest;
6+
import org.jspecify.annotations.Nullable;
67

78
import java.util.Set;
89
import java.util.concurrent.ConcurrentHashMap;
@@ -84,22 +85,22 @@ private boolean isIpAllowed(String ip) {
8485
* @param ip the IP address
8586
* @return the trimmed IP address, or {@code null} if the input is {@code null}
8687
*/
87-
private String normalizeIp(String ip) {
88+
private @Nullable String normalizeIp(@Nullable String ip) {
8889
return ip == null ? null : ip.trim();
8990
}
9091

9192
public void setMode(FilterMode mode) {
9293
this.mode = mode;
9394
}
9495

95-
public void addBlockedIp(String ip) {
96+
public void addBlockedIp(@Nullable String ip) {
9697
if (ip == null) {
9798
throw new IllegalArgumentException("IP address cannot be null");
9899
}
99100
blockedIps.add(normalizeIp(ip));
100101
}
101102

102-
public void addAllowedIp(String ip) {
103+
public void addAllowedIp(@Nullable String ip) {
103104
if (ip == null) {
104105
throw new IllegalArgumentException("IP address cannot be null");
105106
}

src/main/java/org/example/filter/LocaleFilter.java

Whitespace-only changes.

src/main/java/org/example/filter/LocaleFilterWithCookie.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import org.example.http.HttpResponseBuilder;
44
import org.example.httpparser.HttpRequest;
5+
import org.jspecify.annotations.Nullable;
56

67
import java.util.Map;
78

@@ -74,7 +75,7 @@ private String resolveLocale(HttpRequest request) {
7475
* <p>
7576
* If the cookie header is missing, blank, or malformed, returns null.
7677
*/
77-
private String extractLocaleFromCookie(HttpRequest request) {
78+
private @Nullable String extractLocaleFromCookie(HttpRequest request) {
7879
Map<String, String> headers = request.getHeaders();
7980
if (headers == null) {
8081
return null;
@@ -111,7 +112,7 @@ private String extractLocaleFromCookie(HttpRequest request) {
111112
* If the header is missing, blank, or malformed, returns null.
112113
* The first language tag is used and any optional quality value (e.g., ";q=0.9") is stripped.
113114
*/
114-
private String extractLocaleFromHeader(HttpRequest request) {
115+
private @Nullable String extractLocaleFromHeader(HttpRequest request) {
115116
Map<String, String> headers = request.getHeaders();
116117
if (headers == null) {
117118
return null;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
@NullMarked
2+
package org.example.filter;
3+
4+
import org.jspecify.annotations.NullMarked;

src/main/java/org/example/http/MimeTypeDetector.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.example.http;
22

3+
import org.jspecify.annotations.Nullable;
4+
35
import java.util.Map;
46

57
/**
@@ -56,7 +58,7 @@ private MimeTypeDetector() {
5658
*/
5759

5860

59-
public static String detectMimeType(String filename) {
61+
public static String detectMimeType(@Nullable String filename) {
6062

6163
String octet = "application/octet-stream";
6264

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

0 commit comments

Comments
 (0)