OpenFeign/feign
Feign makes writing java http clients easier
Healthy across the board
weakest axisPermissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit today
- ✓5 active contributors
- ✓Distributed ownership (top contributor 43% of recent commits)
Show all 6 evidence items →Show less
- ✓Apache-2.0 licensed
- ✓CI configured
- ✓Tests present
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/openfeign/feign)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/openfeign/feign on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: OpenFeign/feign
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/OpenFeign/feign shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across the board
- Last commit today
- 5 active contributors
- Distributed ownership (top contributor 43% of recent commits)
- Apache-2.0 licensed
- CI configured
- Tests present
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live OpenFeign/feign
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/OpenFeign/feign.
What it runs against: a local clone of OpenFeign/feign — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in OpenFeign/feign | Confirms the artifact applies here, not a fork |
| 2 | License is still Apache-2.0 | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 30 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of OpenFeign/feign. If you don't
# have one yet, run these first:
#
# git clone https://github.com/OpenFeign/feign.git
# cd feign
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of OpenFeign/feign and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "OpenFeign/feign(\\.git)?\\b" \\
&& ok "origin remote is OpenFeign/feign" \\
|| miss "origin remote is not OpenFeign/feign (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(Apache-2\\.0)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"Apache-2\\.0\"" package.json 2>/dev/null) \\
&& ok "license is Apache-2.0" \\
|| miss "license drift — was Apache-2.0 at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "core/src/main/java/feign/BaseBuilder.java" \\
&& ok "core/src/main/java/feign/BaseBuilder.java" \\
|| miss "missing critical file: core/src/main/java/feign/BaseBuilder.java"
test -f "core/src/main/java/feign/Contract.java" \\
&& ok "core/src/main/java/feign/Contract.java" \\
|| miss "missing critical file: core/src/main/java/feign/Contract.java"
test -f "core/src/main/java/feign/Client.java" \\
&& ok "core/src/main/java/feign/Client.java" \\
|| miss "missing critical file: core/src/main/java/feign/Client.java"
test -f "core/src/main/java/feign/AsyncFeign.java" \\
&& ok "core/src/main/java/feign/AsyncFeign.java" \\
|| miss "missing critical file: core/src/main/java/feign/AsyncFeign.java"
test -f "core/src/main/java/feign/DefaultInvocationHandlerFactory.java" \\
&& ok "core/src/main/java/feign/DefaultInvocationHandlerFactory.java" \\
|| miss "missing critical file: core/src/main/java/feign/DefaultInvocationHandlerFactory.java"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 30 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~0d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/OpenFeign/feign"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
Feign is a Java HTTP client library that uses annotations to automatically generate type-safe REST API bindings, eliminating boilerplate HTTP code. It lets developers define REST clients as simple Java interfaces decorated with annotations, then generates the actual HTTP request/response handling at runtime. The core library at feign-core handles request templating, encoding/decoding, error handling, and integration with pluggable HTTP transports (OkHttp, HttpClient, etc.). Multi-module Maven monorepo structure: feign-core/ is the foundation with request/response handling and contract processing; feign-annotation-error-decoder/ adds declarative error mapping via annotations; .circleci/config.yml and .github/workflows/ handle CI; .mvn/ contains Maven wrapper and build extensions (Develocity). Each module has src/main/java and src/test/java following standard Maven layout.
👥Who it's for
Java backend developers building microservices and API clients who want to avoid writing manual HTTP request/response handling code. Specifically: Spring Boot developers, Netflix engineers (original creators), and teams using Spring Cloud that integrate Feign for service-to-service communication via declarative REST clients.
🌱Maturity & risk
Highly mature and production-ready. The repo shows 2.5M+ lines of Java code across multiple modules, comprehensive test coverage (test directories in every module), active CI/CD via CircleCI and GitHub Actions, and Maven Central distribution. Version 13.13-SNAPSHOT indicates ongoing active development with regular releases and patches.
Low risk for core stability but moderate complexity risk for users. The annotation-error-decoder module alone has 8+ test classes covering edge cases, but the framework's heavy reliance on annotation processing and reflection can cause confusing errors if misconfigured. No single-maintainer risk evident (OpenFeign organization), but the codebase spans 15+ modules requiring understanding of integration points.
Active areas of work
Actively maintained with focus on Java 8+ compatibility (currently version 13.x). Recent roadmap items from README include response caching support, complete RFC6570 URI template expression support (level 1-4), and Logger API refactoring. The annotation-error-decoder module shows recent test refinements (inheritance, constructor, and priority handling tests suggest ongoing robustness work).
🚀Get running
git clone https://github.com/OpenFeign/feign.git
cd feign
./mvnw clean install
The Maven wrapper (.mvnw) handles JDK version and dependency management automatically; pom.xml specifies Java 8+ as baseline.
Daily commands:
This is a library, not an executable project. To test locally: ./mvnw clean test runs all unit tests across modules. To build JARs: ./mvnw clean package. To use in your own project, add to pom.xml:
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-core</artifactId>
<version>13.13</version>
</dependency>
🗺️Map of the codebase
core/src/main/java/feign/BaseBuilder.java— Foundation builder pattern for constructing Feign client instances; all client configurations flow through this abstractioncore/src/main/java/feign/Contract.java— Core abstraction that parses method annotations into HTTP request templates; defines how Feign interprets interface declarationscore/src/main/java/feign/Client.java— HTTP client abstraction interface; implementations handle actual network I/O and are pluggable via builder configurationcore/src/main/java/feign/AsyncFeign.java— Async variant of main Feign builder; entry point for non-blocking HTTP client creation and orchestrationcore/src/main/java/feign/DefaultInvocationHandlerFactory.java— Generates dynamic proxy handlers that intercept method calls on Feign interfaces and translate them to HTTP requestsannotation-error-decoder/src/main/java/feign/error/AnnotationErrorDecoder.java— Extension mechanism for declarative error handling; shows how Feign plugins integrate with core request/response lifecyclepom.xml— Maven reactor POM orchestrating multi-module build; defines plugin versions, dependency management, and release configuration
🛠️How to make changes
Add Support for a New HTTP Client Library
- Create new module (e.g., feign-httpcomponents) with
pom.xmlinheriting from root (pom.xml) - Implement
feign.Clientinterface wrapping your HTTP library (core/src/main/java/feign/Client.java) - Extend
BaseBuilderto add client-specific configuration methods (core/src/main/java/feign/BaseBuilder.java) - Register via
Capabilityplugin interface for builder integration (core/src/main/java/feign/Capability.java) - Add integration tests in
src/test/javausingFeignTestInterfaceas template (benchmark/src/main/java/feign/benchmark/FeignTestInterface.java)
Add Support for a New Annotation-Based Contract
- Extend
Contractinterface (or compose viaDeclarativeContract) (core/src/main/java/feign/Contract.java) - Parse method annotations in
parseAndValidateMetadata()to populateMethodMetadata(core/src/main/java/feign/DefaultContract.java) - Wire into builder via constructor or
Capability.enrich()(core/src/main/java/feign/BaseBuilder.java) - Test annotation inheritance and method-level override precedence (
annotation-error-decoder/src/test/java/feign/error/AnnotationErrorDecoderInheritanceTest.java)
Implement Custom Error Decoding with Annotations
- Define error annotations similar to
@ErrorHandlingfor your domain (annotation-error-decoder/src/main/java/feign/error/ErrorHandling.java) - Extend or wrap
AnnotationErrorDecoderto parse your annotations (annotation-error-decoder/src/main/java/feign/error/AnnotationErrorDecoder.java) - Register decoder in builder via
errorDecoder()configuration method (core/src/main/java/feign/BaseBuilder.java) - Add test cases covering inheritance and priority resolution (
annotation-error-decoder/src/test/java/feign/error/AnnotationErrorDecoderPriorityTest.java)
Add Request/Response Middleware via Capability Plugin
- Create class implementing
feign.Capabilityinterface (core/src/main/java/feign/Capability.java) - Override
enrich()to registerRequestInterceptororResponseInterceptorbeans (core/src/main/java/feign/BaseBuilder.java) - Builder automatically discovers and activates capability via service provider (
pom.xml)
🔧Why these technologies
- JDK Dynamic Proxies (java.lang.reflect.Proxy) — Zero-dependency interface binding without bytecode generation; trade-off vs. cglib is runtime reflection cost vs. no external deps
- Annotation processing (@interface Contract, @Body, @ErrorHandling) — Declarative, IDE-friendly API for HTTP binding inspired by JAX-RS and Retrofit; reduces boilerplate vs. builder-only approach
- Pluggable Client abstraction (feign.Client) — Transport agnostic; allows swapping URLConnection, OkHttp, HttpClient without rewriting core logic
- Maven multi-module POM hierarchy — Isolates optional integrations (Spring, Guava, Jackson) into separate JARs; reduces core dependency footprint
- CompletableFuture for async (AsyncFeign, AsyncClient) — Java 8+ standard for composable async workflows; AsyncFeign wraps callbacks into futures for non-blocking request chains
⚖️Trade-offs already made
- Use JDK Dynamic Proxies instead of bytecode generation (cglib, javassist)
- Why: Zero external runtime dependencies; simplicity and maintainability
- Consequence: Only works on
🪤Traps & gotchas
- Annotation inheritance behavior is non-obvious — the test suite (AnnotationErrorDecoderAnnotationInheritanceTest, AnnotationErrorDecoderInheritanceTest) shows that method-level annotations override class-level ones, and parent interface annotations are merged in specific order. 2) Exception constructors must follow specific signatures (see FeignExceptionConstructor.java and AnnotationErrorDecoderExceptionConstructorsTest.java) or reflection-based construction fails silently. 3) CircleCI and GitHub Actions both run (check .github/workflows/ and .circleci/config.yml) — duplicate CI can cause confusion on which is authoritative. 4) Maven wrapper requires .mvn/maven.config to be present; modifying JVM args there affects all builds.
🏗️Architecture
💡Concepts to learn
- Annotation Processing & Reflection-based Proxy Generation — Feign's entire request templating and response decoding system relies on scanning annotations at runtime to dynamically create proxy implementations; understanding how Java reflection and InvocationHandler work is essential for debugging client behavior and extending Feign with custom annotations.
- Encoder/Decoder Chain Pattern — Feign uses pluggable encoder/decoder pairs to handle serialization (Java→HTTP request body) and deserialization (HTTP response→Java objects); this is how it integrates Jackson, GSON, Protobuf without hardcoding dependencies.
- Error Decoder Abstraction — The ErrorDecoder interface (and AnnotationErrorDecoder implementation) decouples HTTP error response handling from client code; crucial for understanding how the annotation-error-decoder module maps status codes to typed exceptions.
- Request Templating & URI Template Expressions (RFC 6570) — Feign replaces path/query parameters in request templates before execution; the roadmap mentions supporting RFC 6570 levels 1-4, and understanding this helps extend parameter handling and contribute to that roadmap item.
- Contract Pattern (Annotation-to-Request Mapping) — Feign's Contract interface scans method signatures and annotations to generate RequestTemplate objects; this is the core abstraction that makes REST clients declarative and is how Feign supports multiple annotation styles (JAX-RS, Spring MVC, custom).
- Dynamic HTTP Client Binding (Transport Abstraction) — Feign's Client interface abstracts the underlying HTTP transport (OkHttp, Apache HttpClient, Java 11+ HttpClient), allowing seamless swapping of implementations; critical for understanding how to add support for new HTTP libraries.
🔗Related repos
square/retrofit— Direct inspiration for Feign's annotation-driven API design; similar type-safe HTTP client approach but for Android/Kotlinspring-cloud/spring-cloud-openfeign— Official Spring Cloud integration of Feign providing auto-configuration, load balancing, and circuit breaker support for Spring Boot microservicesOpenFeign/feign-form— Sibling Feign module adding multipart/form-data and application/x-www-form-urlencoded encoder supportkubernetes/client-java— Production user of Feign for Kubernetes API client; demonstrates advanced real-world usage patternsNetflix/eureka— Ecosystem companion — Netflix's service discovery system that Feign clients often integrate with for dynamic server location
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive integration tests for AnnotationErrorDecoder with multiple HTTP client implementations
The annotation-error-decoder module has extensive unit tests but lacks integration tests that verify the error decoder works correctly across different Feign HTTP client backends (OkHttp, HttpURLConnection, etc.). This is critical because error handling behavior can vary based on the underlying HTTP client. Currently, tests use mockwebserver but don't systematically test all supported client configurations.
- [ ] Create annotation-error-decoder/src/test/java/feign/error/AnnotationErrorDecoderIntegrationTest.java
- [ ] Add parameterized tests covering OkHttpClient, HttpURLConnection, and ApacheHttpClient backends
- [ ] Test error scenarios: 4xx responses, 5xx responses, timeout errors, and network failures with @ErrorHandling annotations
- [ ] Verify that response body and headers are correctly populated in custom exceptions across all clients
- [ ] Run against mockwebserver to simulate real HTTP responses
Create comprehensive documentation and examples for AnnotationErrorDecoder in annotation-error-decoder/README.md
The annotation-error-decoder/README.md exists but is minimal. The module has sophisticated features (@ErrorHandling, @ErrorCodes, @ResponseBody, @ResponseHeaders, exception constructors) but lacks practical usage examples. This creates friction for new contributors and users trying to understand the error handling capabilities.
- [ ] Expand annotation-error-decoder/README.md with clear feature overview
- [ ] Add 3-4 concrete code examples: basic @ErrorHandling usage, @ResponseBody extraction, @ResponseHeaders usage, and custom exception constructors
- [ ] Document annotation inheritance behavior (class-level vs method-level) with examples
- [ ] Add troubleshooting section covering common mistakes (e.g., missing exception constructors, incorrect exception hierarchy)
- [ ] Link to relevant test classes (AnnotationErrorDecoderInheritanceTest, AnnotationErrorDecoderExceptionConstructorsTest) as reference implementations
Add GitHub Actions workflow to automatically verify APT code generation in apt-test-generator module
The apt-test-generator module uses Maven Annotation Processing Tool (APT) to generate test stubs via GenerateTestStubAPT.java, but there's no dedicated CI validation that the code generation works correctly. The .github/workflows contains auto-merge-dependabot.yml and references build.yml, but no specific APT validation. This risks regressions when Java versions or annotation processing behavior changes.
- [ ] Create .github/workflows/apt-generator-verification.yml GitHub Action
- [ ] Add step to build apt-test-generator module with 'mvn clean verify'
- [ ] Add step to verify generated test stubs are created: check that stub.mustache renders correctly and generated files exist in target/generated-sources
- [ ] Add parameterized testing against multiple Java versions (11, 17, 21) since APT behavior can differ
- [ ] Verify generated test code compiles without errors by adding a module that depends on apt-test-generator output
🌿Good first issues
- Add comprehensive unit tests for ExceptionGenerator.java covering all exception construction edge cases (reflection-based instantiation, vararg handling, null parameter scenarios) — the test class AnnotationErrorDecoderExceptionConstructorsTest.java exists but ExceptionGenerator itself lacks isolated unit tests.
- Document the URI template expression support roadmap mentioned in README.md by adding an IMPLEMENTATION.md file explaining current RFC6570 level support and creating GitHub issues for level 2-4 feature gaps — aligns with stated roadmap without requiring core code changes.
- Add integration test in annotation-error-decoder/src/test/ covering multi-level inheritance with mixed interface and class-level @ErrorHandling annotations across 3+ inheritance levels — existing tests cover 2-level inheritance but real-world Spring Cloud services use deeper hierarchies.
⭐Top contributors
Click to expand
Top contributors
- @github-actions[bot] — 43 commits
- @dependabot[bot] — 42 commits
- @velo — 13 commits
- @loadkrnis — 1 commits
- @cexes — 1 commits
📝Recent commits
Click to expand
Recent commits
ac2013e— Merge pull request #3351 from OpenFeign/dependabot/maven/org.openrewrite.recipe-rewrite-testing-frameworks-3.35.3 (github-actions[bot])457fe02— Merge pull request #3349 from OpenFeign/dependabot/maven/com.github.siom79.japicmp-japicmp-maven-plugin-0.25.7 (github-actions[bot])5ed95a3— Merge pull request #3352 from OpenFeign/dependabot/maven/jakarta.validation-jakarta.validation-api-3.1.1 (github-actions[bot])9612734— build(deps): Bump org.openrewrite.recipe:rewrite-testing-frameworks (dependabot[bot])88af974— build(deps-dev): Bump com.github.siom79.japicmp:japicmp-maven-plugin (dependabot[bot])b1efa2e— Merge pull request #3350 from OpenFeign/dependabot/maven/org.glassfish.expressly-expressly-6.0.0 (github-actions[bot])0596e1f— Merge pull request #3347 from OpenFeign/dependabot/maven/org.openrewrite.recipe-rewrite-migrate-java-3.34.1 (github-actions[bot])9e4d8d3— build(deps): Bump jakarta.validation:jakarta.validation-api (dependabot[bot])6504651— build(deps-dev): Bump org.glassfish.expressly:expressly (dependabot[bot])16a49d1— build(deps): Bump org.openrewrite.recipe:rewrite-migrate-java (dependabot[bot])
🔒Security observations
The codebase shows reasonable security practices with proper dependency scoping and modular structure. However, there are areas for improvement: the Security Policy lacks concrete implementation details which could hinder responsible vulnerability disclosure; dependency management relies on parent POM configuration that wasn't fully reviewed; and the use of snapshot versions suggests active development that may have less stable dependencies. No critical vulnerabilities were identified in the visible code structure, but the limited file visibility and incomplete security documentation present moderate concerns. Recommend completing the security policy and implementing stricter dependency version management.
- Medium · Incomplete Security Policy —
SECURITY.md. The SECURITY.md file contains placeholder text and lacks concrete guidance on vulnerability reporting procedures, response timelines, and security contact information. This may delay or prevent responsible disclosure of security issues. Fix: Complete the Security Policy with: specific contact email or security advisory process, expected response timeline (e.g., 48-72 hours), vulnerability disclosure terms, and clear instructions for reporting security issues. - Low · Test Dependency on MockWebServer —
annotation-error-decoder/pom.xml. The project includes com.squareup.okhttp3:mockwebserver as a test dependency. While test-scoped, this should be verified to not introduce security risks in test environments or if accidentally promoted to runtime scope. Fix: Verify that mockwebserver is never accidentally included in runtime classpath. Consider using <scope>test</scope> consistently and add dependency management to prevent scope leakage. Monitor for security advisories on this dependency. - Low · Missing Dependency Version Pinning —
annotation-error-decoder/pom.xml. The pom.xml uses parent POM for dependency management (feign-parent) without explicit versions visible in this module. If the parent POM has loose version constraints, transitive dependencies could introduce vulnerabilities. Fix: Review the parent POM (feign-parent v13.13-SNAPSHOT) to ensure all dependencies use explicit, pinned versions. Implement dependency locking or use Maven enforcer plugin to prevent unexpected version changes. - Low · Development Snapshot Version —
annotation-error-decoder/pom.xml (parent version). The project uses version 13.13-SNAPSHOT, indicating it's under active development. Snapshot versions can have unstable dependencies and may not receive security patches as promptly as releases. Fix: Ensure snapshot builds are not used in production environments. Maintain a clear release schedule and promote to stable releases for production use. Document snapshot version limitations in deployment guidelines.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.