Feign Documentation
repository·master·Indexed 27 days ago
https://github.com/openfeign/feignA Java library that simplifies writing HTTP clients by binding Java interfaces to HTTP APIs using annotations. It features the annotation-error-decoder for mapping HTTP status codes to custom exceptions via @ErrorHandling, and the feign-apt-test-generator for automatically generating mock clients using the Java Annotation Processing Tool (APT).
What's inside Feign
- Feign is a Java-to-HTTP client binder inspired by Retrofit, JAXRS-2.0, and WebSocket. It is designed to reduce the complexity of binding code to HTTP APIs by processing annotations into templatized requests. Feign is highly customizable through decoders and error handling, making it suitable for any text-based HTTP API.
Overview of Feign GraphQL APT
masterFeign GraphQL APT is an annotation processor for
feign-graphqlthat generates Java records from GraphQL schemas at compile time.When you provide a
@GraphqlSchema-annotated interface, the processor performs the following:- Parses the referenced
.graphqlschema file. - Validates all
@GraphqlQuerystrings against the schema. - Generates Java records for result types, input types, and enums.
- Maps custom scalars to Java types using
@Scalarannotations.
- Parses the referenced
Use Feign Jakarta for Jakarta-spec annotation processing
masterThe
feign-jakartamodule allows Feign to use standard annotations from the Jakarta specification (currently targeting the 3.1 spec) instead of Feign's own internal annotations. This is useful for developers wanting to align their client interfaces with Jakarta EE standards.Important Limitations:
- Best Effort Compatibility: This implementation is not 100% compatible with full Jakarta server interface behavior. It is a best-effort implementation.
- Interface Only: Feign only supports processing Java interfaces. It does not support abstract or concrete classes.
- Client vs. Server Design: While you may attempt to reuse the same interface for both client and server, Jakarta resource annotations were not originally designed for client-side processing.
Use Feign JAXRS 2 for JAX-RS specification compliance
masterThe Feign JAXRS 2 module allows you to use standard JAX-RS annotations (targeting the 1.1 spec) for defining HTTP client interfaces instead of Feign's native annotations. This is useful when you want to align your client interfaces with JAX-RS server specifications.
Important Limitations:
- Best Effort Compatibility: This implementation is not 100% compatible with full JAX-RS server behavior. JAX-RS annotations were designed for servers, not clients.
- Interface Only: Feign only supports processing Java interfaces. It does not support abstract or concrete classes.
- Package Hierarchy: Note that JAX-RS 2.0 has a different package hierarchy for client invocation compared to the 1.1 spec targeted here.
- Null/Empty Values: An
IllegalArgumentException(ISE) is raised if any annotation's value is empty or null (e.g.,@Path("")).
Use Feign JAX-RS for HTTP client interfaces
masterThe Feign JAX-RS module allows you to define HTTP client interfaces using standard JAX-RS (version 1.1) annotations instead of Feign-specific ones. This is useful for aligning client definitions with JAX-RS specifications.
Important Constraints:
- Interface Only: Feign only supports processing Java interfaces. It does not support abstract or concrete classes.
- Best Effort Compatibility: This implementation is a "best effort" and does not guarantee 100% compatibility with JAX-RS server-side behavior.
- Version Note: This module targets the JAX-RS 1.1 specification. JAX-RS 2.0 uses a different package hierarchy for client invocation and may not be fully compatible.
Customize ObjectMapper in Jackson-Jaxb Codec
masterYou can provide a custom
ObjectMappertoJacksonJaxbJsonEncoderandJacksonJaxbJsonDecoderto control serialization and deserialization behavior (e.g., handling null values or unknown properties).ObjectMapper mapper = new ObjectMapper() .setSerializationInclusion(JsonInclude.Include.NON_NULL) .configure(SerializationFeature.INDENT_OUTPUT, true) .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); GitHub github = Feign.builder() .encoder(new JacksonJaxbJsonEncoder(mapper)) .decoder(new JacksonJaxbJsonDecoder(mapper)) .target(GitHub.class, "https://api.github.com");Handle Array Unwrapping and Optional Return Types
masterSingle Result from Array Queries
If a GraphQL query returns an array (e.g.,
[User!]) but the Java method returns a single object, the decoder automatically unwraps the first element. If the array is empty,nullis returned.Optional Return Types
You can return
Optional<T>to handle nullable results. The client will returnOptional.empty()if the data is missing.// Unwrapping array to single object @GraphqlQuery("query topUser($limit: Int!) { topUsers(limit: $limit) { id name email } }") User topUser(int limit); // Using Optional for null safety @GraphqlQuery("query getUser($id: String!) { getUser(id: $id) { id name email } }") Optional<User> findUser(String id);Configure GsonEncoder and GsonDecoder separately
masterIf you need granular control, you can configure the encoder and decoder independently in your
Feign.BuilderusingGsonEncoderandGsonDecoder.GitHub github = Feign.builder() .encoder(new GsonEncoder()) .decoder(new GsonDecoder()) .target(GitHub.class, "https://api.github.com");Add Feign APT test generator to Maven classpath
masterThe simplest way to use the generator is to add it to your project's test dependency list. The Java compiler should automatically detect and run the code generation during the build process.
<dependency> <groupId>io.github.openfeign.experimental</groupId> <artifactId>feign-apt-test-generator</artifactId> <version>${feign.version}</version> <scope>test</scope> </dependency>Use Base APIs with inheritance
masterFeign supports single-inheritance interfaces to allow sharing common API patterns. You can define a
BaseApiwith common methods and type parameters, then extend it in specific service interfaces.@Headers("Accept: application/json") interface BaseApi<V> { @RequestLine("GET /api/{key}") V get(@Param("key") String key); @RequestLine("GET /api") List<V> list(); @Headers("Content-Type: application/json") @RequestLine("PUT /api/{key}") void put(@Param("key") String key, V value); } interface FooApi extends BaseApi<Foo> { } interface BarApi extends BaseApi<Bar> { }Extending Feign via forks or separate repositories
masterFeign is optimized for low maintenance and prefers small, well-tested features. If a feature is large or has a high maintenance burden, it may be deferred or rejected from the main repository. In these cases, you should:
- Fork the repository: Use a fork to experiment with and vet features before they are proposed for the main repo.
- Create a separate repository: For large integrations (e.g., those exceeding 1000 lines of code), move the implementation to a standalone repository to ensure the sustainability of the core Feign project. An example of a successful large integration is
spring-cloud-netflix.
Configure Feign with Jakarta Bean Validation
masterTo use Jakarta Bean Validation with a Feign client, register a
BeanValidationMethodInterceptorusing the Feign builder. You can use the default validator factory or provide an explicitValidatorinstance and specific validation groups.// Using the default validator factory Api api = Feign.builder() .methodInterceptor(BeanValidationMethodInterceptor.usingDefaultFactory()) .target(Api.class, "https://example.com"); // Using an explicit Validator and validation groups Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); Feign.builder() .methodInterceptor(new BeanValidationMethodInterceptor(validator, Create.class)) .target(Api.class, "https://example.com");