Skip to content

Multi encoder#3485

Open
trumpetinc wants to merge 60 commits into
OpenFeign:14.xfrom
trumpetinc:multi-encoder
Open

Multi encoder#3485
trumpetinc wants to merge 60 commits into
OpenFeign:14.xfrom
trumpetinc:multi-encoder

Conversation

@trumpetinc

@trumpetinc trumpetinc commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Continuing work started in: #3485

Co-authored-by: trumpetinc 6618744+trumpetinc@users.noreply.github.com

Note

Target branch: 14.x

Important

Please squash and merge this PR if it's approved.

Important

Please add Co-authored-by: trumpetinc <6618744+trumpetinc@users.noreply.github.com> footer to the commit message if this PR is approved.

Summary

This PR introduces multi-encoder support in Feign, allowing users to register multiple encoders that are automatically selected at request time. The Encoder.encode() method now returns boolean (true if the encoder handled the object, false otherwise), and a new Encoder.of() factory combines encoders into a DelegatingEncoder.

Motivation

Previously, Feign only supported a single Encoder registered via Feign.builder().encoder(...). For APIs that mix different content types (JSON, XML, form data, etc.), users had to manually wrap encoders (e.g., new FormEncoder(new JacksonEncoder())). This was brittle and didn't scale well.

Changes

New API

  • Encoder.encode() now returns boolean — return true when encoding succeeds, false if the encoder does not handle the request. This replaces the need for a separate canEncode() method.

  • Encoder.of(Encoder...) / Encoder.of(List<Encoder>) — factory method that creates a DelegatingEncoder, which tries each delegate's encode() in order and uses the first one that returns true. Throws EncodeException if no encoder succeeds.

  • DelegatingEncoder — a composite encoder that delegates to a list of encoders, using the first one whose encode() returns true.

  • Util.isJsonContentType(RequestTemplate) / Util.isXmlContentType(RequestTemplate) — utility methods that check the Content-Type header against JSON (application/json, application/ld+json, etc.) and XML (text/xml, application/xml, etc.) patterns.

Encoder Updates

All built-in encoders now return boolean from encode() and gate on Content-Type where applicable:

Encoder Strategy
DefaultEncoder Type-based: accepts String, byte[], File, Path, InputStream, Request.Body, and null
FormEncoder Content-Type-based: accepts multipart/form-data and application/x-www-form-urlencoded
GraphqlEncoder Metadata-based: accepts requests matched by GraphqlContract; delegates to wrapped encoder otherwise
MeteredEncoder (all variants) Delegates to the wrapped encoder
All JSON encoders Content-Type check via Util.isJsonContentType(template)
All XML encoders Content-Type check via Util.isXmlContentType(template)

Example Usage

Before:

// Only one encoder — had to manually wrap
Feign.builder()
    .encoder(new FormEncoder(new JacksonEncoder()))
    .target(MyApi.class, "https://api.example.com");

After:

Feign.builder()
    .encoder(Encoder.of(
        new FormEncoder(),          // handles multipart/form-urlencoded by Content-Type
        new JacksonEncoder()       // handles JSON encoding
    ))
    .target(MyApi.class, "https://api.example.com");

Breaking Changes

Breaking changes are documented in MIGRATION-v14.md (sections 14–17):

  1. Encoder.encode() now returns boolean instead of void. All custom Encoder implementations must update the return type and return true on success or false when the encoder does not handle the request.
  2. Single encoder usage is unchangedFeign.builder().encoder(new JacksonEncoder()) still works.

Files Changed

  • New: api/src/main/java/feign/codec/DelegatingEncoder.java
  • Modified: Encoder.java, Util.java, Feign.java, AsyncFeign.java, HystrixFeign.java, VertxFeign.java, DefaultEncoder.java, FormEncoder.java, GraphqlEncoder.java, MeteredEncoder.java (×3), JAXBEncoder.java (×2), SOAPEncoder.java (×2), JacksonEncoder.java, Jackson3Encoder.java, GsonEncoder.java, MoshiEncoder.java, Fastjson2Encoder.java, JacksonJrEncoder.java, JacksonJaxbJsonEncoder.java
  • Tests: DelegatingEncoderTest.java, all JSON/XML encoder test files, and various integration tests
  • Documentation: MIGRATION-v14.md, CHANGELOG.md

dependabot Bot and others added 30 commits June 26, 2026 05:15
Bumps [io.undertow:undertow-core](https://github.com/undertow-io/undertow) from 2.4.1.Final to 2.4.2.Final.
- [Release notes](https://github.com/undertow-io/undertow/releases)
- [Commits](undertow-io/undertow@2.4.1.Final...2.4.2.Final)

---
updated-dependencies:
- dependency-name: io.undertow:undertow-core
  dependency-version: 2.4.2.Final
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
…undertow-undertow-core-2.4.2.Final

build(deps-dev): Bump io.undertow:undertow-core from 2.4.1.Final to 2.4.2.Final
Bumps [org.junit:junit-bom](https://github.com/junit-team/junit-framework) from 6.1.0 to 6.1.1.
- [Release notes](https://github.com/junit-team/junit-framework/releases)
- [Commits](junit-team/junit-framework@r6.1.0...r6.1.1)

---
updated-dependencies:
- dependency-name: org.junit:junit-bom
  dependency-version: 6.1.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
….junit-junit-bom-6.1.1

build(deps): Bump org.junit:junit-bom from 6.1.0 to 6.1.1
Bumps [org.apache.httpcomponents.client5:httpclient5](https://github.com/apache/httpcomponents-client) from 5.6.1 to 5.6.2.
- [Changelog](https://github.com/apache/httpcomponents-client/blob/rel/v5.6.2/RELEASE_NOTES.txt)
- [Commits](apache/httpcomponents-client@rel/v5.6.1...rel/v5.6.2)

---
updated-dependencies:
- dependency-name: org.apache.httpcomponents.client5:httpclient5
  dependency-version: 5.6.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [com.gradle:common-custom-user-data-maven-extension](https://github.com/gradle/common-custom-user-data-maven-extension) from 2.2.0 to 2.3.0.
- [Release notes](https://github.com/gradle/common-custom-user-data-maven-extension/releases)
- [Commits](gradle/common-custom-user-data-maven-extension@v2.2.0...v2.3.0)

---
updated-dependencies:
- dependency-name: com.gradle:common-custom-user-data-maven-extension
  dependency-version: 2.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [com.google.http-client:google-http-client](https://github.com/googleapis/google-http-java-client) from 2.1.0 to 2.1.1.
- [Release notes](https://github.com/googleapis/google-http-java-client/releases)
- [Changelog](https://github.com/googleapis/google-http-java-client/blob/main/CHANGELOG.md)
- [Commits](googleapis/google-http-java-client@v2.1.0...v2.1.1)

---
updated-dependencies:
- dependency-name: com.google.http-client:google-http-client
  dependency-version: 2.1.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
….gradle-common-custom-user-data-maven-extension-2.3.0

build(deps): Bump com.gradle:common-custom-user-data-maven-extension from 2.2.0 to 2.3.0
….apache.httpcomponents.client5-httpclient5-5.6.2

build(deps): Bump org.apache.httpcomponents.client5:httpclient5 from 5.6.1 to 5.6.2
….google.http-client-google-http-client-2.1.1

build(deps): Bump com.google.http-client:google-http-client from 2.1.0 to 2.1.1
Bumps [com.github.jknack:handlebars](https://github.com/jknack/handlebars.java) from 4.5.2 to 4.5.3.
- [Release notes](https://github.com/jknack/handlebars.java/releases)
- [Commits](jknack/handlebars.java@v4.5.2...v4.5.3)

---
updated-dependencies:
- dependency-name: com.github.jknack:handlebars
  dependency-version: 4.5.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps com.gradle:develocity-maven-extension from 2.4.2 to 2.5.0.

---
updated-dependencies:
- dependency-name: com.gradle:develocity-maven-extension
  dependency-version: 2.5.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
….gradle-develocity-maven-extension-2.5.0

build(deps-dev): Bump com.gradle:develocity-maven-extension from 2.4.2 to 2.5.0
….github.jknack-handlebars-4.5.3

build(deps): Bump com.github.jknack:handlebars from 4.5.2 to 4.5.3
Bumps [org.openrewrite.recipe:rewrite-migrate-java](https://github.com/openrewrite/rewrite-migrate-java) from 3.38.0 to 3.39.0.
- [Release notes](https://github.com/openrewrite/rewrite-migrate-java/releases)
- [Commits](openrewrite/rewrite-migrate-java@v3.38.0...v3.39.0)

---
updated-dependencies:
- dependency-name: org.openrewrite.recipe:rewrite-migrate-java
  dependency-version: 3.39.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [org.openrewrite.maven:rewrite-maven-plugin](https://github.com/openrewrite/rewrite-maven-plugin) from 6.42.0 to 6.43.0.
- [Release notes](https://github.com/openrewrite/rewrite-maven-plugin/releases)
- [Commits](openrewrite/rewrite-maven-plugin@v6.42.0...v6.43.0)

---
updated-dependencies:
- dependency-name: org.openrewrite.maven:rewrite-maven-plugin
  dependency-version: 6.43.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
….openrewrite.recipe-rewrite-migrate-java-3.39.0

build(deps): Bump org.openrewrite.recipe:rewrite-migrate-java from 3.38.0 to 3.39.0
….openrewrite.maven-rewrite-maven-plugin-6.43.0

build(deps-dev): Bump org.openrewrite.maven:rewrite-maven-plugin from 6.42.0 to 6.43.0
Bumps [org.openrewrite.recipe:rewrite-testing-frameworks](https://github.com/openrewrite/rewrite-testing-frameworks) from 3.40.0 to 3.41.0.
- [Release notes](https://github.com/openrewrite/rewrite-testing-frameworks/releases)
- [Commits](openrewrite/rewrite-testing-frameworks@v3.40.0...v3.41.0)

---
updated-dependencies:
- dependency-name: org.openrewrite.recipe:rewrite-testing-frameworks
  dependency-version: 3.41.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
….openrewrite.recipe-rewrite-testing-frameworks-3.41.0

build(deps): Bump org.openrewrite.recipe:rewrite-testing-frameworks from 3.40.0 to 3.41.0
Bumps `netty.version` from 4.2.15.Final to 4.2.16.Final.

Updates `io.netty:netty-bom` from 4.2.15.Final to 4.2.16.Final
- [Release notes](https://github.com/netty/netty/releases)
- [Commits](netty/netty@netty-4.2.15.Final...netty-4.2.16.Final)

Updates `io.netty:netty-handler` from 4.2.15.Final to 4.2.16.Final
- [Release notes](https://github.com/netty/netty/releases)
- [Commits](netty/netty@netty-4.2.15.Final...netty-4.2.16.Final)

Updates `io.netty:netty-codec-http` from 4.2.15.Final to 4.2.16.Final
- [Release notes](https://github.com/netty/netty/releases)
- [Commits](netty/netty@netty-4.2.15.Final...netty-4.2.16.Final)

---
updated-dependencies:
- dependency-name: io.netty:netty-bom
  dependency-version: 4.2.16.Final
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: io.netty:netty-handler
  dependency-version: 4.2.16.Final
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: io.netty:netty-codec-http
  dependency-version: 4.2.16.Final
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
…ty.version-4.2.16.Final

build(deps): Bump netty.version from 4.2.15.Final to 4.2.16.Final
Bumps `jackson.version` from 2.22.0 to 2.22.1.

Updates `com.fasterxml.jackson:jackson-bom` from 2.22.0 to 2.22.1
- [Commits](FasterXML/jackson-bom@jackson-bom-2.22.0...jackson-bom-2.22.1)

Updates `com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider` from 2.22.0 to 2.22.1

---
updated-dependencies:
- dependency-name: com.fasterxml.jackson:jackson-bom
  dependency-version: 2.22.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider
  dependency-version: 2.22.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps `vertx.version` from 5.1.3 to 5.1.4.

Updates `io.vertx:vertx-junit5` from 5.1.3 to 5.1.4
- [Commits](eclipse-vertx/vertx-junit5@5.1.3...5.1.4)

Updates `io.vertx:vertx-web-client` from 5.1.3 to 5.1.4
- [Commits](vert-x3/vertx-web@5.1.3...5.1.4)

---
updated-dependencies:
- dependency-name: io.vertx:vertx-junit5
  dependency-version: 5.1.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
- dependency-name: io.vertx:vertx-web-client
  dependency-version: 5.1.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
…tx/feign-vertx5-test/vertx.version-5.1.4

build(deps-dev): Bump vertx.version from 5.1.3 to 5.1.4 in /vertx/feign-vertx5-test
…kson.version-2.22.1

build(deps): Bump jackson.version from 2.22.0 to 2.22.1
Bumps `vertx.version` from 4.5.28 to 4.5.29.

Updates `io.vertx:vertx-junit5` from 4.5.28 to 4.5.29
- [Commits](eclipse-vertx/vertx-junit5@4.5.28...4.5.29)

Updates `io.vertx:vertx-web-client` from 4.5.28 to 4.5.29
- [Commits](vert-x3/vertx-web@4.5.28...4.5.29)

---
updated-dependencies:
- dependency-name: io.vertx:vertx-junit5
  dependency-version: 4.5.29
  dependency-type: direct:development
  update-type: version-update:semver-patch
- dependency-name: io.vertx:vertx-web-client
  dependency-version: 4.5.29
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
…tx/feign-vertx4-test/vertx.version-4.5.29

build(deps-dev): Bump vertx.version from 4.5.28 to 4.5.29 in /vertx/feign-vertx4-test
Bumps [tools.jackson:jackson-bom](https://github.com/FasterXML/jackson-bom) from 3.2.0 to 3.2.1.
- [Commits](FasterXML/jackson-bom@jackson-bom-3.2.0...jackson-bom-3.2.1)

---
updated-dependencies:
- dependency-name: tools.jackson:jackson-bom
  dependency-version: 3.2.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [org.junit:junit-bom](https://github.com/junit-team/junit-framework) from 6.1.1 to 6.1.2.
- [Release notes](https://github.com/junit-team/junit-framework/releases)
- [Commits](junit-team/junit-framework@r6.1.1...r6.1.2)

---
updated-dependencies:
- dependency-name: org.junit:junit-bom
  dependency-version: 6.1.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
dependabot Bot and others added 24 commits July 14, 2026 05:13
Bumps `vertx.version` from 5.1.4 to 5.1.5.

Updates `io.vertx:vertx-junit5` from 5.1.4 to 5.1.5
- [Commits](eclipse-vertx/vertx-junit5@5.1.4...5.1.5)

Updates `io.vertx:vertx-web-client` from 5.1.4 to 5.1.5
- [Commits](vert-x3/vertx-web@5.1.4...5.1.5)

---
updated-dependencies:
- dependency-name: io.vertx:vertx-junit5
  dependency-version: 5.1.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
- dependency-name: io.vertx:vertx-web-client
  dependency-version: 5.1.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
…tx/feign-vertx5-test/vertx.version-5.1.5

build(deps-dev): Bump vertx.version from 5.1.4 to 5.1.5 in /vertx/feign-vertx5-test
…tx/feign-vertx4-test/vertx.version-4.5.30

build(deps-dev): Bump vertx.version from 4.5.29 to 4.5.30 in /vertx/feign-vertx4-test
Bumps `kotlin.version` from 2.4.0 to 2.4.10.

Updates `org.jetbrains.kotlin:kotlin-stdlib-jdk8` from 2.4.0 to 2.4.10
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md)
- [Commits](JetBrains/kotlin@v2.4.0...v2.4.10)

Updates `org.jetbrains.kotlin:kotlin-reflect` from 2.4.0 to 2.4.10
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md)
- [Commits](JetBrains/kotlin@v2.4.0...v2.4.10)

Updates `org.jetbrains.kotlin:kotlin-maven-plugin` from 2.4.0 to 2.4.10

---
updated-dependencies:
- dependency-name: org.jetbrains.kotlin:kotlin-stdlib-jdk8
  dependency-version: 2.4.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.jetbrains.kotlin:kotlin-reflect
  dependency-version: 2.4.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.jetbrains.kotlin:kotlin-maven-plugin
  dependency-version: 2.4.10
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [org.openrewrite.maven:rewrite-maven-plugin](https://github.com/openrewrite/rewrite-maven-plugin) from 6.43.0 to 6.44.0.
- [Release notes](https://github.com/openrewrite/rewrite-maven-plugin/releases)
- [Commits](openrewrite/rewrite-maven-plugin@v6.43.0...v6.44.0)

---
updated-dependencies:
- dependency-name: org.openrewrite.maven:rewrite-maven-plugin
  dependency-version: 6.44.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [org.openrewrite.recipe:rewrite-migrate-java](https://github.com/openrewrite/rewrite-migrate-java) from 3.39.0 to 3.40.0.
- [Release notes](https://github.com/openrewrite/rewrite-migrate-java/releases)
- [Commits](openrewrite/rewrite-migrate-java@v3.39.0...v3.40.0)

---
updated-dependencies:
- dependency-name: org.openrewrite.recipe:rewrite-migrate-java
  dependency-version: 3.40.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
…lin.version-2.4.10

build(deps): Bump kotlin.version from 2.4.0 to 2.4.10
….openrewrite.maven-rewrite-maven-plugin-6.44.0

build(deps-dev): Bump org.openrewrite.maven:rewrite-maven-plugin from 6.43.0 to 6.44.0
….openrewrite.recipe-rewrite-migrate-java-3.40.0

build(deps): Bump org.openrewrite.recipe:rewrite-migrate-java from 3.39.0 to 3.40.0
Bumps [org.openrewrite.recipe:rewrite-testing-frameworks](https://github.com/openrewrite/rewrite-testing-frameworks) from 3.41.0 to 3.42.0.
- [Release notes](https://github.com/openrewrite/rewrite-testing-frameworks/releases)
- [Commits](openrewrite/rewrite-testing-frameworks@v3.41.0...v3.42.0)

---
updated-dependencies:
- dependency-name: org.openrewrite.recipe:rewrite-testing-frameworks
  dependency-version: 3.42.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
….openrewrite.recipe-rewrite-testing-frameworks-3.42.0

build(deps): Bump org.openrewrite.recipe:rewrite-testing-frameworks from 3.41.0 to 3.42.0
Co-authored-by: trumpetinc <6618744+trumpetinc@users.noreply.github.com>
Co-authored-by: trumpetinc <6618744+trumpetinc@users.noreply.github.com>
Co-authored-by: trumpetinc <6618744+trumpetinc@users.noreply.github.com>
Co-authored-by: trumpetinc <6618744+trumpetinc@users.noreply.github.com>
Co-authored-by: trumpetinc <6618744+trumpetinc@users.noreply.github.com>
Bumps [org.json:json](https://github.com/douglascrockford/JSON-java) from 20260522 to 20260719.
- [Release notes](https://github.com/douglascrockford/JSON-java/releases)
- [Changelog](https://github.com/stleary/JSON-java/blob/master/docs/RELEASES.md)
- [Commits](stleary/JSON-java@2026052...2026071)

---
updated-dependencies:
- dependency-name: org.json:json
  dependency-version: '20260719'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
….json-json-20260719

build(deps): Bump org.json:json from 20260522 to 20260719
@yvasyliev

Copy link
Copy Markdown
Contributor

Could you please set target branch = 14.x?

@trumpetinc
trumpetinc changed the base branch from master to 14.x July 22, 2026 01:04
@trumpetinc

Copy link
Copy Markdown
Contributor Author

Could you please set target branch = 14.x?

Yes - sorry about missing that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants