Closed bskorka closed 10 months ago
Enum conversion works as designed. null
values in the column map to null
values in the domain model. Anything else is being looked up through Enum.valueOf(…)
. Translating empty string values to null
is a rule specific to your domain and not something that applies broadly.
As this is a rather specific issue, please configure a custom conversions bean for your application.
I don't know if you get my point here.
When I create the custom conversion bean it is not used. The org.springframework.core.convert.support.StringToEnumConverterFactory.StringToEnum
is used instead and it deals with empty strings.
The question is why the Spring StringToEnum
is used only if R2dbcCustomConversions
are declared (not empty), and why my custom bean is not used.
@mp911de - I still think it's a bug or a inconsistent behavior, do you disagree?
R2dbcCustomConversions
keeps track of read and write targets. When registering a converter, we determine the custom read or write target. If that is set, then we register the converter in Spring's ConversionService and use the conversion service to perform the actual conversion.
Spring's ConversionService
comes already with a converter (StringToEnumConverterFactory
) that matches Enum<T>
as target type. Because of type erasure, the T
from EmptyStringToEnumReadingConverter<T extends Enum<T>>
is being flattened down to Enum
and therefore, the conversion service now has two converters. Spring's ConversionService checks the raw type for your converter and since the raw type is Enum
and not Debt.DebtSource
, the custom converter isn't used.
Instead, StringToEnum
is provided by the StringToEnumConverterFactory
that is a ConverterFactory
and it creates an instance for string to enum conversion with an exact type match.
Let me know whether this helps.
After the explanation, I got the point of why my converter is not used.
What I didn't understand was why the Spring ConversionService
and StringToEnumConverterFactory
were not used without the registration of the R2dbcCustomConversions
bean. I thought that spring
and spring-data-r2dbc
would treat the data equally. Your answer covers that a little.
It is also a little bit unclear that one day we will throw an error on an empty string, and on the next day if you register the custom converter for literally anything, your enums will be converted without any error.
Hey! I observed an error in our logs thrown by the repository when the value for the enum in one of the columns is an empty string. Everything works properly when the value is
null
or one of the proper ones.I have created a converter and the configuration then:
It worked immediately, but I wanted to check something and changed the implementation of the
convert
method to justreturn null
. The conversion was still working, and it was returning correct values when the value in DB was one of the enum ones. To check it I put some breakpoints and it became clear that the code is now usingorg.springframework.core.convert.support.StringToEnumConverterFactory.StringToEnum
instead of my custom conversion.The moment I passed just an empty list as
converters
to theR2dbcCustomConversions
it stopped working.It looks like I need to initialize the
R2dbcCustomConversions
with someConverter
(I can even pass different enum classes than I need), and then the code is using the SpringStringToEnum
converter which handles the empty string. Otherwise, it fails at any time.Summary:
What can I do to use
StringToEnum
by default here, without the need to create some custom conversion which is not used at all?Spring Boot version - 2.7.17