Commit 4ffeff20 by Spencer Gibb

Merge pull request #734 from hscholz/master

* pull734: fixes gh-716 adds option to decode 404s
parents a00fd2c3 66c047e6
...@@ -64,6 +64,11 @@ public @interface FeignClient { ...@@ -64,6 +64,11 @@ public @interface FeignClient {
String url() default ""; String url() default "";
/** /**
* Whether 404s should be decoded instead of throwing FeignExceptions
*/
boolean decode404() default false;
/**
* A custom <code>@Configuration</code> for the feign client. Can contain override * A custom <code>@Configuration</code> for the feign client. Can contain override
* <code>@Bean</code> definition for the pieces that make up the client, for instance * <code>@Bean</code> definition for the pieces that make up the client, for instance
* {@link feign.codec.Decoder}, {@link feign.codec.Encoder}, {@link feign.Contract}. * {@link feign.codec.Decoder}, {@link feign.codec.Encoder}, {@link feign.Contract}.
......
...@@ -55,6 +55,8 @@ class FeignClientFactoryBean implements FactoryBean<Object>, InitializingBean, A ...@@ -55,6 +55,8 @@ class FeignClientFactoryBean implements FactoryBean<Object>, InitializingBean, A
private String url; private String url;
private boolean decode404;
private ApplicationContext context; private ApplicationContext context;
@Override @Override
...@@ -105,6 +107,10 @@ class FeignClientFactoryBean implements FactoryBean<Object>, InitializingBean, A ...@@ -105,6 +107,10 @@ class FeignClientFactoryBean implements FactoryBean<Object>, InitializingBean, A
builder.requestInterceptors(requestInterceptors.values()); builder.requestInterceptors(requestInterceptors.values());
} }
if (decode404) {
builder.decode404();
}
return builder; return builder;
} }
......
...@@ -173,6 +173,7 @@ public class FeignClientsRegistrar implements ImportBeanDefinitionRegistrar, ...@@ -173,6 +173,7 @@ public class FeignClientsRegistrar implements ImportBeanDefinitionRegistrar,
definition.addPropertyValue("url", getUrl(attributes)); definition.addPropertyValue("url", getUrl(attributes));
definition.addPropertyValue("name", getServiceId(attributes)); definition.addPropertyValue("name", getServiceId(attributes));
definition.addPropertyValue("type", className); definition.addPropertyValue("type", className);
definition.addPropertyValue("decode404", attributes.get("decode404"));
definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE); definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
String beanName = StringUtils String beanName = StringUtils
......
...@@ -43,6 +43,7 @@ import org.springframework.web.bind.annotation.RestController; ...@@ -43,6 +43,7 @@ import org.springframework.web.bind.annotation.RestController;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
/** /**
* @author Spencer Gibb * @author Spencer Gibb
...@@ -66,7 +67,12 @@ public class SpringDecoderTests extends FeignClientFactoryBean { ...@@ -66,7 +67,12 @@ public class SpringDecoderTests extends FeignClientFactoryBean {
} }
public TestClient testClient() { public TestClient testClient() {
return testClient(false);
}
public TestClient testClient(boolean decode404) {
setType(this.getClass()); setType(this.getClass());
setDecode404(decode404);
return feign(factory).target(TestClient.class, "http://localhost:" + this.port); return feign(factory).target(TestClient.class, "http://localhost:" + this.port);
} }
...@@ -120,6 +126,13 @@ public class SpringDecoderTests extends FeignClientFactoryBean { ...@@ -120,6 +126,13 @@ public class SpringDecoderTests extends FeignClientFactoryBean {
testClient().getNotFound(); testClient().getNotFound();
} }
@Test
public void testDecodes404() {
final ResponseEntity<String> response = testClient(true).getNotFound();
assertNotNull("response was null", response);
assertNull("response body was not null", response.getBody());
}
@Data @Data
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
......
...@@ -20,6 +20,7 @@ import static org.hamcrest.Matchers.instanceOf; ...@@ -20,6 +20,7 @@ import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
...@@ -91,6 +92,9 @@ public class FeignClientTests { ...@@ -91,6 +92,9 @@ public class FeignClientTests {
private TestClientServiceId testClientServiceId; private TestClientServiceId testClientServiceId;
@Autowired @Autowired
private DecodingTestClient decodingTestClient;
@Autowired
private Client feignClient; private Client feignClient;
@FeignClient(value = "localapp", configuration = TestClientConfig.class) @FeignClient(value = "localapp", configuration = TestClientConfig.class)
...@@ -149,14 +153,21 @@ public class FeignClientTests { ...@@ -149,14 +153,21 @@ public class FeignClientTests {
Hello getHello(); Hello getHello();
} }
@FeignClient(name = "localapp2", decode404 = true)
protected interface DecodingTestClient {
@RequestMapping(method = RequestMethod.GET, value = "/notFound")
ResponseEntity<String> notFound();
}
@Configuration @Configuration
@EnableAutoConfiguration @EnableAutoConfiguration
@RestController @RestController
@EnableFeignClients(clients = {TestClientServiceId.class, TestClient.class}, @EnableFeignClients(clients = {TestClientServiceId.class, TestClient.class, DecodingTestClient.class},
defaultConfiguration = TestDefaultFeignConfig.class) defaultConfiguration = TestDefaultFeignConfig.class)
@RibbonClients({ @RibbonClients({
@RibbonClient(name = "localapp", configuration = LocalRibbonClientConfiguration.class), @RibbonClient(name = "localapp", configuration = LocalRibbonClientConfiguration.class),
@RibbonClient(name = "localapp1", configuration = LocalRibbonClientConfiguration.class) @RibbonClient(name = "localapp1", configuration = LocalRibbonClientConfiguration.class),
@RibbonClient(name = "localapp2", configuration = LocalRibbonClientConfiguration.class)
}) })
protected static class Application { protected static class Application {
...@@ -204,6 +215,11 @@ public class FeignClientTests { ...@@ -204,6 +215,11 @@ public class FeignClientTests {
return ResponseEntity.ok().build(); return ResponseEntity.ok().build();
} }
@RequestMapping(method = RequestMethod.GET, value = "/notFound")
ResponseEntity notFound() {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body((String)null);
}
public static void main(String[] args) { public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).properties( new SpringApplicationBuilder(Application.class).properties(
"spring.application.name=feignclienttest", "spring.application.name=feignclienttest",
...@@ -299,6 +315,14 @@ public class FeignClientTests { ...@@ -299,6 +315,14 @@ public class FeignClientTests {
assertEquals("status code was wrong", HttpStatus.OK, response.getStatusCode()); assertEquals("status code was wrong", HttpStatus.OK, response.getStatusCode());
} }
@Test
public void testDecodeNotFound() {
ResponseEntity response = decodingTestClient.notFound();
assertNotNull("response was null", response);
assertEquals("status code was wrong", HttpStatus.NOT_FOUND, response.getStatusCode());
assertNull("response body was not null", response.getBody());
}
@Data @Data
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment