Feign
Feign makes writing java http clients easier
Install / Use
/learn @OpenFeign/FeignREADME
Feign simplifies the process of writing Java HTTP clients
Feign is a Java to HTTP client binder inspired by Retrofit, JAXRS-2.0, and WebSocket. Feign's first goal was reducing the complexity of binding Denominator uniformly to HTTP APIs regardless of ReSTfulness.
Why Feign and not X?
Feign uses tools like Jersey and CXF to write Java clients for ReST or SOAP services. Furthermore, Feign allows you to write your own code on top of http libraries such as Apache HC. Feign connects your code to http APIs with minimal overhead and code via customizable decoders and error handling, which can be written to any text-based http API.
How does Feign work?
Feign works by processing annotations into a templatized request. Arguments are applied to these templates in a straightforward fashion before output. Although Feign is limited to supporting text-based APIs, it dramatically simplifies system aspects such as replaying requests. Furthermore, Feign makes it easy to unit test your conversions knowing this.
Java Version Compatibility
Feign 10.x and above are built on Java 8 and should work on Java 9, 10, and 11. For those that need JDK 6 compatibility, please use Feign 9.x
Feature overview
This is a map with current key features provided by feign:
Roadmap
Feign 11 and beyond
Making API clients easier
Short Term - What we're working on now. ⏰
- Response Caching
- Support caching of api responses. Allow for users to define under what conditions a response is eligible for caching and what type of caching mechanism should be used.
- Support in-memory caching and external cache implementations (EhCache, Google, Spring, etc...)
- Complete URI Template expression support
- Support level 1 through level 4 URI template expressions.
- Use URI Templates TCK to verify compliance.
LoggerAPI refactor- Refactor the
LoggerAPI to adhere closer to frameworks like SLF4J providing a common mental model for logging within Feign. This model will be used by Feign itself throughout and provide clearer direction on how theLoggerwill be used.
- Refactor the
RetryAPI refactor- Refactor the
RetryAPI to support user-supplied conditions and better control over back-off policies. This may result in non-backward-compatible breaking changes
- Refactor the
Medium Term - What's up next. ⏲
- Async execution support via
CompletableFuture- Allow for
Futurechaining and executor management for the request/response lifecycle. Implementation will require non-backward-compatible breaking changes. However this feature is required before Reactive execution can be considered.
- Allow for
- Reactive execution support via Reactive Streams
- For JDK 9+, consider a native implementation that uses
java.util.concurrent.Flow. - Support for Project Reactor and RxJava 2+ implementations on JDK 8.
- For JDK 9+, consider a native implementation that uses
Long Term - The future ☁️
- Additional Circuit Breaker Support.
- Support additional Circuit Breaker implementations like Resilience4J and Spring Circuit Breaker
Usage
The feign library is available from Maven Central.
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-core</artifactId>
<version>??feign.version??</version>
</dependency>
Basics
Usage typically looks like this, an adaptation of the canonical Retrofit sample.
interface GitHub {
@RequestLine("GET /repos/{owner}/{repo}/contributors")
List<Contributor> contributors(@Param("owner") String owner, @Param("repo") String repo);
@RequestLine("POST /repos/{owner}/{repo}/issues")
void createIssue(Issue issue, @Param("owner") String owner, @Param("repo") String repo);
}
public static class Contributor {
String login;
int contributions;
}
public static class Issue {
String title;
String body;
List<String> assignees;
int milestone;
List<String> labels;
}
public class MyApp {
public static void main(String... args) {
GitHub github = Feign.builder()
.decoder(new GsonDecoder())
.target(GitHub.class, "https://api.github.com");
// Fetch and print a list of the contributors to this library.
List<Contributor> contributors = github.contributors("OpenFeign", "feign");
for (Contributor contributor : contributors) {
System.out.println(contributor.login + " (" + contributor.contributions + ")");
}
}
}
Interface Annotations
Feign annotations define the Contract between the interface and how the underlying client
should work. Feign's default contract defines the following annotations:
| Annotation | Interface Target | Usage |
|----------------|------------------|-------|
| @RequestLine | Method | Defines the HttpMethod and UriTemplate for request. Expressions, values wrapped in curly-braces {expression} are resolved using their corresponding @Param annotated parameters. |
| @Param | Parameter | Defines a template variable, whose value will be used to resolve the corresponding template Expression, by name provided as annotation value. If value is missing it will try to get the name from bytecode method parameter name (if the code was compiled with -parameters flag). |
| @Headers | Method, Type | Defines a HeaderTemplate; a variation on a UriTemplate. that uses @Param annotated values to resolve the corresponding Expressions. When used on a Type, the template will be applied to every request. When used on a Method, the template will apply only to the annotated method. |
| @QueryMap | Parameter | Defines a Map of name-value pairs, or POJO, to expand into a query string. |
| @HeaderMap | Parameter | Defines a Map of name-value pairs, to expand into Http Headers |
| @Body | Method | Defines a Template, similar to a UriTemplate and HeaderTemplate, that uses @Param annotated values to resolve the corresponding Expressions.|
Overriding the Request Line
If there is a need to target a request to a different host then the one supplied when the Feign client was created, or you want to supply a target host for each request, include a
java.net.URIparameter and Feign will use that value as the request target.@RequestLine("POST /repos/{owner}/{repo}/issues") void createIssue(URI host, Issue issue, @Param("owner") String owner, @Param("repo") String repo);
Templates and Expressions
Feign Expressions represent Simple String Expressions (Level 1) as defined by URI Template - RFC 6570. Expressions are expanded using
their corresponding Param annotated method parameters.
Example
public interface GitHub {
@RequestLine("GET /repos/{owner}/{repo}/contributors")
List<Contributor> contributors(@Param("owner") String owner, @Param("repo") String repository);
class Contributor {
String login;
int contributions;
}
}
public class MyApp {
public static void main(String[] args) {
GitHub github = Feign.builder()
.decoder(new GsonDecoder())
.target(GitHub.class, "https://api.github.com");
/* The owner and repository parameters will be used to expand the owner and repo expressions
* defined in the RequestLine.
*
* the resulting uri will be https://api.github.com/repos/OpenFeign/feign/contributors
*/
github.contributors("OpenFeign", "feign");
}
}
Expressions must be enclosed in curly braces {} and may contain regular expression patterns, separated by a colon : to restrict
resolved values. Example owner must be alphabetic. {owner:[a-zA-Z]*}
Request Parameter Expansion
RequestLine and QueryMap templates follow the URI Template - RFC 6570 specification for Level 1 templates, which specifies the following:
- Unresolved expressions are omitted.
- All literals and variable values are pct-encoded, if not already encoded or marked
encodedvia a@Paramannotation.
We also have limited support for Level 3, Path Style Expressions, with the following restrictions:
- Maps and Lists are expanded by default.
- Only Single variable templates are supported.
Examples:
{;who} ;who=fred
{;half} ;half=50%25
{;empty} ;empty
{;list} ;list=red;list=green;list=blue
{;map} ;semi=%3B;dot=.;comma=%2C
public interface MatrixService {
@RequestLine("GET /repos{;owners}")
List<Contributor> cont

