Skip to content

Commit

Permalink
Handling custom ErrorDecoder (#6)
Browse files Browse the repository at this point in the history
* ErrorDecoder handling
* Version update & changelogs

Co-authored-by: SEBASTIEN MONEUSE - E437830 <sebastien.moneuse@ext.mpsa.com>
  • Loading branch information
smoneuse and psa-smo committed Nov 6, 2020
1 parent 4024e06 commit 65146b2
Show file tree
Hide file tree
Showing 12 changed files with 146 additions and 1 deletion.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Version 1.5.0 (2020-11-06)

* [new] Support configuration of injectable custom error decoders using the `errorDecoder` configuration property.
# Version 1.4.0 (2020-08-05)

* [new] Support configuration of injectable endpoint request interceptors using the `interceptors` configuration property.
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

<groupId>org.seedstack.addons.feign</groupId>
<artifactId>feign</artifactId>
<version>1.4.0-SNAPSHOT</version>
<version>1.5.0-SNAPSHOT</version>
<properties>
<seed.version>3.10.0</seed.version>
<feign.version>11.0</feign.version>
Expand Down
10 changes: 10 additions & 0 deletions src/main/java/org/seedstack/feign/FeignConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import feign.Target.HardCodedTarget;
import feign.codec.Decoder;
import feign.codec.Encoder;
import feign.codec.ErrorDecoder;
import feign.jackson.JacksonDecoder;
import feign.jackson.JacksonEncoder;
import feign.slf4j.Slf4jLogger;
Expand Down Expand Up @@ -72,6 +73,7 @@ public static class EndpointConfig {
@NotNull
private HystrixWrapperMode hystrixWrapper = HystrixWrapperMode.AUTO;
private Class<?> fallback;
private Class<?extends ErrorDecoder> errorDecoder;

public String getBaseUrl() {
return baseUrl;
Expand Down Expand Up @@ -210,5 +212,13 @@ public List<Class<? extends RequestInterceptor>> getInterceptors() {
public void addInterceptor(Class<? extends RequestInterceptor> interceptor) {
this.interceptors.add(interceptor);
}

public Class<? extends ErrorDecoder> getErrorDecoder() {
return errorDecoder;
}

public void setErrorDecoder(Class<? extends ErrorDecoder> errorDecoder) {
this.errorDecoder = errorDecoder;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ public enum FeignErrorCode implements ErrorCode {
ERROR_INSTANTIATING_TARGET,
ERROR_INSTANTIATING_FALLBACK,
ERROR_INSTANTIATING_LOGGER,
ERROR_INSTANTIATING_ERROR_DECODER,
HYSTRIX_NOT_PRESENT
}
3 changes: 3 additions & 0 deletions src/main/java/org/seedstack/feign/internal/FeignPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ protected InitState initialize(InitContext initContext) {
}
bindings.add(endpointConfig.getEncoder());
bindings.add(endpointConfig.getDecoder());
if(endpointConfig.getErrorDecoder() !=null) {
bindings.add(endpointConfig.getErrorDecoder());
}
bindings.add(endpointConfig.getLogger());
Class<?> fallback = endpointConfig.getFallback();
if (fallback != null) {
Expand Down
14 changes: 14 additions & 0 deletions src/main/java/org/seedstack/feign/internal/FeignProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import feign.Target.HardCodedTarget;
import feign.codec.Decoder;
import feign.codec.Encoder;
import feign.codec.ErrorDecoder;
import feign.hystrix.FallbackFactory;
import feign.hystrix.HystrixFeign;
import org.seedstack.feign.FeignConfig;
Expand Down Expand Up @@ -53,6 +54,10 @@ public Object get() {
builder.contract(instantiateContract(endpointConfig.getContract()));
}

if(endpointConfig.getErrorDecoder() != null){
builder.errorDecoder(instantiateErrorDecoder(endpointConfig.getErrorDecoder()));
}

// Logger
builder.logger(instantiateLogger(endpointConfig.getLogger()));
builder.logLevel(endpointConfig.getLogLevel());
Expand Down Expand Up @@ -155,6 +160,15 @@ private Decoder instantiateDecoder(Class<? extends Decoder> decoderClass) {
}
}

private ErrorDecoder instantiateErrorDecoder(Class<? extends ErrorDecoder> errorDecoderClass){
try{
return injector.getInstance(errorDecoderClass);
}catch (Exception e){
throw SeedException.wrap(e, FeignErrorCode.ERROR_INSTANTIATING_ERROR_DECODER)
.put("class", errorDecoderClass);
}
}

private Target<T> instantiateTarget(EndpointConfig endpointConfig) {
Class<? extends Target<T>> targetClass = endpointConfig.getTarget(feignApi);
if (HardCodedTarget.class.equals(targetClass)) {
Expand Down
20 changes: 20 additions & 0 deletions src/test/java/org/seedstack/feign/AbstractFeignIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
*/
package org.seedstack.feign;

import feign.FeignException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.seedstack.feign.fixtures.FeignTestException;
import org.seedstack.feign.fixtures.Message;
import org.seedstack.feign.fixtures.TestContract;
import org.seedstack.feign.fixtures.TestInterceptor;
Expand Down Expand Up @@ -51,6 +53,9 @@ public abstract class AbstractFeignIT {
@Inject
private TargetableAPI targetableAPI;

@Inject
private ErrorDecoderTestAPI errorDecoderTestAPI;

@Test
public void feignClientIsInjectable() throws Exception {
assertThat(testAPI).isNotNull();
Expand Down Expand Up @@ -143,4 +148,19 @@ public void testTargetableNominalCall() {
assertThat(message.getAuthor()).isEqualTo("or i thought so");
}

@Test
public void testErrorDecoderAPI(){
boolean exceptionHasBeenRaised=false;
assertThat(errorDecoderTestAPI).isNotNull();
try {
errorDecoderTestAPI.fakeRequest();
}
catch(Exception e){
assertThat(e.getCause()).isInstanceOf(FeignTestException.class);
assertThat(e.getCause().getMessage()).isEqualTo("Feign addon unit test : received HTTP 404 error code");
exceptionHasBeenRaised=true;
}
assertThat(exceptionHasBeenRaised).isTrue();
}

}
21 changes: 21 additions & 0 deletions src/test/java/org/seedstack/feign/fixtures/FeignTestException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Copyright © 2013-2020, The SeedStack authors <http://seedstack.org>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.seedstack.feign.fixtures;

/**
* Feign addon test exception
*/
public class FeignTestException extends Exception{
/**
* Statndard constructor
* @param message exception message
*/
public FeignTestException(String message){
super(message);
}
}
36 changes: 36 additions & 0 deletions src/test/java/org/seedstack/feign/fixtures/TestErrorDecoder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright © 2013-2020, The SeedStack authors <http://seedstack.org>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.seedstack.feign.fixtures;

import feign.FeignException;
import feign.Response;
import feign.codec.ErrorDecoder;

/**
* Custom Error Decoder
*/
public class TestErrorDecoder implements ErrorDecoder {

/**
* Treat request error, as used in a unit test, resolving with a specific error message in the exception that should be verified in the unit test
* @param methodKey The method key
* @param response the feign request response
* @return Exception
*/
@Override
public Exception decode(String methodKey, Response response) {
switch (response.status()){
case 404 : {
return new FeignTestException("Feign addon unit test : received HTTP 404 error code");
}
default:{
return new FeignTestException(response.reason());
}
}
}
}
8 changes: 8 additions & 0 deletions src/test/java/org/seedstack/feign/fixtures/TestResource.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.seedstack.seed.Logging;
import org.slf4j.Logger;

Expand Down Expand Up @@ -52,4 +54,10 @@ public Message timeout() {
public Message targetSay() {
return new Message("I was routed trough a custom target", "or i thought so");
}

@GET
@Path("/testErrorDecoder")
public Response notFound(){
return Response.status(Response.Status.NOT_FOUND).entity("There is no content here").build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright © 2013-2020, The SeedStack authors <http://seedstack.org>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.seedstack.feign.fixtures.apis;

import feign.RequestLine;
import org.seedstack.feign.FeignApi;
import org.seedstack.feign.fixtures.Message;

/**
* Unit test API for error handling
*/
@FeignApi
public interface ErrorDecoderTestAPI {

/**
* Requesting the endpoint responding HTTP 204
*/
@RequestLine("GET /testErrorDecoder")
Message fakeRequest();
}
4 changes: 4 additions & 0 deletions src/test/resources/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ feign:
logLevel: BASIC
target: org.seedstack.feign.fixtures.TestTarget
hystrixWrapper: DISABLED
org.seedstack.feign.fixtures.apis.ErrorDecoderTestAPI:
baseUrl: ${runtime.web.baseUrl}/feign
errorDecoder: org.seedstack.feign.fixtures.TestErrorDecoder
hystrixWrapper: DISABLED

security:
users:
Expand Down

0 comments on commit 65146b2

Please sign in to comment.