Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
languagexml
<dependency>
	<groupId>se.sundsvall.dept44</groupId>
	<artifactId>dept44-starter-feign</artifactId>
</dependency>

Alternativ 1 - FeignBuilder

FeignBuilder används, precis som det låter, för att bygga en REST-klient vars metoder definieras i ett interface som annoteras med Spring:s annoteringar för request-mappning, t.ex.:

...

[4] Om angiven (användarnamn och lösenord) sätts Basic-autentisering upp.
[5] Anger connect timeout. Default-värde är 10 sekunder.
[6] Anger read timeout. Default-värde är 60 sekunder.
[7] Anger om REST-klienten ska följa omdirigeringar. Default-värde är true.
[8]-[12] Kan, om så önskas, användas för att exempelvis använda en alternativ HTTP-klient eller för att konfigurera retry-policy och liknande.
[13] Skapar själva REST-klienten, av given typ.

Notera att det inte går att använda FeignBuilder där OAuth2- och Basic-autentisering konfigureras samtidigt.

Alternativ 2 - annoteringar

Först och främst behövs ett klient-interface:

...

Code Block
languagejava
@Import(FeignConfiguration.class)
class GithubClientConfiguration {

    @Bean
    RequestInterceptor basicAuthInterceptor(String username, String password) { [1]
        return FeignHelper.basicAuthInterceptor(username, password);
    }

    @Bean
    FeignBuilderCustomizer feignBuilderCustomizer() {                           [2]
        return FeignHelper.customizeRequestOptions()
            .withConnectTimeout(Duration.ofSeconds(60))
            .withReadTimeout(Duration.ofSeconds(5))
            .build();
    }
    	
    @Bean
	ErrorDecoder errorDecoder() {                                               [3]
		return new GenericJsonErrorDecoder("GithubClient");
	}
}

Ifall konfigurationen definierar någon böna av typen RequestInterceptor, likt [1], kommer den automatiskt att knytas in i Feign-klienten. I exemplet används en utility-klass från ramverket - FeignHelper - för att skapa en interceptor för Basic-autentisering. FeignHelper har även stöd för att jacka in exempelvis en interceptor för OAuth2 och för att anpassa timeouts likt [2].

I exemplet ovan knyts även en generisk ErrorDecoder in i Feign-klienten [3]. Detta är allt som krävs för att klienten skall kunna hantera error-response av Problem-typ (läs mer i befintlig RFC).

Utifrån ovan kan sedan klienten autowire:as in som en vanlig Spring-komponent där den behövs:

Code Block
languagejava
@Component
public class MyClass {
  
  private GithubClient ghClient;
  
  public MyClass(GithubClient ghClient) {
      this.ghClient = ghClient;
  }
  
  public List<Repo> getRepositories(String user) {
      return ghClient.getRepositories(user);
  }

Generisk ErrorDecoder

Ramverket erbjuder en generisk ErrorDecoder. D.v.s. en mappning mellan “error-response” från tjänsten som anropas och exceptions i den egna tjänsten.

Genom att använda den GenericJsonErrorDecoder behöver man inte implementera en egen. Har anropad tjänst även implementerat felhantering enligt https://datatracker.ietf.org/doc/html/rfc7807 behöver man inte göra någonting mer än att skapa bönan i sin konfigurationsklass (se första exemplet nedan).

Om anropad tjänst däremot har uppfunnit en egen modell för fel, kan man behöva peka ut den data man vill mappa med hjälp av JSON-path.

Konfiguration som krävs när back-end implementerat RFC-7807:

Code Block
languagejava
@Import(FeignConfiguration.class)
class GithubClientConfiguration {

    @Bean
	ErrorDecoder errorDecoder() {                                               
		return new GenericJsonErrorDecoder("GithubClient");
	}
}


Konfiguration för fel som avviker från standard. Genom att ange sökvägen via JSON-path till den data vi vill mappa kan vi hantera vilka strukturer på felmeddelandet som helst:

Error-response:

Code Block
languagejson
{
	"errorMessage": "This is a custom error",
	"extraInfo": {
		"details": "This is details",
		"status": "500"
	}
}

Konfiguration:

Code Block
languagejava
@Import(FeignConfiguration.class)
class GithubClientConfiguration {

    @Bean
	ErrorDecoder errorDecoder() {                                               
		new GenericJsonErrorDecoder("GithubClient", new JsonPathSetup(
			"$['errorMessage']", "$['extraInfo']['details']", "$['extraInfo']['status']"))
	}
}