Compare commits

..
38 Commits
Author SHA1 Message Date
buildmaster d111204007 Update SNAPSHOT to 3.0.8 2022-07-27 10:26:03 +00:00
fml2 b4c9567de5 Update spring-cloud-openfeign.adoc 2022-07-25 16:00:28 +02:00
Nikita Konev 8fdb488697 fix cascading deserialization Spring Data's Page by setting @JsonIgnoreProperties(ignoreUnknown = true), revert ignoring getTotalPages(), getNumberOfElements(), isFirst(), isLast() (#653) 2022-07-25 15:12:22 +02:00
buildmaster 7e01355317 Bumping versions to 3.0.8-SNAPSHOT after release 2022-06-29 22:15:46 +00:00
buildmaster fc459044b5 Going back to snapshots 2022-06-29 22:15:46 +00:00
buildmaster e321e72e3d Update SNAPSHOT to 3.0.7 2022-06-29 22:14:15 +00:00
Olga Maciaszek-Sharma ae63aae6eb Add deprecations for OAuth2. 2022-06-29 17:40:23 +02:00
Olga Maciaszek-Sharma 10fefea29b Remove incompatible test. 2022-06-28 15:46:11 +02:00
Olga MaciaszekSharma 24d9b08d5c Backport bugfix and resolve conflicts. 2022-06-28 15:36:06 +02:00
Olga Maciaszek-Sharma d4832788f6 Resolve conflicts for backport. 2022-06-28 15:02:16 +02:00
Olga Maciaszek-Sharma ff96850ec0 Wrap underlying checked exception with IllegalStateException. Add tests. 2022-06-28 14:53:37 +02:00
Olga Maciaszek-Sharma 9023cc2dc5 Unwarap InvocationTargetException and NoFallbackAvailableException. 2022-06-28 14:53:27 +02:00
Olga Maciaszek-Sharma 6c3b8c257e Fixes gh-680. 2022-06-28 14:44:00 +02:00
buildmaster fe43b6c52b Bumping versions 2022-02-24 10:52:51 +00:00
Olga MaciaszekSharma 3e5aa41490 Update license entries. 2022-01-11 14:47:10 +01:00
Olga Maciaszek-Sharma 3a1d19f74f Upgarde protobuf-java (security fix) and vavr. (#663) 2022-01-11 14:12:31 +01:00
buildmaster 0853ccc1e5 Bumping versions to 3.0.7-SNAPSHOT after release 2021-12-15 17:02:34 +00:00
buildmaster 13f91320b1 Going back to snapshots 2021-12-15 17:02:33 +00:00
buildmaster 7af0efd569 Update SNAPSHOT to 3.0.6 2021-12-15 17:01:03 +00:00
Been24 70a9002002 Update RetryableFeignBlockingLoadBalancerClient.java
fix log  class
2021-11-29 16:45:40 +01:00
Nikita Konev ad892a23f0 Support size = 0 in PageJacksonModule 2021-11-29 16:30:20 +01:00
Hyeonmin Park c0f314a5f0 GitHub workflows: Use Java version in matrix, cache functionality of actions/setup-java@v2 (#614)
* Fix GitHub workflows not using Java version in matrix

* Use cache functionality of actions/setup-java@v2
2021-10-28 18:15:02 +02:00
buildmaster 56dc4e07e4 Bumping versions to 3.0.6-SNAPSHOT after release 2021-10-21 11:48:48 +00:00
buildmaster 9167752bfb Going back to snapshots 2021-10-21 11:48:47 +00:00
buildmaster 127c866616 Update SNAPSHOT to 3.0.5 2021-10-21 11:46:52 +00:00
Olga MaciaszekSharma 0e6b33f480 Merge remote-tracking branch 'origin/2.2.x' into 3.0.x 2021-10-21 13:04:57 +02:00
Olga MaciaszekSharma 17d0161faf Reformat. 2021-10-21 12:40:20 +02:00
Olga MaciaszekSharma d6783a6f1e Block clas-level request mapping on Feign clients. 2021-10-21 12:14:19 +02:00
Olga MaciaszekSharma 1275875ddb Reformat. 2021-07-07 18:58:48 +02:00
Olga MaciaszekSharma c4b9492a9b Bumping versions to 2.2.10.BUILD-SNAPSHOT after release
This reverts commit f7e490c466.
2021-07-07 18:46:53 +02:00
Olga MaciaszekSharma 3acf5f9e92 Going back to snapshots
This reverts commit 6479db0a54.
2021-07-07 18:46:20 +02:00
buildmaster e9e38d0274 Bumping versions 2021-07-07 14:07:20 +00:00
Olga MaciaszekSharma 28b50401c5 Revert "Update SNAPSHOT to 2.2.9.RELEASE"
This reverts commit 1005749eb5.
2021-07-07 14:38:12 +02:00
Olga MaciaszekSharma 6479db0a54 Revert "Going back to snapshots"
This reverts commit 190f5a9083.
2021-07-07 14:37:39 +02:00
Olga MaciaszekSharma f7e490c466 Revert "Bumping versions to 2.2.10.BUILD-SNAPSHOT after release"
This reverts commit d60cda824d.
2021-07-07 14:37:03 +02:00
buildmaster d60cda824d Bumping versions to 2.2.10.BUILD-SNAPSHOT after release 2021-07-06 14:53:53 +00:00
buildmaster 190f5a9083 Going back to snapshots 2021-07-06 14:53:53 +00:00
buildmaster 1005749eb5 Update SNAPSHOT to 2.2.9.RELEASE 2021-07-06 14:52:01 +00:00
186 changed files with 860 additions and 938 deletions
+7 -12
View File
@@ -5,9 +5,9 @@ name: Build
on:
push:
branches: [ main ]
branches: [ 3.0.x ]
pull_request:
branches: [ main ]
branches: [ 3.0.x ]
jobs:
build:
@@ -20,17 +20,12 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: Set up JDK 1.8
uses: actions/setup-java@v1
- name: Set up JDK ${{ matrix.java }}
uses: actions/setup-java@v2
with:
java-version: 1.8
- name: Cache local Maven repository
uses: actions/cache@v2
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
distribution: 'zulu'
java-version: ${{ matrix.java }}
cache: 'maven'
- name: Build with Maven
run: ./mvnw clean install -B -U -P sonar
- uses: codecov/codecov-action@v1
+53 -1
View File
@@ -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
View File
@@ -6,7 +6,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-openfeign</artifactId>
<version>3.1.0-M3</version>
<version>3.0.8</version>
</parent>
<artifactId>spring-cloud-openfeign-docs</artifactId>
<packaging>jar</packaging>
+1
View File
@@ -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
View File
@@ -1 +0,0 @@
include::spring-cloud-openfeign.adoc[]
+1
View File
@@ -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);
}
----
@@ -200,7 +197,7 @@ feign:
Default configurations can be specified in the `@EnableFeignClients` attribute `defaultConfiguration` in a similar manner as described above. The difference is that this configuration will apply to _all_ feign clients.
If you prefer using configuration properties to configured all `@FeignClient`, you can create configuration properties with `default` feign name.
If you prefer using configuration properties to configure all `@FeignClient`, you can create configuration properties with `default` feign name.
You can use `feign.client.config.feignName.defaultQueryParameters` and `feign.client.config.feignName.defaultRequestHeaders` to specify query parameters and headers that will be sent with every request of the client named `feignName`.
@@ -494,10 +491,7 @@ public interface UserClient extends UserService {
}
----
NOTE: It is generally not advisable to share an interface between a
server and a client. It introduces tight coupling, and is also not supported by
all the maintained Spring MVC versions (method parameter
mapping is not inherited in some versions).
WARNING: `@FeignClient` interfaces should not be shared between server and client and annotating `@FeignClient` interfaces with `@RequestMapping` on class level is no longer supported.
=== Feign request/response compression
@@ -521,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.
+3 -3
View File
@@ -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-M3</version>
<version>3.0.8</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-M3</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-M3</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>
+3 -3
View File
@@ -6,7 +6,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-openfeign</artifactId>
<version>3.1.0-M3</version>
<version>3.0.8</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,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,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,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,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,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,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,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,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.
@@ -58,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;
@@ -86,6 +87,7 @@ import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResour
@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);
@@ -310,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,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,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,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,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,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,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,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,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,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,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,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,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);
}
}
@@ -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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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;
}
}
@@ -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);
}
}
@@ -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,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,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,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,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,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,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,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,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,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;
@@ -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,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.
@@ -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;
}
}
}
@@ -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))));
}
}
@@ -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,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,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,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,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,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,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.
@@ -22,6 +22,7 @@ import java.util.function.Function;
import com.fasterxml.jackson.annotation.JsonAlias;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.databind.Module;
@@ -38,6 +39,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 {
@@ -57,6 +60,7 @@ public class PageJacksonModule extends Module {
}
@JsonDeserialize(as = SimplePageImpl.class)
@JsonIgnoreProperties(ignoreUnknown = true)
private interface PageMixIn {
}
@@ -69,15 +73,19 @@ 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
@@ -176,6 +184,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();
}
}
}
@@ -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) {
@@ -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,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,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,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,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());
}
}
@@ -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,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.
@@ -35,10 +35,11 @@ import feign.Feign;
import feign.MethodMetadata;
import feign.Param;
import feign.Request;
import org.apache.commons.logging.Log;
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;
@@ -83,6 +84,8 @@ import static org.springframework.core.annotation.AnnotatedElementUtils.findMerg
*/
public class SpringMvcContract extends Contract.BaseContract implements ResourceLoaderAware {
private static final Log LOG = LogFactory.getLog(SpringMvcContract.class);
private static final String ACCEPT = "Accept";
private static final String CONTENT_TYPE = "Content-Type";
@@ -170,47 +173,18 @@ public class SpringMvcContract extends Contract.BaseContract implements Resource
@Override
protected void processAnnotationOnClass(MethodMetadata data, Class<?> clz) {
if (clz.getInterfaces().length == 0) {
RequestMapping classAnnotation = findMergedAnnotation(clz, RequestMapping.class);
if (classAnnotation != null) {
// Prepend path from class annotation if specified
if (classAnnotation.value().length > 0) {
String pathValue = emptyToNull(classAnnotation.value()[0]);
pathValue = resolve(pathValue);
if (!pathValue.startsWith("/")) {
pathValue = "/" + pathValue;
}
data.template().uri(pathValue);
if (data.template().decodeSlash() != decodeSlash) {
data.template().decodeSlash(decodeSlash);
}
}
}
RequestMapping classAnnotation = findMergedAnnotation(clz, RequestMapping.class);
if (classAnnotation != null) {
LOG.error("Cannot process class: " + clz.getName()
+ ". @RequestMapping annotation is not allowed on @FeignClient interfaces.");
throw new IllegalArgumentException("@RequestMapping annotation not allowed on @FeignClient interfaces");
}
}
@Override
public MethodMetadata parseAndValidateMetadata(Class<?> targetType, Method method) {
processedMethods.put(Feign.configKey(targetType, method), method);
MethodMetadata md = super.parseAndValidateMetadata(targetType, method);
RequestMapping classAnnotation = findMergedAnnotation(targetType, RequestMapping.class);
if (classAnnotation != null) {
// produces - use from class annotation only if method has not specified this
if (!md.template().headers().containsKey(ACCEPT)) {
parseProduces(md, method, classAnnotation);
}
// consumes -- use from class annotation only if method has not specified this
if (!md.template().headers().containsKey(CONTENT_TYPE)) {
parseConsumes(md, method, classAnnotation);
}
// headers -- class annotation is inherited to methods, always write these if
// present
parseHeaders(md, method, classAnnotation);
}
return md;
return super.parseAndValidateMetadata(targetType, method);
}
@Override
@@ -361,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;
}
@@ -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",
@@ -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,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,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,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,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,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,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,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,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,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,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,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