From 525bb603f78e9a70308f104dc0493caf3c61e9bd Mon Sep 17 00:00:00 2001 From: Can Bezmen Date: Tue, 28 Apr 2020 18:46:56 +0300 Subject: [PATCH] Fix sort problem for serialize and deserialize. Unit test added. --- .../openfeign/FeignClientsConfiguration.java | 23 +++++--- .../openfeign/support/SortJacksonModule.java | 35 +++++++++++++ .../encoding/FeignPageableEncodingTests.java | 10 ++++ .../support/PageJacksonModuleTests.java | 18 +------ .../support/SortJacksonModuleTests.java | 52 +++++++++++++++++++ 5 files changed, 114 insertions(+), 24 deletions(-) create mode 100644 spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SortJacksonModule.java create mode 100644 spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/support/SortJacksonModuleTests.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 af37d449..97fb278a 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 @@ -45,6 +45,7 @@ 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.ResponseEntityDecoder; +import org.springframework.cloud.openfeign.support.SortJacksonModule; import org.springframework.cloud.openfeign.support.SpringDecoder; import org.springframework.cloud.openfeign.support.SpringEncoder; import org.springframework.cloud.openfeign.support.SpringMvcContract; @@ -84,7 +85,7 @@ public class FeignClientsConfiguration { @ConditionalOnMissingBean public Decoder feignDecoder() { return new OptionalDecoder( - new ResponseEntityDecoder(new SpringDecoder(this.messageConverters))); + new ResponseEntityDecoder(new SpringDecoder(this.messageConverters))); } @Bean @@ -98,17 +99,17 @@ public class FeignClientsConfiguration { @ConditionalOnClass(name = "org.springframework.data.domain.Pageable") @ConditionalOnMissingBean public Encoder feignEncoderPageable( - ObjectProvider formWriterProvider) { + ObjectProvider formWriterProvider) { PageableSpringEncoder encoder = new PageableSpringEncoder( - springEncoder(formWriterProvider)); + springEncoder(formWriterProvider)); if (springDataWebProperties != null) { encoder.setPageParameter( - springDataWebProperties.getPageable().getPageParameter()); + springDataWebProperties.getPageable().getPageParameter()); encoder.setSizeParameter( - springDataWebProperties.getPageable().getSizeParameter()); + springDataWebProperties.getPageable().getSizeParameter()); encoder.setSortParameter( - springDataWebProperties.getSort().getSortParameter()); + springDataWebProperties.getSort().getSortParameter()); } return encoder; } @@ -153,12 +154,18 @@ public class FeignClientsConfiguration { return new PageJacksonModule(); } + @Bean + @ConditionalOnClass(name = "org.springframework.data.domain.Page") + public Module sortModule() { + return new SortJacksonModule(); + } + private Encoder springEncoder(ObjectProvider formWriterProvider) { AbstractFormWriter formWriter = formWriterProvider.getIfAvailable(); if (formWriter != null) { return new SpringEncoder(new SpringPojoFormEncoder(formWriter), - this.messageConverters); + this.messageConverters); } else { return new SpringEncoder(new SpringFormEncoder(), this.messageConverters); @@ -185,7 +192,7 @@ public class FeignClientsConfiguration { super(); MultipartFormContentProcessor processor = (MultipartFormContentProcessor) getContentProcessor( - MULTIPART); + MULTIPART); processor.addFirstWriter(formWriter); } diff --git a/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SortJacksonModule.java b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SortJacksonModule.java new file mode 100644 index 00000000..e70857b5 --- /dev/null +++ b/spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SortJacksonModule.java @@ -0,0 +1,35 @@ +package org.springframework.cloud.openfeign.support; + +import com.fasterxml.jackson.core.Version; +import com.fasterxml.jackson.databind.Module; +import com.fasterxml.jackson.databind.module.SimpleDeserializers; +import com.fasterxml.jackson.databind.module.SimpleSerializers; + +import org.springframework.data.domain.Sort; + +/** + * This jackson module provides support to add serialize and deserialize for spring {@link Sort} object. + * @author canbezmen + */ +public class SortJacksonModule extends Module { + @Override + public String getModuleName() { + return "SortModule"; + } + + @Override + public Version version() { + return new Version(0, 1, 0, "", null, null); + } + + @Override + public void setupModule(SetupContext context) { + SimpleSerializers serializers = new SimpleSerializers(); + serializers.addSerializer(Sort.class, new SortJsonComponent.SortSerializer()); + context.addSerializers(serializers); + + SimpleDeserializers deserializers = new SimpleDeserializers(); + deserializers.addDeserializer(Sort.class, new SortJsonComponent.SortDeserializer()); + context.addDeserializers(deserializers); + } +} diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/encoding/FeignPageableEncodingTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/encoding/FeignPageableEncodingTests.java index 8224dfd8..524bb550 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/encoding/FeignPageableEncodingTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/encoding/FeignPageableEncodingTests.java @@ -21,6 +21,8 @@ import java.util.Collections; import com.netflix.loadbalancer.BaseLoadBalancer; import com.netflix.loadbalancer.ILoadBalancer; import com.netflix.loadbalancer.Server; +import java.util.Optional; + import org.junit.Test; import org.junit.runner.RunWith; @@ -81,6 +83,14 @@ public class FeignPageableEncodingTests { assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(response.getBody()).isNotNull(); assertThat(pageable.getPageSize()).isEqualTo(response.getBody().getSize()); + assertThat(response.getBody().getPageable().getSort()).hasSize(1); + Optional optionalOrder = response.getBody().getPageable().getSort().get() + .findFirst(); + if (optionalOrder.isPresent()) { + Sort.Order order = optionalOrder.get(); + assertThat(order.getDirection()).isEqualTo(Sort.Direction.ASC); + assertThat(order.getProperty()).isEqualTo("sortProperty"); + } } diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/support/PageJacksonModuleTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/support/PageJacksonModuleTests.java index 6e954a23..465617fd 100644 --- a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/support/PageJacksonModuleTests.java +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/support/PageJacksonModuleTests.java @@ -16,16 +16,12 @@ package org.springframework.cloud.openfeign.support; -import java.util.Optional; - import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.module.SimpleModule; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.springframework.data.domain.Page; -import org.springframework.data.domain.Sort; import static org.assertj.core.api.Assertions.assertThat; @@ -39,16 +35,13 @@ public class PageJacksonModuleTests { @BeforeAll public static void initialize() { objectMapper = new ObjectMapper(); - SimpleModule module = new SimpleModule(); - module.addSerializer(Sort.class, new SortJsonComponent.SortSerializer()); - module.addDeserializer(Sort.class, new SortJsonComponent.SortDeserializer()); - objectMapper.registerModules(new PageJacksonModule(), module); + objectMapper.registerModule(new PageJacksonModule()); } @Test public void deserializePage() throws JsonProcessingException { // Given - String pageJson = "{\"content\":[\"A name\"],\"number\":1,\"size\":2,\"totalElements\":3,\"sort\":[{\"direction\":\"ASC\",\"property\":\"field\",\"ignoreCase\":false,\"nullHandling\":\"NATIVE\",\"descending\":false,\"ascending\":true}]}"; + String pageJson = "{\"content\":[\"A name\"], \"number\":1, \"size\":2, \"totalElements\": 3}"; // When Page result = objectMapper.readValue(pageJson, Page.class); // Then @@ -58,13 +51,6 @@ public class PageJacksonModuleTests { assertThat(result.getPageable()).isNotNull(); assertThat(result.getPageable().getPageSize()).isEqualTo(2); assertThat(result.getPageable().getPageNumber()).isEqualTo(1); - assertThat(result.getPageable().getSort()).hasSize(1); - Optional optionalOrder = result.getPageable().getSort().get().findFirst(); - if (optionalOrder.isPresent()) { - Sort.Order order = optionalOrder.get(); - assertThat(order.getDirection()).isEqualTo(Sort.Direction.ASC); - assertThat(order.getProperty()).isEqualTo("field"); - } } } diff --git a/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/support/SortJacksonModuleTests.java b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/support/SortJacksonModuleTests.java new file mode 100644 index 00000000..27f0c92b --- /dev/null +++ b/spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/support/SortJacksonModuleTests.java @@ -0,0 +1,52 @@ +package org.springframework.cloud.openfeign.support; + +import java.util.Optional; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Sort; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author canbezmen + */ +class SortJacksonModuleTests { + + private static ObjectMapper objectMapper; + + @BeforeAll + public static void initialize() { + objectMapper = new ObjectMapper(); + objectMapper.registerModules(new PageJacksonModule()); + objectMapper.registerModule(new SortJacksonModule()); + } + + @Test + public void deserializePage() throws JsonProcessingException { + // Given + String pageJson = "{\"content\":[\"A name\"],\"number\":1,\"size\":2,\"totalElements\":3,\"sort\":[{\"direction\":\"ASC\",\"property\":\"field\",\"ignoreCase\":false,\"nullHandling\":\"NATIVE\",\"descending\":false,\"ascending\":true}]}"; + // When + Page result = objectMapper.readValue(pageJson, Page.class); + // Then + assertThat(result).isNotNull(); + assertThat(result.getTotalElements()).isEqualTo(3); + assertThat(result.getContent()).hasSize(1); + assertThat(result.getPageable()).isNotNull(); + assertThat(result.getPageable().getPageSize()).isEqualTo(2); + assertThat(result.getPageable().getPageNumber()).isEqualTo(1); + assertThat(result.getPageable().getSort()).hasSize(1); + Optional optionalOrder = result.getPageable().getSort().get() + .findFirst(); + if (optionalOrder.isPresent()) { + Sort.Order order = optionalOrder.get(); + assertThat(order.getDirection()).isEqualTo(Sort.Direction.ASC); + assertThat(order.getProperty()).isEqualTo("field"); + } + } + +}