This file provides guidance to AI coding assistants when working with code in this repository.
mvn clean install- Default build command (installs all modules)mvn clean install -Pdev- ALWAYS use this profile for development - enables code formatting and other dev toolsmvn clean install -Pquickbuild- Skip tests and validation for faster buildsmvn test- Run all testsmvn test -Dtest=ClassName- Run specific test class
mvn clean install -pl core- Build only the core modulemvn clean install -pl core,gson- Build specific modulesmvn clean test -pl core -Dtest=FeignTest- Run specific test in specific module
- Code is automatically formatted using Google Java Format via git hooks
- License headers are enforced via maven-license-plugin
- Use
mvn validateto check formatting and license compliance
Feign is a declarative HTTP client library with a modular design:
Core Module (core/): Contains the main Feign API and implementation
Feign.java- Main factory class for creating HTTP clientsClient.java- HTTP client abstraction (default implementation + pluggable alternatives)Contract.java- Annotation processing interface (Default, JAX-RS, Spring contracts)Encoder/Decoder.java- Request/response serialization interfacesTarget.java- Represents the remote HTTP service to invokeRequestTemplate.java- Template for building HTTP requests with parameter substitutionMethodMetadata.java- Metadata about interface methods and their annotations
Integration Modules: Each module provides integration with specific libraries:
gson/,jackson/,fastjson2/- JSON serializationokhttp/,httpclient/,hc5/,java11/- HTTP client implementationsjaxrs/,jaxrs2/,jaxrs3/- JAX-RS annotation supportspring/- Spring MVC annotation supporthystrix/- Circuit breaker integrationmicrometer/,dropwizard-metrics4/5/- Metrics integration
- Builder Pattern:
Feign.builder()for configuring clients - Factory Pattern:
Feign.newInstance(Target)creates proxy instances - Strategy Pattern: Pluggable
Client,Encoder,Decoder,Contractimplementations - Template Method:
RequestTemplatefor building HTTP requests with parameter substitution - Proxy Pattern: Dynamic proxies created for interface-based clients
- Parent POM manages dependencies and common configuration
- Each integration is a separate Maven module
- Modules can be built independently:
mvn clean install -pl module-name - Example modules depend on
feign-coreand their respective 3rd party libraries
feign-corecontainsAbstractClientTestbase class for testing HTTP clients- Each module has its own test suite
- Integration tests use MockWebServer for HTTP mocking
- Tests are run with JUnit 5 and AssertJ assertions
- Google Java Format is enforced via git hooks
- Code is formatted automatically on commit
- Package-private visibility is preferred over public when possible
- 3rd party dependencies are minimized in core module
- Core module: Minimal dependencies (only what's needed for HTTP client abstraction)
- Integration modules: Add specific 3rd party libraries (Jackson, OkHttp, etc.)
- BOM (Bill of Materials) manages version consistency across modules
- Source/target: Java 8 (for
src/main) - Tests: Java 21 (for
src/test) - Maintains backwards compatibility with Java 8 in main codebase
When a module's dependencies require a newer Java version (e.g., due to dependency upgrades), you need to override the Java version in that module's pom.xml:
- Add a
<properties>section to the module'spom.xml(or update existing one) - Set
<main.java.version>to the required version (11, 17, 21, etc.)
Example:
<properties>
<main.java.version>17</main.java.version>
</properties>Common scenarios requiring Java version updates:
- Dropwizard Metrics 5.x requires Java 17
- Handlebars 4.5.0+ requires Java 17
- Jakarta EE modules typically require Java 11+
Examples of modules with custom Java versions:
spring/- Java 17 (for Spring 6.x)jaxrs4/- Java 17 (for Jakarta EE 9+)dropwizard-metrics5/- Java 17 (for Metrics 5.x)apt-test-generator/- Java 17 (for Handlebars 4.5.0+)soap-jakarta/,jaxb-jakarta/- Java 11 (for Jakarta namespace)
Some modules define the same Maven property name (e.g., jersey.version, vertx.version) at different major versions. Dependabot treats these as a single property across the reactor and tries to set them all to the same value, which breaks modules locked to a specific major.
Current split-property modules:
jersey.version: 2.x (jaxrs2), 3.x (jaxrs3), 4.x (jaxrs4)vertx.version: 4.x (feign-vertx4-test), 5.x (feign-vertx, feign-vertx5-test)
How it works in .github/dependabot.yml:
- The root
/entry ignores the conflicting dependencies entirely (jersey, vertx) - Each module gets its own entry with
allow(only the conflicting dependency) andignore(block major version bumps) - Other dependencies that use different property names per major (e.g.,
jaxb-impl-2.versionvsjaxb-impl-4.version) only needupdate-types: ["version-update:semver-major"]on the root entry
When adding a new module that reuses a version property at a different major:
- Add the dependency to the root entry's
ignorelist (fully ignored, not just major) - Add a per-directory entry for the new module with
allowfor the specific dependency andignoreforversion-update:semver-major - Verify existing modules with the same property also have their own per-directory entries
The release script is at scripts/release.sh. It handles version updates, tagging, and pushing.
./scripts/release.sh— auto-detect release version from pom (strips-SNAPSHOT), auto-compute next snapshot./scripts/release.sh <release-version>— release a specific version, auto-compute next snapshot./scripts/release.sh <release-version> <next-snapshot>— release a specific version with explicit next snapshot
# Standard release (pom is at 13.10-SNAPSHOT, releases 13.10, next becomes 13.11-SNAPSHOT)
./scripts/release.sh
# Patch release with custom next snapshot
./scripts/release.sh 13.9.1 13.10-SNAPSHOT- Sets pom versions to the release version (removes
-SNAPSHOT) - Formats license headers and commits locally (no push)
- Creates and pushes a git tag for the release version
- Sets pom versions to the next snapshot and commits/pushes
When doing a patch release (e.g., 13.9.1 while pom is at 13.10-SNAPSHOT), pass both arguments so the next snapshot returns to the current development version:
./scripts/release.sh 13.9.1 13.10-SNAPSHOT- New modules must include a
README.mdwith usage examples following the style of existing module READMEs (e.g.,jackson/README.md,graphql/README.md) - New public functionality (annotations, contracts, encoders, decoders) must be documented in the module's
README.md - README should include: Maven dependency coordinates,
Feign.builder()configuration examples, and advanced usage if applicable - Update this file's Integration Modules list when adding a new module