fap
fap

Reputation: 683

Defining multiple Spring Converters with target type Optional?

I'm using Spring Boot 1.5.10 and have a problem with my custom converters.

I'm defining multiple converters with target type Optional Something like this:

@Component
public class StringToSomeTypeConverter implements Converter<String, Optional<SomeType>> { ... }


@Component
public class StringToOtherTypeConverter implements Converter<String, Optional<OtherType>> { ... }

My problem is that there is apparently only one converter registered for the type Optional. So at runtime only one Converter gets called in all my Controllers. No matter the generic target type. (SomeType or OtherType in the example)

I did some digging and the converter is chosen in GenericConversionService#getConverter. The method takes TypeDescriptor targetType as argument and constructs a ConverterCacheKey from sourceType and targetType. Sadly TypeDescriptor#equals only compares getType() (Optional) and not resolvableType (SomeType or OtherType in our example). This explains why only one Converter gets picked up.

Is there any way to make Spring aware of the ResolvableType so I can use Optional as my target type for multiple Converters?

Upvotes: 2

Views: 2638

Answers (1)

Melardev
Melardev

Reputation: 1162

I can not tell for sure what is going on, but having browsed Spring MVC source code many times I guess the problem would be in some code that is iterating thorugh registered Converters and checking if they can convert, so the target type would be Optional(not Optional< Class < Integer > >, but Optional), if you run this code:

Optional<Class<String>> ops = Optional.of(String.class);
Optional<Class<Integer>> ops2 = Optional.of(Integer.class);
System.out.println(ops2.getClass().equals(ops.getClass()));

You will see on the console, it prints true, meaning, they are considered as the same datatype !! so if Spring truly iterates through the list of converters, it makes sense that hte first one is always called, because it can handle all Optional objects no matter what, my suggestion would be:

Update: If you are interested in debugging that at Spring framework you have to place a breakpoint on methods from the ConversionService interface, it is the service that manages the conversions, at least this is how it works in Spring Core, and you will should see the execution flow and at one moment in time is checking which converter is suitable and if some of them implements ConditionalConverter, look at one of the core methods of this process yourself at: https://github.com/spring-projects/spring-framework/blob/master/spring-core/src/main/java/org/springframework/core/convert/support/GenericConversionService.java#L560

Upvotes: 3

Related Questions