diff --git a/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/UriToDomainObjectResolver.java b/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/UriToDomainObjectResolver.java index 750cf43f5..6dee130a0 100644 --- a/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/UriToDomainObjectResolver.java +++ b/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/UriToDomainObjectResolver.java @@ -2,6 +2,8 @@ package org.springframework.data.rest.repository; import java.io.Serializable; import java.net.URI; +import java.util.Arrays; +import java.util.List; import java.util.Stack; import org.springframework.beans.factory.annotation.Autowired; @@ -20,14 +22,14 @@ public class UriToDomainObjectResolver implements Resolver { @Autowired(required = false) - private ConversionService conversionService = new DefaultFormattingConversionService(); + private List conversionServices = Arrays.asList(new DefaultFormattingConversionService()); - public ConversionService getConversionService() { - return conversionService; + public List getConversionServices() { + return conversionServices; } - public UriToDomainObjectResolver setConversionService(ConversionService conversionService) { - this.conversionService = conversionService; + public UriToDomainObjectResolver setConversionServices(List conversionServices) { + this.conversionServices = conversionServices; return this; } @@ -56,11 +58,16 @@ public class UriToDomainObjectResolver } Class idType = (Class)entityMeta.idAttribute().type(); - Serializable serId; + Serializable serId = null; if(ClassUtils.isAssignable(idType, String.class)) { serId = sId; } else { - serId = conversionService.convert(sId, idType); + for(ConversionService cs : conversionServices) { + if(cs.canConvert(String.class, idType)) { + serId = cs.convert(sId, idType); + break; + } + } } return repo.findOne(serId); diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryAwareMappingHttpMessageConverter.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryAwareMappingHttpMessageConverter.java index f155a34c9..e5dd7ca91 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryAwareMappingHttpMessageConverter.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryAwareMappingHttpMessageConverter.java @@ -60,7 +60,7 @@ public class RepositoryAwareMappingHttpMessageConverter private final ObjectMapper mapper = new ObjectMapper(); @Autowired(required = false) - protected ConversionService conversionService = new DefaultFormattingConversionService(); + protected List conversionServices = Arrays.asList(new DefaultFormattingConversionService()); @Autowired(required = false) protected List repositoryExporters = Collections.emptyList(); @Autowired(required = false) @@ -84,12 +84,12 @@ public class RepositoryAwareMappingHttpMessageConverter } } - public ConversionService getConversionService() { - return conversionService; + public List getConversionServices() { + return conversionServices; } - public RepositoryAwareMappingHttpMessageConverter setConversionService(ConversionService conversionService) { - this.conversionService = conversionService; + public RepositoryAwareMappingHttpMessageConverter setConversionServices(List conversionServices) { + this.conversionServices = conversionServices; return this; } @@ -258,7 +258,13 @@ public class RepositoryAwareMappingHttpMessageConverter } Serializable serId = (Serializable)idAttr.get(value); - String sId = conversionService.convert(serId, String.class); + String sId = null; + for(ConversionService cs : conversionServices) { + if(cs.canConvert(idAttr.type(), String.class)) { + sId = cs.convert(serId, String.class); + break; + } + } if(null == sId) { sId = serId.toString(); } @@ -291,7 +297,13 @@ public class RepositoryAwareMappingHttpMessageConverter } Serializable serId = (Serializable)idAttr.get(value); - String sId = conversionService.convert(serId, String.class); + String sId = null; + for(ConversionService cs : conversionServices) { + if(cs.canConvert(idAttr.type(), String.class)) { + sId = cs.convert(serId, String.class); + break; + } + } if(null == sId) { sId = serId.toString(); } diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestController.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestController.java index 6514fdc64..80915e1d8 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestController.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestController.java @@ -33,8 +33,10 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; +import org.springframework.core.MethodParameter; import org.springframework.core.convert.ConversionFailedException; import org.springframework.core.convert.ConversionService; +import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.converter.Converter; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.dao.OptimisticLockingFailureException; @@ -176,22 +178,28 @@ public class RepositoryRestController /** * Get the {@link ConversionService} in use by the controller. * - * @return The internal {@link ConversionService}. + * @return The internal {@link ConversionService}s. */ public ConversionService getConversionService() { return conversionService; } /** - * Add this {@link ConversionService} to the list of those being delegated to by the internal {@link + * Add these {@link ConversionService}s to the list of those being delegated to by the internal {@link * DelegatingConversionService}. Although this method does an 'add', it is called 'set' to make it JavaBean-friendly. * - * @param conversionService + * @param conversionServices */ @Autowired(required = false) - public void setConversionService(ConversionService conversionService) { + public void setConversionServices(List conversionServices) { + if(null == conversionServices) { + return; + } + Collections.reverse(conversionServices); if(null != conversionService) { - this.conversionService.addConversionServices(conversionService); + this.conversionService.addConversionServices( + conversionServices.toArray(new ConversionService[conversionServices.size()]) + ); } } @@ -205,14 +213,14 @@ public class RepositoryRestController } /** - * @param conversionService + * @param conversionServices * * @return @this * - * @see RepositoryRestController#setConversionService(org.springframework.core.convert.ConversionService) + * @see RepositoryRestController#setConversionServices(java.util.List) */ - public RepositoryRestController conversionService(ConversionService conversionService) { - setConversionService(conversionService); + public RepositoryRestController conversionServices(List conversionServices) { + setConversionServices(conversionServices); return this; } @@ -589,6 +597,10 @@ public class RepositoryRestController continue; } + TypeDescriptor stringTypeDesc = TypeDescriptor.valueOf(String[].class); + MethodParameter methodParam = new MethodParameter(queryMethod.method(), i); + TypeDescriptor targetTypeDesc = new TypeDescriptor(methodParam); + Class> converter = null; for(Annotation anno : annotations[i]) { if(ConvertWith.class.isAssignableFrom(anno.getClass())) { @@ -620,9 +632,9 @@ public class RepositoryRestController } else if(String.class.isAssignableFrom(paramTypes[i])) { // Param type is a String paramVals[i] = firstVal; - } else if(conversionService.canConvert(String.class, paramTypes[i])) { + } else if(conversionService.canConvert(stringTypeDesc, targetTypeDesc)) { // There's a converter from String -> param type - paramVals[i] = conversionService.convert(firstVal, paramTypes[i]); + paramVals[i] = conversionService.convert(queryVals, stringTypeDesc, targetTypeDesc); } else { // Param type isn't a "simple" type or no converter exists, try JSON try { diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/ApplicationConfig.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/ApplicationConfig.java index 5d120eb39..5a2ec6b21 100644 --- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/ApplicationConfig.java +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/ApplicationConfig.java @@ -1,5 +1,7 @@ package org.springframework.data.rest.test.webmvc; +import java.util.ArrayList; +import java.util.List; import javax.persistence.EntityManagerFactory; import javax.sql.DataSource; @@ -7,9 +9,12 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import org.springframework.core.convert.ConversionService; +import org.springframework.core.convert.converter.Converter; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.data.rest.webmvc.RepositoryRestConfiguration; import org.springframework.data.rest.webmvc.RepositoryRestMvcConfiguration; +import org.springframework.format.support.DefaultFormattingConversionService; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; import org.springframework.orm.jpa.JpaDialect; @@ -70,4 +75,18 @@ public class ApplicationConfig { return new TestRepositoryEventListener(); } + @Bean public ConversionService customConversionService() { + DefaultFormattingConversionService cs = new DefaultFormattingConversionService(); + cs.addConverter(new Converter>() { + @Override public List convert(String[] source) { + List longs = new ArrayList(source.length); + for(String s : source) { + longs.add(Long.parseLong(s)); + } + return longs; + } + }); + return cs; + } + } diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/PersonRepository.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/PersonRepository.java index 5b7b5c941..555669e1d 100644 --- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/PersonRepository.java +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/PersonRepository.java @@ -30,8 +30,8 @@ public interface PersonRepository extends PagingAndSortingRepository findById(@Param("id") @ConvertWith(StringToListOfLongsConverter.class) List ids, Pageable pageable); + Page findById(@Param("ids") List ids, Pageable pageable); }