Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Empty collection not converted to correct type when using element-wise converters #796

Closed
jurriaan opened this issue Nov 7, 2022 · 1 comment
Assignees
Labels
type: bug A general bug

Comments

@jurriaan
Copy link

jurriaan commented Nov 7, 2022

We're using java Duration types that get converted to Interval using Reading/WritingConverters:

@WritingConverter
object DurationToIntervalConverter : Converter<Duration, Interval> {
    override fun convert(source: Duration): Interval = Interval.of(source)
}

This seems to work fine for columns of type Duration, however it does not work on List<Duration> when that list is an empty list.
When trying to persist an empty list I get the following error:

java.lang.IllegalArgumentException: Cannot encode parameter of type [Ljava.time.Duration; ([Ljava.time.Duration;@45b7445b)
	at io.r2dbc.postgresql.codec.DefaultCodecs.encodeParameterValue(DefaultCodecs.java:276)
	at io.r2dbc.postgresql.codec.DefaultCodecs.encode(DefaultCodecs.java:250)
	at io.r2dbc.postgresql.PostgresqlStatement.bind(PostgresqlStatement.java:107)

This can be tracked down to this part of spring-data-r2dbc:

Class<?> actualType = null;
if (value.getValue() instanceof Collection) {
actualType = CollectionUtils.findCommonElementType((Collection<?>) value.getValue());
} else if (!value.isEmpty() && value.getValue().getClass().isArray()) {
actualType = value.getValue().getClass().getComponentType();
}
if (actualType == null) {
actualType = property.getActualType();
}
actualType = converter.getTargetType(actualType);

For collections it first tries to find a common type based on the elements using CollectionUtils.findCommonElementType((Collection<?>) value.getValue()) (which are already converted if there were elements in the array).

This means that for non-empty collections it will correctly use the Interval type, but for empty collections it will actually use converter.getTargetType(actualType), which returns Duration.

Is there a way to get converters to work properly?

Especially since the docs say that per-element converters is the way to go:

Please note that converters get applied on singular properties. Collection properties (e.g. Collection) are iterated and converted element-wise.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Nov 7, 2022
@mp911de mp911de added type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged labels Nov 7, 2022
@mp911de mp911de self-assigned this Nov 7, 2022
@mp911de mp911de added this to the 1.5.6 (2021.2.6) milestone Nov 11, 2022
mp911de added a commit that referenced this issue Nov 11, 2022
We now consider the target type for empty collections.

Closes #796
@mp911de
Copy link
Member

mp911de commented Nov 11, 2022

That's fixed and forward-ported now.

@mp911de mp911de closed this as completed Nov 11, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug A general bug
Projects
None yet
Development

No branches or pull requests

3 participants