@@ -692,20 +692,21 @@ public interface DemoTemplate {
|
||||
----
|
||||
|
||||
=== Feign `CollectionFormat` support
|
||||
We support `feign.CollectionFormat` by providing the `@CollectionFormat` annotation.You can annotate a Feign client method with it by passing the desired `feign.CollectionFormat` as annotation value.
|
||||
We support `feign.CollectionFormat` by providing the `@CollectionFormat` annotation.
|
||||
You can annotate a Feign client method (or the whole class to affect all methods) with it by passing the desired `feign.CollectionFormat` as annotation value.
|
||||
|
||||
In the following example, the `CSV` format is used instead of the default `EXPLODED` to process the method.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@FeignClient(name = "demo")
|
||||
protected interface PageableFeignClient {
|
||||
protected interface PageableFeignClient {
|
||||
|
||||
@CollectionFormat(feign.CollectionFormat.CSV)
|
||||
@GetMapping(path = "/page")
|
||||
ResponseEntity performRequest(Pageable page);
|
||||
@CollectionFormat(feign.CollectionFormat.CSV)
|
||||
@GetMapping(path = "/page")
|
||||
ResponseEntity performRequest(Pageable page);
|
||||
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
TIP: Set the `CSV` format while sending `Pageable` as a query parameter in order for it to be encoded correctly.
|
||||
|
||||
@@ -25,9 +25,10 @@ import java.lang.annotation.Target;
|
||||
* Indicates which collection format should be used while processing the annotated method.
|
||||
*
|
||||
* @author Olga Maciaszek-Sharma
|
||||
* @author Sam Kruglov
|
||||
* @see feign.CollectionFormat
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface CollectionFormat {
|
||||
|
||||
|
||||
@@ -80,6 +80,7 @@ import static org.springframework.core.annotation.AnnotatedElementUtils.findMerg
|
||||
* @author Artyom Romanenko
|
||||
* @author Darren Foong
|
||||
* @author Ram Anaswara
|
||||
* @author Sam Kruglov
|
||||
*/
|
||||
public class SpringMvcContract extends Contract.BaseContract implements ResourceLoaderAware {
|
||||
|
||||
@@ -171,11 +172,11 @@ public class SpringMvcContract extends Contract.BaseContract implements Resource
|
||||
@Override
|
||||
protected void processAnnotationOnClass(MethodMetadata data, Class<?> clz) {
|
||||
if (clz.getInterfaces().length == 0) {
|
||||
RequestMapping classAnnotation = findMergedAnnotation(clz, RequestMapping.class);
|
||||
if (classAnnotation != null) {
|
||||
RequestMapping requestMapping = findMergedAnnotation(clz, RequestMapping.class);
|
||||
if (requestMapping != null) {
|
||||
// Prepend path from class annotation if specified
|
||||
if (classAnnotation.value().length > 0) {
|
||||
String pathValue = emptyToNull(classAnnotation.value()[0]);
|
||||
if (requestMapping.value().length > 0) {
|
||||
String pathValue = emptyToNull(requestMapping.value()[0]);
|
||||
pathValue = resolve(pathValue);
|
||||
if (!pathValue.startsWith("/")) {
|
||||
pathValue = "/" + pathValue;
|
||||
@@ -186,6 +187,10 @@ public class SpringMvcContract extends Contract.BaseContract implements Resource
|
||||
}
|
||||
}
|
||||
}
|
||||
CollectionFormat collectionFormat = findMergedAnnotation(clz, CollectionFormat.class);
|
||||
if (collectionFormat != null) {
|
||||
data.template().collectionFormat(collectionFormat.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -62,6 +62,7 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.ANY;
|
||||
import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE;
|
||||
import static feign.CollectionFormat.CSV;
|
||||
import static feign.CollectionFormat.SSV;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
@@ -73,6 +74,7 @@ import static org.junit.Assume.assumeTrue;
|
||||
* @author Aaron Whiteside
|
||||
* @author Artyom Romanenko
|
||||
* @author Olga Maciaszek-Sharma
|
||||
* @author Sam Kruglov
|
||||
*/
|
||||
public class SpringMvcContractTests {
|
||||
|
||||
@@ -302,6 +304,15 @@ public class SpringMvcContractTests {
|
||||
assertThat(data.template().collectionFormat()).isEqualTo(SSV);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void processAnnotationOnClass_CollectionFormat() throws NoSuchMethodException {
|
||||
Method method = TestTemplate_Advanced.class.getDeclaredMethod("getWithoutCollectionFormat");
|
||||
|
||||
MethodMetadata data = contract.parseAndValidateMetadata(method.getDeclaringClass(), method);
|
||||
|
||||
assertThat(data.template().collectionFormat()).isEqualTo(CSV);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessAnnotations_Advanced() throws Exception {
|
||||
Method method = TestTemplate_Advanced.class.getDeclaredMethod("getTest", String.class, String.class,
|
||||
@@ -744,12 +755,16 @@ public class SpringMvcContractTests {
|
||||
|
||||
@JsonAutoDetect
|
||||
@RequestMapping("/advanced")
|
||||
@CollectionFormat(CSV)
|
||||
public interface TestTemplate_Advanced {
|
||||
|
||||
@CollectionFormat(SSV)
|
||||
@GetMapping
|
||||
ResponseEntity<TestObject> getWithCollectionFormat();
|
||||
|
||||
@GetMapping
|
||||
ResponseEntity<TestObject> getWithoutCollectionFormat();
|
||||
|
||||
@ExceptionHandler
|
||||
@PutMapping(path = "/test/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
ResponseEntity<TestObject> getTest(@RequestHeader("Authorization") String auth, @PathVariable("id") String id,
|
||||
|
||||
Reference in New Issue
Block a user