Skip to content

MappingRelationalConverter fails with IllegalStateException when read conversion returns null #2217

@cwatzl

Description

@cwatzl

I am trying to migrate an existing application from Spring Data JDBC 3.x to 4.0.

I have a legacy MSSQL schema that I can't change, where some numeric values are encoded as char type, like so:

CREATE TABLE my_item (
  id bigint primary key,
  quantity varchar(50)
);

Mapped to something like:

@Data
public class MyItem {
  @Id
  Long id;
  
  @Nullable
  Integer quantity;
}

The SQL table may contain blank strings in quantity.

In 3.x, this was converted to null when reading from the table. The application relies on that behavior.
However, in 4.x, This gets me:

Converted must not be null
java.lang.IllegalStateException: Converted must not be null
	at org.springframework.util.Assert.state(Assert.java:80)
	at org.springframework.data.relational.core.conversion.MappingRelationalConverter.getPotentiallyConvertedSimpleRead(MappingRelationalConverter.java:690)
	at org.springframework.data.jdbc.core.convert.MappingJdbcConverter.readValue(MappingJdbcConverter.java:229)
	at org.springframework.data.relational.core.conversion.MappingRelationalConverter.readProperties(MappingRelationalConverter.java:586)
	at org.springframework.data.relational.core.conversion.MappingRelationalConverter.populateProperties(MappingRelationalConverter.java:551)
	at org.springframework.data.relational.core.conversion.MappingRelationalConverter.read(MappingRelationalConverter.java:487)
	at org.springframework.data.relational.core.conversion.MappingRelationalConverter.readAggregate(MappingRelationalConverter.java:376)
	at org.springframework.data.relational.core.conversion.MappingRelationalConverter.readAggregate(MappingRelationalConverter.java:334)

Apparently, since 4.x, as soon as type conversion is performed (e.g. from a string type to a boxed Integer), the conversion result can not be null, no matter whether the target type is nullable.

I also tried to register a custom converter for String -> Integer that explicitly converts blank to null, but even that will cause the same assertion IllegalStateException.

The JavaDoc of MappingRelationalConverter.getPotentiallyConvertedSimpleRead states that it "might return null", however, this is seems to be a lie, as it will now raise an IllegalStateException when the conversion result is null. It seems to me that this behavior is not quite intentional, since the JavaDoc contradicts the implementation.

Reproducer: https://github.com/cwatzl/data-jdbc-issue-2217

JSpecify @Nullable annotations on the affected fields have no effect either. As a workaround, I could wrap all affected properties into Optional. This is, however, bad practice according to conventional wisdom, and flagged as such by static code analysis tools. Also it's clunky, and not idiomatic for Kotlin.

Metadata

Metadata

Assignees

Labels

type: regressionA regression from a previous release

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions