Skip to content

Commit 634933b

Browse files
committed
Polish nullability annotations
See gh-46926
1 parent 5ca904c commit 634933b

File tree

12 files changed

+103
-63
lines changed

12 files changed

+103
-63
lines changed

core/spring-boot/src/main/java/org/springframework/boot/json/JsonValueWriter.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ else if (value instanceof Number || value instanceof Boolean) {
149149
}
150150
}
151151

152-
private <V> boolean canWriteAsArray(Iterable<?> iterable) {
152+
private boolean canWriteAsArray(Iterable<?> iterable) {
153153
return !(iterable instanceof Path);
154154
}
155155

@@ -349,7 +349,8 @@ private String processName(String name, NameProcessor nameProcessor) {
349349
// Lambda isn't detected with the correct nullability
350350
@SuppressWarnings({ "unchecked", "NullAway" })
351351
private <V> @Nullable V processValue(@Nullable V value, ValueProcessor<?> valueProcessor) {
352-
return (V) LambdaSafe.callback(ValueProcessor.class, valueProcessor, this.path, new Object[] { value })
352+
return (V) LambdaSafe
353+
.callback(ValueProcessor.class, valueProcessor, this.path, new @Nullable Object[] { value })
353354
.invokeAnd((call) -> call.processValue(this.path, value))
354355
.get(value);
355356
}
@@ -389,7 +390,7 @@ private final class ActiveSeries {
389390

390391
private int index;
391392

392-
private Set<String> names = new HashSet<>();
393+
private final Set<String> names = new HashSet<>();
393394

394395
private ActiveSeries(Series series) {
395396
this.series = series;

core/spring-boot/src/main/java/org/springframework/boot/json/JsonWriter.java

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import java.util.function.Supplier;
3030
import java.util.function.UnaryOperator;
3131

32+
import org.jspecify.annotations.NonNull;
3233
import org.jspecify.annotations.Nullable;
3334

3435
import org.springframework.boot.json.JsonValueWriter.Series;
@@ -118,9 +119,9 @@ default JsonWriter<T> withNewLineAtEnd() {
118119
* Return a new {@link JsonWriter} instance that appends the given suffix after the
119120
* JSON has been written.
120121
* @param suffix the suffix to write, if any
121-
* @return a new {@link JsonWriter} instance that appends a suffixafter the JSON
122+
* @return a new {@link JsonWriter} instance that appends a suffix after the JSON
122123
*/
123-
default JsonWriter<T> withSuffix(String suffix) {
124+
default JsonWriter<T> withSuffix(@Nullable String suffix) {
124125
if (!StringUtils.hasLength(suffix)) {
125126
return this;
126127
}
@@ -221,7 +222,7 @@ public <V> Member<V> add(String name, @Nullable V value) {
221222
* @param supplier a supplier of the value
222223
* @return the added {@link Member} which may be configured further
223224
*/
224-
public <V> Member<V> add(String name, Supplier<V> supplier) {
225+
public <V> Member<V> add(String name, Supplier<@Nullable V> supplier) {
225226
Assert.notNull(supplier, "'supplier' must not be null");
226227
return add(name, (instance) -> supplier.get());
227228
}
@@ -233,7 +234,7 @@ public <V> Member<V> add(String name, Supplier<V> supplier) {
233234
* @param extractor {@link Extractor} to extract the value
234235
* @return the added {@link Member} which may be configured further
235236
*/
236-
public <V> Member<V> add(String name, Extractor<T, ? extends @Nullable V> extractor) {
237+
public <V> Member<V> add(String name, Extractor<T, V> extractor) {
237238
Assert.notNull(name, "'name' must not be null");
238239
Assert.notNull(extractor, "'extractor' must not be null");
239240
return addMember(name, extractor);
@@ -268,7 +269,7 @@ public <M extends Map<K, V>, K, V> Member<M> addMapEntries(Extractor<T, M> extra
268269
* @param value the member value
269270
* @return the added {@link Member} which may be configured further
270271
*/
271-
public <V> Member<V> from(V value) {
272+
public <V> Member<V> from(@Nullable V value) {
272273
return from((instance) -> value);
273274
}
274275

@@ -279,7 +280,7 @@ public <V> Member<V> from(V value) {
279280
* @param supplier a supplier of the value
280281
* @return the added {@link Member} which may be configured further
281282
*/
282-
public <V> Member<V> from(Supplier<V> supplier) {
283+
public <V> Member<V> from(Supplier<@Nullable V> supplier) {
283284
Assert.notNull(supplier, "'supplier' must not be null");
284285
return from((instance) -> supplier.get());
285286
}
@@ -323,7 +324,7 @@ public void applyingValueProcessor(ValueProcessor<?> valueProcessor) {
323324
this.jsonProcessors.valueProcessors().add(valueProcessor);
324325
}
325326

326-
private <V> Member<V> addMember(@Nullable String name, Extractor<T, ? extends @Nullable V> extractor) {
327+
private <V> Member<V> addMember(@Nullable String name, Extractor<T, V> extractor) {
327328
Member<V> member = new Member<>(this.members.size(), name, ValueExtractor.of(extractor));
328329
this.members.add(member);
329330
return member;
@@ -396,7 +397,7 @@ public Member<T> whenNotNull() {
396397
* @param extractor an function used to extract the value to test
397398
* @return a {@link Member} which may be configured further
398399
*/
399-
public Member<T> whenNotNull(Function<T, ?> extractor) {
400+
public Member<T> whenNotNull(Function<@Nullable T, ?> extractor) {
400401
Assert.notNull(extractor, "'extractor' must not be null");
401402
return when((instance) -> Objects.nonNull(extractor.apply(instance)));
402403
}
@@ -417,15 +418,16 @@ public Member<T> whenHasLength() {
417418
* @return a {@link Member} which may be configured further
418419
*/
419420
public Member<T> whenNotEmpty() {
420-
return whenNot(ObjectUtils::isEmpty);
421+
Predicate<@Nullable T> isEmpty = ObjectUtils::isEmpty;
422+
return whenNot(isEmpty);
421423
}
422424

423425
/**
424426
* Only include this member when the given predicate does not match.
425427
* @param predicate the predicate to test
426428
* @return a {@link Member} which may be configured further
427429
*/
428-
public Member<T> whenNot(Predicate<T> predicate) {
430+
public Member<T> whenNot(Predicate<@Nullable T> predicate) {
429431
Assert.notNull(predicate, "'predicate' must not be null");
430432
return when(predicate.negate());
431433
}
@@ -448,7 +450,7 @@ public Member<T> when(Predicate<? super @Nullable T> predicate) {
448450
* @return a {@link Member} which may be configured further
449451
*/
450452
@SuppressWarnings("unchecked")
451-
public <R> Member<R> as(Extractor<T, ? extends @Nullable R> extractor) {
453+
public <R> Member<R> as(Extractor<T, R> extractor) {
452454
Assert.notNull(extractor, "'adapter' must not be null");
453455
Member<R> result = (Member<R>) this;
454456
result.valueExtractor = this.valueExtractor.as(extractor::extract);
@@ -688,7 +690,7 @@ public String toString() {
688690
* @param <T> the member type
689691
*/
690692
@FunctionalInterface
691-
interface ValueExtractor<T> {
693+
interface ValueExtractor<T extends @Nullable Object> {
692694

693695
/**
694696
* Represents a skipped value.
@@ -722,7 +724,7 @@ default ValueExtractor<T> when(Predicate<? super @Nullable T> predicate) {
722724
* @param extractor the extractor to use
723725
* @return a new {@link ValueExtractor}
724726
*/
725-
default <R> ValueExtractor<R> as(Extractor<T, ? extends @Nullable R> extractor) {
727+
default <R> ValueExtractor<R> as(Extractor<T, R> extractor) {
726728
return (instance) -> apply(extract(instance), extractor);
727729
}
728730

@@ -946,7 +948,7 @@ interface NameProcessor {
946948
* @param existingName the existing and possibly already processed name.
947949
* @return the new name
948950
*/
949-
String processName(MemberPath path, String existingName);
951+
@Nullable String processName(MemberPath path, String existingName);
950952

951953
/**
952954
* Factory method to create a new {@link NameProcessor} for the given operation.
@@ -969,15 +971,15 @@ static NameProcessor of(UnaryOperator<String> operation) {
969971
* @param <T> the value type
970972
*/
971973
@FunctionalInterface
972-
interface ValueProcessor<T> {
974+
interface ValueProcessor<T extends @Nullable Object> {
973975

974976
/**
975977
* Process the value at the given path.
976978
* @param path the path of the member containing the value
977979
* @param value the value being written (may be {@code null})
978980
* @return the processed value
979981
*/
980-
T processValue(MemberPath path, T value);
982+
@Nullable T processValue(MemberPath path, @Nullable T value);
981983

982984
/**
983985
* Return a new processor from this one that only applied to members with the
@@ -1018,7 +1020,8 @@ default ValueProcessor<T> whenHasPath(Predicate<MemberPath> predicate) {
10181020
* type.
10191021
*/
10201022
default ValueProcessor<T> whenInstanceOf(Class<?> type) {
1021-
return when(type::isInstance);
1023+
Predicate<@Nullable T> isInstance = type::isInstance;
1024+
return when(isInstance);
10221025
}
10231026

10241027
/**
@@ -1028,7 +1031,7 @@ default ValueProcessor<T> whenInstanceOf(Class<?> type) {
10281031
* @return a new {@link ValueProcessor} that only applies when the predicate
10291032
* matches
10301033
*/
1031-
default ValueProcessor<T> when(Predicate<T> predicate) {
1034+
default ValueProcessor<T> when(Predicate<@Nullable T> predicate) {
10321035
return (name, value) -> (predicate.test(value)) ? processValue(name, value) : value;
10331036
}
10341037

@@ -1040,7 +1043,7 @@ default ValueProcessor<T> when(Predicate<T> predicate) {
10401043
* @param action the action to apply
10411044
* @return a new {@link ValueProcessor} instance
10421045
*/
1043-
static <T> ValueProcessor<T> of(Class<? extends T> type, UnaryOperator<T> action) {
1046+
static <T> ValueProcessor<T> of(Class<? extends T> type, UnaryOperator<@Nullable T> action) {
10441047
return of(action).whenInstanceOf(type);
10451048
}
10461049

@@ -1051,7 +1054,7 @@ static <T> ValueProcessor<T> of(Class<? extends T> type, UnaryOperator<T> action
10511054
* @param action the action to apply
10521055
* @return a new {@link ValueProcessor} instance
10531056
*/
1054-
static <T> ValueProcessor<T> of(UnaryOperator<T> action) {
1057+
static <T> ValueProcessor<T> of(UnaryOperator<@Nullable T> action) {
10551058
Assert.notNull(action, "'action' must not be null");
10561059
return (name, value) -> action.apply(value);
10571060
}
@@ -1065,14 +1068,14 @@ static <T> ValueProcessor<T> of(UnaryOperator<T> action) {
10651068
* @param <R> the result type
10661069
*/
10671070
@FunctionalInterface
1068-
interface Extractor<T, R> {
1071+
interface Extractor<T extends @Nullable Object, R extends @Nullable Object> {
10691072

10701073
/**
10711074
* Extract from the given value.
10721075
* @param value the source value (never {@code null})
10731076
* @return an extracted value or {@code null}
10741077
*/
1075-
@Nullable R extract(T value);
1078+
@Nullable R extract(@NonNull T value);
10761079

10771080
}
10781081

core/spring-boot/src/main/java/org/springframework/boot/logging/log4j2/GraylogExtendedLogFormatStructuredLogFormatter.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818

1919
import java.math.BigDecimal;
2020
import java.util.Set;
21-
import java.util.function.BinaryOperator;
21+
import java.util.function.Function;
22+
import java.util.function.Predicate;
2223
import java.util.regex.Pattern;
2324

2425
import org.apache.commons.logging.Log;
@@ -37,6 +38,7 @@
3738
import org.springframework.boot.logging.StackTracePrinter;
3839
import org.springframework.boot.logging.structured.CommonStructuredLogFormat;
3940
import org.springframework.boot.logging.structured.ContextPairs;
41+
import org.springframework.boot.logging.structured.ContextPairs.Joiner;
4042
import org.springframework.boot.logging.structured.GraylogExtendedLogFormatProperties;
4143
import org.springframework.boot.logging.structured.JsonWriterStructuredLogFormatter;
4244
import org.springframework.boot.logging.structured.StructuredLogFormatter;
@@ -91,12 +93,15 @@ private static void jsonMembers(Environment environment, @Nullable StackTracePri
9193
members.add("_process_thread_name", LogEvent::getThreadName);
9294
GraylogExtendedLogFormatProperties.get(environment).jsonMembers(members);
9395
members.add("_log_logger", LogEvent::getLoggerName);
96+
Predicate<@Nullable ReadOnlyStringMap> mapIsEmpty = (map) -> map == null || map.isEmpty();
9497
members.from(LogEvent::getContextData)
95-
.whenNot(ReadOnlyStringMap::isEmpty)
98+
.whenNot(mapIsEmpty)
9699
.usingPairs(contextPairs.flat(additionalFieldJoiner(),
97100
GraylogExtendedLogFormatStructuredLogFormatter::addContextDataPairs));
101+
Function<@Nullable LogEvent, @Nullable Object> getThrownProxy = (event) -> (event != null)
102+
? event.getThrownProxy() : null;
98103
members.add()
99-
.whenNotNull(LogEvent::getThrownProxy)
104+
.whenNotNull(getThrownProxy)
100105
.usingMembers((thrownProxyMembers) -> throwableMembers(thrownProxyMembers, extractor));
101106
}
102107

@@ -140,7 +145,7 @@ private static void addContextDataPairs(ContextPairs.Pairs<ReadOnlyStringMap> co
140145
contextPairs.add((contextData, pairs) -> contextData.forEach(pairs::accept));
141146
}
142147

143-
private static BinaryOperator<@Nullable String> additionalFieldJoiner() {
148+
private static Joiner additionalFieldJoiner() {
144149
return (prefix, name) -> {
145150
name = prefix + name;
146151
if (!FIELD_NAME_VALID_PATTERN.matcher(name).matches()) {

core/spring-boot/src/main/java/org/springframework/boot/logging/log4j2/LogstashStructuredLogFormatter.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.time.format.DateTimeFormatter;
2222
import java.util.Set;
2323
import java.util.TreeSet;
24+
import java.util.function.Predicate;
2425

2526
import org.apache.logging.log4j.Level;
2627
import org.apache.logging.log4j.Marker;
@@ -61,13 +62,15 @@ private static void jsonMembers(@Nullable StackTracePrinter stackTracePrinter, C
6162
members.add("thread_name", LogEvent::getThreadName);
6263
members.add("level", LogEvent::getLevel).as(Level::name);
6364
members.add("level_value", LogEvent::getLevel).as(Level::intLevel);
65+
Predicate<@Nullable ReadOnlyStringMap> mapIsEmpty = (map) -> map == null || map.isEmpty();
6466
members.from(LogEvent::getContextData)
65-
.whenNot(ReadOnlyStringMap::isEmpty)
67+
.whenNot(mapIsEmpty)
6668
.usingPairs(contextPairs.flat("_", LogstashStructuredLogFormatter::addContextDataPairs));
69+
Predicate<@Nullable Set<String>> collectionIsEmpty = CollectionUtils::isEmpty;
6770
members.add("tags", LogEvent::getMarker)
6871
.whenNotNull()
6972
.as(LogstashStructuredLogFormatter::getMarkers)
70-
.whenNot(CollectionUtils::isEmpty);
73+
.whenNot(collectionIsEmpty);
7174
members.add("stack_trace", LogEvent::getThrownProxy).whenNotNull().as(extractor::stackTrace);
7275
}
7376

core/spring-boot/src/main/java/org/springframework/boot/logging/logback/ElasticCommonSchemaStructuredLogFormatter.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.List;
2121
import java.util.Set;
2222
import java.util.TreeSet;
23+
import java.util.function.Function;
2324

2425
import ch.qos.logback.classic.pattern.ThrowableProxyConverter;
2526
import ch.qos.logback.classic.spi.ILoggingEvent;
@@ -77,7 +78,9 @@ private static void jsonMembers(Environment environment, @Nullable StackTracePri
7778
pairs.addMapEntries(ILoggingEvent::getMDCPropertyMap);
7879
pairs.add(ILoggingEvent::getKeyValuePairs, keyValuePairExtractor);
7980
}));
80-
members.add().whenNotNull(ILoggingEvent::getThrowableProxy).usingMembers((throwableMembers) -> {
81+
Function<@Nullable ILoggingEvent, @Nullable Object> getThrowableProxy = (event) -> (event != null)
82+
? event.getThrowableProxy() : null;
83+
members.add().whenNotNull(getThrowableProxy).usingMembers((throwableMembers) -> {
8184
throwableMembers.add("error").usingMembers((error) -> {
8285
error.add("type", ILoggingEvent::getThrowableProxy).as(IThrowableProxy::getClassName);
8386
error.add("message", ILoggingEvent::getThrowableProxy).as(IThrowableProxy::getMessage);

core/spring-boot/src/main/java/org/springframework/boot/logging/logback/GraylogExtendedLogFormatStructuredLogFormatter.java

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

1919
import java.math.BigDecimal;
2020
import java.util.Set;
21-
import java.util.function.BinaryOperator;
21+
import java.util.function.Function;
2222
import java.util.regex.Pattern;
2323

2424
import ch.qos.logback.classic.pattern.ThrowableProxyConverter;
@@ -37,6 +37,7 @@
3737
import org.springframework.boot.logging.StackTracePrinter;
3838
import org.springframework.boot.logging.structured.CommonStructuredLogFormat;
3939
import org.springframework.boot.logging.structured.ContextPairs;
40+
import org.springframework.boot.logging.structured.ContextPairs.Joiner;
4041
import org.springframework.boot.logging.structured.GraylogExtendedLogFormatProperties;
4142
import org.springframework.boot.logging.structured.JsonWriterStructuredLogFormatter;
4243
import org.springframework.boot.logging.structured.StructuredLogFormatter;
@@ -100,8 +101,10 @@ private static void jsonMembers(Environment environment, @Nullable StackTracePri
100101
pairs.addMapEntries(ILoggingEvent::getMDCPropertyMap);
101102
pairs.add(ILoggingEvent::getKeyValuePairs, keyValuePairExtractor);
102103
}));
104+
Function<@Nullable ILoggingEvent, @Nullable Object> getThrowableProxy = (event) -> (event != null)
105+
? event.getThrowableProxy() : null;
103106
members.add()
104-
.whenNotNull(ILoggingEvent::getThrowableProxy)
107+
.whenNotNull(getThrowableProxy)
105108
.usingMembers((throwableMembers) -> throwableMembers(throwableMembers, extractor));
106109
}
107110

@@ -128,7 +131,7 @@ private static void throwableMembers(Members<ILoggingEvent> members, Extractor e
128131
members.add("_error_message", ILoggingEvent::getThrowableProxy).as(IThrowableProxy::getMessage);
129132
}
130133

131-
private static BinaryOperator<@Nullable String> additionalFieldJoiner() {
134+
private static Joiner additionalFieldJoiner() {
132135
return (prefix, name) -> {
133136
name = prefix + name;
134137
if (!FIELD_NAME_VALID_PATTERN.matcher(name).matches()) {

core/spring-boot/src/main/java/org/springframework/boot/logging/logback/LogstashStructuredLogFormatter.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import java.util.LinkedHashSet;
2525
import java.util.List;
2626
import java.util.Set;
27+
import java.util.function.Function;
2728

2829
import ch.qos.logback.classic.Level;
2930
import ch.qos.logback.classic.pattern.ThrowableProxyConverter;
@@ -76,9 +77,9 @@ private static void jsonMembers(@Nullable StackTracePrinter stackTracePrinter, C
7677
.whenNotNull()
7778
.as(LogstashStructuredLogFormatter::getMarkers)
7879
.whenNotEmpty();
79-
members.add("stack_trace", (event) -> event)
80-
.whenNotNull(ILoggingEvent::getThrowableProxy)
81-
.as(extractor::stackTrace);
80+
Function<@Nullable ILoggingEvent, @Nullable Object> getThrowableProxy = (event) -> (event != null)
81+
? event.getThrowableProxy() : null;
82+
members.add("stack_trace", (event) -> event).whenNotNull(getThrowableProxy).as(extractor::stackTrace);
8283
}
8384

8485
private static String asTimestamp(Instant instant) {

0 commit comments

Comments
 (0)