From beba48bd4f2547ca7484ea26a846a72da56b6f23 Mon Sep 17 00:00:00 2001 From: Darren Foong Date: Fri, 27 Mar 2020 10:06:47 +0800 Subject: [PATCH 01/28] Add Pojo and failing test to FeignClientTests --- .../openfeign/valid/FeignClientTests.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java index 0dd60ad51..e390170f1 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java @@ -458,6 +458,16 @@ public void testMultipleRequestParts() { assertThat(response).isEqualTo("abc123hello.bin"); } + @Test + public void testMultiplePojoRequestParts() { + MockMultipartFile file = new MockMultipartFile("file", "hello.bin", null, + "hello".getBytes()); + Pojo pojo1 = new FeignClientTests.Pojo("hello", "world", 1); + Pojo pojo2 = new FeignClientTests.Pojo("hello", "world", 2); + String response = this.multipartClient.multipartPojo(pojo1, pojo2, file); + assertThat(response).isEqualTo("abc123hello.bin"); + } + @Test public void testRequestPartWithListOfMultipartFiles() { List multipartFiles = Arrays.asList( @@ -678,6 +688,13 @@ String multipart(@RequestPart("hello") String hello, @RequestPart("world") String world, @RequestPart("file") MultipartFile file); + @RequestMapping(method = RequestMethod.POST, path = "/multipartPojo", + consumes = MediaType.MULTIPART_FORM_DATA_VALUE, + produces = MediaType.TEXT_PLAIN_VALUE) + String multipartPojo(@RequestPart("pojo1") Pojo pojo1, + @RequestPart("pojo2") Pojo pojo2, + @RequestPart("file") MultipartFile file); + @RequestMapping(method = RequestMethod.POST, path = "/multipartNames", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.TEXT_PLAIN_VALUE) @@ -1122,4 +1139,15 @@ public ServerList ribbonServerList() { } + private static class Pojo { + private String value1; + private String value2; + private Integer value3; + + public Pojo(String value1, String value2, Integer value3) { + this.value1 = value1; + this.value2 = value2; + this.value3 = value3; + } + } } From b629e136d37d5c5027da567d15a72adef50a3a44 Mon Sep 17 00:00:00 2001 From: Darren Foong Date: Sat, 28 Mar 2020 23:20:24 +0800 Subject: [PATCH 02/28] Add SpringPojoFormEncoder --- .../openfeign/FeignClientsConfiguration.java | 20 +++++- .../support/PojoJsonSerializationWriter.java | 24 +++++++ .../support/PojoSerializationWriter.java | 68 +++++++++++++++++++ .../openfeign/support/SpringEncoder.java | 8 ++- .../support/SpringPojoFormEncoder.java | 15 ++++ 5 files changed, 132 insertions(+), 3 deletions(-) create mode 100644 spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoJsonSerializationWriter.java create mode 100644 spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoSerializationWriter.java create mode 100644 spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringPojoFormEncoder.java diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java index e01d709fe..37a9cb5c9 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java @@ -40,6 +40,7 @@ import org.springframework.boot.autoconfigure.http.HttpMessageConverters; import org.springframework.cloud.openfeign.support.PageJacksonModule; import org.springframework.cloud.openfeign.support.PageableSpringEncoder; +import org.springframework.cloud.openfeign.support.PojoSerializationWriter; import org.springframework.cloud.openfeign.support.ResponseEntityDecoder; import org.springframework.cloud.openfeign.support.SpringDecoder; import org.springframework.cloud.openfeign.support.SpringEncoder; @@ -73,6 +74,9 @@ public class FeignClientsConfiguration { @Autowired(required = false) private SpringDataWebProperties springDataWebProperties; + @Autowired(required = false) + private PojoSerializationWriter pojoSerializationWriter; + @Bean @ConditionalOnMissingBean public Decoder feignDecoder() { @@ -84,15 +88,27 @@ public Decoder feignDecoder() { @ConditionalOnMissingBean @ConditionalOnMissingClass("org.springframework.data.domain.Pageable") public Encoder feignEncoder() { - return new SpringEncoder(this.messageConverters); + if (this.pojoSerializationWriter != null) { + return new SpringEncoder(this.messageConverters); + } else { + return new SpringEncoder(this.pojoSerializationWriter, this.messageConverters); + } } @Bean @ConditionalOnClass(name = "org.springframework.data.domain.Pageable") @ConditionalOnMissingBean public Encoder feignEncoderPageable() { - PageableSpringEncoder encoder = new PageableSpringEncoder( + PageableSpringEncoder encoder; + + if (this.pojoSerializationWriter != null) { + encoder = new PageableSpringEncoder( new SpringEncoder(this.messageConverters)); + } else { + encoder = new PageableSpringEncoder( + new SpringEncoder(this.pojoSerializationWriter, this.messageConverters)); + } + if (springDataWebProperties != null) { encoder.setPageParameter( springDataWebProperties.getPageable().getPageParameter()); diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoJsonSerializationWriter.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoJsonSerializationWriter.java new file mode 100644 index 000000000..8d671153f --- /dev/null +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoJsonSerializationWriter.java @@ -0,0 +1,24 @@ +package org.springframework.cloud.openfeign.support; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Component; + +import java.io.IOException; + +@Component +public class PojoJsonSerializationWriter extends PojoSerializationWriter { + @Autowired + private ObjectMapper objectMapper; + + @Override + protected MediaType getContentType() { + return MediaType.APPLICATION_JSON; + } + + @Override + protected String serialize(Object object) throws IOException { + return objectMapper.writeValueAsString(object); + } +} diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoSerializationWriter.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoSerializationWriter.java new file mode 100644 index 000000000..38f0adef4 --- /dev/null +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoSerializationWriter.java @@ -0,0 +1,68 @@ +package org.springframework.cloud.openfeign.support; + +import feign.codec.EncodeException; +import feign.form.multipart.AbstractWriter; +import feign.form.multipart.Output; +import org.springframework.http.MediaType; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.Iterator; + +import static feign.form.ContentProcessor.CRLF; +import static feign.form.util.PojoUtil.isUserPojo; + +public abstract class PojoSerializationWriter extends AbstractWriter { + @Override + public boolean isApplicable(Object object) { + return !(object instanceof MultipartFile) && !(object instanceof MultipartFile[]) + && (isUserPojoCollection(object) || isUserPojo(object)); + } + + @Override + public void write (Output output, String key, Object object) throws EncodeException { + try { + String string = new StringBuilder() + .append("Content-Disposition: form-data; name=\"").append(key).append('"') + .append(CRLF) + .append("Content-Type: ").append(getContentType()) + .append("; charset=").append(output.getCharset().name()) + .append(CRLF) + .append(CRLF) + .append(serialize(object)) + .toString(); + + output.write(string); + } catch (IOException e) { + throw new EncodeException(e.getMessage()); + } + } + + protected abstract MediaType getContentType(); + + protected abstract String serialize(Object object) throws IOException; + + private boolean isUserPojoCollection(Object object) { + // TODO Refactor! + if (object.getClass().isArray()) { + Object[] array = (Object[]) object; + + return array.length > 1 && isUserPojo(array[0]); + } + + if (!(object instanceof Iterable)) { + return false; + } + + Iterable iterable = (Iterable) object; + Iterator iterator = iterable.iterator(); + + if (iterator.hasNext()) { + Object next = iterator.next(); + + return !(next instanceof MultipartFile) && isUserPojo(next); + } else { + return false; + } + } +} diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringEncoder.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringEncoder.java index dedee915c..eeffbba8a 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringEncoder.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringEncoder.java @@ -59,11 +59,17 @@ public class SpringEncoder implements Encoder { private static final Log log = LogFactory.getLog(SpringEncoder.class); - private final SpringFormEncoder springFormEncoder = new SpringFormEncoder(); + private SpringFormEncoder springFormEncoder; private final ObjectFactory messageConverters; public SpringEncoder(ObjectFactory messageConverters) { + this.springFormEncoder = new SpringFormEncoder(); + this.messageConverters = messageConverters; + } + + public SpringEncoder(PojoSerializationWriter writer, ObjectFactory messageConverters) { + this.springFormEncoder = new SpringPojoFormEncoder(writer); this.messageConverters = messageConverters; } diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringPojoFormEncoder.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringPojoFormEncoder.java new file mode 100644 index 000000000..92ad5baa1 --- /dev/null +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringPojoFormEncoder.java @@ -0,0 +1,15 @@ +package org.springframework.cloud.openfeign.support; + +import feign.form.MultipartFormContentProcessor; +import feign.form.spring.SpringFormEncoder; + +import static feign.form.ContentType.MULTIPART; + +public class SpringPojoFormEncoder extends SpringFormEncoder { + public SpringPojoFormEncoder(PojoSerializationWriter pojoSerializationWriter) { + super(); + + MultipartFormContentProcessor processor = (MultipartFormContentProcessor) getContentProcessor(MULTIPART); + processor.addFirstWriter(pojoSerializationWriter); + } +} From 59df0b61ad3fc67af2bf1ef9d506438f0bb6cec1 Mon Sep 17 00:00:00 2001 From: Darren Foong Date: Sat, 28 Mar 2020 23:32:15 +0800 Subject: [PATCH 03/28] Fix configuration --- .../cloud/openfeign/FeignClientsConfiguration.java | 8 ++++---- .../cloud/openfeign/valid/FeignClientTests.java | 7 +++++++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java index 37a9cb5c9..889c83f76 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java @@ -89,9 +89,9 @@ public Decoder feignDecoder() { @ConditionalOnMissingClass("org.springframework.data.domain.Pageable") public Encoder feignEncoder() { if (this.pojoSerializationWriter != null) { - return new SpringEncoder(this.messageConverters); - } else { return new SpringEncoder(this.pojoSerializationWriter, this.messageConverters); + } else { + return new SpringEncoder(this.messageConverters); } } @@ -103,10 +103,10 @@ public Encoder feignEncoderPageable() { if (this.pojoSerializationWriter != null) { encoder = new PageableSpringEncoder( - new SpringEncoder(this.messageConverters)); + new SpringEncoder(this.pojoSerializationWriter, this.messageConverters)); } else { encoder = new PageableSpringEncoder( - new SpringEncoder(this.pojoSerializationWriter, this.messageConverters)); + new SpringEncoder(this.messageConverters)); } if (springDataWebProperties != null) { diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java index e390170f1..933c49598 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java @@ -57,6 +57,8 @@ import org.junit.Test; import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; +import org.springframework.cloud.openfeign.support.PojoJsonSerializationWriter; +import org.springframework.cloud.openfeign.support.PojoSerializationWriter; import rx.Observable; import rx.Single; @@ -941,6 +943,11 @@ public OtherArg parse(String text, Locale locale) }; } + @Bean + public PojoSerializationWriter pojoSerializationWriter() { + return new PojoJsonSerializationWriter(); + } + @RequestMapping(method = RequestMethod.GET, path = "/hello") public Hello getHello() { return new Hello(HELLO_WORLD_1); From f965475a08186dc5d5c867b6a6ee36b10c59db19 Mon Sep 17 00:00:00 2001 From: Darren Foong Date: Sat, 28 Mar 2020 23:39:24 +0800 Subject: [PATCH 04/28] Update Pojo --- .../openfeign/valid/FeignClientTests.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java index 933c49598..30a16669d 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java @@ -1151,10 +1151,36 @@ private static class Pojo { private String value2; private Integer value3; + public Pojo() {}; + public Pojo(String value1, String value2, Integer value3) { this.value1 = value1; this.value2 = value2; this.value3 = value3; } + + public String getValue1() { + return value1; + } + + public void setValue1(String value1) { + this.value1 = value1; + } + + public String getValue2() { + return value2; + } + + public void setValue2(String value2) { + this.value2 = value2; + } + + public Integer getValue3() { + return value3; + } + + public void setValue3(Integer value3) { + this.value3 = value3; + } } } From 93b7f8004808b21d3ef49815f40bed2cc62ef403 Mon Sep 17 00:00:00 2001 From: Darren Foong Date: Sat, 28 Mar 2020 23:53:14 +0800 Subject: [PATCH 05/28] Implement multipartPojo --- .../cloud/openfeign/valid/FeignClientTests.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java index 30a16669d..bbdaf30b6 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java @@ -467,7 +467,7 @@ public void testMultiplePojoRequestParts() { Pojo pojo1 = new FeignClientTests.Pojo("hello", "world", 1); Pojo pojo2 = new FeignClientTests.Pojo("hello", "world", 2); String response = this.multipartClient.multipartPojo(pojo1, pojo2, file); - assertThat(response).isEqualTo("abc123hello.bin"); + assertThat(response).isEqualTo("helloworld1helloworld2hello.bin"); } @Test @@ -1066,6 +1066,15 @@ String multipart(@RequestPart("hello") String hello, return hello + world + file.getOriginalFilename(); } + @RequestMapping(method = RequestMethod.POST, path = "/multipartPojo", + consumes = MediaType.MULTIPART_FORM_DATA_VALUE, + produces = MediaType.TEXT_PLAIN_VALUE) + String multipartPojo(@RequestPart("pojo1") Pojo pojo1, + @RequestPart("pojo2") Pojo pojo2, + @RequestPart("file") MultipartFile file) { + return pojo1.getValue1() + pojo1.getValue2() + pojo1.getValue3() + pojo2.getValue1() + pojo2.getValue2() + pojo2.getValue3() + file.getOriginalFilename(); + } + @RequestMapping(method = RequestMethod.POST, path = "/multipartNames", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.TEXT_PLAIN_VALUE) From a8b7cb051101b28e77470fb7941dbefb8bc1afa2 Mon Sep 17 00:00:00 2001 From: Darren Foong Date: Sun, 29 Mar 2020 01:44:46 +0800 Subject: [PATCH 06/28] Does not work if Pojo has one field: this is crazy --- .../openfeign/valid/FeignClientTests.java | 28 +++---------------- 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java index bbdaf30b6..7fa52dbc2 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java @@ -464,8 +464,8 @@ public void testMultipleRequestParts() { public void testMultiplePojoRequestParts() { MockMultipartFile file = new MockMultipartFile("file", "hello.bin", null, "hello".getBytes()); - Pojo pojo1 = new FeignClientTests.Pojo("hello", "world", 1); - Pojo pojo2 = new FeignClientTests.Pojo("hello", "world", 2); + Pojo pojo1 = new FeignClientTests.Pojo("hello"); + Pojo pojo2 = new FeignClientTests.Pojo("hello"); String response = this.multipartClient.multipartPojo(pojo1, pojo2, file); assertThat(response).isEqualTo("helloworld1helloworld2hello.bin"); } @@ -1072,7 +1072,7 @@ String multipart(@RequestPart("hello") String hello, String multipartPojo(@RequestPart("pojo1") Pojo pojo1, @RequestPart("pojo2") Pojo pojo2, @RequestPart("file") MultipartFile file) { - return pojo1.getValue1() + pojo1.getValue2() + pojo1.getValue3() + pojo2.getValue1() + pojo2.getValue2() + pojo2.getValue3() + file.getOriginalFilename(); + return pojo1.getValue1() + pojo2.getValue1() + file.getOriginalFilename(); } @RequestMapping(method = RequestMethod.POST, path = "/multipartNames", @@ -1157,15 +1157,11 @@ public ServerList ribbonServerList() { private static class Pojo { private String value1; - private String value2; - private Integer value3; public Pojo() {}; - public Pojo(String value1, String value2, Integer value3) { + public Pojo(String value1) { this.value1 = value1; - this.value2 = value2; - this.value3 = value3; } public String getValue1() { @@ -1175,21 +1171,5 @@ public String getValue1() { public void setValue1(String value1) { this.value1 = value1; } - - public String getValue2() { - return value2; - } - - public void setValue2(String value2) { - this.value2 = value2; - } - - public Integer getValue3() { - return value3; - } - - public void setValue3(Integer value3) { - this.value3 = value3; - } } } From ce3b96f74c30b40112c7f06d5b649c4a6a2cae00 Mon Sep 17 00:00:00 2001 From: Darren Foong Date: Sun, 29 Mar 2020 02:26:23 +0800 Subject: [PATCH 07/28] Disable expansion for multipart/form-data --- .../openfeign/support/SpringMvcContract.java | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringMvcContract.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringMvcContract.java index 02dcf8327..c4d651d20 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringMvcContract.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringMvcContract.java @@ -20,14 +20,7 @@ import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import feign.Contract; import feign.Feign; @@ -42,6 +35,7 @@ import org.springframework.cloud.openfeign.annotation.RequestHeaderParameterProcessor; import org.springframework.cloud.openfeign.annotation.RequestParamParameterProcessor; import org.springframework.cloud.openfeign.annotation.RequestPartParameterProcessor; +import org.springframework.cloud.openfeign.encoding.HttpEncoding; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.ResourceLoaderAware; import org.springframework.core.DefaultParameterNameDiscoverer; @@ -54,6 +48,7 @@ import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.ResourceLoader; +import org.springframework.http.MediaType; import org.springframework.util.Assert; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.RequestMapping; @@ -272,6 +267,15 @@ private void checkOne(Method method, Object[] values, String fieldName) { @Override protected boolean processAnnotationsOnParameter(MethodMetadata data, Annotation[] annotations, int paramIndex) { + boolean isMultipartFormData = false; + + Collection contentTypes = data.template().headers().get(HttpEncoding.CONTENT_TYPE); + + if (contentTypes != null && !contentTypes.isEmpty()) { + String type = contentTypes.iterator().next(); + isMultipartFormData = Objects.equals(MediaType.valueOf(type), MediaType.MULTIPART_FORM_DATA); + } + boolean isHttpAnnotation = false; AnnotatedParameterProcessor.AnnotatedParameterContext context = new SimpleAnnotatedParameterContext( @@ -291,7 +295,7 @@ protected boolean processAnnotationsOnParameter(MethodMetadata data, } } - if (isHttpAnnotation && data.indexToExpander().get(paramIndex) == null) { + if (!isMultipartFormData && isHttpAnnotation && data.indexToExpander().get(paramIndex) == null) { TypeDescriptor typeDescriptor = createTypeDescriptor(method, paramIndex); if (this.conversionService.canConvert(typeDescriptor, STRING_TYPE_DESCRIPTOR)) { From b66c3babf8991f4a1c2526a3f8d9b43affe16c78 Mon Sep 17 00:00:00 2001 From: Darren Foong Date: Sun, 29 Mar 2020 02:28:17 +0800 Subject: [PATCH 08/28] Remove Pojo --- .../openfeign/valid/FeignClientTests.java | 32 ++++--------------- 1 file changed, 7 insertions(+), 25 deletions(-) diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java index 7fa52dbc2..e75c68ffa 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java @@ -464,8 +464,8 @@ public void testMultipleRequestParts() { public void testMultiplePojoRequestParts() { MockMultipartFile file = new MockMultipartFile("file", "hello.bin", null, "hello".getBytes()); - Pojo pojo1 = new FeignClientTests.Pojo("hello"); - Pojo pojo2 = new FeignClientTests.Pojo("hello"); + Hello pojo1 = new Hello("hello"); + Hello pojo2 = new Hello("hello"); String response = this.multipartClient.multipartPojo(pojo1, pojo2, file); assertThat(response).isEqualTo("helloworld1helloworld2hello.bin"); } @@ -693,8 +693,8 @@ String multipart(@RequestPart("hello") String hello, @RequestMapping(method = RequestMethod.POST, path = "/multipartPojo", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.TEXT_PLAIN_VALUE) - String multipartPojo(@RequestPart("pojo1") Pojo pojo1, - @RequestPart("pojo2") Pojo pojo2, + String multipartPojo(@RequestPart("pojo1") Hello pojo1, + @RequestPart("pojo2") Hello pojo2, @RequestPart("file") MultipartFile file); @RequestMapping(method = RequestMethod.POST, path = "/multipartNames", @@ -1069,10 +1069,10 @@ String multipart(@RequestPart("hello") String hello, @RequestMapping(method = RequestMethod.POST, path = "/multipartPojo", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.TEXT_PLAIN_VALUE) - String multipartPojo(@RequestPart("pojo1") Pojo pojo1, - @RequestPart("pojo2") Pojo pojo2, + String multipartHello(@RequestPart("pojo1") Hello pojo1, + @RequestPart("pojo2") Hello pojo2, @RequestPart("file") MultipartFile file) { - return pojo1.getValue1() + pojo2.getValue1() + file.getOriginalFilename(); + return pojo1.getMessage() + pojo2.getMessage() + file.getOriginalFilename(); } @RequestMapping(method = RequestMethod.POST, path = "/multipartNames", @@ -1154,22 +1154,4 @@ public ServerList ribbonServerList() { } } - - private static class Pojo { - private String value1; - - public Pojo() {}; - - public Pojo(String value1) { - this.value1 = value1; - } - - public String getValue1() { - return value1; - } - - public void setValue1(String value1) { - this.value1 = value1; - } - } } From 9cdfc491e4e0afac222e4541c6c7aeb65578b6de Mon Sep 17 00:00:00 2001 From: Darren Foong Date: Sun, 29 Mar 2020 11:17:38 +0800 Subject: [PATCH 09/28] Tidy code --- .../cloud/openfeign/valid/FeignClientTests.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java index e75c68ffa..f46f8da42 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java @@ -1069,7 +1069,7 @@ String multipart(@RequestPart("hello") String hello, @RequestMapping(method = RequestMethod.POST, path = "/multipartPojo", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.TEXT_PLAIN_VALUE) - String multipartHello(@RequestPart("pojo1") Hello pojo1, + String multipartPojo(@RequestPart("pojo1") Hello pojo1, @RequestPart("pojo2") Hello pojo2, @RequestPart("file") MultipartFile file) { return pojo1.getMessage() + pojo2.getMessage() + file.getOriginalFilename(); @@ -1154,4 +1154,5 @@ public ServerList ribbonServerList() { } } + } From 1a695600d9f862a580632fd3cf0df3d469cc4f32 Mon Sep 17 00:00:00 2001 From: Darren Foong Date: Sun, 29 Mar 2020 11:24:47 +0800 Subject: [PATCH 10/28] Add testSinglePojoRequestPart --- .../openfeign/valid/FeignClientTests.java | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java index f46f8da42..75e84b30d 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java @@ -452,6 +452,12 @@ public void testSingleRequestPart() { assertThat(response).isEqualTo("abc"); } + @Test + public void testSinglePojoRequestPart() { + String response = this.multipartClient.singlePojoPart(new Hello(HELLO_WORLD_1)); + assertThat(response).isEqualTo(HELLO_WORLD_1); + } + @Test public void testMultipleRequestParts() { MockMultipartFile file = new MockMultipartFile("file", "hello.bin", null, @@ -683,6 +689,11 @@ protected interface MultipartClient { produces = MediaType.TEXT_PLAIN_VALUE) String singlePart(@RequestPart("hello") String hello); + @RequestMapping(method = RequestMethod.POST, path = "/singlePojoPart", + consumes = MediaType.MULTIPART_FORM_DATA_VALUE, + produces = MediaType.TEXT_PLAIN_VALUE) + String singlePojoPart(@RequestPart("hello") Hello hello); + @RequestMapping(method = RequestMethod.POST, path = "/multipart", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.TEXT_PLAIN_VALUE) @@ -1053,10 +1064,17 @@ Collection getToString(@RequestParam("arg") Collection args) { @RequestMapping(method = RequestMethod.POST, path = "/singlePart", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.TEXT_PLAIN_VALUE) - String multipart(@RequestPart("hello") String hello) { + String singlePart(@RequestPart("hello") String hello) { return hello; } + @RequestMapping(method = RequestMethod.POST, path = "/singlePojoPart", + consumes = MediaType.MULTIPART_FORM_DATA_VALUE, + produces = MediaType.TEXT_PLAIN_VALUE) + String singlePojoPart(@RequestPart("hello") Hello hello) { + return hello.getMessage(); + } + @RequestMapping(method = RequestMethod.POST, path = "/multipart", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.TEXT_PLAIN_VALUE) From 1a917e2ed17c4c99944d54fc607be5ab5720f1fd Mon Sep 17 00:00:00 2001 From: Darren Foong Date: Sun, 29 Mar 2020 11:30:31 +0800 Subject: [PATCH 11/28] Update testMultiplePojoRequestPart --- .../cloud/openfeign/valid/FeignClientTests.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java index 75e84b30d..c4982e41e 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java @@ -461,19 +461,19 @@ public void testSinglePojoRequestPart() { @Test public void testMultipleRequestParts() { MockMultipartFile file = new MockMultipartFile("file", "hello.bin", null, - "hello".getBytes()); + "hello".getBytes()); String response = this.multipartClient.multipart("abc", "123", file); assertThat(response).isEqualTo("abc123hello.bin"); } @Test public void testMultiplePojoRequestParts() { + Hello pojo1 = new Hello(HELLO_WORLD_1); + Hello pojo2 = new Hello(OI_TERRA_2); MockMultipartFile file = new MockMultipartFile("file", "hello.bin", null, "hello".getBytes()); - Hello pojo1 = new Hello("hello"); - Hello pojo2 = new Hello("hello"); String response = this.multipartClient.multipartPojo(pojo1, pojo2, file); - assertThat(response).isEqualTo("helloworld1helloworld2hello.bin"); + assertThat(response).isEqualTo("hello world 1oi terra 2hello.bin"); } @Test From 0e3b5fa87240284e267a14ab721026917fb80b64 Mon Sep 17 00:00:00 2001 From: Darren Foong Date: Sun, 29 Mar 2020 11:34:34 +0800 Subject: [PATCH 12/28] Update testMultiplePojoRequestPart --- .../cloud/openfeign/valid/FeignClientTests.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java index c4982e41e..61c5d1771 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java @@ -472,8 +472,8 @@ public void testMultiplePojoRequestParts() { Hello pojo2 = new Hello(OI_TERRA_2); MockMultipartFile file = new MockMultipartFile("file", "hello.bin", null, "hello".getBytes()); - String response = this.multipartClient.multipartPojo(pojo1, pojo2, file); - assertThat(response).isEqualTo("hello world 1oi terra 2hello.bin"); + String response = this.multipartClient.multipartPojo("abc", "123", pojo1, pojo2, file); + assertThat(response).isEqualTo("abc123hello world 1oi terra 2hello.bin"); } @Test @@ -704,7 +704,9 @@ String multipart(@RequestPart("hello") String hello, @RequestMapping(method = RequestMethod.POST, path = "/multipartPojo", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.TEXT_PLAIN_VALUE) - String multipartPojo(@RequestPart("pojo1") Hello pojo1, + String multipartPojo(@RequestPart("hello") String hello, + @RequestPart("world") String world, + @RequestPart("pojo1") Hello pojo1, @RequestPart("pojo2") Hello pojo2, @RequestPart("file") MultipartFile file); @@ -1087,10 +1089,12 @@ String multipart(@RequestPart("hello") String hello, @RequestMapping(method = RequestMethod.POST, path = "/multipartPojo", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.TEXT_PLAIN_VALUE) - String multipartPojo(@RequestPart("pojo1") Hello pojo1, + String multipartPojo(@RequestPart("hello") String hello, + @RequestPart("world") String world, + @RequestPart("pojo1") Hello pojo1, @RequestPart("pojo2") Hello pojo2, @RequestPart("file") MultipartFile file) { - return pojo1.getMessage() + pojo2.getMessage() + file.getOriginalFilename(); + return hello + world + pojo1.getMessage() + pojo2.getMessage() + file.getOriginalFilename(); } @RequestMapping(method = RequestMethod.POST, path = "/multipartNames", From 5312520acd537cca0764334b173c6437be9e2365 Mon Sep 17 00:00:00 2001 From: Darren Foong Date: Sun, 29 Mar 2020 11:47:23 +0800 Subject: [PATCH 13/28] Add testRequestPartWithListOfPojosAndListOfMultipartFiles --- .../openfeign/valid/FeignClientTests.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java index 61c5d1771..d392db002 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java @@ -489,6 +489,20 @@ public void testRequestPartWithListOfMultipartFiles() { assertThat(fileNames).contains("hello1.bin", "hello2.bin"); } + @Test + public void testRequestPartWithListOfPojosAndListOfMultipartFiles() { + Hello pojo1 = new Hello(HELLO_WORLD_1); + Hello pojo2 = new Hello(OI_TERRA_2); + MockMultipartFile file1 = new MockMultipartFile("file1", "hello1.bin", null, + "hello".getBytes()); + MockMultipartFile file2 = new MockMultipartFile("file2", "hello2.bin", null, + "hello".getBytes()); + String response = this.multipartClient + .requestPartListOfPojosAndListOfMultipartFiles(Arrays.asList(pojo1, pojo2), Arrays.asList(file1, file2)); + assertThat(response).isEqualTo("hello world 1oi terra 2hello1.binhello2.bin"); + } + + @Test public void testRequestBodyWithSingleMultipartFile() { String partName = UUID.randomUUID().toString(); @@ -722,6 +736,13 @@ String requestPartListOfMultipartFilesReturnsPartNames( String requestPartListOfMultipartFilesReturnsFileNames( @RequestPart("files") List files); + @RequestMapping(method = RequestMethod.POST, path = "/multipartPojosFiles", + consumes = MediaType.MULTIPART_FORM_DATA_VALUE, + produces = MediaType.TEXT_PLAIN_VALUE) + String requestPartListOfPojosAndListOfMultipartFiles( + @RequestPart("pojos") List pojos, + @RequestPart("files") List files); + @RequestMapping(method = RequestMethod.POST, path = "/multipartNames", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.TEXT_PLAIN_VALUE) @@ -1113,6 +1134,24 @@ String multipartFilenames(HttpServletRequest request) throws Exception { .collect(Collectors.joining(",")); } + @RequestMapping(method = RequestMethod.POST, path = "/multipartPojosFiles", + consumes = MediaType.MULTIPART_FORM_DATA_VALUE, + produces = MediaType.TEXT_PLAIN_VALUE) + String requestPartListOfPojosAndListOfMultipartFiles( + @RequestPart("pojos") List pojos, + @RequestPart("files") List files) { + StringBuilder result = new StringBuilder(); + + for (Hello pojo : pojos) { + result.append(pojo.getMessage()); + } + + for (MultipartFile file : files) { + result.append(file.getOriginalFilename()); + } + + return result.toString(); + } } public static class Hello { From a7d98fe5ab9b9f0a330aa348345445d41a09cc89 Mon Sep 17 00:00:00 2001 From: Darren Foong Date: Sun, 29 Mar 2020 12:12:48 +0800 Subject: [PATCH 14/28] Fix Checkstyle errors --- .../openfeign/FeignClientsConfiguration.java | 15 ++-- .../support/PojoJsonSerializationWriter.java | 23 ++++++- .../support/PojoSerializationWriter.java | 48 +++++++++---- .../openfeign/support/SpringEncoder.java | 3 +- .../openfeign/support/SpringMvcContract.java | 19 +++-- .../support/SpringPojoFormEncoder.java | 21 +++++- .../openfeign/valid/FeignClientTests.java | 69 ++++++++++--------- 7 files changed, 135 insertions(+), 63 deletions(-) diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java index 889c83f76..3bbf82d91 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java @@ -89,8 +89,10 @@ public Decoder feignDecoder() { @ConditionalOnMissingClass("org.springframework.data.domain.Pageable") public Encoder feignEncoder() { if (this.pojoSerializationWriter != null) { - return new SpringEncoder(this.pojoSerializationWriter, this.messageConverters); - } else { + return new SpringEncoder(this.pojoSerializationWriter, + this.messageConverters); + } + else { return new SpringEncoder(this.messageConverters); } } @@ -102,11 +104,12 @@ public Encoder feignEncoderPageable() { PageableSpringEncoder encoder; if (this.pojoSerializationWriter != null) { + encoder = new PageableSpringEncoder(new SpringEncoder( + this.pojoSerializationWriter, this.messageConverters)); + } + else { encoder = new PageableSpringEncoder( - new SpringEncoder(this.pojoSerializationWriter, this.messageConverters)); - } else { - encoder = new PageableSpringEncoder( - new SpringEncoder(this.messageConverters)); + new SpringEncoder(this.messageConverters)); } if (springDataWebProperties != null) { diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoJsonSerializationWriter.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoJsonSerializationWriter.java index 8d671153f..a53cb000d 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoJsonSerializationWriter.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoJsonSerializationWriter.java @@ -1,14 +1,32 @@ +/* + * Copyright 2013-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.springframework.cloud.openfeign.support; +import java.io.IOException; + import com.fasterxml.jackson.databind.ObjectMapper; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.stereotype.Component; -import java.io.IOException; - @Component public class PojoJsonSerializationWriter extends PojoSerializationWriter { + @Autowired private ObjectMapper objectMapper; @@ -21,4 +39,5 @@ protected MediaType getContentType() { protected String serialize(Object object) throws IOException { return objectMapper.writeValueAsString(object); } + } diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoSerializationWriter.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoSerializationWriter.java index 38f0adef4..8263e983d 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoSerializationWriter.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoSerializationWriter.java @@ -1,39 +1,55 @@ +/* + * Copyright 2013-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.springframework.cloud.openfeign.support; +import java.io.IOException; +import java.util.Iterator; + import feign.codec.EncodeException; import feign.form.multipart.AbstractWriter; import feign.form.multipart.Output; + import org.springframework.http.MediaType; import org.springframework.web.multipart.MultipartFile; -import java.io.IOException; -import java.util.Iterator; - import static feign.form.ContentProcessor.CRLF; import static feign.form.util.PojoUtil.isUserPojo; public abstract class PojoSerializationWriter extends AbstractWriter { + @Override public boolean isApplicable(Object object) { return !(object instanceof MultipartFile) && !(object instanceof MultipartFile[]) - && (isUserPojoCollection(object) || isUserPojo(object)); + && (isUserPojoCollection(object) || isUserPojo(object)); } @Override - public void write (Output output, String key, Object object) throws EncodeException { + public void write(Output output, String key, Object object) throws EncodeException { try { String string = new StringBuilder() - .append("Content-Disposition: form-data; name=\"").append(key).append('"') - .append(CRLF) - .append("Content-Type: ").append(getContentType()) - .append("; charset=").append(output.getCharset().name()) - .append(CRLF) - .append(CRLF) - .append(serialize(object)) - .toString(); + .append("Content-Disposition: form-data; name=\"").append(key) + .append('"').append(CRLF).append("Content-Type: ") + .append(getContentType()).append("; charset=") + .append(output.getCharset().name()).append(CRLF).append(CRLF) + .append(serialize(object)).toString(); output.write(string); - } catch (IOException e) { + } + catch (IOException e) { throw new EncodeException(e.getMessage()); } } @@ -61,8 +77,10 @@ private boolean isUserPojoCollection(Object object) { Object next = iterator.next(); return !(next instanceof MultipartFile) && isUserPojo(next); - } else { + } + else { return false; } } + } diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringEncoder.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringEncoder.java index eeffbba8a..7dd274c9f 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringEncoder.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringEncoder.java @@ -68,7 +68,8 @@ public SpringEncoder(ObjectFactory messageConverters) { this.messageConverters = messageConverters; } - public SpringEncoder(PojoSerializationWriter writer, ObjectFactory messageConverters) { + public SpringEncoder(PojoSerializationWriter writer, + ObjectFactory messageConverters) { this.springFormEncoder = new SpringPojoFormEncoder(writer); this.messageConverters = messageConverters; } diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringMvcContract.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringMvcContract.java index c4d651d20..827c3c157 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringMvcContract.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringMvcContract.java @@ -20,7 +20,15 @@ import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.lang.reflect.Type; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; import feign.Contract; import feign.Feign; @@ -269,11 +277,13 @@ protected boolean processAnnotationsOnParameter(MethodMetadata data, Annotation[] annotations, int paramIndex) { boolean isMultipartFormData = false; - Collection contentTypes = data.template().headers().get(HttpEncoding.CONTENT_TYPE); + Collection contentTypes = data.template().headers() + .get(HttpEncoding.CONTENT_TYPE); if (contentTypes != null && !contentTypes.isEmpty()) { String type = contentTypes.iterator().next(); - isMultipartFormData = Objects.equals(MediaType.valueOf(type), MediaType.MULTIPART_FORM_DATA); + isMultipartFormData = Objects.equals(MediaType.valueOf(type), + MediaType.MULTIPART_FORM_DATA); } boolean isHttpAnnotation = false; @@ -295,7 +305,8 @@ protected boolean processAnnotationsOnParameter(MethodMetadata data, } } - if (!isMultipartFormData && isHttpAnnotation && data.indexToExpander().get(paramIndex) == null) { + if (!isMultipartFormData && isHttpAnnotation + && data.indexToExpander().get(paramIndex) == null) { TypeDescriptor typeDescriptor = createTypeDescriptor(method, paramIndex); if (this.conversionService.canConvert(typeDescriptor, STRING_TYPE_DESCRIPTOR)) { diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringPojoFormEncoder.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringPojoFormEncoder.java index 92ad5baa1..8ed90b3f7 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringPojoFormEncoder.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringPojoFormEncoder.java @@ -1,3 +1,19 @@ +/* + * Copyright 2013-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.springframework.cloud.openfeign.support; import feign.form.MultipartFormContentProcessor; @@ -6,10 +22,13 @@ import static feign.form.ContentType.MULTIPART; public class SpringPojoFormEncoder extends SpringFormEncoder { + public SpringPojoFormEncoder(PojoSerializationWriter pojoSerializationWriter) { super(); - MultipartFormContentProcessor processor = (MultipartFormContentProcessor) getContentProcessor(MULTIPART); + MultipartFormContentProcessor processor = (MultipartFormContentProcessor) getContentProcessor( + MULTIPART); processor.addFirstWriter(pojoSerializationWriter); } + } diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java index d392db002..482130213 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java @@ -57,8 +57,6 @@ import org.junit.Test; import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; -import org.springframework.cloud.openfeign.support.PojoJsonSerializationWriter; -import org.springframework.cloud.openfeign.support.PojoSerializationWriter; import rx.Observable; import rx.Single; @@ -77,6 +75,8 @@ import org.springframework.cloud.openfeign.FeignFormatterRegistrar; import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient; import org.springframework.cloud.openfeign.support.FallbackCommand; +import org.springframework.cloud.openfeign.support.PojoJsonSerializationWriter; +import org.springframework.cloud.openfeign.support.PojoSerializationWriter; import org.springframework.cloud.openfeign.test.NoSecurityConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -461,7 +461,7 @@ public void testSinglePojoRequestPart() { @Test public void testMultipleRequestParts() { MockMultipartFile file = new MockMultipartFile("file", "hello.bin", null, - "hello".getBytes()); + "hello".getBytes()); String response = this.multipartClient.multipart("abc", "123", file); assertThat(response).isEqualTo("abc123hello.bin"); } @@ -471,8 +471,9 @@ public void testMultiplePojoRequestParts() { Hello pojo1 = new Hello(HELLO_WORLD_1); Hello pojo2 = new Hello(OI_TERRA_2); MockMultipartFile file = new MockMultipartFile("file", "hello.bin", null, - "hello".getBytes()); - String response = this.multipartClient.multipartPojo("abc", "123", pojo1, pojo2, file); + "hello".getBytes()); + String response = this.multipartClient.multipartPojo("abc", "123", pojo1, pojo2, + file); assertThat(response).isEqualTo("abc123hello world 1oi terra 2hello.bin"); } @@ -494,15 +495,15 @@ public void testRequestPartWithListOfPojosAndListOfMultipartFiles() { Hello pojo1 = new Hello(HELLO_WORLD_1); Hello pojo2 = new Hello(OI_TERRA_2); MockMultipartFile file1 = new MockMultipartFile("file1", "hello1.bin", null, - "hello".getBytes()); + "hello".getBytes()); MockMultipartFile file2 = new MockMultipartFile("file2", "hello2.bin", null, - "hello".getBytes()); + "hello".getBytes()); String response = this.multipartClient - .requestPartListOfPojosAndListOfMultipartFiles(Arrays.asList(pojo1, pojo2), Arrays.asList(file1, file2)); + .requestPartListOfPojosAndListOfMultipartFiles( + Arrays.asList(pojo1, pojo2), Arrays.asList(file1, file2)); assertThat(response).isEqualTo("hello world 1oi terra 2hello1.binhello2.bin"); } - @Test public void testRequestBodyWithSingleMultipartFile() { String partName = UUID.randomUUID().toString(); @@ -704,8 +705,8 @@ protected interface MultipartClient { String singlePart(@RequestPart("hello") String hello); @RequestMapping(method = RequestMethod.POST, path = "/singlePojoPart", - consumes = MediaType.MULTIPART_FORM_DATA_VALUE, - produces = MediaType.TEXT_PLAIN_VALUE) + consumes = MediaType.MULTIPART_FORM_DATA_VALUE, + produces = MediaType.TEXT_PLAIN_VALUE) String singlePojoPart(@RequestPart("hello") Hello hello); @RequestMapping(method = RequestMethod.POST, path = "/multipart", @@ -716,13 +717,12 @@ String multipart(@RequestPart("hello") String hello, @RequestPart("file") MultipartFile file); @RequestMapping(method = RequestMethod.POST, path = "/multipartPojo", - consumes = MediaType.MULTIPART_FORM_DATA_VALUE, - produces = MediaType.TEXT_PLAIN_VALUE) + consumes = MediaType.MULTIPART_FORM_DATA_VALUE, + produces = MediaType.TEXT_PLAIN_VALUE) String multipartPojo(@RequestPart("hello") String hello, - @RequestPart("world") String world, - @RequestPart("pojo1") Hello pojo1, - @RequestPart("pojo2") Hello pojo2, - @RequestPart("file") MultipartFile file); + @RequestPart("world") String world, @RequestPart("pojo1") Hello pojo1, + @RequestPart("pojo2") Hello pojo2, + @RequestPart("file") MultipartFile file); @RequestMapping(method = RequestMethod.POST, path = "/multipartNames", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, @@ -737,11 +737,11 @@ String requestPartListOfMultipartFilesReturnsFileNames( @RequestPart("files") List files); @RequestMapping(method = RequestMethod.POST, path = "/multipartPojosFiles", - consumes = MediaType.MULTIPART_FORM_DATA_VALUE, - produces = MediaType.TEXT_PLAIN_VALUE) + consumes = MediaType.MULTIPART_FORM_DATA_VALUE, + produces = MediaType.TEXT_PLAIN_VALUE) String requestPartListOfPojosAndListOfMultipartFiles( - @RequestPart("pojos") List pojos, - @RequestPart("files") List files); + @RequestPart("pojos") List pojos, + @RequestPart("files") List files); @RequestMapping(method = RequestMethod.POST, path = "/multipartNames", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, @@ -1092,8 +1092,8 @@ String singlePart(@RequestPart("hello") String hello) { } @RequestMapping(method = RequestMethod.POST, path = "/singlePojoPart", - consumes = MediaType.MULTIPART_FORM_DATA_VALUE, - produces = MediaType.TEXT_PLAIN_VALUE) + consumes = MediaType.MULTIPART_FORM_DATA_VALUE, + produces = MediaType.TEXT_PLAIN_VALUE) String singlePojoPart(@RequestPart("hello") Hello hello) { return hello.getMessage(); } @@ -1108,14 +1108,14 @@ String multipart(@RequestPart("hello") String hello, } @RequestMapping(method = RequestMethod.POST, path = "/multipartPojo", - consumes = MediaType.MULTIPART_FORM_DATA_VALUE, - produces = MediaType.TEXT_PLAIN_VALUE) + consumes = MediaType.MULTIPART_FORM_DATA_VALUE, + produces = MediaType.TEXT_PLAIN_VALUE) String multipartPojo(@RequestPart("hello") String hello, - @RequestPart("world") String world, - @RequestPart("pojo1") Hello pojo1, - @RequestPart("pojo2") Hello pojo2, - @RequestPart("file") MultipartFile file) { - return hello + world + pojo1.getMessage() + pojo2.getMessage() + file.getOriginalFilename(); + @RequestPart("world") String world, @RequestPart("pojo1") Hello pojo1, + @RequestPart("pojo2") Hello pojo2, + @RequestPart("file") MultipartFile file) { + return hello + world + pojo1.getMessage() + pojo2.getMessage() + + file.getOriginalFilename(); } @RequestMapping(method = RequestMethod.POST, path = "/multipartNames", @@ -1135,11 +1135,11 @@ String multipartFilenames(HttpServletRequest request) throws Exception { } @RequestMapping(method = RequestMethod.POST, path = "/multipartPojosFiles", - consumes = MediaType.MULTIPART_FORM_DATA_VALUE, - produces = MediaType.TEXT_PLAIN_VALUE) + consumes = MediaType.MULTIPART_FORM_DATA_VALUE, + produces = MediaType.TEXT_PLAIN_VALUE) String requestPartListOfPojosAndListOfMultipartFiles( - @RequestPart("pojos") List pojos, - @RequestPart("files") List files) { + @RequestPart("pojos") List pojos, + @RequestPart("files") List files) { StringBuilder result = new StringBuilder(); for (Hello pojo : pojos) { @@ -1152,6 +1152,7 @@ String requestPartListOfPojosAndListOfMultipartFiles( return result.toString(); } + } public static class Hello { From c8c1f0b0ae96b230cd46a6892a242007e991b4bb Mon Sep 17 00:00:00 2001 From: Darren Foong Date: Sun, 29 Mar 2020 12:17:30 +0800 Subject: [PATCH 15/28] Update license year and authors --- .../cloud/openfeign/FeignClientsConfiguration.java | 3 ++- .../cloud/openfeign/support/PojoJsonSerializationWriter.java | 3 +++ .../cloud/openfeign/support/PojoSerializationWriter.java | 3 +++ .../springframework/cloud/openfeign/support/SpringEncoder.java | 3 ++- .../cloud/openfeign/support/SpringMvcContract.java | 3 ++- .../cloud/openfeign/support/SpringPojoFormEncoder.java | 3 +++ .../cloud/openfeign/valid/FeignClientTests.java | 3 ++- 7 files changed, 17 insertions(+), 4 deletions(-) diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java index 3bbf82d91..037697f23 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -55,6 +55,7 @@ /** * @author Dave Syer * @author Venil Noronha + * @author Darren Foong */ @Configuration(proxyBeanMethods = false) public class FeignClientsConfiguration { diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoJsonSerializationWriter.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoJsonSerializationWriter.java index a53cb000d..1382dd015 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoJsonSerializationWriter.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoJsonSerializationWriter.java @@ -24,6 +24,9 @@ import org.springframework.http.MediaType; import org.springframework.stereotype.Component; +/** + * @author Darren Foong + */ @Component public class PojoJsonSerializationWriter extends PojoSerializationWriter { diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoSerializationWriter.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoSerializationWriter.java index 8263e983d..5229255d9 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoSerializationWriter.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoSerializationWriter.java @@ -29,6 +29,9 @@ import static feign.form.ContentProcessor.CRLF; import static feign.form.util.PojoUtil.isUserPojo; +/** + * @author Darren Foong + */ public abstract class PojoSerializationWriter extends AbstractWriter { @Override diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringEncoder.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringEncoder.java index 7dd274c9f..f6e1e5946 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringEncoder.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringEncoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -54,6 +54,7 @@ * @author Scien Jus * @author Ahmad Mozafarnia * @author Aaron Whiteside + * @author Darren Foong */ public class SpringEncoder implements Encoder { diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringMvcContract.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringMvcContract.java index 827c3c157..1f4dbc4c5 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringMvcContract.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringMvcContract.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -75,6 +75,7 @@ * @author Olga Maciaszek-Sharma * @author Aaron Whiteside * @author Artyom Romanenko + * @author Darren Foong */ public class SpringMvcContract extends Contract.BaseContract implements ResourceLoaderAware { diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringPojoFormEncoder.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringPojoFormEncoder.java index 8ed90b3f7..6ebd2869f 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringPojoFormEncoder.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringPojoFormEncoder.java @@ -21,6 +21,9 @@ import static feign.form.ContentType.MULTIPART; +/** + * @author Darren Foong + */ public class SpringPojoFormEncoder extends SpringFormEncoder { public SpringPojoFormEncoder(PojoSerializationWriter pojoSerializationWriter) { diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java index 482130213..3461d563f 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2019 the original author or authors. + * Copyright 2013-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -109,6 +109,7 @@ * @author Erik Kringen * @author Halvdan Hoem Grelland * @author Aaron Whiteside + * @author Darren Foong */ @RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(classes = FeignClientTests.Application.class, From e33e0fd7ad760febf178f5cc15096fa55f73c69a Mon Sep 17 00:00:00 2001 From: Darren Foong Date: Sun, 29 Mar 2020 12:34:59 +0800 Subject: [PATCH 16/28] Tidy isApplicable --- .../cloud/openfeign/support/PojoSerializationWriter.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoSerializationWriter.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoSerializationWriter.java index 5229255d9..b30a40cd5 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoSerializationWriter.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoSerializationWriter.java @@ -36,8 +36,12 @@ public abstract class PojoSerializationWriter extends AbstractWriter { @Override public boolean isApplicable(Object object) { - return !(object instanceof MultipartFile) && !(object instanceof MultipartFile[]) - && (isUserPojoCollection(object) || isUserPojo(object)); + boolean isMultipartFileOrCollection = (object instanceof MultipartFile) + || (object instanceof MultipartFile[]); + boolean isUserPojoOrCollection = isUserPojoCollection(object) + || isUserPojo(object); + + return !isMultipartFileOrCollection && isUserPojoOrCollection; } @Override From d18b7ab2fff5eb4f1940fcfb8b88bcfa64599d33 Mon Sep 17 00:00:00 2001 From: Darren Foong Date: Sun, 29 Mar 2020 12:44:00 +0800 Subject: [PATCH 17/28] Refactor isApplicable --- .../support/PojoSerializationWriter.java | 32 +++++++------------ 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoSerializationWriter.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoSerializationWriter.java index b30a40cd5..99b823c19 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoSerializationWriter.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoSerializationWriter.java @@ -18,10 +18,12 @@ import java.io.IOException; import java.util.Iterator; +import java.util.function.Predicate; import feign.codec.EncodeException; import feign.form.multipart.AbstractWriter; import feign.form.multipart.Output; +import feign.form.util.PojoUtil; import org.springframework.http.MediaType; import org.springframework.web.multipart.MultipartFile; @@ -36,12 +38,8 @@ public abstract class PojoSerializationWriter extends AbstractWriter { @Override public boolean isApplicable(Object object) { - boolean isMultipartFileOrCollection = (object instanceof MultipartFile) - || (object instanceof MultipartFile[]); - boolean isUserPojoOrCollection = isUserPojoCollection(object) - || isUserPojo(object); - - return !isMultipartFileOrCollection && isUserPojoOrCollection; + return !isTypeOrCollection(object, o -> o instanceof MultipartFile) + && isTypeOrCollection(object, PojoUtil::isUserPojo); } @Override @@ -65,28 +63,20 @@ public void write(Output output, String key, Object object) throws EncodeExcepti protected abstract String serialize(Object object) throws IOException; - private boolean isUserPojoCollection(Object object) { - // TODO Refactor! + private boolean isTypeOrCollection(Object object, Predicate isType) { if (object.getClass().isArray()) { Object[] array = (Object[]) object; - return array.length > 1 && isUserPojo(array[0]); - } - - if (!(object instanceof Iterable)) { - return false; + return array.length > 1 && isType.test(array[0]); } + else if (object instanceof Iterable) { + Iterable iterable = (Iterable) object; + Iterator iterator = iterable.iterator(); - Iterable iterable = (Iterable) object; - Iterator iterator = iterable.iterator(); - - if (iterator.hasNext()) { - Object next = iterator.next(); - - return !(next instanceof MultipartFile) && isUserPojo(next); + return iterator.hasNext() && isType.test(iterator.next()); } else { - return false; + return isType.test(object); } } From 974bf01be77b8404e3e749b54b8829342011d408 Mon Sep 17 00:00:00 2001 From: Darren Foong Date: Sun, 29 Mar 2020 12:50:41 +0800 Subject: [PATCH 18/28] Rename classes and methods --- .../cloud/openfeign/FeignClientsConfiguration.java | 4 ++-- ...onSerializationWriter.java => JsonPojoFormWriter.java} | 4 ++-- .../{PojoSerializationWriter.java => PojoFormWriter.java} | 6 +++--- .../cloud/openfeign/support/SpringEncoder.java | 2 +- .../cloud/openfeign/support/SpringPojoFormEncoder.java | 2 +- .../cloud/openfeign/valid/FeignClientTests.java | 8 ++++---- 6 files changed, 13 insertions(+), 13 deletions(-) rename spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/{PojoJsonSerializationWriter.java => JsonPojoFormWriter.java} (89%) rename spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/{PojoSerializationWriter.java => PojoFormWriter.java} (92%) diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java index 037697f23..78033c09b 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java @@ -40,7 +40,7 @@ import org.springframework.boot.autoconfigure.http.HttpMessageConverters; import org.springframework.cloud.openfeign.support.PageJacksonModule; import org.springframework.cloud.openfeign.support.PageableSpringEncoder; -import org.springframework.cloud.openfeign.support.PojoSerializationWriter; +import org.springframework.cloud.openfeign.support.PojoFormWriter; import org.springframework.cloud.openfeign.support.ResponseEntityDecoder; import org.springframework.cloud.openfeign.support.SpringDecoder; import org.springframework.cloud.openfeign.support.SpringEncoder; @@ -76,7 +76,7 @@ public class FeignClientsConfiguration { private SpringDataWebProperties springDataWebProperties; @Autowired(required = false) - private PojoSerializationWriter pojoSerializationWriter; + private PojoFormWriter pojoSerializationWriter; @Bean @ConditionalOnMissingBean diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoJsonSerializationWriter.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/JsonPojoFormWriter.java similarity index 89% rename from spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoJsonSerializationWriter.java rename to spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/JsonPojoFormWriter.java index 1382dd015..17074e0ef 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoJsonSerializationWriter.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/JsonPojoFormWriter.java @@ -28,7 +28,7 @@ * @author Darren Foong */ @Component -public class PojoJsonSerializationWriter extends PojoSerializationWriter { +public class JsonPojoFormWriter extends PojoFormWriter { @Autowired private ObjectMapper objectMapper; @@ -39,7 +39,7 @@ protected MediaType getContentType() { } @Override - protected String serialize(Object object) throws IOException { + protected String writePojoAsString(Object object) throws IOException { return objectMapper.writeValueAsString(object); } diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoSerializationWriter.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoFormWriter.java similarity index 92% rename from spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoSerializationWriter.java rename to spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoFormWriter.java index 99b823c19..3a2d180c8 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoSerializationWriter.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoFormWriter.java @@ -34,7 +34,7 @@ /** * @author Darren Foong */ -public abstract class PojoSerializationWriter extends AbstractWriter { +public abstract class PojoFormWriter extends AbstractWriter { @Override public boolean isApplicable(Object object) { @@ -50,7 +50,7 @@ public void write(Output output, String key, Object object) throws EncodeExcepti .append('"').append(CRLF).append("Content-Type: ") .append(getContentType()).append("; charset=") .append(output.getCharset().name()).append(CRLF).append(CRLF) - .append(serialize(object)).toString(); + .append(writePojoAsString(object)).toString(); output.write(string); } @@ -61,7 +61,7 @@ public void write(Output output, String key, Object object) throws EncodeExcepti protected abstract MediaType getContentType(); - protected abstract String serialize(Object object) throws IOException; + protected abstract String writePojoAsString(Object object) throws IOException; private boolean isTypeOrCollection(Object object, Predicate isType) { if (object.getClass().isArray()) { diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringEncoder.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringEncoder.java index f6e1e5946..e8fcdeb89 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringEncoder.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringEncoder.java @@ -69,7 +69,7 @@ public SpringEncoder(ObjectFactory messageConverters) { this.messageConverters = messageConverters; } - public SpringEncoder(PojoSerializationWriter writer, + public SpringEncoder(PojoFormWriter writer, ObjectFactory messageConverters) { this.springFormEncoder = new SpringPojoFormEncoder(writer); this.messageConverters = messageConverters; diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringPojoFormEncoder.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringPojoFormEncoder.java index 6ebd2869f..d5030e76e 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringPojoFormEncoder.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringPojoFormEncoder.java @@ -26,7 +26,7 @@ */ public class SpringPojoFormEncoder extends SpringFormEncoder { - public SpringPojoFormEncoder(PojoSerializationWriter pojoSerializationWriter) { + public SpringPojoFormEncoder(PojoFormWriter pojoSerializationWriter) { super(); MultipartFormContentProcessor processor = (MultipartFormContentProcessor) getContentProcessor( diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java index 3461d563f..2a61bfff8 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java @@ -75,8 +75,8 @@ import org.springframework.cloud.openfeign.FeignFormatterRegistrar; import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient; import org.springframework.cloud.openfeign.support.FallbackCommand; -import org.springframework.cloud.openfeign.support.PojoJsonSerializationWriter; -import org.springframework.cloud.openfeign.support.PojoSerializationWriter; +import org.springframework.cloud.openfeign.support.JsonPojoFormWriter; +import org.springframework.cloud.openfeign.support.PojoFormWriter; import org.springframework.cloud.openfeign.test.NoSecurityConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -979,8 +979,8 @@ public OtherArg parse(String text, Locale locale) } @Bean - public PojoSerializationWriter pojoSerializationWriter() { - return new PojoJsonSerializationWriter(); + public PojoFormWriter pojoSerializationWriter() { + return new JsonPojoFormWriter(); } @RequestMapping(method = RequestMethod.GET, path = "/hello") From 75066f980922087b4e4858dd429d88a36cc5a3c3 Mon Sep 17 00:00:00 2001 From: Darren Foong Date: Sun, 29 Mar 2020 12:57:40 +0800 Subject: [PATCH 19/28] Change variable names --- .../cloud/openfeign/FeignClientsConfiguration.java | 13 ++++++------- .../openfeign/support/SpringPojoFormEncoder.java | 4 ++-- .../cloud/openfeign/valid/FeignClientTests.java | 2 +- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java index 78033c09b..9a07d4861 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java @@ -76,7 +76,7 @@ public class FeignClientsConfiguration { private SpringDataWebProperties springDataWebProperties; @Autowired(required = false) - private PojoFormWriter pojoSerializationWriter; + private PojoFormWriter pojoFormWriter; @Bean @ConditionalOnMissingBean @@ -89,9 +89,8 @@ public Decoder feignDecoder() { @ConditionalOnMissingBean @ConditionalOnMissingClass("org.springframework.data.domain.Pageable") public Encoder feignEncoder() { - if (this.pojoSerializationWriter != null) { - return new SpringEncoder(this.pojoSerializationWriter, - this.messageConverters); + if (this.pojoFormWriter != null) { + return new SpringEncoder(this.pojoFormWriter, this.messageConverters); } else { return new SpringEncoder(this.messageConverters); @@ -104,9 +103,9 @@ public Encoder feignEncoder() { public Encoder feignEncoderPageable() { PageableSpringEncoder encoder; - if (this.pojoSerializationWriter != null) { - encoder = new PageableSpringEncoder(new SpringEncoder( - this.pojoSerializationWriter, this.messageConverters)); + if (this.pojoFormWriter != null) { + encoder = new PageableSpringEncoder( + new SpringEncoder(this.pojoFormWriter, this.messageConverters)); } else { encoder = new PageableSpringEncoder( diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringPojoFormEncoder.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringPojoFormEncoder.java index d5030e76e..634048c51 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringPojoFormEncoder.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringPojoFormEncoder.java @@ -26,12 +26,12 @@ */ public class SpringPojoFormEncoder extends SpringFormEncoder { - public SpringPojoFormEncoder(PojoFormWriter pojoSerializationWriter) { + public SpringPojoFormEncoder(PojoFormWriter pojoFormWriter) { super(); MultipartFormContentProcessor processor = (MultipartFormContentProcessor) getContentProcessor( MULTIPART); - processor.addFirstWriter(pojoSerializationWriter); + processor.addFirstWriter(pojoFormWriter); } } diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java index 2a61bfff8..426daa700 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java @@ -979,7 +979,7 @@ public OtherArg parse(String text, Locale locale) } @Bean - public PojoFormWriter pojoSerializationWriter() { + public PojoFormWriter pojoFormWriter() { return new JsonPojoFormWriter(); } From 9a9112f189088e910106811e295454eea4f9853d Mon Sep 17 00:00:00 2001 From: Darren Foong Date: Thu, 9 Apr 2020 19:56:40 +0800 Subject: [PATCH 20/28] Rename PojoFormWriter to AbstractFormWriter --- .../cloud/openfeign/FeignClientsConfiguration.java | 12 ++++++------ .../{PojoFormWriter.java => AbstractFormWriter.java} | 6 +++--- .../{JsonPojoFormWriter.java => JsonFormWriter.java} | 4 ++-- .../cloud/openfeign/support/SpringEncoder.java | 2 +- .../openfeign/support/SpringPojoFormEncoder.java | 4 ++-- .../cloud/openfeign/valid/FeignClientTests.java | 8 ++++---- 6 files changed, 18 insertions(+), 18 deletions(-) rename spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/{PojoFormWriter.java => AbstractFormWriter.java} (92%) rename spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/{JsonPojoFormWriter.java => JsonFormWriter.java} (90%) diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java index 9a07d4861..afdcbd72a 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java @@ -38,9 +38,9 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.data.web.SpringDataWebProperties; import org.springframework.boot.autoconfigure.http.HttpMessageConverters; +import org.springframework.cloud.openfeign.support.AbstractFormWriter; import org.springframework.cloud.openfeign.support.PageJacksonModule; import org.springframework.cloud.openfeign.support.PageableSpringEncoder; -import org.springframework.cloud.openfeign.support.PojoFormWriter; import org.springframework.cloud.openfeign.support.ResponseEntityDecoder; import org.springframework.cloud.openfeign.support.SpringDecoder; import org.springframework.cloud.openfeign.support.SpringEncoder; @@ -76,7 +76,7 @@ public class FeignClientsConfiguration { private SpringDataWebProperties springDataWebProperties; @Autowired(required = false) - private PojoFormWriter pojoFormWriter; + private AbstractFormWriter abstractFormWriter; @Bean @ConditionalOnMissingBean @@ -89,8 +89,8 @@ public Decoder feignDecoder() { @ConditionalOnMissingBean @ConditionalOnMissingClass("org.springframework.data.domain.Pageable") public Encoder feignEncoder() { - if (this.pojoFormWriter != null) { - return new SpringEncoder(this.pojoFormWriter, this.messageConverters); + if (this.abstractFormWriter != null) { + return new SpringEncoder(this.abstractFormWriter, this.messageConverters); } else { return new SpringEncoder(this.messageConverters); @@ -103,9 +103,9 @@ public Encoder feignEncoder() { public Encoder feignEncoderPageable() { PageableSpringEncoder encoder; - if (this.pojoFormWriter != null) { + if (this.abstractFormWriter != null) { encoder = new PageableSpringEncoder( - new SpringEncoder(this.pojoFormWriter, this.messageConverters)); + new SpringEncoder(this.abstractFormWriter, this.messageConverters)); } else { encoder = new PageableSpringEncoder( diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoFormWriter.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/AbstractFormWriter.java similarity index 92% rename from spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoFormWriter.java rename to spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/AbstractFormWriter.java index 3a2d180c8..1be7ad791 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/PojoFormWriter.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/AbstractFormWriter.java @@ -34,7 +34,7 @@ /** * @author Darren Foong */ -public abstract class PojoFormWriter extends AbstractWriter { +public abstract class AbstractFormWriter extends AbstractWriter { @Override public boolean isApplicable(Object object) { @@ -50,7 +50,7 @@ public void write(Output output, String key, Object object) throws EncodeExcepti .append('"').append(CRLF).append("Content-Type: ") .append(getContentType()).append("; charset=") .append(output.getCharset().name()).append(CRLF).append(CRLF) - .append(writePojoAsString(object)).toString(); + .append(writeAsString(object)).toString(); output.write(string); } @@ -61,7 +61,7 @@ public void write(Output output, String key, Object object) throws EncodeExcepti protected abstract MediaType getContentType(); - protected abstract String writePojoAsString(Object object) throws IOException; + protected abstract String writeAsString(Object object) throws IOException; private boolean isTypeOrCollection(Object object, Predicate isType) { if (object.getClass().isArray()) { diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/JsonPojoFormWriter.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/JsonFormWriter.java similarity index 90% rename from spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/JsonPojoFormWriter.java rename to spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/JsonFormWriter.java index 17074e0ef..82aa4be3e 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/JsonPojoFormWriter.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/JsonFormWriter.java @@ -28,7 +28,7 @@ * @author Darren Foong */ @Component -public class JsonPojoFormWriter extends PojoFormWriter { +public class JsonFormWriter extends AbstractFormWriter { @Autowired private ObjectMapper objectMapper; @@ -39,7 +39,7 @@ protected MediaType getContentType() { } @Override - protected String writePojoAsString(Object object) throws IOException { + protected String writeAsString(Object object) throws IOException { return objectMapper.writeValueAsString(object); } diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringEncoder.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringEncoder.java index e8fcdeb89..965f2c0b9 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringEncoder.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringEncoder.java @@ -69,7 +69,7 @@ public SpringEncoder(ObjectFactory messageConverters) { this.messageConverters = messageConverters; } - public SpringEncoder(PojoFormWriter writer, + public SpringEncoder(AbstractFormWriter writer, ObjectFactory messageConverters) { this.springFormEncoder = new SpringPojoFormEncoder(writer); this.messageConverters = messageConverters; diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringPojoFormEncoder.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringPojoFormEncoder.java index 634048c51..cb29d4b43 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringPojoFormEncoder.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringPojoFormEncoder.java @@ -26,12 +26,12 @@ */ public class SpringPojoFormEncoder extends SpringFormEncoder { - public SpringPojoFormEncoder(PojoFormWriter pojoFormWriter) { + public SpringPojoFormEncoder(AbstractFormWriter abstractFormWriter) { super(); MultipartFormContentProcessor processor = (MultipartFormContentProcessor) getContentProcessor( MULTIPART); - processor.addFirstWriter(pojoFormWriter); + processor.addFirstWriter(abstractFormWriter); } } diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java index 426daa700..c2e82bfb4 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java @@ -74,9 +74,9 @@ import org.springframework.cloud.openfeign.FeignClient; import org.springframework.cloud.openfeign.FeignFormatterRegistrar; import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient; +import org.springframework.cloud.openfeign.support.AbstractFormWriter; import org.springframework.cloud.openfeign.support.FallbackCommand; -import org.springframework.cloud.openfeign.support.JsonPojoFormWriter; -import org.springframework.cloud.openfeign.support.PojoFormWriter; +import org.springframework.cloud.openfeign.support.JsonFormWriter; import org.springframework.cloud.openfeign.test.NoSecurityConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -979,8 +979,8 @@ public OtherArg parse(String text, Locale locale) } @Bean - public PojoFormWriter pojoFormWriter() { - return new JsonPojoFormWriter(); + public AbstractFormWriter pojoFormWriter() { + return new JsonFormWriter(); } @RequestMapping(method = RequestMethod.GET, path = "/hello") From 1b515cb403bce106b8e7252a3840efffa5789bbd Mon Sep 17 00:00:00 2001 From: Darren Foong Date: Thu, 9 Apr 2020 23:18:09 +0800 Subject: [PATCH 21/28] Rename method --- .../springframework/cloud/openfeign/valid/FeignClientTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java index c2e82bfb4..86ef5f502 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/valid/FeignClientTests.java @@ -979,7 +979,7 @@ public OtherArg parse(String text, Locale locale) } @Bean - public AbstractFormWriter pojoFormWriter() { + public AbstractFormWriter jsonFormWriter() { return new JsonFormWriter(); } From a5e07ba37b03c4b2b3320c098f59469d6272680a Mon Sep 17 00:00:00 2001 From: Darren Foong Date: Fri, 10 Apr 2020 14:30:57 +0800 Subject: [PATCH 22/28] Use ObjectProvider --- .../openfeign/FeignClientsConfiguration.java | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java index afdcbd72a..228b5e975 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java @@ -31,6 +31,7 @@ import feign.optionals.OptionalDecoder; import org.springframework.beans.factory.ObjectFactory; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -76,7 +77,7 @@ public class FeignClientsConfiguration { private SpringDataWebProperties springDataWebProperties; @Autowired(required = false) - private AbstractFormWriter abstractFormWriter; + private AbstractFormWriter formWriter; @Bean @ConditionalOnMissingBean @@ -88,9 +89,11 @@ public Decoder feignDecoder() { @Bean @ConditionalOnMissingBean @ConditionalOnMissingClass("org.springframework.data.domain.Pageable") - public Encoder feignEncoder() { - if (this.abstractFormWriter != null) { - return new SpringEncoder(this.abstractFormWriter, this.messageConverters); + public Encoder feignEncoder(ObjectProvider formWriterProvider) { + AbstractFormWriter formWriter = formWriterProvider.getIfAvailable(); + + if (formWriter != null) { + return new SpringEncoder(formWriter, this.messageConverters); } else { return new SpringEncoder(this.messageConverters); @@ -100,12 +103,15 @@ public Encoder feignEncoder() { @Bean @ConditionalOnClass(name = "org.springframework.data.domain.Pageable") @ConditionalOnMissingBean - public Encoder feignEncoderPageable() { + public Encoder feignEncoderPageable( + ObjectProvider formWriterProvider) { + AbstractFormWriter formWriter = formWriterProvider.getIfAvailable(); + PageableSpringEncoder encoder; - if (this.abstractFormWriter != null) { + if (formWriter != null) { encoder = new PageableSpringEncoder( - new SpringEncoder(this.abstractFormWriter, this.messageConverters)); + new SpringEncoder(formWriter, this.messageConverters)); } else { encoder = new PageableSpringEncoder( From 33a279b2b4eff92796c2bf08e0981897ff80b8bd Mon Sep 17 00:00:00 2001 From: Darren Foong Date: Fri, 10 Apr 2020 14:50:07 +0800 Subject: [PATCH 23/28] Change constructor of SpringEncoder to move SpringPojoFormEncoder to FeignClientsConfiguration --- .../openfeign/FeignClientsConfiguration.java | 27 +++++++++++--- .../openfeign/support/SpringEncoder.java | 9 +---- .../support/SpringPojoFormEncoder.java | 37 ------------------- .../proto/ProtobufNotInClasspathTest.java | 4 +- .../proto/ProtobufSpringEncoderTest.java | 3 +- 5 files changed, 29 insertions(+), 51 deletions(-) delete mode 100644 spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringPojoFormEncoder.java diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java index 228b5e975..1153647a3 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java @@ -27,6 +27,8 @@ import feign.Retryer; import feign.codec.Decoder; import feign.codec.Encoder; +import feign.form.MultipartFormContentProcessor; +import feign.form.spring.SpringFormEncoder; import feign.hystrix.HystrixFeign; import feign.optionals.OptionalDecoder; @@ -53,6 +55,8 @@ import org.springframework.format.support.DefaultFormattingConversionService; import org.springframework.format.support.FormattingConversionService; +import static feign.form.ContentType.MULTIPART; + /** * @author Dave Syer * @author Venil Noronha @@ -93,10 +97,11 @@ public Encoder feignEncoder(ObjectProvider formWriterProvide AbstractFormWriter formWriter = formWriterProvider.getIfAvailable(); if (formWriter != null) { - return new SpringEncoder(formWriter, this.messageConverters); + return new SpringEncoder(new SpringPojoFormEncoder(formWriter), + this.messageConverters); } else { - return new SpringEncoder(this.messageConverters); + return new SpringEncoder(new SpringFormEncoder(), this.messageConverters); } } @@ -110,12 +115,12 @@ public Encoder feignEncoderPageable( PageableSpringEncoder encoder; if (formWriter != null) { - encoder = new PageableSpringEncoder( - new SpringEncoder(formWriter, this.messageConverters)); + encoder = new PageableSpringEncoder(new SpringEncoder( + new SpringPojoFormEncoder(formWriter), this.messageConverters)); } else { encoder = new PageableSpringEncoder( - new SpringEncoder(this.messageConverters)); + new SpringEncoder(new SpringFormEncoder(), this.messageConverters)); } if (springDataWebProperties != null) { @@ -183,4 +188,16 @@ public Feign.Builder feignHystrixBuilder() { } + private class SpringPojoFormEncoder extends SpringFormEncoder { + + SpringPojoFormEncoder(AbstractFormWriter abstractFormWriter) { + super(); + + MultipartFormContentProcessor processor = (MultipartFormContentProcessor) getContentProcessor( + MULTIPART); + processor.addFirstWriter(abstractFormWriter); + } + + } + } diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringEncoder.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringEncoder.java index 965f2c0b9..fc97112ab 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringEncoder.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringEncoder.java @@ -64,14 +64,9 @@ public class SpringEncoder implements Encoder { private final ObjectFactory messageConverters; - public SpringEncoder(ObjectFactory messageConverters) { - this.springFormEncoder = new SpringFormEncoder(); - this.messageConverters = messageConverters; - } - - public SpringEncoder(AbstractFormWriter writer, + public SpringEncoder(SpringFormEncoder springFormEncoder, ObjectFactory messageConverters) { - this.springFormEncoder = new SpringPojoFormEncoder(writer); + this.springFormEncoder = springFormEncoder; this.messageConverters = messageConverters; } diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringPojoFormEncoder.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringPojoFormEncoder.java deleted file mode 100644 index cb29d4b43..000000000 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringPojoFormEncoder.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2013-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.openfeign.support; - -import feign.form.MultipartFormContentProcessor; -import feign.form.spring.SpringFormEncoder; - -import static feign.form.ContentType.MULTIPART; - -/** - * @author Darren Foong - */ -public class SpringPojoFormEncoder extends SpringFormEncoder { - - public SpringPojoFormEncoder(AbstractFormWriter abstractFormWriter) { - super(); - - MultipartFormContentProcessor processor = (MultipartFormContentProcessor) getContentProcessor( - MULTIPART); - processor.addFirstWriter(abstractFormWriter); - } - -} diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/encoding/proto/ProtobufNotInClasspathTest.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/encoding/proto/ProtobufNotInClasspathTest.java index 1fada18c8..d637dc9be 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/encoding/proto/ProtobufNotInClasspathTest.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/encoding/proto/ProtobufNotInClasspathTest.java @@ -17,6 +17,7 @@ package org.springframework.cloud.openfeign.encoding.proto; import feign.RequestTemplate; +import feign.form.spring.SpringFormEncoder; import org.junit.Test; import org.junit.runner.RunWith; @@ -49,7 +50,8 @@ public HttpMessageConverters getObject() throws BeansException { }; RequestTemplate requestTemplate = new RequestTemplate(); requestTemplate.method(POST); - new SpringEncoder(converters).encode("a=b", String.class, requestTemplate); + new SpringEncoder(new SpringFormEncoder(), converters).encode("a=b", String.class, + requestTemplate); } } diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/encoding/proto/ProtobufSpringEncoderTest.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/encoding/proto/ProtobufSpringEncoderTest.java index a450fe8b0..a813637c7 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/encoding/proto/ProtobufSpringEncoderTest.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/encoding/proto/ProtobufSpringEncoderTest.java @@ -26,6 +26,7 @@ import com.google.protobuf.InvalidProtocolBufferException; import feign.RequestTemplate; +import feign.form.spring.SpringFormEncoder; import feign.httpclient.ApacheHttpClient; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; @@ -116,7 +117,7 @@ public HttpMessageConverters getObject() throws BeansException { return new HttpMessageConverters(new ProtobufHttpMessageConverter()); } }; - return new SpringEncoder(converters); + return new SpringEncoder(new SpringFormEncoder(), converters); } private RequestTemplate newRequestTemplate() { From 93050f3f9922698ac69575abda7503250660c7c2 Mon Sep 17 00:00:00 2001 From: Darren Foong Date: Fri, 10 Apr 2020 14:54:13 +0800 Subject: [PATCH 24/28] Rename variables --- .../cloud/openfeign/FeignClientsConfiguration.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java index 1153647a3..aa1a84b05 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java @@ -190,12 +190,12 @@ public Feign.Builder feignHystrixBuilder() { private class SpringPojoFormEncoder extends SpringFormEncoder { - SpringPojoFormEncoder(AbstractFormWriter abstractFormWriter) { + SpringPojoFormEncoder(AbstractFormWriter formWriter) { super(); MultipartFormContentProcessor processor = (MultipartFormContentProcessor) getContentProcessor( MULTIPART); - processor.addFirstWriter(abstractFormWriter); + processor.addFirstWriter(formWriter); } } From dcc120ea21ca061b6a0d902cac85a482d7d7c4c4 Mon Sep 17 00:00:00 2001 From: Darren Foong Date: Sat, 11 Apr 2020 23:56:23 +0800 Subject: [PATCH 25/28] Remove unused variable --- .../cloud/openfeign/FeignClientsConfiguration.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java index aa1a84b05..923e7f134 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java @@ -80,9 +80,6 @@ public class FeignClientsConfiguration { @Autowired(required = false) private SpringDataWebProperties springDataWebProperties; - @Autowired(required = false) - private AbstractFormWriter formWriter; - @Bean @ConditionalOnMissingBean public Decoder feignDecoder() { From a1440a49c28748129371551556135d10243e9ccb Mon Sep 17 00:00:00 2001 From: Darren Foong Date: Sun, 12 Apr 2020 00:15:21 +0800 Subject: [PATCH 26/28] Extract springEncoder() method --- .../openfeign/FeignClientsConfiguration.java | 36 ++++++++----------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java index 923e7f134..af37d4498 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/FeignClientsConfiguration.java @@ -91,15 +91,7 @@ public Decoder feignDecoder() { @ConditionalOnMissingBean @ConditionalOnMissingClass("org.springframework.data.domain.Pageable") public Encoder feignEncoder(ObjectProvider formWriterProvider) { - AbstractFormWriter formWriter = formWriterProvider.getIfAvailable(); - - if (formWriter != null) { - return new SpringEncoder(new SpringPojoFormEncoder(formWriter), - this.messageConverters); - } - else { - return new SpringEncoder(new SpringFormEncoder(), this.messageConverters); - } + return springEncoder(formWriterProvider); } @Bean @@ -107,18 +99,8 @@ public Encoder feignEncoder(ObjectProvider formWriterProvide @ConditionalOnMissingBean public Encoder feignEncoderPageable( ObjectProvider formWriterProvider) { - AbstractFormWriter formWriter = formWriterProvider.getIfAvailable(); - - PageableSpringEncoder encoder; - - if (formWriter != null) { - encoder = new PageableSpringEncoder(new SpringEncoder( - new SpringPojoFormEncoder(formWriter), this.messageConverters)); - } - else { - encoder = new PageableSpringEncoder( - new SpringEncoder(new SpringFormEncoder(), this.messageConverters)); - } + PageableSpringEncoder encoder = new PageableSpringEncoder( + springEncoder(formWriterProvider)); if (springDataWebProperties != null) { encoder.setPageParameter( @@ -171,6 +153,18 @@ public Module pageJacksonModule() { return new PageJacksonModule(); } + private Encoder springEncoder(ObjectProvider formWriterProvider) { + AbstractFormWriter formWriter = formWriterProvider.getIfAvailable(); + + if (formWriter != null) { + return new SpringEncoder(new SpringPojoFormEncoder(formWriter), + this.messageConverters); + } + else { + return new SpringEncoder(new SpringFormEncoder(), this.messageConverters); + } + } + @Configuration(proxyBeanMethods = false) @ConditionalOnClass({ HystrixCommand.class, HystrixFeign.class }) protected static class HystrixFeignConfiguration { From 3b7f9b28daf5507f7be4cf03058f031d51310caa Mon Sep 17 00:00:00 2001 From: Darren Foong Date: Sun, 12 Apr 2020 00:22:39 +0800 Subject: [PATCH 27/28] Restore previous constructor --- .../cloud/openfeign/support/SpringEncoder.java | 7 ++++++- .../encoding/proto/ProtobufNotInClasspathTest.java | 4 +--- .../encoding/proto/ProtobufSpringEncoderTest.java | 3 +-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringEncoder.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringEncoder.java index fc97112ab..ed99a2b9b 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringEncoder.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringEncoder.java @@ -60,10 +60,15 @@ public class SpringEncoder implements Encoder { private static final Log log = LogFactory.getLog(SpringEncoder.class); - private SpringFormEncoder springFormEncoder; + private final SpringFormEncoder springFormEncoder; private final ObjectFactory messageConverters; + public SpringEncoder(ObjectFactory messageConverters) { + this.springFormEncoder = new SpringFormEncoder(); + this.messageConverters = messageConverters; + } + public SpringEncoder(SpringFormEncoder springFormEncoder, ObjectFactory messageConverters) { this.springFormEncoder = springFormEncoder; diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/encoding/proto/ProtobufNotInClasspathTest.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/encoding/proto/ProtobufNotInClasspathTest.java index d637dc9be..1fada18c8 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/encoding/proto/ProtobufNotInClasspathTest.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/encoding/proto/ProtobufNotInClasspathTest.java @@ -17,7 +17,6 @@ package org.springframework.cloud.openfeign.encoding.proto; import feign.RequestTemplate; -import feign.form.spring.SpringFormEncoder; import org.junit.Test; import org.junit.runner.RunWith; @@ -50,8 +49,7 @@ public HttpMessageConverters getObject() throws BeansException { }; RequestTemplate requestTemplate = new RequestTemplate(); requestTemplate.method(POST); - new SpringEncoder(new SpringFormEncoder(), converters).encode("a=b", String.class, - requestTemplate); + new SpringEncoder(converters).encode("a=b", String.class, requestTemplate); } } diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/encoding/proto/ProtobufSpringEncoderTest.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/encoding/proto/ProtobufSpringEncoderTest.java index a813637c7..a450fe8b0 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/encoding/proto/ProtobufSpringEncoderTest.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/encoding/proto/ProtobufSpringEncoderTest.java @@ -26,7 +26,6 @@ import com.google.protobuf.InvalidProtocolBufferException; import feign.RequestTemplate; -import feign.form.spring.SpringFormEncoder; import feign.httpclient.ApacheHttpClient; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; @@ -117,7 +116,7 @@ public HttpMessageConverters getObject() throws BeansException { return new HttpMessageConverters(new ProtobufHttpMessageConverter()); } }; - return new SpringEncoder(new SpringFormEncoder(), converters); + return new SpringEncoder(converters); } private RequestTemplate newRequestTemplate() { From 1799adea319f0abb33fdc6a3ef425ed0951d8985 Mon Sep 17 00:00:00 2001 From: Darren Foong Date: Sun, 12 Apr 2020 00:30:54 +0800 Subject: [PATCH 28/28] Extract isMultipartFormData() method --- .../openfeign/support/SpringMvcContract.java | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringMvcContract.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringMvcContract.java index 1f4dbc4c5..433c93358 100644 --- a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringMvcContract.java +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringMvcContract.java @@ -276,17 +276,6 @@ private void checkOne(Method method, Object[] values, String fieldName) { @Override protected boolean processAnnotationsOnParameter(MethodMetadata data, Annotation[] annotations, int paramIndex) { - boolean isMultipartFormData = false; - - Collection contentTypes = data.template().headers() - .get(HttpEncoding.CONTENT_TYPE); - - if (contentTypes != null && !contentTypes.isEmpty()) { - String type = contentTypes.iterator().next(); - isMultipartFormData = Objects.equals(MediaType.valueOf(type), - MediaType.MULTIPART_FORM_DATA); - } - boolean isHttpAnnotation = false; AnnotatedParameterProcessor.AnnotatedParameterContext context = new SimpleAnnotatedParameterContext( @@ -306,7 +295,7 @@ protected boolean processAnnotationsOnParameter(MethodMetadata data, } } - if (!isMultipartFormData && isHttpAnnotation + if (!isMultipartFormData(data) && isHttpAnnotation && data.indexToExpander().get(paramIndex) == null) { TypeDescriptor typeDescriptor = createTypeDescriptor(method, paramIndex); if (this.conversionService.canConvert(typeDescriptor, @@ -404,6 +393,18 @@ private boolean shouldAddParameterName(int parameterIndex, Type[] parameterTypes && parameterTypes != null && parameterTypes.length > parameterIndex; } + private boolean isMultipartFormData(MethodMetadata data) { + Collection contentTypes = data.template().headers() + .get(HttpEncoding.CONTENT_TYPE); + + if (contentTypes != null && !contentTypes.isEmpty()) { + String type = contentTypes.iterator().next(); + return Objects.equals(MediaType.valueOf(type), MediaType.MULTIPART_FORM_DATA); + } + + return false; + } + /** * @deprecated Not used internally anymore. Will be removed in the future. */