Feign is a Java HTTP client binder that makes writing HTTP clients easier through declarative interfaces and pluggable encoders/decoders
pkg:gradle/com.netflix.feign/feign@8.18.x
npx @tessl/cli install tessl/gradle-com-netflix-feign--feign@8.18.0Feign is a Java HTTP client binder that makes writing HTTP clients easier through declarative interfaces. Inspired by Retrofit, JAXRS-2.0, and WebSocket, Feign reduces the complexity of binding to HTTP APIs regardless of RESTfulness. It works by processing annotations into templated requests, applying arguments just before sending.
dependencies {
compile 'com.netflix.feign:feign-core:8.18.0'
}import feign.Feign;
import feign.RequestLine;
import feign.Param;
import feign.Headers;import feign.Feign;
import feign.RequestLine;
import feign.Param;
import feign.gson.GsonDecoder;
import java.util.List;
// Define API interface with Feign annotations
interface GitHub {
@RequestLine("GET /repos/{owner}/{repo}/contributors")
List<Contributor> contributors(@Param("owner") String owner, @Param("repo") String repo);
}
static class Contributor {
String login;
int contributions;
}
// Create client instance
GitHub github = Feign.builder()
.decoder(new GsonDecoder())
.target(GitHub.class, "https://api.github.com");
// Use the client
List<Contributor> contributors = github.contributors("netflix", "feign");Feign is built around several key components:
The main entry point for creating HTTP clients with extensive configuration options.
/**
* Main factory class for generating HTTP API clients
*/
public abstract class Feign {
/** Creates a new builder for configuring a Feign client */
public static Builder builder();
/** Generates configuration key for method */
public static String configKey(Class targetType, Method method);
/** Creates new API implementation instance */
public abstract <T> T newInstance(Target<T> target);
}
/**
* Fluent builder for configuring Feign HTTP clients
*/
public static class Feign.Builder {
/** Set logging level (NONE, BASIC, HEADERS, FULL) */
public Builder logLevel(Logger.Level logLevel);
/** Set annotation processing contract */
public Builder contract(Contract contract);
/** Set HTTP client implementation */
public Builder client(Client client);
/** Set retry logic */
public Builder retryer(Retryer retryer);
/** Set request/response logger */
public Builder logger(Logger logger);
/** Set request body encoder */
public Builder encoder(Encoder encoder);
/** Set response body decoder */
public Builder decoder(Decoder decoder);
/** Enable 404 decoding as empty response */
public Builder decode404();
/** Set error response decoder */
public Builder errorDecoder(ErrorDecoder errorDecoder);
/** Set request timeout options */
public Builder options(Options options);
/** Add single request interceptor */
public Builder requestInterceptor(RequestInterceptor requestInterceptor);
/** Set all request interceptors */
public Builder requestInterceptors(Iterable<RequestInterceptor> requestInterceptors);
/** Set invocation handler factory */
public Builder invocationHandlerFactory(InvocationHandlerFactory invocationHandlerFactory);
/** Create client for interface and URL */
public <T> T target(Class<T> apiType, String url);
/** Create client for custom target */
public <T> T target(Target<T> target);
/** Build configured Feign instance */
public Feign build();
}Core annotations for defining HTTP API interfaces declaratively.
/**
* HTTP method and URL template annotation
*/
public @interface RequestLine {
/** HTTP method and URL template (e.g., "GET /users/{id}") */
String value();
/** Whether to decode slashes in URL template */
boolean decodeSlash() default true;
}
/**
* Parameter binding for URL templates, headers, and body templates
*/
public @interface Param {
/** Parameter name for template substitution */
String value();
/** Custom parameter expansion logic */
Class<? extends Param.Expander> expander() default ToStringExpander.class;
}
/**
* Static and templated headers
*/
public @interface Headers {
/** Array of header strings with template support */
String[] value();
}
/**
* Templated request body
*/
public @interface Body {
/** Body template with parameter placeholders */
String value();
}
/**
* Map of query parameters
*/
public @interface QueryMap {
/** Whether parameters are pre-encoded */
boolean encoded() default false;
}
/**
* Map of headers
*/
public @interface HeaderMap {
}Pluggable HTTP client interface with default HttpURLConnection implementation.
/**
* HTTP client interface for executing requests
*/
public interface Client {
/** Execute HTTP request with options */
Response execute(Request request, Options options) throws IOException;
/** Default implementation using HttpURLConnection */
public static class Default implements Client {
public Default(SSLSocketFactory sslContextFactory, HostnameVerifier hostnameVerifier);
}
}
/**
* HTTP request configuration options
*/
public static class Request.Options {
public Options(int connectTimeoutMillis, int readTimeoutMillis);
public int connectTimeoutMillis();
public int readTimeoutMillis();
}Pluggable encoder/decoder system for request and response body handling.
/**
* Request body encoding interface
*/
public interface Encoder {
/** Encode object to request body */
void encode(Object object, Type bodyType, RequestTemplate template) throws EncodeException;
/** Default encoder handling String and byte[] */
public static class Default implements Encoder;
}
/**
* Response body decoding interface
*/
public interface Decoder {
/** Decode response body to object */
Object decode(Response response, Type type) throws IOException, DecodeException, FeignException;
/** Default decoder with String, byte[], and 404 handling */
public static class Default implements Decoder;
}
/**
* Error response handling interface
*/
public interface ErrorDecoder {
/** Convert error response to exception */
Exception decode(String methodKey, Response response);
/** Default error decoder creating FeignException */
public static class Default implements ErrorDecoder;
}Target configuration for API interface binding and URL resolution.
/**
* Target configuration interface
*/
public interface Target<T> {
/** Interface class */
Class<T> type();
/** Configuration name */
String name();
/** Base URL */
String url();
/** Apply target-specific request configuration */
Request apply(RequestTemplate input);
/** Simple URL-based target */
public static class HardCodedTarget<T> implements Target<T> {
public HardCodedTarget(Class<T> type, String url);
public HardCodedTarget(Class<T> type, String name, String url);
}
}Feign provides extensive extension modules for popular libraries and frameworks.
JSON encoding and decoding support via popular libraries.
// Gson support
feign.gson.GsonEncoder // JSON encoding via Gson
feign.gson.GsonDecoder // JSON decoding via Gson
// Jackson support
feign.jackson.JacksonEncoder // JSON encoding via Jackson
feign.jackson.JacksonDecoder // JSON decoding via Jackson
// Jackson with JAXB annotations
feign.jackson.jaxb.JacksonJaxbJsonEncoder
feign.jackson.jaxb.JacksonJaxbJsonDecoderXML encoding and decoding support.
// JAXB support
feign.jaxb.JAXBEncoder // XML encoding via JAXB
feign.jaxb.JAXBDecoder // XML decoding via JAXB
// SAX parsing
feign.sax.SAXDecoder // XML parsing via SAXAlternative HTTP client implementations.
// Apache HttpClient
feign.httpclient.ApacheHttpClient
// OkHttp client
feign.okhttp.OkHttpClientNetflix Hystrix circuit breaker integration.
// Hystrix integration
feign.hystrix.HystrixFeign
feign.hystrix.HystrixFeign.BuilderNetflix Ribbon load balancing integration.
// Ribbon integration
feign.ribbon.RibbonClient
feign.ribbon.LoadBalancingTargetJAX-RS annotation support as alternative to Feign annotations.
// JAX-RS contract
feign.jaxrs.JAXRSContractAlternative logging implementations.
// SLF4J logging
feign.slf4j.Slf4jLogger/**
* Immutable HTTP request
*/
public final class Request {
public String method();
public String url();
public Map<String, Collection<String>> headers();
public byte[] body();
public Charset charset();
public static class Options {
public Options(int connectTimeoutMillis, int readTimeoutMillis);
}
}
/**
* Immutable HTTP response
*/
public final class Response {
public int status();
public String reason();
public Map<String, Collection<String>> headers();
public Body body();
public interface Body extends Closeable {
Integer length();
boolean isRepeatable();
InputStream asInputStream() throws IOException;
Reader asReader() throws IOException;
}
}
/**
* Mutable request template used during processing
*/
public final class RequestTemplate {
public RequestTemplate method(String method);
public RequestTemplate append(String value);
public RequestTemplate query(String name, String... values);
public RequestTemplate header(String name, String... values);
public RequestTemplate body(byte[] bodyData, Charset charset);
}
/**
* Method metadata extracted from annotations
*/
public final class MethodMetadata {
public String configKey();
public RequestTemplate template();
public List<String> formParams();
public Map<Integer, String> indexToName();
}
/**
* Base exception for Feign-related errors
*/
public class FeignException extends RuntimeException {
public static FeignException errorStatus(String methodKey, Response response);
public static FeignException errorReading(Request request, Response response, IOException cause);
}
/**
* Request modification interface
*/
public interface RequestInterceptor {
/** Modify request template before execution */
void apply(RequestTemplate template);
}
/**
* HTTP Basic authentication interceptor
*/
public class BasicAuthRequestInterceptor implements RequestInterceptor {
public BasicAuthRequestInterceptor(String username, String password);
public BasicAuthRequestInterceptor(String username, String password, Charset charset);
}
/**
* Retry logic interface
*/
public abstract class Retryer implements Cloneable {
/** Decide whether to retry or propagate exception */
public void continueOrPropagate(RetryableException e);
/** Default exponential backoff implementation */
public static class Default implements Retryer {
public Default();
public Default(long period, long maxPeriod, int maxAttempts);
}
/** Never retry implementation */
public static final Retryer NEVER_RETRY;
}
/**
* Exception indicating retryable failure
*/
public class RetryableException extends FeignException {
public RetryableException(String message, Date retryAfter);
}
/**
* Request/response logging interface
*/
public abstract class Logger {
/** Logging levels */
public enum Level { NONE, BASIC, HEADERS, FULL }
/** Log request */
protected abstract void log(String configKey, String format, Object... args);
/** No-op logger implementation */
public static final Logger NoOpLogger;
/** System.err logger implementation */
public static class ErrorLogger extends Logger;
/** java.util.logging implementation */
public static class JavaLogger extends Logger {
public JavaLogger appendToFile(String logfile);
}
}
/**
* Annotation processing interface
*/
public abstract class Contract {
/** Parse method metadata from annotations */
public List<MethodMetadata> parseAndValidatateMetadata(Class<?> targetType);
/** Default contract processing Feign annotations */
public static class Default extends BaseContract;
/** Base contract for custom implementations */
public abstract static class BaseContract implements Contract;
}