allow @CollectionFormat on class level (#596) (#610)

This commit is contained in:
Sam Kruglov
2021-10-20 16:39:52 +03:00
committed by GitHub
parent 3de4b98b3d
commit 21adacbc43
4 changed files with 33 additions and 11 deletions

View File

@@ -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.

View File

@@ -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 {

View File

@@ -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());
}
}
}

View File

@@ -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,