Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
7368fb0
refactor: split feign-core into feign-api and feign-core
velo Jun 3, 2026
6444388
Publish feign-bom as a real module so it auto-deploys to Central
velo Jun 3, 2026
70bed89
refactor: update integration modules to compile against feign-api and…
velo Jun 3, 2026
6c621c3
Merge pull request #3384 from OpenFeign/worktree-feign-bom-module
velo Jun 3, 2026
6769d9a
Fix flaky vertx http2NoConnectionLeak test by using h2c prior knowledge
velo Jun 3, 2026
c5dc1dd
Merge pull request #3385 from OpenFeign/feature/fix-vertx-http2-leak-…
velo Jun 3, 2026
46c4acd
build(deps): Bump netty.version from 4.2.14.Final to 4.2.15.Final
dependabot[bot] Jun 3, 2026
bfcc81c
build(deps-dev): Bump vertx.version in /vertx/feign-vertx5-test
dependabot[bot] Jun 3, 2026
f14b7e6
build(deps-dev): Bump vertx.version in /vertx/feign-vertx4-test
dependabot[bot] Jun 3, 2026
334e888
build(deps): Bump kotlin.version from 2.3.21 to 2.4.0
dependabot[bot] Jun 3, 2026
05e421f
build(deps): Bump org.openrewrite.recipe:rewrite-migrate-java
dependabot[bot] Jun 3, 2026
03b9d7e
build(deps-dev): Bump org.openrewrite.maven:rewrite-maven-plugin
dependabot[bot] Jun 3, 2026
465be4c
Merge pull request #3386 from OpenFeign/dependabot/maven/netty.versio…
github-actions[bot] Jun 3, 2026
34c6124
Merge pull request #3387 from OpenFeign/dependabot/maven/vertx/feign-…
github-actions[bot] Jun 3, 2026
ac408cf
Merge pull request #3388 from OpenFeign/dependabot/maven/vertx/feign-…
github-actions[bot] Jun 3, 2026
e6fa29a
Merge pull request #3389 from OpenFeign/dependabot/maven/kotlin.versi…
github-actions[bot] Jun 3, 2026
cfdbdb3
Merge pull request #3390 from OpenFeign/dependabot/maven/org.openrewr…
github-actions[bot] Jun 3, 2026
8753a13
Merge pull request #3391 from OpenFeign/dependabot/maven/org.openrewr…
github-actions[bot] Jun 3, 2026
5866ebb
build(deps): Bump org.openrewrite.recipe:rewrite-testing-frameworks
dependabot[bot] Jun 3, 2026
56836bf
Merge pull request #3392 from OpenFeign/dependabot/maven/org.openrewr…
github-actions[bot] Jun 3, 2026
9ec8f46
test: relocate Feign integration tests to feign-core and remove dupli…
velo Jun 4, 2026
a4d4833
refactor: resolve feign defaults via a single memoized FeignDefaults …
velo Jun 4, 2026
b576eda
test: keep assertj helpers in feign-core test-jar for downstream modules
velo Jun 4, 2026
b45c2d9
Merge remote-tracking branch 'origin/master' into feature/split-feign…
velo Jun 5, 2026
2244ef3
build: regenerate feign-bom for 14.0-alpha1-SNAPSHOT with feign-api a…
velo Jun 5, 2026
7d1f9fb
build: fix copyright symbol encoding in generated feign-bom license h…
velo Jun 5, 2026
2a91ede
Merge 14.x into feature/split-feign-core-api: resolve streaming body …
velo Jun 6, 2026
62a3fe8
fix: update tests to use streaming Request.Body API after 14.x merge
velo Jun 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@

import feign.Response;
import feign.codec.Decoder;
import feign.codec.DefaultDecoder;
import feign.codec.DefaultErrorDecoder;
import feign.codec.ErrorDecoder;
import feign.core.codec.DefaultDecoder;
import feign.core.codec.DefaultErrorDecoder;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

import static org.assertj.core.api.Assertions.assertThat;

import feign.codec.DefaultDecoder;
import feign.core.codec.DefaultDecoder;
import feign.error.AnnotationErrorDecoderExceptionConstructorsTest.TestClientInterfaceWithDifferentExceptionConstructors;
import feign.error.AnnotationErrorDecoderExceptionConstructorsTest.TestClientInterfaceWithDifferentExceptionConstructors.DeclaredDefaultConstructorException;
import feign.error.AnnotationErrorDecoderExceptionConstructorsTest.TestClientInterfaceWithDifferentExceptionConstructors.DeclaredDefaultConstructorWithOtherConstructorsException;
Expand Down
133 changes: 133 additions & 0 deletions api/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--

Copyright © 2012 The Feign Authors (feign@commonhaus.dev)

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-parent</artifactId>
<version>14.0-alpha1-SNAPSHOT</version>
</parent>

<artifactId>feign-api</artifactId>
<name>Feign API</name>
<description>Feign API</description>

<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>mockwebserver</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-context.version}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>com.google.auto.service</groupId>
<artifactId>auto-service-annotations</artifactId>
<version>${auto-service-annotations.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>com.google.auto.service</groupId>
<artifactId>auto-service</artifactId>
<version>${auto-service-annotations.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<executions>
<execution>
<id>enforce-banned-dependencies</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<bannedDependencies>
<message>feign-api should never include any dependencies, this is a design choice to keep api light</message>
<excludes>
<exclude>*:*:*:*:*:*</exclude>
</excludes>
<includes>
<include>*:*:*:*:test:*</include>
<include>com.google.auto.service:auto-service-annotations</include>
</includes>
</bannedDependencies>
</rules>
<fail>true</fail>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import feign.Request.Options;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;

/** Submits HTTP {@link Request requests} asynchronously, with an optional context. */
@Experimental
Expand All @@ -39,17 +38,6 @@ public interface AsyncClient<C> {
*/
CompletableFuture<Response> execute(Request request, Options options, Optional<C> requestContext);

/**
* @deprecated use {@link DefaultAsyncClient} instead.
*/
@Deprecated
class Default<C> extends DefaultAsyncClient<C> {

public Default(Client client, ExecutorService executorService) {
super(client, executorService);
}
}

/**
* A synchronous implementation of {@link AsyncClient}
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public static class AsyncBuilder<C> extends BaseBuilder<AsyncBuilder<C>, AsyncFe
private AsyncContextSupplier<C> defaultContextSupplier = () -> null;
private AsyncClient<C> client =
new DefaultAsyncClient<>(
new DefaultClient(null, null), LazyInitializedExecutorService.instance);
ServiceLoaderUtils.defaults().client(), LazyInitializedExecutorService.instance);
private MethodInfoResolver methodInfoResolver = MethodInfo::new;

@Deprecated
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,9 @@
import static feign.ExceptionPropagationPolicy.NONE;

import feign.Feign.ResponseMappingDecoder;
import feign.Logger.NoOpLogger;
import feign.Request.Options;
import feign.codec.Codec;
import feign.codec.Decoder;
import feign.codec.DefaultDecoder;
import feign.codec.DefaultEncoder;
import feign.codec.DefaultErrorDecoder;
import feign.codec.Encoder;
import feign.codec.ErrorDecoder;
import feign.interceptor.MethodInterceptor;
Expand All @@ -46,25 +42,33 @@ public abstract class BaseBuilder<B extends BaseBuilder<B, T>, T> implements Clo
protected List<ResponseInterceptor> responseInterceptors = new ArrayList<>();
protected List<MethodInterceptor> methodInterceptors = new ArrayList<>();
protected Logger.Level logLevel = Logger.Level.NONE;
protected Contract contract = new DefaultContract();
protected Retryer retryer = new DefaultRetryer();
protected Logger logger = new NoOpLogger();
protected Encoder encoder = new DefaultEncoder();
protected Decoder decoder = new DefaultDecoder();
protected Contract contract;
protected Retryer retryer;
protected Logger logger;
protected Encoder encoder;
protected Decoder decoder;
protected boolean closeAfterDecode = true;
protected boolean decodeVoid = false;
protected QueryMapEncoder queryMapEncoder = QueryMap.MapEncoder.FIELD.instance();
protected ErrorDecoder errorDecoder = new DefaultErrorDecoder();
protected QueryMapEncoder queryMapEncoder;
protected ErrorDecoder errorDecoder;
protected Options options = new Options();
protected InvocationHandlerFactory invocationHandlerFactory =
new DefaultInvocationHandlerFactory();
protected InvocationHandlerFactory invocationHandlerFactory;
protected boolean dismiss404;
protected ExceptionPropagationPolicy propagationPolicy = NONE;
protected List<Capability> capabilities = new ArrayList<>();

public BaseBuilder() {
super();
thisB = (B) this;
FeignDefaults defaults = ServiceLoaderUtils.defaults();
this.contract = defaults.contract();
this.retryer = defaults.retryer();
this.logger = defaults.logger();
this.encoder = defaults.encoder();
this.decoder = defaults.decoder();
this.queryMapEncoder = defaults.queryMapEncoder();
this.errorDecoder = defaults.errorDecoder();
this.invocationHandlerFactory = defaults.invocationHandlerFactory();
}

public B logLevel(Logger.Level logLevel) {
Expand Down
File renamed without changes.
33 changes: 33 additions & 0 deletions api/src/main/java/feign/Client.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright © 2012 The Feign Authors (feign@commonhaus.dev)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package feign;

import feign.Request.Options;
import java.io.IOException;

/** Submits HTTP {@link Request requests}. Implementations are expected to be thread-safe. */
public interface Client {

/**
* Executes a request against its {@link Request#url() url} and returns a response.
*
* @param request safe to replay.
* @param options options to apply to this request.
* @return connected response, {@link Response.Body} is absent or unread.
* @throws IOException on a network error connecting to {@link Request#url()}.
*/
Response execute(Request request, Options options) throws IOException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -245,10 +245,4 @@ protected void nameParam(MethodMetadata data, String name, int i) {
data.indexToName().put(i, names);
}
}

/**
* @deprecated use {@link DefaultContract} instead.
*/
@Deprecated
class Default extends DefaultContract {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public static String configKey(Method method) {

public static class Builder extends BaseBuilder<Builder, Feign> {

private Client client = new DefaultClient(null, null);
private Client client = ServiceLoaderUtils.defaults().client();

@Override
public Builder logLevel(Logger.Level logLevel) {
Expand Down
51 changes: 51 additions & 0 deletions api/src/main/java/feign/FeignDefaults.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright © 2012 The Feign Authors (feign@commonhaus.dev)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package feign;

import feign.codec.Decoder;
import feign.codec.Encoder;
import feign.codec.ErrorDecoder;

/**
* Aggregated factory for Feign's built-in default components. A single implementation is discovered
* once through {@link java.util.ServiceLoader}, replacing what would otherwise be a separate lookup
* per component. {@code feign-core} supplies the standard implementation; an application may
* override the whole set by registering its own provider (any implementation outside the {@code
* feign.core} package takes precedence).
*
* <p>Each accessor returns a fresh instance, mirroring the per-builder defaults Feign created
* before the lookups were consolidated.
*/
public interface FeignDefaults {

Contract contract();

Retryer retryer();

Logger logger();

Encoder encoder();

Decoder decoder();

QueryMapEncoder queryMapEncoder();

ErrorDecoder errorDecoder();

InvocationHandlerFactory invocationHandlerFactory();

Client client();
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,4 @@ interface Factory<C> {
MethodHandler create(Target<?> target, MethodMetadata md, C requestContext);
}
}

/**
* @deprecated use {@link DefaultInvocationHandlerFactory} instead.
*/
@Deprecated
static final class Default extends DefaultInvocationHandlerFactory {}
}
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import feign.querymap.BeanQueryMapEncoder;
import feign.querymap.FieldQueryMapEncoder;
import java.lang.annotation.Retention;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -88,11 +86,21 @@

public enum MapEncoder {
// the latter DEFAULT will use BaseBuilder instance
BEAN(new BeanQueryMapEncoder()),
FIELD(new FieldQueryMapEncoder()),
DEFAULT(null);
BEAN("feign.core.querymap.BeanQueryMapEncoder"),
FIELD("feign.core.querymap.FieldQueryMapEncoder"),
DEFAULT((QueryMapEncoder) null);

private QueryMapEncoder mapEncoder;
private final QueryMapEncoder mapEncoder;

private MapEncoder(String className) {
QueryMapEncoder encoder = null;
try {
encoder = (QueryMapEncoder) Class.forName(className).getDeclaredConstructor().newInstance();
} catch (Exception e) {
// ignore
}
this.mapEncoder = encoder;
}

private MapEncoder(QueryMapEncoder mapEncoder) {
this.mapEncoder = mapEncoder;
Expand Down
Loading