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.
baseUrlis this only mandatory option.encoderanddecoderlet you configure how your data is transformed when sent and received, respectively.errorDecoderlet you define a custom injectable errorDecoder related to this API for request error handling. (See https://github.com/OpenFeign/feign#error-handling )loggerlet you choose which logger to use to log the requests.logLevelis an enum (NONE,BASIC,HEADERS,FULL).hystrixWrapperis an enum (AUTO,ENABLED,DISABLED). Feign comes with Hystrix circuit-breaker support.DISABLEDdisables this functionality.ENABLEDtells Feign to wrap all requests in Hystrix mechanism, but the lib Hystrix must be in the classpath of your project.AUTOmode will scan the classpath and if Hystrix is present, will wrap requests with it.fallbacktakes 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.retryerlet 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
Maven
Gradle