Compare commits
16
Commits
v3.1.0-RC1
..
v3.0.7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e321e72e3d | ||
|
|
ae63aae6eb | ||
|
|
10fefea29b | ||
|
|
24d9b08d5c | ||
|
|
d4832788f6 | ||
|
|
ff96850ec0 | ||
|
|
9023cc2dc5 | ||
|
|
6c3b8c257e | ||
|
|
fe43b6c52b | ||
|
|
3e5aa41490 | ||
|
|
3a1d19f74f | ||
|
|
0853ccc1e5 | ||
|
|
13f91320b1 | ||
|
|
7af0efd569 | ||
|
|
70a9002002 | ||
|
|
ad892a23f0 |
@@ -5,9 +5,9 @@ name: Build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
branches: [ 3.0.x ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
branches: [ 3.0.x ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
+53
-1
@@ -40,7 +40,8 @@ and binding to the Spring Environment and other Spring programming model idioms.
|
||||
|
||||
== Building
|
||||
|
||||
:jdkversion: 1.8
|
||||
|
||||
:jdkversion: 17
|
||||
|
||||
=== Basic Compile and Test
|
||||
|
||||
@@ -303,6 +304,57 @@ Go to `File` -> `Settings` -> `Other settings` -> `Checkstyle`. There click on t
|
||||
|
||||
IMPORTANT: Remember to set the `Scan Scope` to `All sources` since we apply checkstyle rules for production and test sources.
|
||||
|
||||
=== Duplicate Finder
|
||||
|
||||
Spring Cloud Build brings along the `basepom:duplicate-finder-maven-plugin`, that enables flagging duplicate and conflicting classes and resources on the java classpath.
|
||||
|
||||
==== Duplicate Finder configuration
|
||||
|
||||
Duplicate finder is *enabled by default* and will run in the `verify` phase of your Maven build, but it will only take effect in your project if you add the `duplicate-finder-maven-plugin` to the `build` section of the projecst's `pom.xml`.
|
||||
|
||||
.pom.xml
|
||||
[source,xml]
|
||||
----
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.basepom.maven</groupId>
|
||||
<artifactId>duplicate-finder-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
----
|
||||
|
||||
For other properties, we have set defaults as listed in the https://github.com/basepom/duplicate-finder-maven-plugin/wiki[plugin documentation].
|
||||
|
||||
You can easily override them but setting the value of the selected property prefixed with `duplicate-finder-maven-plugin`. For example, set `duplicate-finder-maven-plugin.skip` to `true` in order to skip duplicates check in your build.
|
||||
|
||||
If you need to add `ignoredClassPatterns` or `ignoredResourcePatterns` to your setup, make sure to add them in the plugin configuration section of your project:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.basepom.maven</groupId>
|
||||
<artifactId>duplicate-finder-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<ignoredClassPatterns>
|
||||
<ignoredClassPattern>org.joda.time.base.BaseDateTime</ignoredClassPattern>
|
||||
<ignoredClassPattern>.*module-info</ignoredClassPattern>
|
||||
</ignoredClassPatterns>
|
||||
<ignoredResourcePatterns>
|
||||
<ignoredResourcePattern>changelog.txt</ignoredResourcePattern>
|
||||
</ignoredResourcePatterns>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
----
|
||||
|
||||
|
||||
== License
|
||||
|
||||
The project license file is available https://raw.githubusercontent.com/spring-cloud/spring-cloud-openfeign/main/LICENSE.txt[here].
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-openfeign</artifactId>
|
||||
<version>3.1.0-RC1</version>
|
||||
<version>3.0.7</version>
|
||||
</parent>
|
||||
<artifactId>spring-cloud-openfeign-docs</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|feign.compression.request.mime-types | `[text/xml, application/xml, application/json]` | The list of supported mime types.
|
||||
|feign.compression.request.min-request-size | `2048` | The minimum threshold content size.
|
||||
|feign.compression.response.enabled | `false` | Enables the response from Feign to be compressed.
|
||||
|feign.compression.response.useGzipDecoder | `false` | Enables the default gzip decoder to be used.
|
||||
|feign.encoder.charset-from-content-type | `false` | Indicates whether the charset should be derived from the {@code Content-Type} header.
|
||||
|feign.httpclient.connection-timeout | `2000` |
|
||||
|feign.httpclient.connection-timer-repeat | `3000` |
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
include::spring-cloud-openfeign.adoc[]
|
||||
+1
@@ -0,0 +1 @@
|
||||
spring-cloud-openfeign.adoc
|
||||
@@ -52,9 +52,6 @@ public interface StoreClient {
|
||||
|
||||
@RequestMapping(method = RequestMethod.POST, value = "/stores/{storeId}", consumes = "application/json")
|
||||
Store update(@PathVariable("storeId") Long storeId, Store store);
|
||||
|
||||
@RequestMapping(method = RequestMethod.DELETE, value = "/stores/{storeId:\\d+}")
|
||||
void delete(@PathVariable Long storeId);
|
||||
}
|
||||
----
|
||||
|
||||
@@ -122,7 +119,6 @@ Spring Cloud OpenFeign provides the following beans by default for feign (`BeanT
|
||||
* `Encoder` feignEncoder: `SpringEncoder`
|
||||
* `Logger` feignLogger: `Slf4jLogger`
|
||||
* `MicrometerCapability` micrometerCapability: If `feign-micrometer` is on the classpath and `MeterRegistry` is available
|
||||
* `CachingCapability` cachingCapability: If `@EnableCaching` annotation is used. Can be disabled via `feign.cache.enabled`.
|
||||
* `Contract` feignContract: `SpringMvcContract`
|
||||
* `Feign.Builder` feignBuilder: `FeignCircuitBreaker.Builder`
|
||||
* `Client` feignClient: If Spring Cloud LoadBalancer is on the classpath, `FeignBlockingLoadBalancerClient` is used.
|
||||
@@ -142,7 +138,7 @@ Spring Cloud OpenFeign _does not_ provide the following beans by default for fei
|
||||
* `Collection<RequestInterceptor>`
|
||||
* `SetterFactory`
|
||||
* `QueryMapEncoder`
|
||||
* `Capability` (`MicrometerCapability` and `CachingCapability` are provided by default)
|
||||
* `Capability` (`MicrometerCapability` is provided by default)
|
||||
|
||||
A bean of `Retryer.NEVER_RETRY` with the type `Retryer` is created by default, which will disable retrying.
|
||||
Notice this retrying behavior is different from the Feign default one, where it will automatically retry IOExceptions,
|
||||
@@ -519,6 +515,14 @@ feign.compression.request.min-request-size=2048
|
||||
|
||||
These properties allow you to be selective about the compressed media types and minimum request threshold length.
|
||||
|
||||
For http clients except OkHttpClient, default gzip decoder can be enabled to decode gzip response in UTF-8 encoding:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
feign.compression.response.enabled=true
|
||||
feign.compression.response.useGzipDecoder=true
|
||||
----
|
||||
|
||||
=== Feign logging
|
||||
|
||||
A logger is created for each Feign client created. By default the name of the logger is the full class name of the interface used to create the Feign client. Feign logging only responds to the `DEBUG` level.
|
||||
@@ -603,22 +607,6 @@ public class FooConfiguration {
|
||||
}
|
||||
----
|
||||
|
||||
=== Feign Caching
|
||||
|
||||
If `@EnableCaching` annotation is used, a `CachingCapability` bean is created and registered so that your Feign client recognizes `@Cache*` annotations on its interface:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
public interface DemoClient {
|
||||
|
||||
@GetMapping("/demo/{filterParam}")
|
||||
@Cacheable(cacheNames = "demo-cache", key = "#keyParam")
|
||||
String demoEndpoint(String keyParam, @PathVariable String filterParam);
|
||||
}
|
||||
----
|
||||
|
||||
You can also disable the feature via property `feign.cache.enabled=false`.
|
||||
|
||||
=== Feign @QueryMap support
|
||||
|
||||
The OpenFeign `@QueryMap` annotation provides support for POJOs to be used as
|
||||
@@ -706,21 +694,20 @@ public interface DemoTemplate {
|
||||
----
|
||||
|
||||
=== Feign `CollectionFormat` support
|
||||
We support `feign.CollectionFormat` by providing the `@CollectionFormat` annotation.
|
||||
You can annotate a Feign client method (or the whole class to affect all methods) with it by passing the desired `feign.CollectionFormat` as annotation value.
|
||||
We support `feign.CollectionFormat` by providing the `@CollectionFormat` annotation.You can annotate a Feign client method with it by passing the desired `feign.CollectionFormat` as annotation value.
|
||||
|
||||
In the following example, the `CSV` format is used instead of the default `EXPLODED` to process the method.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@FeignClient(name = "demo")
|
||||
protected interface PageableFeignClient {
|
||||
protected interface PageableFeignClient {
|
||||
|
||||
@CollectionFormat(feign.CollectionFormat.CSV)
|
||||
@GetMapping(path = "/page")
|
||||
ResponseEntity performRequest(Pageable page);
|
||||
@CollectionFormat(feign.CollectionFormat.CSV)
|
||||
@GetMapping(path = "/page")
|
||||
ResponseEntity performRequest(Pageable page);
|
||||
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
TIP: Set the `CSV` format while sending `Pageable` as a query parameter in order for it to be encoded correctly.
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>spring-cloud-openfeign</artifactId>
|
||||
<version>3.1.0-RC1</version>
|
||||
<version>3.0.7</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>Spring Cloud OpenFeign</name>
|
||||
<description>Spring Cloud OpenFeign</description>
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-build</artifactId>
|
||||
<version>3.1.0-RC1</version>
|
||||
<version>3.0.5</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
<scm>
|
||||
@@ -26,7 +26,7 @@
|
||||
<properties>
|
||||
<main.basedir>${basedir}</main.basedir>
|
||||
<jackson.version>2.11.3</jackson.version>
|
||||
<spring-cloud-commons.version>3.1.0-RC1</spring-cloud-commons.version>
|
||||
<spring-cloud-commons.version>3.0.6</spring-cloud-commons.version>
|
||||
|
||||
<!-- Plugin versions -->
|
||||
<maven-eclipse-plugin.version>2.10</maven-eclipse-plugin.version>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-openfeign</artifactId>
|
||||
<version>3.1.0-RC1</version>
|
||||
<version>3.0.7</version>
|
||||
<relativePath>..</relativePath> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<artifactId>spring-cloud-openfeign-core</artifactId>
|
||||
@@ -183,13 +183,13 @@
|
||||
<dependency>
|
||||
<groupId>com.google.protobuf</groupId>
|
||||
<artifactId>protobuf-java</artifactId>
|
||||
<version>3.14.0</version>
|
||||
<version>3.19.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.vavr</groupId>
|
||||
<artifactId>vavr</artifactId>
|
||||
<version>0.10.3</version>
|
||||
<version>0.10.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2021 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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 org.springframework.cloud.openfeign;
|
||||
|
||||
import feign.Capability;
|
||||
import feign.InvocationHandlerFactory;
|
||||
|
||||
import org.springframework.cache.interceptor.CacheInterceptor;
|
||||
|
||||
/**
|
||||
* Allows Spring's @Cache* annotations to be declared on the feign client's methods.
|
||||
*
|
||||
* @author Sam Kruglov
|
||||
*/
|
||||
public class CachingCapability implements Capability {
|
||||
|
||||
private final CacheInterceptor cacheInterceptor;
|
||||
|
||||
public CachingCapability(CacheInterceptor cacheInterceptor) {
|
||||
this.cacheInterceptor = cacheInterceptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InvocationHandlerFactory enrich(InvocationHandlerFactory invocationHandlerFactory) {
|
||||
return new FeignCachingInvocationHandlerFactory(invocationHandlerFactory, cacheInterceptor);
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2021 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+2
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -25,10 +25,9 @@ import java.lang.annotation.Target;
|
||||
* Indicates which collection format should be used while processing the annotated method.
|
||||
*
|
||||
* @author Olga Maciaszek-Sharma
|
||||
* @author Sam Kruglov
|
||||
* @see feign.CollectionFormat
|
||||
*/
|
||||
@Target({ ElementType.METHOD, ElementType.TYPE })
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface CollectionFormat {
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2020 the original author or authors.
|
||||
* Copyright 2016-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+4
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2021 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -27,7 +27,6 @@ import java.util.concurrent.TimeUnit;
|
||||
import javax.annotation.PreDestroy;
|
||||
|
||||
import com.fasterxml.jackson.databind.Module;
|
||||
import feign.Capability;
|
||||
import feign.Client;
|
||||
import feign.Feign;
|
||||
import feign.RequestInterceptor;
|
||||
@@ -51,7 +50,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cache.interceptor.CacheInterceptor;
|
||||
import org.springframework.cloud.client.actuator.HasFeatures;
|
||||
import org.springframework.cloud.client.circuitbreaker.CircuitBreaker;
|
||||
import org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory;
|
||||
@@ -60,6 +58,7 @@ import org.springframework.cloud.commons.httpclient.ApacheHttpClientFactory;
|
||||
import org.springframework.cloud.commons.httpclient.OkHttpClientConnectionPoolFactory;
|
||||
import org.springframework.cloud.commons.httpclient.OkHttpClientFactory;
|
||||
import org.springframework.cloud.openfeign.security.OAuth2FeignRequestInterceptor;
|
||||
import org.springframework.cloud.openfeign.support.DefaultGzipDecoderConfiguration;
|
||||
import org.springframework.cloud.openfeign.support.FeignEncoderProperties;
|
||||
import org.springframework.cloud.openfeign.support.FeignHttpClientProperties;
|
||||
import org.springframework.cloud.openfeign.support.PageJacksonModule;
|
||||
@@ -83,12 +82,12 @@ import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResour
|
||||
* @author Nguyen Ky Thanh
|
||||
* @author Andrii Bohutskyi
|
||||
* @author Kwangyong Kim
|
||||
* @author Sam Kruglov
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass(Feign.class)
|
||||
@EnableConfigurationProperties({ FeignClientProperties.class, FeignHttpClientProperties.class,
|
||||
FeignEncoderProperties.class })
|
||||
@Import(DefaultGzipDecoderConfiguration.class)
|
||||
public class FeignAutoConfiguration {
|
||||
|
||||
private static final Log LOG = LogFactory.getLog(FeignAutoConfiguration.class);
|
||||
@@ -108,13 +107,6 @@ public class FeignAutoConfiguration {
|
||||
return context;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(value = "feign.cache.enabled", matchIfMissing = true)
|
||||
@ConditionalOnBean(CacheInterceptor.class)
|
||||
public Capability cachingCapability(CacheInterceptor cacheInterceptor) {
|
||||
return new CachingCapability(cacheInterceptor);
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass({ Module.class, Page.class, Sort.class })
|
||||
@ConditionalOnProperty(value = "feign.autoconfiguration.jackson.enabled", havingValue = "true")
|
||||
@@ -320,6 +312,7 @@ public class FeignAutoConfiguration {
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass(OAuth2ClientContext.class)
|
||||
@ConditionalOnProperty("feign.oauth2.enabled")
|
||||
@Deprecated // spring-security-oauth2 reached EOL
|
||||
protected static class Oauth2FeignConfiguration {
|
||||
|
||||
@Bean
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
-82
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2021 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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 org.springframework.cloud.openfeign;
|
||||
|
||||
import java.lang.reflect.AccessibleObject;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import feign.InvocationHandlerFactory;
|
||||
import feign.Target;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
import org.springframework.cache.interceptor.CacheInterceptor;
|
||||
|
||||
/**
|
||||
* Allows Spring's @Cache* annotations to be declared on the feign client's methods.
|
||||
*
|
||||
* @author Sam Kruglov
|
||||
*/
|
||||
public class FeignCachingInvocationHandlerFactory implements InvocationHandlerFactory {
|
||||
|
||||
private final InvocationHandlerFactory delegateFactory;
|
||||
|
||||
private final CacheInterceptor cacheInterceptor;
|
||||
|
||||
public FeignCachingInvocationHandlerFactory(InvocationHandlerFactory delegateFactory,
|
||||
CacheInterceptor cacheInterceptor) {
|
||||
this.delegateFactory = delegateFactory;
|
||||
this.cacheInterceptor = cacheInterceptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InvocationHandler create(Target target, Map<Method, MethodHandler> dispatch) {
|
||||
final InvocationHandler delegateHandler = delegateFactory.create(target, dispatch);
|
||||
return (proxy, method, argsNullable) -> {
|
||||
Object[] args = Optional.ofNullable(argsNullable).orElseGet(() -> new Object[0]);
|
||||
return cacheInterceptor.invoke(new MethodInvocation() {
|
||||
@Override
|
||||
public Method getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getArguments() {
|
||||
return args;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object proceed() throws Throwable {
|
||||
return delegateHandler.invoke(proxy, method, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getThis() {
|
||||
return target;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessibleObject getStaticPart() {
|
||||
return method;
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2021 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+19
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.cloud.openfeign;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -29,6 +30,7 @@ import feign.Target;
|
||||
|
||||
import org.springframework.cloud.client.circuitbreaker.CircuitBreaker;
|
||||
import org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory;
|
||||
import org.springframework.cloud.client.circuitbreaker.NoFallbackAvailableException;
|
||||
import org.springframework.web.context.request.RequestAttributes;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
|
||||
@@ -95,15 +97,29 @@ class FeignCircuitBreakerInvocationHandler implements InvocationHandler {
|
||||
try {
|
||||
return this.fallbackMethodMap.get(method).invoke(fallback, args);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalStateException(e);
|
||||
catch (Exception exception) {
|
||||
unwrapAndRethrow(exception);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
return circuitBreaker.run(supplier, fallbackFunction);
|
||||
}
|
||||
return circuitBreaker.run(supplier);
|
||||
}
|
||||
|
||||
private void unwrapAndRethrow(Exception exception) {
|
||||
if (exception instanceof InvocationTargetException || exception instanceof NoFallbackAvailableException) {
|
||||
Throwable underlyingException = exception.getCause();
|
||||
if (underlyingException instanceof RuntimeException) {
|
||||
throw (RuntimeException) underlyingException;
|
||||
}
|
||||
if (underlyingException != null) {
|
||||
throw new IllegalStateException(underlyingException);
|
||||
}
|
||||
throw new IllegalStateException(exception);
|
||||
}
|
||||
}
|
||||
|
||||
private Supplier<Object> asSupplier(final Method method, final Object[] args) {
|
||||
final RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
|
||||
return () -> {
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2021 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+4
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2021 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -443,6 +443,9 @@ public class FeignClientFactoryBean
|
||||
}
|
||||
|
||||
private String cleanPath() {
|
||||
if (path == null) {
|
||||
return "";
|
||||
}
|
||||
String path = this.path.trim();
|
||||
if (StringUtils.hasLength(path)) {
|
||||
if (!path.startsWith("/")) {
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2021 the original author or authors.
|
||||
* Copyright 2021-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2021 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -25,7 +25,7 @@ import org.springframework.cloud.context.named.NamedContextFactory;
|
||||
* @author Dave Syer
|
||||
* @author Gregor Zurowski
|
||||
*/
|
||||
public class FeignClientSpecification implements NamedContextFactory.Specification {
|
||||
class FeignClientSpecification implements NamedContextFactory.Specification {
|
||||
|
||||
private String name;
|
||||
|
||||
@@ -34,7 +34,7 @@ public class FeignClientSpecification implements NamedContextFactory.Specificati
|
||||
FeignClientSpecification() {
|
||||
}
|
||||
|
||||
public FeignClientSpecification(String name, Class<?>[] configuration) {
|
||||
FeignClientSpecification(String name, Class<?>[] configuration) {
|
||||
this.name = name;
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
+14
-26
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2021 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -47,7 +47,6 @@ import org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory;
|
||||
import org.springframework.cloud.openfeign.clientconfig.FeignClientConfigurer;
|
||||
import org.springframework.cloud.openfeign.support.AbstractFormWriter;
|
||||
import org.springframework.cloud.openfeign.support.FeignEncoderProperties;
|
||||
import org.springframework.cloud.openfeign.support.HttpMessageConverterCustomizer;
|
||||
import org.springframework.cloud.openfeign.support.PageableSpringEncoder;
|
||||
import org.springframework.cloud.openfeign.support.PageableSpringQueryMapEncoder;
|
||||
import org.springframework.cloud.openfeign.support.ResponseEntityDecoder;
|
||||
@@ -71,7 +70,6 @@ import static feign.form.ContentType.MULTIPART;
|
||||
* @author Jonatan Ivanov
|
||||
* @author Olga Maciaszek-Sharma
|
||||
* @author Hyeonmin Park
|
||||
* @author Yanming Zhou
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
public class FeignClientsConfiguration {
|
||||
@@ -99,25 +97,22 @@ public class FeignClientsConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public Decoder feignDecoder(ObjectProvider<HttpMessageConverterCustomizer> customizers) {
|
||||
return new OptionalDecoder(new ResponseEntityDecoder(new SpringDecoder(messageConverters, customizers)));
|
||||
public Decoder feignDecoder() {
|
||||
return new OptionalDecoder(new ResponseEntityDecoder(new SpringDecoder(this.messageConverters)));
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnMissingClass("org.springframework.data.domain.Pageable")
|
||||
public Encoder feignEncoder(ObjectProvider<AbstractFormWriter> formWriterProvider,
|
||||
ObjectProvider<HttpMessageConverterCustomizer> customizers) {
|
||||
return springEncoder(formWriterProvider, encoderProperties, customizers);
|
||||
public Encoder feignEncoder(ObjectProvider<AbstractFormWriter> formWriterProvider) {
|
||||
return springEncoder(formWriterProvider, encoderProperties);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnClass(name = "org.springframework.data.domain.Pageable")
|
||||
@ConditionalOnMissingBean
|
||||
public Encoder feignEncoderPageable(ObjectProvider<AbstractFormWriter> formWriterProvider,
|
||||
ObjectProvider<HttpMessageConverterCustomizer> customizers) {
|
||||
PageableSpringEncoder encoder = new PageableSpringEncoder(
|
||||
springEncoder(formWriterProvider, encoderProperties, customizers));
|
||||
public Encoder feignEncoderPageable(ObjectProvider<AbstractFormWriter> formWriterProvider) {
|
||||
PageableSpringEncoder encoder = new PageableSpringEncoder(springEncoder(formWriterProvider, encoderProperties));
|
||||
|
||||
if (springDataWebProperties != null) {
|
||||
encoder.setPageParameter(springDataWebProperties.getPageable().getPageParameter());
|
||||
@@ -131,26 +126,20 @@ public class FeignClientsConfiguration {
|
||||
@ConditionalOnClass(name = "org.springframework.data.domain.Pageable")
|
||||
@ConditionalOnMissingBean
|
||||
public QueryMapEncoder feignQueryMapEncoderPageable() {
|
||||
PageableSpringQueryMapEncoder queryMapEncoder = new PageableSpringQueryMapEncoder();
|
||||
if (springDataWebProperties != null) {
|
||||
queryMapEncoder.setPageParameter(springDataWebProperties.getPageable().getPageParameter());
|
||||
queryMapEncoder.setSizeParameter(springDataWebProperties.getPageable().getSizeParameter());
|
||||
queryMapEncoder.setSortParameter(springDataWebProperties.getSort().getSortParameter());
|
||||
}
|
||||
return queryMapEncoder;
|
||||
return new PageableSpringQueryMapEncoder();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public Contract feignContract(ConversionService feignConversionService) {
|
||||
boolean decodeSlash = feignClientProperties == null || feignClientProperties.isDecodeSlash();
|
||||
return new SpringMvcContract(parameterProcessors, feignConversionService, decodeSlash);
|
||||
return new SpringMvcContract(this.parameterProcessors, feignConversionService, decodeSlash);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FormattingConversionService feignConversionService() {
|
||||
FormattingConversionService conversionService = new DefaultFormattingConversionService();
|
||||
for (FeignFormatterRegistrar feignFormatterRegistrar : feignFormatterRegistrars) {
|
||||
for (FeignFormatterRegistrar feignFormatterRegistrar : this.feignFormatterRegistrars) {
|
||||
feignFormatterRegistrar.registerFormatters(conversionService);
|
||||
}
|
||||
return conversionService;
|
||||
@@ -165,7 +154,7 @@ public class FeignClientsConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(FeignLoggerFactory.class)
|
||||
public FeignLoggerFactory feignLoggerFactory() {
|
||||
return new DefaultFeignLoggerFactory(logger);
|
||||
return new DefaultFeignLoggerFactory(this.logger);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -176,15 +165,14 @@ public class FeignClientsConfiguration {
|
||||
}
|
||||
|
||||
private Encoder springEncoder(ObjectProvider<AbstractFormWriter> formWriterProvider,
|
||||
FeignEncoderProperties encoderProperties, ObjectProvider<HttpMessageConverterCustomizer> customizers) {
|
||||
FeignEncoderProperties encoderProperties) {
|
||||
AbstractFormWriter formWriter = formWriterProvider.getIfAvailable();
|
||||
|
||||
if (formWriter != null) {
|
||||
return new SpringEncoder(new SpringPojoFormEncoder(formWriter), messageConverters, encoderProperties,
|
||||
customizers);
|
||||
return new SpringEncoder(new SpringPojoFormEncoder(formWriter), this.messageConverters, encoderProperties);
|
||||
}
|
||||
else {
|
||||
return new SpringEncoder(new SpringFormEncoder(), messageConverters, encoderProperties, customizers);
|
||||
return new SpringEncoder(new SpringFormEncoder(), this.messageConverters, encoderProperties);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2021 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -302,7 +302,11 @@ class FeignClientsRegistrar implements ImportBeanDefinitionRegistrar, ResourceLo
|
||||
if (resolver == null) {
|
||||
return resolved;
|
||||
}
|
||||
return String.valueOf(resolver.evaluate(resolved, new BeanExpressionContext(beanFactory, null)));
|
||||
Object evaluateValue = resolver.evaluate(resolved, new BeanExpressionContext(beanFactory, null));
|
||||
if (evaluateValue != null) {
|
||||
return String.valueOf(evaluateValue);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2020 the original author or authors.
|
||||
* Copyright 2020-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2020 the original author or authors.
|
||||
* Copyright 2016-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2021 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2021 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
-67
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2021 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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 org.springframework.cloud.openfeign.annotation;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
|
||||
import feign.MethodMetadata;
|
||||
|
||||
import org.springframework.cloud.openfeign.AnnotatedParameterProcessor;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.web.bind.annotation.CookieValue;
|
||||
|
||||
import static feign.Util.checkState;
|
||||
import static feign.Util.emptyToNull;
|
||||
|
||||
/**
|
||||
* @{link CookieValue} annotation processor.
|
||||
* @author Gong Yi
|
||||
*
|
||||
*/
|
||||
public class CookieValueParameterProcessor implements AnnotatedParameterProcessor {
|
||||
|
||||
private static final Class<CookieValue> ANNOTATION = CookieValue.class;
|
||||
|
||||
@Override
|
||||
public Class<? extends Annotation> getAnnotationType() {
|
||||
return ANNOTATION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processArgument(AnnotatedParameterContext context, Annotation annotation, Method method) {
|
||||
int parameterIndex = context.getParameterIndex();
|
||||
MethodMetadata data = context.getMethodMetadata();
|
||||
CookieValue cookie = ANNOTATION.cast(annotation);
|
||||
String name = cookie.value().trim();
|
||||
checkState(emptyToNull(name) != null, "Cookie.name() was empty on parameter %s", parameterIndex);
|
||||
context.setParameterName(name);
|
||||
String cookieExpression = data.template().headers().getOrDefault(HttpHeaders.COOKIE, Arrays.asList("")).stream()
|
||||
.findFirst().orElse("");
|
||||
if (cookieExpression.length() == 0) {
|
||||
cookieExpression = String.format("%s={%s}", name, name);
|
||||
}
|
||||
else {
|
||||
cookieExpression += String.format("; %s={%s}", name, name);
|
||||
}
|
||||
data.template().removeHeader(HttpHeaders.COOKIE);
|
||||
data.template().header(HttpHeaders.COOKIE, cookieExpression);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+2
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -34,7 +34,6 @@ import static feign.Util.emptyToNull;
|
||||
*
|
||||
* @author Jakub Narloch
|
||||
* @author Abhijit Sarkar
|
||||
* @author Yanming Zhou
|
||||
* @see AnnotatedParameterProcessor
|
||||
*/
|
||||
public class PathVariableParameterProcessor implements AnnotatedParameterProcessor {
|
||||
@@ -55,8 +54,7 @@ public class PathVariableParameterProcessor implements AnnotatedParameterProcess
|
||||
|
||||
MethodMetadata data = context.getMethodMetadata();
|
||||
String varName = '{' + name + '}';
|
||||
String varNameRegex = ".*\\{" + name + "(:[^}]+)?\\}.*";
|
||||
if (!data.template().url().matches(varNameRegex) && !searchMapValues(data.template().queries(), varName)
|
||||
if (!data.template().url().contains(varName) && !searchMapValues(data.template().queries(), varName)
|
||||
&& !searchMapValues(data.template().headers(), varName)) {
|
||||
data.formParams().add(name);
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2021 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+25
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2021 the original author or authors.
|
||||
* Copyright 2016-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,18 +16,26 @@
|
||||
|
||||
package org.springframework.cloud.openfeign.hateoas;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
|
||||
import org.springframework.cloud.openfeign.support.HttpMessageConverterCustomizer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.hateoas.config.HateoasConfiguration;
|
||||
import org.springframework.hateoas.config.WebConverters;
|
||||
import org.springframework.hateoas.RepresentationModel;
|
||||
import org.springframework.hateoas.mediatype.hal.HalMediaTypeConfiguration;
|
||||
import org.springframework.hateoas.server.mvc.TypeConstrainedMappingJackson2HttpMessageConverter;
|
||||
|
||||
import static org.springframework.hateoas.MediaTypes.HAL_JSON;
|
||||
|
||||
/**
|
||||
* @author Hector Espert
|
||||
@@ -35,15 +43,23 @@ import org.springframework.hateoas.config.WebConverters;
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnWebApplication
|
||||
@ConditionalOnClass(WebConverters.class)
|
||||
@ConditionalOnClass(RepresentationModel.class)
|
||||
@AutoConfigureAfter({ JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
|
||||
RepositoryRestMvcAutoConfiguration.class, HateoasConfiguration.class })
|
||||
RepositoryRestMvcAutoConfiguration.class })
|
||||
public class FeignHalAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnBean(WebConverters.class)
|
||||
HttpMessageConverterCustomizer webConvertersCustomizer(WebConverters webConverters) {
|
||||
return new WebConvertersCustomizer(webConverters);
|
||||
@ConditionalOnBean(HalMediaTypeConfiguration.class)
|
||||
@ConditionalOnMissingBean
|
||||
public TypeConstrainedMappingJackson2HttpMessageConverter halJacksonHttpMessageConverter(
|
||||
ObjectProvider<ObjectMapper> objectMapper, HalMediaTypeConfiguration halConfiguration) {
|
||||
ObjectMapper mapper = objectMapper.getIfAvailable(ObjectMapper::new).copy();
|
||||
halConfiguration.configureObjectMapper(mapper);
|
||||
TypeConstrainedMappingJackson2HttpMessageConverter converter = new TypeConstrainedMappingJackson2HttpMessageConverter(
|
||||
RepresentationModel.class);
|
||||
converter.setSupportedMediaTypes(Collections.singletonList(HAL_JSON));
|
||||
converter.setObjectMapper(mapper);
|
||||
return converter;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016-2021 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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 org.springframework.cloud.openfeign.hateoas;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.cloud.openfeign.support.HttpMessageConverterCustomizer;
|
||||
import org.springframework.hateoas.config.WebConverters;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
|
||||
/**
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*/
|
||||
public class WebConvertersCustomizer implements HttpMessageConverterCustomizer {
|
||||
|
||||
private final WebConverters webConverters;
|
||||
|
||||
public WebConvertersCustomizer(WebConverters webConverters) {
|
||||
this.webConverters = webConverters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(List<HttpMessageConverter<?>> httpMessageConverters) {
|
||||
webConverters.augmentClient(httpMessageConverters);
|
||||
}
|
||||
|
||||
}
|
||||
+8
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -25,7 +25,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryFactory;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerClientsProperties;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerProperties;
|
||||
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
@@ -39,15 +39,15 @@ import org.springframework.context.annotation.Configuration;
|
||||
* @since 2.2.0
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties(LoadBalancerClientsProperties.class)
|
||||
@EnableConfigurationProperties(LoadBalancerProperties.class)
|
||||
class DefaultFeignLoadBalancerConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@Conditional(OnRetryNotEnabledCondition.class)
|
||||
public Client feignClient(LoadBalancerClient loadBalancerClient,
|
||||
public Client feignClient(LoadBalancerClient loadBalancerClient, LoadBalancerProperties properties,
|
||||
LoadBalancerClientFactory loadBalancerClientFactory) {
|
||||
return new FeignBlockingLoadBalancerClient(new Client.Default(null, null), loadBalancerClient,
|
||||
return new FeignBlockingLoadBalancerClient(new Client.Default(null, null), loadBalancerClient, properties,
|
||||
loadBalancerClientFactory);
|
||||
}
|
||||
|
||||
@@ -58,9 +58,10 @@ class DefaultFeignLoadBalancerConfiguration {
|
||||
@ConditionalOnProperty(value = "spring.cloud.loadbalancer.retry.enabled", havingValue = "true",
|
||||
matchIfMissing = true)
|
||||
public Client feignRetryClient(LoadBalancerClient loadBalancerClient,
|
||||
LoadBalancedRetryFactory loadBalancedRetryFactory, LoadBalancerClientFactory loadBalancerClientFactory) {
|
||||
LoadBalancedRetryFactory loadBalancedRetryFactory, LoadBalancerProperties properties,
|
||||
LoadBalancerClientFactory loadBalancerClientFactory) {
|
||||
return new RetryableFeignBlockingLoadBalancerClient(new Client.Default(null, null), loadBalancerClient,
|
||||
loadBalancedRetryFactory, loadBalancerClientFactory);
|
||||
loadBalancedRetryFactory, properties, loadBalancerClientFactory);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+4
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -60,24 +60,15 @@ public class FeignBlockingLoadBalancerClient implements Client {
|
||||
|
||||
private final LoadBalancerClient loadBalancerClient;
|
||||
|
||||
private final LoadBalancerProperties properties;
|
||||
|
||||
private final LoadBalancerClientFactory loadBalancerClientFactory;
|
||||
|
||||
/**
|
||||
* @deprecated in favour of
|
||||
* {@link FeignBlockingLoadBalancerClient#FeignBlockingLoadBalancerClient(Client, LoadBalancerClient, LoadBalancerClientFactory)}
|
||||
*/
|
||||
@Deprecated
|
||||
public FeignBlockingLoadBalancerClient(Client delegate, LoadBalancerClient loadBalancerClient,
|
||||
LoadBalancerProperties properties, LoadBalancerClientFactory loadBalancerClientFactory) {
|
||||
this.delegate = delegate;
|
||||
this.loadBalancerClient = loadBalancerClient;
|
||||
this.loadBalancerClientFactory = loadBalancerClientFactory;
|
||||
}
|
||||
|
||||
public FeignBlockingLoadBalancerClient(Client delegate, LoadBalancerClient loadBalancerClient,
|
||||
LoadBalancerClientFactory loadBalancerClientFactory) {
|
||||
this.delegate = delegate;
|
||||
this.loadBalancerClient = loadBalancerClient;
|
||||
this.properties = properties;
|
||||
this.loadBalancerClientFactory = loadBalancerClientFactory;
|
||||
}
|
||||
|
||||
@@ -125,7 +116,6 @@ public class FeignBlockingLoadBalancerClient implements Client {
|
||||
}
|
||||
|
||||
private String getHint(String serviceId) {
|
||||
LoadBalancerProperties properties = loadBalancerClientFactory.getProperties(serviceId);
|
||||
String defaultHint = properties.getHint().getOrDefault("default", "default");
|
||||
String hintPropertyValue = properties.getHint().get(serviceId);
|
||||
return hintPropertyValue != null ? hintPropertyValue : defaultHint;
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2021 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+8
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2021 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -27,7 +27,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryFactory;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerClientsProperties;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerProperties;
|
||||
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
|
||||
import org.springframework.cloud.openfeign.clientconfig.HttpClient5FeignConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -46,16 +46,16 @@ import org.springframework.context.annotation.Import;
|
||||
@ConditionalOnBean({ LoadBalancerClient.class, LoadBalancerClientFactory.class })
|
||||
@ConditionalOnProperty(value = "feign.httpclient.hc5.enabled", havingValue = "true")
|
||||
@Import(HttpClient5FeignConfiguration.class)
|
||||
@EnableConfigurationProperties(LoadBalancerClientsProperties.class)
|
||||
@EnableConfigurationProperties(LoadBalancerProperties.class)
|
||||
class HttpClient5FeignLoadBalancerConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@Conditional(OnRetryNotEnabledCondition.class)
|
||||
public Client feignClient(LoadBalancerClient loadBalancerClient, HttpClient httpClient5,
|
||||
LoadBalancerClientFactory loadBalancerClientFactory) {
|
||||
LoadBalancerProperties properties, LoadBalancerClientFactory loadBalancerClientFactory) {
|
||||
Client delegate = new ApacheHttp5Client(httpClient5);
|
||||
return new FeignBlockingLoadBalancerClient(delegate, loadBalancerClient, loadBalancerClientFactory);
|
||||
return new FeignBlockingLoadBalancerClient(delegate, loadBalancerClient, properties, loadBalancerClientFactory);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -65,10 +65,11 @@ class HttpClient5FeignLoadBalancerConfiguration {
|
||||
@ConditionalOnProperty(value = "spring.cloud.loadbalancer.retry.enabled", havingValue = "true",
|
||||
matchIfMissing = true)
|
||||
public Client feignRetryClient(LoadBalancerClient loadBalancerClient, HttpClient httpClient5,
|
||||
LoadBalancedRetryFactory loadBalancedRetryFactory, LoadBalancerClientFactory loadBalancerClientFactory) {
|
||||
LoadBalancedRetryFactory loadBalancedRetryFactory, LoadBalancerProperties properties,
|
||||
LoadBalancerClientFactory loadBalancerClientFactory) {
|
||||
Client delegate = new ApacheHttp5Client(httpClient5);
|
||||
return new RetryableFeignBlockingLoadBalancerClient(delegate, loadBalancerClient, loadBalancedRetryFactory,
|
||||
loadBalancerClientFactory);
|
||||
properties, loadBalancerClientFactory);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+8
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2021 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -27,7 +27,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryFactory;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerClientsProperties;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerProperties;
|
||||
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
|
||||
import org.springframework.cloud.openfeign.HttpClient5DisabledConditions;
|
||||
import org.springframework.cloud.openfeign.clientconfig.HttpClientFeignConfiguration;
|
||||
@@ -50,16 +50,16 @@ import org.springframework.context.annotation.Import;
|
||||
@ConditionalOnProperty(value = "feign.httpclient.enabled", matchIfMissing = true)
|
||||
@Conditional(HttpClient5DisabledConditions.class)
|
||||
@Import(HttpClientFeignConfiguration.class)
|
||||
@EnableConfigurationProperties(LoadBalancerClientsProperties.class)
|
||||
@EnableConfigurationProperties(LoadBalancerProperties.class)
|
||||
class HttpClientFeignLoadBalancerConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@Conditional(OnRetryNotEnabledCondition.class)
|
||||
public Client feignClient(LoadBalancerClient loadBalancerClient, HttpClient httpClient,
|
||||
LoadBalancerClientFactory loadBalancerClientFactory) {
|
||||
LoadBalancerProperties properties, LoadBalancerClientFactory loadBalancerClientFactory) {
|
||||
ApacheHttpClient delegate = new ApacheHttpClient(httpClient);
|
||||
return new FeignBlockingLoadBalancerClient(delegate, loadBalancerClient, loadBalancerClientFactory);
|
||||
return new FeignBlockingLoadBalancerClient(delegate, loadBalancerClient, properties, loadBalancerClientFactory);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -69,10 +69,11 @@ class HttpClientFeignLoadBalancerConfiguration {
|
||||
@ConditionalOnProperty(value = "spring.cloud.loadbalancer.retry.enabled", havingValue = "true",
|
||||
matchIfMissing = true)
|
||||
public Client feignRetryClient(LoadBalancerClient loadBalancerClient, HttpClient httpClient,
|
||||
LoadBalancedRetryFactory loadBalancedRetryFactory, LoadBalancerClientFactory loadBalancerClientFactory) {
|
||||
LoadBalancedRetryFactory loadBalancedRetryFactory, LoadBalancerProperties properties,
|
||||
LoadBalancerClientFactory loadBalancerClientFactory) {
|
||||
ApacheHttpClient delegate = new ApacheHttpClient(httpClient);
|
||||
return new RetryableFeignBlockingLoadBalancerClient(delegate, loadBalancerClient, loadBalancedRetryFactory,
|
||||
loadBalancerClientFactory);
|
||||
properties, loadBalancerClientFactory);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+8
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -26,7 +26,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryFactory;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerClientsProperties;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerProperties;
|
||||
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
|
||||
import org.springframework.cloud.openfeign.clientconfig.OkHttpFeignConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -46,16 +46,16 @@ import org.springframework.context.annotation.Import;
|
||||
@ConditionalOnProperty("feign.okhttp.enabled")
|
||||
@ConditionalOnBean({ LoadBalancerClient.class, LoadBalancerClientFactory.class })
|
||||
@Import(OkHttpFeignConfiguration.class)
|
||||
@EnableConfigurationProperties(LoadBalancerClientsProperties.class)
|
||||
@EnableConfigurationProperties(LoadBalancerProperties.class)
|
||||
class OkHttpFeignLoadBalancerConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@Conditional(OnRetryNotEnabledCondition.class)
|
||||
public Client feignClient(okhttp3.OkHttpClient okHttpClient, LoadBalancerClient loadBalancerClient,
|
||||
LoadBalancerClientFactory loadBalancerClientFactory) {
|
||||
LoadBalancerProperties properties, LoadBalancerClientFactory loadBalancerClientFactory) {
|
||||
OkHttpClient delegate = new OkHttpClient(okHttpClient);
|
||||
return new FeignBlockingLoadBalancerClient(delegate, loadBalancerClient, loadBalancerClientFactory);
|
||||
return new FeignBlockingLoadBalancerClient(delegate, loadBalancerClient, properties, loadBalancerClientFactory);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -65,10 +65,11 @@ class OkHttpFeignLoadBalancerConfiguration {
|
||||
@ConditionalOnProperty(value = "spring.cloud.loadbalancer.retry.enabled", havingValue = "true",
|
||||
matchIfMissing = true)
|
||||
public Client feignRetryClient(LoadBalancerClient loadBalancerClient, okhttp3.OkHttpClient okHttpClient,
|
||||
LoadBalancedRetryFactory loadBalancedRetryFactory, LoadBalancerClientFactory loadBalancerClientFactory) {
|
||||
LoadBalancedRetryFactory loadBalancedRetryFactory, LoadBalancerProperties properties,
|
||||
LoadBalancerClientFactory loadBalancerClientFactory) {
|
||||
OkHttpClient delegate = new OkHttpClient(okHttpClient);
|
||||
return new RetryableFeignBlockingLoadBalancerClient(delegate, loadBalancerClient, loadBalancedRetryFactory,
|
||||
loadBalancerClientFactory);
|
||||
properties, loadBalancerClientFactory);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+5
-16
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -70,7 +70,7 @@ import static org.springframework.cloud.openfeign.loadbalancer.LoadBalancerUtils
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public class RetryableFeignBlockingLoadBalancerClient implements Client {
|
||||
|
||||
private static final Log LOG = LogFactory.getLog(FeignBlockingLoadBalancerClient.class);
|
||||
private static final Log LOG = LogFactory.getLog(RetryableFeignBlockingLoadBalancerClient.class);
|
||||
|
||||
private final Client delegate;
|
||||
|
||||
@@ -78,27 +78,17 @@ public class RetryableFeignBlockingLoadBalancerClient implements Client {
|
||||
|
||||
private final LoadBalancedRetryFactory loadBalancedRetryFactory;
|
||||
|
||||
private final LoadBalancerProperties properties;
|
||||
|
||||
private final LoadBalancerClientFactory loadBalancerClientFactory;
|
||||
|
||||
/**
|
||||
* @deprecated in favour of
|
||||
* {@link RetryableFeignBlockingLoadBalancerClient#RetryableFeignBlockingLoadBalancerClient(Client, LoadBalancerClient, LoadBalancedRetryFactory, LoadBalancerClientFactory)}
|
||||
*/
|
||||
@Deprecated
|
||||
public RetryableFeignBlockingLoadBalancerClient(Client delegate, LoadBalancerClient loadBalancerClient,
|
||||
LoadBalancedRetryFactory loadBalancedRetryFactory, LoadBalancerProperties properties,
|
||||
LoadBalancerClientFactory loadBalancerClientFactory) {
|
||||
this.delegate = delegate;
|
||||
this.loadBalancerClient = loadBalancerClient;
|
||||
this.loadBalancedRetryFactory = loadBalancedRetryFactory;
|
||||
this.loadBalancerClientFactory = loadBalancerClientFactory;
|
||||
}
|
||||
|
||||
public RetryableFeignBlockingLoadBalancerClient(Client delegate, LoadBalancerClient loadBalancerClient,
|
||||
LoadBalancedRetryFactory loadBalancedRetryFactory, LoadBalancerClientFactory loadBalancerClientFactory) {
|
||||
this.delegate = delegate;
|
||||
this.loadBalancerClient = loadBalancerClient;
|
||||
this.loadBalancedRetryFactory = loadBalancedRetryFactory;
|
||||
this.properties = properties;
|
||||
this.loadBalancerClientFactory = loadBalancerClientFactory;
|
||||
}
|
||||
|
||||
@@ -242,7 +232,6 @@ public class RetryableFeignBlockingLoadBalancerClient implements Client {
|
||||
}
|
||||
|
||||
private String getHint(String serviceId) {
|
||||
LoadBalancerProperties properties = loadBalancerClientFactory.getProperties(serviceId);
|
||||
String defaultHint = properties.getHint().getOrDefault("default", "default");
|
||||
String hintPropertyValue = properties.getHint().get(serviceId);
|
||||
return hintPropertyValue != null ? hintPropertyValue : defaultHint;
|
||||
|
||||
+2
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2019 the original author or authors.
|
||||
* Copyright 2015-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -43,6 +43,7 @@ import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
||||
* @author Tim Ysewyn
|
||||
* @since 3.0.0
|
||||
*/
|
||||
@Deprecated // spring-security-oauth2 reached EOL
|
||||
public class OAuth2FeignRequestInterceptor implements RequestInterceptor {
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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 org.springframework.cloud.openfeign.support;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.reflect.Type;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collection;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import feign.FeignException;
|
||||
import feign.Response;
|
||||
import feign.codec.Decoder;
|
||||
|
||||
import org.springframework.cloud.openfeign.encoding.HttpEncoding;
|
||||
|
||||
/**
|
||||
* When response is compressed as gzip, this decompresses and uses {@link SpringDecoder}
|
||||
* to decode.
|
||||
*
|
||||
* @author Jaesik Kim
|
||||
*/
|
||||
public class DefaultGzipDecoder implements Decoder {
|
||||
|
||||
private Decoder decoder;
|
||||
|
||||
public DefaultGzipDecoder(Decoder decoder) {
|
||||
this.decoder = decoder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object decode(final Response response, Type type) throws IOException, FeignException {
|
||||
Collection<String> encoding = response.headers().containsKey(HttpEncoding.CONTENT_ENCODING_HEADER)
|
||||
? response.headers().get(HttpEncoding.CONTENT_ENCODING_HEADER) : null;
|
||||
|
||||
if (encoding != null) {
|
||||
if (encoding.contains(HttpEncoding.GZIP_ENCODING)) {
|
||||
String decompressedBody = decompress(response);
|
||||
if (decompressedBody != null) {
|
||||
Response decompressedResponse = response.toBuilder().body(decompressedBody.getBytes()).build();
|
||||
return decoder.decode(decompressedResponse, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
return decoder.decode(response, type);
|
||||
}
|
||||
|
||||
private String decompress(Response response) throws IOException {
|
||||
if (response.body() == null) {
|
||||
return null;
|
||||
}
|
||||
try (GZIPInputStream gzipInputStream = new GZIPInputStream(response.body().asInputStream());
|
||||
BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(gzipInputStream, StandardCharsets.UTF_8))) {
|
||||
String outputString = "";
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
outputString += line;
|
||||
}
|
||||
return outputString;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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 org.springframework.cloud.openfeign.support;
|
||||
|
||||
import feign.codec.Decoder;
|
||||
import feign.optionals.OptionalDecoder;
|
||||
|
||||
import org.springframework.beans.factory.ObjectFactory;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
|
||||
import org.springframework.cloud.openfeign.FeignAutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* Configures Default Gzip Decoder.
|
||||
*
|
||||
* @author Jaesik Kim
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnProperty("feign.compression.response.enabled")
|
||||
// The OK HTTP client uses "transparent" compression.
|
||||
// If the accept-encoding header is present, it disables transparent compression
|
||||
@ConditionalOnMissingBean(type = "okhttp3.OkHttpClient")
|
||||
@AutoConfigureAfter(FeignAutoConfiguration.class)
|
||||
public class DefaultGzipDecoderConfiguration {
|
||||
|
||||
private ObjectFactory<HttpMessageConverters> messageConverters;
|
||||
|
||||
public DefaultGzipDecoderConfiguration(ObjectFactory<HttpMessageConverters> messageConverters) {
|
||||
this.messageConverters = messageConverters;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnProperty("feign.compression.response.useGzipDecoder")
|
||||
public Decoder defaultGzipDecoder() {
|
||||
return new OptionalDecoder(
|
||||
new ResponseEntityDecoder(new DefaultGzipDecoder(new SpringDecoder(messageConverters))));
|
||||
}
|
||||
|
||||
}
|
||||
-54
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2021 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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 org.springframework.cloud.openfeign.support;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
|
||||
/**
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*/
|
||||
class EmptyObjectProvider<T> implements ObjectProvider<T> {
|
||||
|
||||
@Override
|
||||
public T getObject(Object... args) throws BeansException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getIfAvailable() throws BeansException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getIfUnique() throws BeansException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getObject() throws BeansException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEach(Consumer action) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2021 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2021 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016-2021 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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 org.springframework.cloud.openfeign.support;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
|
||||
/**
|
||||
* Allows customising {@link HttpMessageConverter} objects passed via {@link Consumer}
|
||||
* parameter.
|
||||
*
|
||||
* @author Olga Maciaszek-Sharma
|
||||
* @since 3.1.0
|
||||
*/
|
||||
public interface HttpMessageConverterCustomizer extends Consumer<List<HttpMessageConverter<?>>> {
|
||||
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+44
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -38,6 +38,8 @@ import org.springframework.data.domain.Sort;
|
||||
*
|
||||
* @author Pascal Büttiker
|
||||
* @author Olga Maciaszek-Sharma
|
||||
* @author Pedro Mendes
|
||||
* @author Nikita Konev
|
||||
*/
|
||||
public class PageJacksonModule extends Module {
|
||||
|
||||
@@ -69,18 +71,22 @@ public class PageJacksonModule extends Module {
|
||||
@JsonProperty("size") int size, @JsonProperty("totalElements") @JsonAlias({ "total-elements",
|
||||
"total_elements", "totalelements", "TotalElements" }) long totalElements,
|
||||
@JsonProperty("sort") Sort sort) {
|
||||
PageRequest pageRequest;
|
||||
if (sort != null) {
|
||||
pageRequest = PageRequest.of(number, size, sort);
|
||||
if (size > 0) {
|
||||
PageRequest pageRequest;
|
||||
if (sort != null) {
|
||||
pageRequest = PageRequest.of(number, size, sort);
|
||||
}
|
||||
else {
|
||||
pageRequest = PageRequest.of(number, size);
|
||||
}
|
||||
delegate = new PageImpl<>(content, pageRequest, totalElements);
|
||||
}
|
||||
else {
|
||||
pageRequest = PageRequest.of(number, size);
|
||||
delegate = new PageImpl<>(content);
|
||||
}
|
||||
delegate = new PageImpl<>(content, pageRequest, totalElements);
|
||||
|
||||
}
|
||||
|
||||
@JsonProperty
|
||||
@JsonIgnore
|
||||
@Override
|
||||
public int getTotalPages() {
|
||||
return delegate.getTotalPages();
|
||||
@@ -104,7 +110,7 @@ public class PageJacksonModule extends Module {
|
||||
return delegate.getSize();
|
||||
}
|
||||
|
||||
@JsonProperty
|
||||
@JsonIgnore
|
||||
@Override
|
||||
public int getNumberOfElements() {
|
||||
return delegate.getNumberOfElements();
|
||||
@@ -128,13 +134,13 @@ public class PageJacksonModule extends Module {
|
||||
return delegate.getSort();
|
||||
}
|
||||
|
||||
@JsonProperty
|
||||
@JsonIgnore
|
||||
@Override
|
||||
public boolean isFirst() {
|
||||
return delegate.isFirst();
|
||||
}
|
||||
|
||||
@JsonProperty
|
||||
@JsonIgnore
|
||||
@Override
|
||||
public boolean isLast() {
|
||||
return delegate.isLast();
|
||||
@@ -176,6 +182,33 @@ public class PageJacksonModule extends Module {
|
||||
return delegate.iterator();
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
@Override
|
||||
public Pageable getPageable() {
|
||||
return delegate.getPageable();
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return delegate.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return delegate.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return delegate.equals(obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return delegate.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -32,7 +32,6 @@ import org.springframework.data.domain.Sort;
|
||||
* Provides support for encoding spring Pageable via composition.
|
||||
*
|
||||
* @author Pascal Büttiker
|
||||
* @author Yanming Zhou
|
||||
*/
|
||||
public class PageableSpringEncoder implements Encoder {
|
||||
|
||||
@@ -83,8 +82,8 @@ public class PageableSpringEncoder implements Encoder {
|
||||
Pageable pageable = (Pageable) object;
|
||||
|
||||
if (pageable.isPaged()) {
|
||||
template.query(pageParameter, String.valueOf(pageable.getPageNumber()));
|
||||
template.query(sizeParameter, String.valueOf(pageable.getPageSize()));
|
||||
template.query(pageParameter, pageable.getPageNumber() + "");
|
||||
template.query(sizeParameter, pageable.getPageSize() + "");
|
||||
}
|
||||
|
||||
if (pageable.getSort() != null) {
|
||||
|
||||
+4
-32
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2021 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -31,38 +31,10 @@ import org.springframework.data.domain.Sort;
|
||||
* {@link org.springframework.cloud.openfeign.SpringQueryMap}.
|
||||
*
|
||||
* @author Hyeonmin Park
|
||||
* @author Yanming Zhou
|
||||
* @since 2.2.8
|
||||
*/
|
||||
public class PageableSpringQueryMapEncoder extends BeanQueryMapEncoder {
|
||||
|
||||
/**
|
||||
* Page index parameter name.
|
||||
*/
|
||||
private String pageParameter = "page";
|
||||
|
||||
/**
|
||||
* Page size parameter name.
|
||||
*/
|
||||
private String sizeParameter = "size";
|
||||
|
||||
/**
|
||||
* Sort parameter name.
|
||||
*/
|
||||
private String sortParameter = "sort";
|
||||
|
||||
public void setPageParameter(String pageParameter) {
|
||||
this.pageParameter = pageParameter;
|
||||
}
|
||||
|
||||
public void setSizeParameter(String sizeParameter) {
|
||||
this.sizeParameter = sizeParameter;
|
||||
}
|
||||
|
||||
public void setSortParameter(String sortParameter) {
|
||||
this.sortParameter = sortParameter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> encode(Object object) {
|
||||
if (supports(object)) {
|
||||
@@ -72,8 +44,8 @@ public class PageableSpringQueryMapEncoder extends BeanQueryMapEncoder {
|
||||
Pageable pageable = (Pageable) object;
|
||||
|
||||
if (pageable.isPaged()) {
|
||||
queryMap.put(pageParameter, pageable.getPageNumber());
|
||||
queryMap.put(sizeParameter, pageable.getPageSize());
|
||||
queryMap.put("page", pageable.getPageNumber());
|
||||
queryMap.put("size", pageable.getPageSize());
|
||||
}
|
||||
|
||||
if (pageable.getSort() != null) {
|
||||
@@ -97,7 +69,7 @@ public class PageableSpringQueryMapEncoder extends BeanQueryMapEncoder {
|
||||
sortQueries.add(order.getProperty() + "%2C" + order.getDirection());
|
||||
}
|
||||
if (!sortQueries.isEmpty()) {
|
||||
queryMap.put(sortParameter, sortQueries);
|
||||
queryMap.put("sort", sortQueries);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2021 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+10
-28
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,7 +21,6 @@ import java.io.InputStream;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.WildcardType;
|
||||
import java.util.List;
|
||||
|
||||
import feign.FeignException;
|
||||
import feign.Response;
|
||||
@@ -29,48 +28,31 @@ import feign.codec.DecodeException;
|
||||
import feign.codec.Decoder;
|
||||
|
||||
import org.springframework.beans.factory.ObjectFactory;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.web.client.HttpMessageConverterExtractor;
|
||||
|
||||
import static org.springframework.cloud.openfeign.support.FeignUtils.getHttpHeaders;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*/
|
||||
public class SpringDecoder implements Decoder {
|
||||
|
||||
private final ObjectFactory<HttpMessageConverters> messageConverters;
|
||||
private ObjectFactory<HttpMessageConverters> messageConverters;
|
||||
|
||||
private final ObjectProvider<HttpMessageConverterCustomizer> customizers;
|
||||
|
||||
/**
|
||||
* @deprecated in favour of
|
||||
* {@link SpringDecoder#SpringDecoder(ObjectFactory, ObjectProvider)}
|
||||
*/
|
||||
@Deprecated
|
||||
public SpringDecoder(ObjectFactory<HttpMessageConverters> messageConverters) {
|
||||
this(messageConverters, new EmptyObjectProvider<>());
|
||||
}
|
||||
|
||||
public SpringDecoder(ObjectFactory<HttpMessageConverters> messageConverters,
|
||||
ObjectProvider<HttpMessageConverterCustomizer> customizers) {
|
||||
this.messageConverters = messageConverters;
|
||||
this.customizers = customizers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object decode(final Response response, Type type) throws IOException, FeignException {
|
||||
if (type instanceof Class || type instanceof ParameterizedType || type instanceof WildcardType) {
|
||||
List<HttpMessageConverter<?>> converters = messageConverters.getObject().getConverters();
|
||||
customizers.forEach(customizer -> customizer.accept(converters));
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
HttpMessageConverterExtractor<?> extractor = new HttpMessageConverterExtractor(type, converters);
|
||||
HttpMessageConverterExtractor<?> extractor = new HttpMessageConverterExtractor(type,
|
||||
this.messageConverters.getObject().getConverters());
|
||||
|
||||
return extractor.extractData(new FeignResponseAdapter(response));
|
||||
}
|
||||
@@ -88,23 +70,23 @@ public class SpringDecoder implements Decoder {
|
||||
|
||||
@Override
|
||||
public HttpStatus getStatusCode() throws IOException {
|
||||
return HttpStatus.valueOf(response.status());
|
||||
return HttpStatus.valueOf(this.response.status());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRawStatusCode() throws IOException {
|
||||
return response.status();
|
||||
return this.response.status();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStatusText() throws IOException {
|
||||
return response.reason();
|
||||
return this.response.reason();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
try {
|
||||
response.body().close();
|
||||
this.response.body().close();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
// Ignore exception on close...
|
||||
@@ -113,12 +95,12 @@ public class SpringDecoder implements Decoder {
|
||||
|
||||
@Override
|
||||
public InputStream getBody() throws IOException {
|
||||
return response.body().asInputStream();
|
||||
return this.response.body().asInputStream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpHeaders getHeaders() {
|
||||
return getHttpHeaders(response.headers());
|
||||
return getHttpHeaders(this.response.headers());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-24
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2021 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -24,7 +24,6 @@ import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@@ -36,7 +35,6 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.ObjectFactory;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
|
||||
import org.springframework.cloud.openfeign.encoding.HttpEncoding;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
@@ -76,37 +74,19 @@ public class SpringEncoder implements Encoder {
|
||||
|
||||
private final FeignEncoderProperties encoderProperties;
|
||||
|
||||
private final ObjectProvider<HttpMessageConverterCustomizer> customizers;
|
||||
|
||||
public SpringEncoder(ObjectFactory<HttpMessageConverters> messageConverters) {
|
||||
this(new SpringFormEncoder(), messageConverters);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated in favour of
|
||||
* {@link SpringEncoder#SpringEncoder(SpringFormEncoder, ObjectFactory, FeignEncoderProperties, ObjectProvider)}
|
||||
*/
|
||||
@Deprecated
|
||||
public SpringEncoder(SpringFormEncoder springFormEncoder, ObjectFactory<HttpMessageConverters> messageConverters) {
|
||||
this(springFormEncoder, messageConverters, new FeignEncoderProperties());
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated in favour of
|
||||
* {@link SpringEncoder#SpringEncoder(SpringFormEncoder, ObjectFactory, FeignEncoderProperties, ObjectProvider)}
|
||||
*/
|
||||
@Deprecated
|
||||
public SpringEncoder(SpringFormEncoder springFormEncoder, ObjectFactory<HttpMessageConverters> messageConverters,
|
||||
FeignEncoderProperties encoderProperties) {
|
||||
this(springFormEncoder, messageConverters, encoderProperties, new EmptyObjectProvider<>());
|
||||
}
|
||||
|
||||
public SpringEncoder(SpringFormEncoder springFormEncoder, ObjectFactory<HttpMessageConverters> messageConverters,
|
||||
FeignEncoderProperties encoderProperties, ObjectProvider<HttpMessageConverterCustomizer> customizers) {
|
||||
this.springFormEncoder = springFormEncoder;
|
||||
this.messageConverters = messageConverters;
|
||||
this.encoderProperties = encoderProperties;
|
||||
this.customizers = customizers;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -137,9 +117,7 @@ public class SpringEncoder implements Encoder {
|
||||
|
||||
private void encodeWithMessageConverter(Object requestBody, Type bodyType, RequestTemplate request,
|
||||
MediaType requestContentType) {
|
||||
List<HttpMessageConverter<?>> converters = messageConverters.getObject().getConverters();
|
||||
customizers.forEach(customizer -> customizer.accept(converters));
|
||||
for (HttpMessageConverter messageConverter : converters) {
|
||||
for (HttpMessageConverter messageConverter : this.messageConverters.getObject().getConverters()) {
|
||||
FeignOutputMessage outputMessage;
|
||||
try {
|
||||
if (messageConverter instanceof GenericHttpMessageConverter) {
|
||||
|
||||
+1
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -40,7 +40,6 @@ import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.cloud.openfeign.AnnotatedParameterProcessor;
|
||||
import org.springframework.cloud.openfeign.CollectionFormat;
|
||||
import org.springframework.cloud.openfeign.annotation.CookieValueParameterProcessor;
|
||||
import org.springframework.cloud.openfeign.annotation.MatrixVariableParameterProcessor;
|
||||
import org.springframework.cloud.openfeign.annotation.PathVariableParameterProcessor;
|
||||
import org.springframework.cloud.openfeign.annotation.QueryMapParameterProcessor;
|
||||
@@ -82,7 +81,6 @@ import static org.springframework.core.annotation.AnnotatedElementUtils.findMerg
|
||||
* @author Artyom Romanenko
|
||||
* @author Darren Foong
|
||||
* @author Ram Anaswara
|
||||
* @author Sam Kruglov
|
||||
*/
|
||||
public class SpringMvcContract extends Contract.BaseContract implements ResourceLoaderAware {
|
||||
|
||||
@@ -181,10 +179,6 @@ public class SpringMvcContract extends Contract.BaseContract implements Resource
|
||||
+ ". @RequestMapping annotation is not allowed on @FeignClient interfaces.");
|
||||
throw new IllegalArgumentException("@RequestMapping annotation not allowed on @FeignClient interfaces");
|
||||
}
|
||||
CollectionFormat collectionFormat = findMergedAnnotation(clz, CollectionFormat.class);
|
||||
if (collectionFormat != null) {
|
||||
data.template().collectionFormat(collectionFormat.value());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -341,7 +335,6 @@ public class SpringMvcContract extends Contract.BaseContract implements Resource
|
||||
annotatedArgumentResolvers.add(new RequestHeaderParameterProcessor());
|
||||
annotatedArgumentResolvers.add(new QueryMapParameterProcessor());
|
||||
annotatedArgumentResolvers.add(new RequestPartParameterProcessor());
|
||||
annotatedArgumentResolvers.add(new CookieValueParameterProcessor());
|
||||
|
||||
return annotatedArgumentResolvers;
|
||||
}
|
||||
|
||||
+6
@@ -44,6 +44,12 @@
|
||||
"description": "Enables the response from Feign to be compressed.",
|
||||
"defaultValue": "false"
|
||||
},
|
||||
{
|
||||
"name": "feign.compression.response.useGzipDecoder",
|
||||
"type": "java.lang.Boolean",
|
||||
"description": "Enables the default gzip decoder to be used.",
|
||||
"defaultValue": "false"
|
||||
},
|
||||
{
|
||||
"name": "feign.compression.request.enabled",
|
||||
"type": "java.lang.Boolean",
|
||||
|
||||
+5
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -39,16 +39,15 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Jaesik Kim
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringBootTest(classes = GzipDecodingTests.Application.class,
|
||||
@SpringBootTest(classes = DefaultGzipDecoderTests.Application.class,
|
||||
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
value = { "spring.application.name=defaultGzipDecoderTests", "feign.compression.response.enabled=true",
|
||||
"feign.client.config.default.loggerLevel=none", "feign.metrics.enabled=false",
|
||||
"feign.compression.response.useGzipDecoder=true", "feign.client.config.default.loggerLevel=full",
|
||||
"logging.level.org.springframework.cloud.openfeign=DEBUG" })
|
||||
@DirtiesContext
|
||||
public class GzipDecodingTests extends FeignClientFactoryBean {
|
||||
public class DefaultGzipDecoderTests extends FeignClientFactoryBean {
|
||||
|
||||
@Autowired
|
||||
FeignContext context;
|
||||
@@ -56,7 +55,7 @@ public class GzipDecodingTests extends FeignClientFactoryBean {
|
||||
@Value("${local.server.port}")
|
||||
private int port = 0;
|
||||
|
||||
public GzipDecodingTests() {
|
||||
public DefaultGzipDecoderTests() {
|
||||
setName("tests");
|
||||
setContextId("test");
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2021 the original author or authors.
|
||||
* Copyright 2013-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
-123
@@ -1,123 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020-2020 the original author or authors.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* https://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 org.springframework.cloud.openfeign;
|
||||
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import feign.Contract;
|
||||
import feign.RequestLine;
|
||||
import feign.RetryableException;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.cache.interceptor.SimpleKey;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
/**
|
||||
* @author Sam Kruglov
|
||||
*/
|
||||
@SpringBootTest(classes = FeignClientCacheTests.TestConfiguration.class)
|
||||
@DirtiesContext
|
||||
public class FeignClientCacheTests {
|
||||
|
||||
private static final String CACHE_NAME = "foo-cache";
|
||||
|
||||
@Autowired
|
||||
private FooClient foo;
|
||||
|
||||
@Test
|
||||
void cacheExists(@Autowired CacheManager cacheManager) {
|
||||
assertThat(cacheManager.getCache(CACHE_NAME)).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void interceptedCallsReal() {
|
||||
assertThatExceptionOfType(RetryableException.class).isThrownBy(foo::getWithCache)
|
||||
.withRootCauseInstanceOf(UnknownHostException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void nonInterceptedCallsReal() {
|
||||
assertThatExceptionOfType(RetryableException.class).isThrownBy(foo::getWithoutCache)
|
||||
.withRootCauseInstanceOf(UnknownHostException.class);
|
||||
}
|
||||
|
||||
@Nested
|
||||
class givenCached {
|
||||
|
||||
String cachedValue = "cached";
|
||||
|
||||
@BeforeEach
|
||||
void setUp(@Autowired CacheManager cacheManager) {
|
||||
cacheManager.getCache(CACHE_NAME).put(SimpleKey.EMPTY, cachedValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
void interceptedReturnsCached() {
|
||||
assertThat(foo.getWithCache()).isSameAs(cachedValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
void nonInterceptedCallsReal() {
|
||||
assertThatExceptionOfType(RetryableException.class).isThrownBy(foo::getWithoutCache)
|
||||
.withRootCauseInstanceOf(UnknownHostException.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableFeignClients(clients = FooClient.class)
|
||||
@EnableAutoConfiguration
|
||||
@EnableCaching
|
||||
protected static class TestConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@FeignClient(name = "foo", url = "http://foo", configuration = FooConfiguration.class)
|
||||
interface FooClient {
|
||||
|
||||
@RequestLine("GET /with-cache")
|
||||
@Cacheable(cacheNames = CACHE_NAME)
|
||||
String getWithCache();
|
||||
|
||||
@RequestLine("GET /without-cache")
|
||||
String getWithoutCache();
|
||||
|
||||
}
|
||||
|
||||
public static class FooConfiguration {
|
||||
|
||||
@Bean
|
||||
Contract feignContract() {
|
||||
return new Contract.Default();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2021 the original author or authors.
|
||||
* Copyright 2021-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2021 the original author or authors.
|
||||
* Copyright 2021-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2021-2021 the original author or authors.
|
||||
* Copyright 2021-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user