Skip to content

Conversation

cppwfs
Copy link
Contributor

@cppwfs cppwfs commented Sep 8, 2025

Related to: #10083

  • Add Nullability support to support.management package
  • Add Nullability support to support.management.micrometer package
  • Add Nullability support to support.management.observation
  • Add Nullability support to support.json

Object correlationId = message.getHeaders().getId();
AtomicInteger sequenceNumber = new AtomicInteger(1);

Assert.state(correlationId != null, "Correlation ID must not be null.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is redundant here.
The createBuilder() can accept it as null.
And then e have a check at the applySequence condition.

* @see IntegrationMessageHeaderAccessor#isReadOnly(String)
*/
@SuppressWarnings("NullAway") // Dataflow analysis limitation
public B readOnlyHeaders(@Nullable String... readOnlyHeaders) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This @Nullable is at wrong place.
Has to be next to ellipsis.
Therefore private String @Nullable [] readOnlyHeaders;
Then everything else in this class should be fixed well.

* @since 4.3.2
*/
@SuppressWarnings("NullAway") // Dataflow analysis limitation
public void setReadOnlyHeaders(@Nullable String... readOnlyHeaders) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DITTO

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missed to fix properly: setReadOnlyHeaders(String @Nullable ... readOnlyHeaders)

* @param role the role.
*/
public void startLifecyclesInRole(String role) {
public void startLifecyclesInRole(@Nullable String role) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is wrong.
This is not possible by the logic of this API.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On line 321 startLifecyclesInRole is used and a nullable value can be passed in. Do we add a Assert.state prior to line 321?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's revise that AbstractLeaderEvent instead!
Remove AbstractLeaderEvent(Object source) ctor as it is out of use.
Looks like the other ctor is never used with null.

}
Assert.notNull(headers, error);

Assert.state(payload != null, () -> "Payload must not be null");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class is marked for removal.
So, it is OK to not spend any time on it and just mark the whole class with NullAway.

private final String[] trustedPackages;

@SuppressWarnings("NullAway") // Dataflow analysis limitation
AllowListTypeResolverBuilder(String... trustedPackages) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

String @Nullable ... instead.


default <T> T fromJson(Object json, Class<T> valueType) throws IOException {
@Nullable
default <T> T fromJson(@Nullable Object json, Class<T> valueType) throws IOException {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How that happened that we allow null over here?
Doesn't looks like Jackson accepts such a behavior:

    public <T> T readValue(String content, JavaType valueType) throws JacksonException
    {
        _assertNotNull("content", content);

Please, revise all the places which put a null for this API.

replyBuilder = (responseBody instanceof Message<?>)
? messageBuilderFactory.fromMessage((Message<?>) responseBody)
: messageBuilderFactory.withPayload(responseBody); // NOSONAR - hasBody()
Assert.state(responseBody != null, "The response body must not be null");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not correct. The httpResponse.hasBody() does cover this.
Please, revise. Perhaps in favor of NullAway

}

protected abstract <T> T fromJson(Object json, J type) throws IOException;
protected abstract <T> T fromJson(@Nullable Object json, J type) throws IOException;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, revise these from methods.
No null is allowed.

@cppwfs cppwfs force-pushed the GH-10083-core-support branch 2 times, most recently from 5ff7320 to fc29e23 Compare September 8, 2025 20:01
* @since 4.3.2
*/
@SuppressWarnings("NullAway") // Dataflow analysis limitation
public void setReadOnlyHeaders(@Nullable String... readOnlyHeaders) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missed to fix properly: setReadOnlyHeaders(String @Nullable ... readOnlyHeaders)

@Override
public void onApplicationEvent(AbstractLeaderEvent event) {
if (event instanceof OnGrantedEvent) {
Assert.state(event.getRole() != null, "A role is required");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's not what I meant.
That AbstractLeaderEvent has to be fixed to not accept (and produce) nulls at all.
Thanks

* @param role the role.
*/
public void stopLifecyclesInRole(String role) {
public void stopLifecyclesInRole(@Nullable String role) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Therefore, same here: no null allowed.

public class DefaultMessageBuilderFactory implements MessageBuilderFactory {

private String[] readOnlyHeaders;
@SuppressWarnings("NullAway.Init")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the property is nullable, then this suppression is redundant.

private volatile boolean modified;

private String[] readOnlyHeaders;
@SuppressWarnings("NullAway.Init")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this, please.

* @see IntegrationMessageHeaderAccessor#isReadOnly(String)
*/
public B readOnlyHeaders(@Nullable String... readOnlyHeaders) {
public B readOnlyHeaders(String... readOnlyHeaders) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put @Nullable next to ellipsis.

public <T> MessageBuilder<T> fromMessage(Message<T> message) {
return MessageBuilder.fromMessage(message)
.readOnlyHeaders(this.readOnlyHeaders);
if (this.readOnlyHeaders != null) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When you fix BaseMessageBuilder, then this change has to be reverted.

public <T> MessageBuilder<T> withPayload(T payload) {
return MessageBuilder.withPayload(payload)
.readOnlyHeaders(this.readOnlyHeaders);
if (this.readOnlyHeaders != null) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DITTO

if (!ObjectUtils.isEmpty(this.readOnlyHeaders)) {
for (String readOnly : this.readOnlyHeaders) {
if (headers.containsKey(readOnly)) {
if (readOnly != null && headers.containsKey(readOnly)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not reflect reality.
The String @Nullable [] is about the whole array being null.
To reflect that individual items could be null, too, we have to make it like:

@Nullable String @Nullable []

But that is not our case.
Therefore this != null is not true.

}

private boolean containsReadOnly(MessageHeaders headers) {
if (!ObjectUtils.isEmpty(this.readOnlyHeaders)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's change this to != null to remove that @SuppressWarnings("NullAway.Init") on the property.

cppwfs and others added 4 commits September 8, 2025 17:13
Related to:  spring-projects#10083
* Add Nullability support to support.management package
* Add Nullability support to support.management.micrometer package
* Add Nullability support to  support.management.observation
* Add Nullability support to  support.json
* Disabled null checks in Deprecated Jackson2 classes

Remove Nullable from Jackson2 classes
Remove unnecessary if statements following review
@cppwfs cppwfs force-pushed the GH-10083-core-support branch from febeea9 to d0f07eb Compare September 8, 2025 21:15
@artembilan artembilan merged commit 448cee7 into spring-projects:main Sep 8, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants