Spring JPA + REST data method: Enum to Integer conversion

I have an endpoint:

/api/offers/search/findByType?type=X 

where X should be an Integer value (the ordinal value of my OfferType instance), while Spring considers X a String and will apply its StringToEnumConverterFactory to StringToEnum >.

 public interface OfferRepository extends PagingAndSortingRepository<Offer, Long> { List<Offer> findByType(@Param("type") OfferType type); } 

So, I wrote a custom Converter<Integer, OfferType> , which simply gets the instance at the given serial number:

 public class IntegerToOfferTypeConverter implements Converter<Integer, OfferType> { @Override public OfferType convert(Integer source) { return OfferType.class.getEnumConstants()[source]; } } 

Then I registered it correctly using Configuration :

 @EnableWebMvc @Configuration @RequiredArgsConstructor public class GlobalMVCConfiguration extends WebMvcConfigurerAdapter { @Override public void addFormatters(FormatterRegistry registry) { registry.addConverter(new IntegerToOfferTypeConverter()); } } 

And I was expecting all requests to findByType?type=X go through my converter, but they do not.

Is it possible to say that all enumerations defined as query parameters should be represented as Integer ? Also, is there a way to say this globally, and not just for a specific listing?

EDIT: I found IntegerToEnumConverterFactory in my class path, which does everything I need. And it is registered in DefaultConversionService , which is the default conversion service. How can this be applied?

EDIT2: This is such a trivial thing, I was wondering if there is a property to enable the enum transform.

EDIT3: I tried writing Converter<String, OfferType> after I got a String from TypeDescriptor.forObject(value) , this did not help.

EDIT4:. My problem was that I placed my own registration of the converter in the MVC configuration ( WebMvcConfigurerAdapter with addFormatters ) instead of the REST repositories alone ( RepositoryRestConfigurerAdapter with configureConversionService ).

+6
source share
1 answer

Spring parses query parameters as strings. I believe that it always uses Converter<String, ?> Converters to convert from query parameters to repository parameter parameters. It uses the advanced converter service, as it registers its own converters , such as Converter<Entity, Resource> .

So you need to create Converter<String, OfferType> , for example:

 @Component public class StringToOfferTypeConverter implements Converter<String, OfferType> { @Override public OfferType convert(String source) { return OfferType.class.getEnumConstants()[Integer.valueOf(source)]; } } 

And then configure this converter, which will be used by Spring Data REST, in a class extending RepositoryRestConfigurerAdapter :

 @Configuration public class ConverterConfiguration extends RepositoryRestConfigurerAdapter { @Autowired StringToOfferTypeConverter converter; @Override public void configureConversionService(ConfigurableConversionService conversionService) { conversionService.addConverter(converter); super.configureConversionService(conversionService); } } 

I tried adding this to the basic tutorial , added a simple enumeration to the Person class:

 public enum OfferType { ONE, TWO; } @Entity public class Person { @Id @GeneratedValue(strategy = GenerationType.AUTO) private long id; private OfferType type; public OfferType getType() { return type; } public void setType(OfferType type) { this.type = type; } } 

And when I call:

http: // localhost: 8080 / people / search / findByType? type = 1

I get the result without errors:

 { "_embedded" : { "people" : [ ] }, "_links" : { "self" : { "href" : "http://localhost:8080/people/search/findByType?type=1" } } } 

To implement the global Enum converter, you need to create a factory and register it in the configuration using the method: conversionService.addConverterFactory() . The code below is a modified example from the documentation :

 public class StringToEnumFactory implements ConverterFactory<String, Enum> { public <T extends Enum> Converter<String, T> getConverter(Class<T> targetType) { return new StringToEnum(targetType); } private final class StringToEnum<T extends Enum> implements Converter<String, T> { private Class<T> enumType; public StringToEnum(Class<T> enumType) { this.enumType = enumType; } public T convert(String source) { Integer index = Integer.valueOf(source); return enumType.getEnumConstants()[index]; } } } 
+4
source

Source: https://habr.com/ru/post/1015736/


All Articles