Feign
This component allows you to define an HTTP client with a simple Java interface that you can then inject and use transparently in your code.
<dependency>
<groupId>org.seedstack.addons.feign</groupId>
<artifactId>feign</artifactId>
</dependency>
Show version
dependencies {
compile("org.seedstack.addons.feign:feign:1.5.0")
}
How to use
First, you need to create an interface annotated by @FeignApi
, with each method being an HTTP call. Annotate each method with @RequestLine
:
@FeignApi
public interface Api {
@RequestLine("GET /message")
List<Message> getMessages();
@RequestLine("GET /message/{id}")
Message getMessage(@Param("id") int id);
}
Then, you can use this API by injecting it:
public class MyClass {
@Inject
private Api api;
@Logging
private Logger logger;
public void someMethod() {
List<Message> messages = api.getMessages();
for (Message message : messages) {
logger.info("Received message from {}", message.author);
}
}
}
For more information about OpenFeign, look into its documentation: https://github.com/OpenFeign/feign.
Configuration
Configuration is done by
Feign is configurable by endpoint, and in its basic form is:
feign:
endpoints:
com.mycompany.myapp.Api: http://base.url.to.api:port
com.mycompany.myapp.Api
is the fully qualified name of your api interface, and you can add as many as you want.
http://base.url.to.api:port
is the base URL of this API.
With all the options, the configuration file looks like this:
feign:
endpoints:
com.mycompany.myapp.Api:
baseUrl: http://base.url.to.api:port
encoder: feign.jackson.JacksonEncoder
decoder: feign.jackson.JacksonDecoder
errorDecoder: com.mycompany.myapp.MyApiErrorDecoder
logger: feign.slf4j.SLF4JLogger
logLevel: NONE
hystrixWrapper: AUTO
fallback: com.mycompany.myapp.Fallback
retryer: com.mycompany.myapp.MyRetryer
The values in this example are the default values, except for baseUrl
and fallback
that don’t have default values.
baseUrl
is this only mandatory option.encoder
anddecoder
let you configure how your data is transformed when sent and received, respectively.errorDecoder
let you define a custom injectable errorDecoder related to this API for request error handling. (See https://github.com/OpenFeign/feign#error-handling )logger
let you choose which logger to use to log the requests.logLevel
is an enum (NONE
,BASIC
,HEADERS
,FULL
).hystrixWrapper
is an enum (AUTO
,ENABLED
,DISABLED
). Feign comes with Hystrix circuit-breaker support.DISABLED
disables this functionality.ENABLED
tells Feign to wrap all requests in Hystrix mechanism, but the lib Hystrix must be in the classpath of your project.AUTO
mode will scan the classpath and if Hystrix is present, will wrap requests with it.fallback
takes a fully qualified class name and is only relevant when Hystrix is used. The fallback class must implement your API interface and will be used to return default values in case the requests are in error.retryer
let you define a custom injectable Retryer related to this endpoint for retry policy handling. ( See https://github.com/OpenFeign/feign#retry ). See below for more retry configuration options.
Authentication
To call an API protected with authentication you can specify a header in your Feign interface with the @Headers
annotation (example for basic authentication):
@FeignApi
@Headers({"Authorization: Basic {credentials}"})
public interface neosdServer {
@RequestLine("GET /file/getfilesprop")
List<NeosdFile> getfilesprop(@Param("credentials") String credentials);
@RequestLine("GET /file/getfiles")
List<String> getfiles(@Param("credentials") String credentials);
}
Note that @Headers
can also be used on individual methods.
Then, pass the credentials as method parameter. An example implementation, with credentials coming from your application configuration, coudl be:
public class MyClass {
@Configuration("myApp.credentials.user")
private String username;
@Configuration("myApp.credentials.password")
private String password;
@Inject
private NeoSdClient client;
public void myMethod() {
List<String> files = client.getFiles(encodeCredentials());
}
private String encodeCredentials() {
return BaseEncoding
.base64()
.encode((username + ":" + password)
.getBytes(Charsets.UTF_8));
}
}
Fallback
A fallback class is done by implementing the Feign interface and return default values from it:
public class Fallback implements Api {
@Override
List<Message> getMessages() {
// return your default value here
}
@Override
Message getMessage(@Param("id") int id) {
// return your default value here
}
}
For more information on Hystrix: https://github.com/Netflix/Hystrix/wiki
Retry configuration
Feign plugin retry configuration has two levels : global configuration and endpoint configuration.
The endpoint configuration has priority upon global configration, letting you having global settings and, if necessary specific settings for particular endpoints.
To resume, if an endpoint has a retry configuration set, it will be applyed, if not, the global configuration will be applyed, if there is no retry configuration set (global or specific ), the default feign retry configuration will be applyed.
There are two type of retry configuration : standard parameters or retryer class configuration. Both types can’t be defined for the same configuration level (global /endpoint ).
Standard parameters configuration
The following retry parameters can be set :
* period
: The initial time period, in milliseconds, between two requests attemps. Feign will increase this period by half ( multiply by 1.5 ) until it reaches the maximum allowed period.
* maxPeriod
: Maximum allowed period, in milliseconds, between two attempts. Feign won’t increase a retry period more than this parameter.
* maxAttempts
: Maximum retry attempts for a single request. If the request still fails after the last attempt, the feign API will throw an exception.
Global configuration
Here is a sample for global retry configuration, applyed to each endpoint with no retry/retryer configuration
feign:
retry:
period: 100
maxPeriod: 1000
maxAttempts: 3
endpoints:
com.mycompany.myapp.Api: http://base.url.to.api:port
Endpoint configuration
Here is a sample for specific endpoint retry configuration, applyed only to this specific endpoint :
feign:
endpoints:
com.mycompany.myapp.Api: http://base.url.to.api:port
retry:
period: 100
maxPeriod: 1000
maxAttempts: 3
Retryer class configuration
With feign, you can define a retryer having the role to determine if a request should be retryed or not, letting you decide of the retry policy you want to apply to your endpoint ( See https://github.com/OpenFeign/feign#retry ). This feature is supported in the seedstack feign plugin. Your custom retryer class has to implement the feign «Retryer» interface and added to your plugin configuration. Note that this class is injectable.
Global configuration
Here is a sample for global retryer configuration, applyed to each endpoint with no retry/retryer configuration
feign:
retryer: com.mycompany.myapp.MyRetryer
endpoints:
com.mycompany.myapp.Api: http://base.url.to.api:port
Endpoint configuration
Here is a sample for a specific endpoint retryer configuration, applyed only to this specific endpoint :
feign:
endpoints:
com.mycompany.myapp.Api: http://base.url.to.api:port
retryer: com.mycompany.myapp.MyRetryer
To dump the feign
configuration options:
mvn -q -Dargs="feign" seedstack:config