Compare commits

...
Author SHA1 Message Date
buildmaster c2430c0e29 Update SNAPSHOT to 2.2.5.RELEASE 2020-08-28 20:02:41 +00:00
Olga Maciaszek-Sharma b66e08fda8 Fix the docs. 2020-08-13 14:37:55 +02:00
spencergibb 84819e1328 Bumps s-c-build to 2.3.2.BUILD-SNAPSHOT 2020-08-03 13:21:35 -04:00
spencergibb b6422db8e9 ignores .sdkmanrc 2020-08-03 13:21:17 -04:00
Olga Maciaszek-Sharma 4bf010e810 Ignore InvalidMediaTypeException when verifying if Multipart content. Fixes gh-363. (#388) 2020-08-03 10:02:05 +02:00
buildmaster bd671efed9 Bumping versions to 2.2.5.BUILD-SNAPSHOT after release 2020-07-31 20:53:35 +00:00
buildmaster bfd473cb8f Going back to snapshots 2020-07-31 20:53:35 +00:00
buildmaster 2f5d63a061 Update SNAPSHOT to 2.2.4.RELEASE 2020-07-31 20:51:47 +00:00
Olga Maciaszek-Sharma 14929cbfee Revert "Fix double @RequestMapping with empty value (#245)"
This reverts commit 0afb60a72a.

# Conflicts:
#	spring-cloud-openfeign-core/src/main/java/org/springframework/cloud/openfeign/support/SpringMvcContract.java
#	spring-cloud-openfeign-core/src/test/java/org/springframework/cloud/openfeign/support/SpringMvcContractTests.java
2020-07-30 16:18:25 +02:00
11 changed files with 153 additions and 111 deletions
+1
View File
@@ -20,4 +20,5 @@ _site/
*.swo
.vscode/
.flattened-pom.xml
.sdkmanrc
+1 -1
View File
@@ -6,7 +6,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-openfeign</artifactId>
<version>2.2.4.BUILD-SNAPSHOT</version>
<version>2.2.5.RELEASE</version>
</parent>
<artifactId>spring-cloud-openfeign-docs</artifactId>
<packaging>pom</packaging>
@@ -112,7 +112,7 @@ public interface StoreClient {
}
----
Spring Cloud Netflix provides the following beans by default for feign (`BeanType` beanName: `ClassName`):
Spring Cloud OpenFeign provides the following beans by default for feign (`BeanType` beanName: `ClassName`):
* `Decoder` feignDecoder: `ResponseEntityDecoder` (which wraps a `SpringDecoder`)
* `Encoder` feignEncoder: `SpringEncoder`
@@ -305,7 +305,7 @@ class FooController {
----
NOTE: In the above example `FeignClientsConfiguration.class` is the default configuration
provided by Spring Cloud Netflix.
provided by Spring Cloud OpenFeign.
NOTE: `PROD-SVC` is the name of the service the Clients will be making requests to.
@@ -388,7 +388,7 @@ WARNING: There is a limitation with the implementation of fallbacks in Feign and
=== Feign and `@Primary`
When using Feign with Hystrix fallbacks, there are multiple beans in the `ApplicationContext` of the same type. This will cause `@Autowired` to not work because there isn't exactly one bean, or one marked as primary. To work around this, Spring Cloud Netflix marks all Feign instances as `@Primary`, so Spring Framework will know which bean to inject. In some cases, this may not be desirable. To turn off this behavior set the `primary` attribute of `@FeignClient` to false.
When using Feign with Hystrix fallbacks, there are multiple beans in the `ApplicationContext` of the same type. This will cause `@Autowired` to not work because there isn't exactly one bean, or one marked as primary. To work around this, Spring Cloud OpenFeign marks all Feign instances as `@Primary`, so Spring Framework will know which bean to inject. In some cases, this may not be desirable. To turn off this behavior set the `primary` attribute of `@FeignClient` to false.
[source,java,indent=0]
----
+4 -4
View File
@@ -4,14 +4,14 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-openfeign</artifactId>
<version>2.2.4.BUILD-SNAPSHOT</version>
<version>2.2.5.RELEASE</version>
<packaging>pom</packaging>
<name>Spring Cloud OpenFeign</name>
<description>Spring Cloud OpenFeign</description>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-build</artifactId>
<version>2.3.1.BUILD-SNAPSHOT</version>
<version>2.3.1.RELEASE</version>
<relativePath/>
</parent>
<scm>
@@ -26,8 +26,8 @@
<properties>
<main.basedir>${basedir}</main.basedir>
<jackson.version>2.7.3</jackson.version>
<spring-cloud-commons.version>2.2.4.BUILD-SNAPSHOT</spring-cloud-commons.version>
<spring-cloud-netflix.version>2.2.4.BUILD-SNAPSHOT</spring-cloud-netflix.version>
<spring-cloud-commons.version>2.2.5.RELEASE</spring-cloud-commons.version>
<spring-cloud-netflix.version>2.2.5.RELEASE</spring-cloud-netflix.version>
<!-- Plugin versions -->
<maven-compiler-plugin.version>3.6.1</maven-compiler-plugin.version>
+1 -7
View File
@@ -6,7 +6,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-openfeign</artifactId>
<version>2.2.4.BUILD-SNAPSHOT</version>
<version>2.2.5.RELEASE</version>
<relativePath>..</relativePath> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-cloud-openfeign-core</artifactId>
@@ -231,12 +231,6 @@
<artifactId>spring-cloud-loadbalancer</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>pl.pragmatists</groupId>
<artifactId>JUnitParams</artifactId>
<version>1.1.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<profiles>
<profile>
@@ -57,6 +57,7 @@ import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.ResourceLoader;
import org.springframework.http.InvalidMediaTypeException;
import org.springframework.http.MediaType;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -173,14 +174,15 @@ public class SpringMvcContract extends Contract.BaseContract
if (clz.getInterfaces().length == 0) {
RequestMapping classAnnotation = findMergedAnnotation(clz,
RequestMapping.class);
if (classAnnotation != null && classAnnotation.value().length > 0) {
if (classAnnotation != null) {
// Prepend path from class annotation if specified
String pathValue = emptyToNull(classAnnotation.value()[0]);
if (pathValue != null) {
if (classAnnotation.value().length > 0) {
String pathValue = emptyToNull(classAnnotation.value()[0]);
pathValue = resolve(pathValue);
if (!pathValue.equals("/")) {
data.template().uri(pathValue);
if (!pathValue.startsWith("/")) {
pathValue = "/" + pathValue;
}
data.template().uri(pathValue);
}
}
}
@@ -240,9 +242,11 @@ public class SpringMvcContract extends Contract.BaseContract
String pathValue = emptyToNull(methodMapping.value()[0]);
if (pathValue != null) {
pathValue = resolve(pathValue);
if (!pathValue.equals("/")) {
data.template().uri(pathValue, true);
// Append path from @RequestMapping if value is present on method
if (!pathValue.startsWith("/") && !data.template().path().endsWith("/")) {
pathValue = "/" + pathValue;
}
data.template().uri(pathValue, true);
}
}
@@ -405,7 +409,13 @@ public class SpringMvcContract extends Contract.BaseContract
if (contentTypes != null && !contentTypes.isEmpty()) {
String type = contentTypes.iterator().next();
return Objects.equals(MediaType.valueOf(type), MediaType.MULTIPART_FORM_DATA);
try {
return Objects.equals(MediaType.valueOf(type),
MediaType.MULTIPART_FORM_DATA);
}
catch (InvalidMediaTypeException ignored) {
return false;
}
}
return false;
@@ -16,6 +16,7 @@
package org.springframework.cloud.openfeign.support;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
@@ -53,6 +54,11 @@ public class PageableSupportTest {
String.valueOf(SocketUtils.findAvailableTcpPort()));
}
@AfterAll
public static void afterClass() {
System.clearProperty("server.port");
}
@Test
void shouldProperlyFormatPageable() {
String direction = feignClient.performRequest(
@@ -0,0 +1,116 @@
/*
* 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.nio.charset.Charset;
import feign.codec.Decoder;
import feign.codec.Encoder;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.cloud.openfeign.test.NoSecurityConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.http.HttpHeaders;
import org.springframework.util.SocketUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;
import static org.assertj.core.api.Assertions.assertThatCode;
/**
* Integration tests for {@link SpringMvcContract}
*
* @author Olga Maciaszek-Sharma
*/
@SpringBootTest(classes = SpringMvcContractIntegrationTests.Config.class,
webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
public class SpringMvcContractIntegrationTests {
@Autowired
private TestClient client;
@BeforeAll
public static void beforeClass() {
System.setProperty("server.port",
String.valueOf(SocketUtils.findAvailableTcpPort()));
}
@AfterAll
public static void afterClass() {
System.clearProperty("server.port");
}
@Test
public void shouldNotThrowInvalidMediaTypeExceptionWhenContentTypeTemplateUsed() {
assertThatCode(() -> client.sendMessage("test", "text/markdown"))
.doesNotThrowAnyException();
}
@FeignClient(name = "test", url = "http://localhost:${server.port}/",
configuration = NoCodecsFeignConfiguration.class)
interface TestClient {
@PostMapping("/test")
Object sendMessage(@RequestBody String message,
@RequestHeader(HttpHeaders.CONTENT_TYPE) String acceptHeader);
}
@Configuration(proxyBeanMethods = false)
@EnableFeignClients(clients = TestClient.class)
@EnableAutoConfiguration
@RestController
@Import(NoSecurityConfiguration.class)
protected static class Config {
@PostMapping("/test")
Object sendMessage(@RequestBody String message,
@RequestHeader(HttpHeaders.CONTENT_TYPE) String acceptHeader) {
return message;
}
}
// avoid feign.codec.EncodeException - this feature works for users that override
// Encoder
protected static class NoCodecsFeignConfiguration {
@Bean
public Decoder decoder() {
return (response, type) -> response;
}
@Bean
public Encoder encoder() {
return (object, bodyType, request) -> request
.body(object.toString().getBytes(), Charset.defaultCharset());
}
}
}
@@ -31,11 +31,8 @@ import java.util.Map;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import feign.MethodMetadata;
import feign.Param;
import junitparams.JUnitParamsRunner;
import junitparams.Parameters;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.cloud.openfeign.CollectionFormat;
import org.springframework.cloud.openfeign.SpringQueryMap;
@@ -75,7 +72,6 @@ import static org.junit.Assume.assumeTrue;
* @author Artyom Romanenko
* @author Olga Maciaszek-Sharma
*/
@RunWith(JUnitParamsRunner.class)
public class SpringMvcContractTests {
private static final Class<?> EXECUTABLE_TYPE;
@@ -602,53 +598,6 @@ public class SpringMvcContractTests {
"{Accept}");
}
private Class[] doubleMappingClassesProvider() {
return new Class[] { TestTemplate_RequestMapping_Empty_Class.class,
TestTemplate_RequestMapping_Empty_Method.class };
}
@Test
@Parameters(method = "doubleMappingClassesProvider")
public void testDoubleRequestMapping_root(Class clazz) throws NoSuchMethodException {
Method method = clazz.getDeclaredMethod("root");
MethodMetadata data = contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertThat(data.template().url()).isEqualTo("/");
}
@Test
@Parameters(method = "doubleMappingClassesProvider")
public void testDoubleRequestMapping_rootReverse(Class clazz)
throws NoSuchMethodException {
Method method = clazz.getDeclaredMethod("rootReverse");
MethodMetadata data = contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertThat(data.template().url()).isEqualTo("/");
}
@Test
@Parameters(method = "doubleMappingClassesProvider")
public void testDoubleRequestMapping_sub(Class clazz) throws NoSuchMethodException {
Method method = clazz.getDeclaredMethod("sub");
MethodMetadata data = contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertThat(data.template().url()).isEqualTo("/sub");
}
@Test
@Parameters(method = "doubleMappingClassesProvider")
public void testDoubleRequestMapping_subEmpty(Class clazz)
throws NoSuchMethodException {
Method method = clazz.getDeclaredMethod("subEmpty");
MethodMetadata data = contract
.parseAndValidateMetadata(method.getDeclaringClass(), method);
assertThat(data.template().url()).isEqualTo("/subEmpty");
}
@Test
public void testMultipleRequestPartAnnotations() throws NoSuchMethodException {
Method method = TestTemplate_RequestPart.class.getDeclaredMethod(
@@ -841,40 +790,6 @@ public class SpringMvcContractTests {
}
@RequestMapping("")
public interface TestTemplate_RequestMapping_Empty_Class {
@RequestMapping("/")
String root();
@RequestMapping("")
String rootReverse();
@RequestMapping("/sub")
String sub();
@RequestMapping("subEmpty")
String subEmpty();
}
@RequestMapping("/")
public interface TestTemplate_RequestMapping_Empty_Method {
@RequestMapping("")
String root();
@RequestMapping("/")
String rootReverse();
@RequestMapping("/sub")
String sub();
@RequestMapping("subEmpty")
String subEmpty();
}
@JsonAutoDetect(fieldVisibility = ANY, getterVisibility = NONE,
setterVisibility = NONE)
public class TestObject {
+2 -2
View File
@@ -6,11 +6,11 @@
<parent>
<artifactId>spring-cloud-dependencies-parent</artifactId>
<groupId>org.springframework.cloud</groupId>
<version>2.3.1.BUILD-SNAPSHOT</version>
<version>2.3.1.RELEASE</version>
<relativePath/>
</parent>
<artifactId>spring-cloud-openfeign-dependencies</artifactId>
<version>2.2.4.BUILD-SNAPSHOT</version>
<version>2.2.5.RELEASE</version>
<packaging>pom</packaging>
<name>spring-cloud-openfeign-dependencies</name>
<description>Spring Cloud OpenFeign Dependencies</description>
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-openfeign</artifactId>
<version>2.2.4.BUILD-SNAPSHOT</version>
<version>2.2.5.RELEASE</version>
<relativePath>..</relativePath>
</parent>
<artifactId>spring-cloud-starter-openfeign</artifactId>