-
Notifications
You must be signed in to change notification settings - Fork 1.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Flux type response should be corresponding to List #2199
Conversation
WalkthroughThis pull request introduces significant enhancements to the Feign library, adding support for reactive programming with Reactor and RxJava. It includes new decoders for handling Changes
TipsChat with CodeRabbit Bot (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review Status
Actionable comments generated: 3
Files selected for processing (4)
- core/src/main/java/feign/Types.java (2 hunks)
- core/src/main/java/feign/Util.java (1 hunks)
- reactive/README.md (2 hunks)
- reactive/src/main/java/feign/reactive/ReactiveDecoder.java (1 hunks)
Files skipped from review due to trivial changes (1)
- core/src/main/java/feign/Util.java
Additional comments (Suppressed): 4
reactive/README.md (1)
- 37-38: The
ReactorFeign.builder()
now includes adecoder
method call. Ensure that theReactiveDecoder
class is properly implemented and that it correctly handlesMono
andFlux
types.core/src/main/java/feign/Types.java (3)
327-358: The new method
resolveLastTypeParameter
is introduced to resolve the last type parameter of a parameterized supertype. It throws anIllegalStateException
if the supertype cannot be resolved into a parameterized type using the provided context. This method is copied fromretrofit.RestMethodInfo
. Ensure that the copied method is compatible with the current codebase and that it doesn't introduce any licensing issues.360-362: The new method
parameterize
is introduced to create a newParameterizedTypeImpl
instance. It takes a raw class and an array of type arguments as parameters. This method improves the modularity of the code by providing a way to createParameterizedTypeImpl
instances.364-366: The
ParameterizedTypeImpl
class is now made package-private (default access modifier in Java). This change restricts the visibility of the class to the package in which it is defined. Ensure that this change doesn't break any code outside the package that might be using this class.
@RequestLine("GET /repos/{owner}/{repo}/contributors") | ||
Flux<Contributor> contributors(@Param("owner") String owner, @Param("repo") String repo); | ||
Flux<Contributor> contributorsFlux(@Param("owner") String owner, @Param("repo") String repo); | ||
|
||
@RequestLine("GET /repos/{owner}/{repo}/contributors") | ||
Mono<List<Contributor>> contributorsMono(@Param("owner") String owner, @Param("repo") String repo); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The contributorsFlux
and contributorsMono
methods have the same @RequestLine
annotation. This could lead to confusion and potential errors. Consider renaming these methods to better reflect their return types or the data they are fetching.
### Iterable and Collections responses | ||
|
||
Due to the Synchronous nature of Feign requests, methods that return `Iterable` types must specify the collection | ||
in the `Publisher`. For `Reactor` types, this limits the use of `Flux` as a response type. If you | ||
want to use `Flux`, you will need to manually convert the `Mono` or `Iterable` response types into | ||
`Flux` using the `fromIterable` method. | ||
|
||
in the `Publisher`. For `Reactor` types, this limits the use of `Flux` as a response type. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The removal of the example code that demonstrates how to manually convert Mono
or Iterable
response types into Flux
using the fromIterable
method could potentially confuse users. Consider adding a similar example or providing a link to documentation that explains this process.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm good with the change, but can we get at least one test?
Sure. I'll add. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review Status
Actionable comments generated: 3
Files selected for processing (9)
- reactive/README.md (3 hunks)
- reactive/src/main/java/feign/reactive/ReactiveDelegatingContract.java (1 hunks)
- reactive/src/main/java/feign/reactive/ReactorDecoder.java (1 hunks)
- reactive/src/main/java/feign/reactive/ReactorInvocationHandler.java (1 hunks)
- reactive/src/main/java/feign/reactive/RxJavaDecoder.java (1 hunks)
- reactive/src/test/java/feign/reactive/ReactiveFeignIntegrationTest.java (12 hunks)
- reactive/src/test/java/feign/reactive/examples/ConsoleLogger.java (1 hunks)
- reactive/src/test/java/feign/reactive/examples/ReactorGitHubExample.java (1 hunks)
- reactive/src/test/java/feign/reactive/examples/RxJavaGitHubExample.java (1 hunks)
Files skipped from review due to trivial changes (1)
- reactive/src/test/java/feign/reactive/examples/ConsoleLogger.java
Additional comments (Suppressed): 20
reactive/src/main/java/feign/reactive/ReactorDecoder.java (1)
- 27-50: The
ReactorDecoder
class is implementing theDecoder
interface and overriding thedecode
method to handleMono
andFlux
types. However, forFlux
type, it seems to be decoding the response into aList
. This might not be the expected behavior asFlux
is a stream of 0 to N items, and decoding it into aList
might cause memory issues for large data streams. Consider returning aFlux
instead of aList
.- Type listType = Types.parameterize(List.class, lastType); - return delegate.decode(response, listType); + return Flux.fromIterable((List<?>) delegate.decode(response, listType));reactive/src/test/java/feign/reactive/examples/RxJavaGitHubExample.java (1)
- 31-36: The
RxJavaDecoder
is being used withJacksonDecoder
which is a good practice for handling JSON responses. However, ensure that theJacksonDecoder
is compatible with the data being returned from the API calls. If the API returns a different data format, you may need to use a different decoder.reactive/src/test/java/feign/reactive/examples/ReactorGitHubExample.java (5)
33-37: The
ReactorFeign.builder()
is correctly configured with the newReactorDecoder
andJacksonDecoder
. The logger and log level are also set appropriately. The target URL is correctly set to "https://api.github.com".39-45: The
contributorsFlux
method is used to fetch a list of contributors using aFlux
type. ThecollectList()
method is used to convert theFlux
to aList
, and theblock()
method is used to subscribe to theFlux
and block until it completes. The contributors are then printed to the console. This is a correct usage of theFlux
type.47-52: The
contributorsMono
method is used to fetch a list of contributors using aMono
type. Theblock()
method is used to subscribe to theMono
and block until it completes. The contributors are then printed to the console. This is a correct usage of theMono
type.56-61: The
GitHub
interface is correctly defined with two methods:contributorsFlux
andcontributorsMono
. Both methods use the@RequestLine
annotation to define the HTTP request, and the@Param
annotation to define the path parameters. ThecontributorsFlux
method returns aFlux<Contributor>
, and thecontributorsMono
method returns aMono<List<Contributor>>
.63-74: The
Contributor
class is correctly defined with two fields:login
andcontributions
. ThesetLogin
andsetContributions
methods are used to set the values of these fields.reactive/src/main/java/feign/reactive/ReactiveDelegatingContract.java (1)
- 55-59: The new hunk has replaced the direct assignment of the first type argument to the method's return type with a call to the
type()
method. This change could potentially alter the behavior of the code if thetype()
method does not return the first type argument as expected. Please verify that thetype()
method is implemented correctly and that this change does not introduce any unexpected behavior.reactive/src/main/java/feign/reactive/ReactorInvocationHandler.java (1)
- 36-42: The new hunk introduces a
flatMapIterable
operation on theFlux
type. This operation transforms the elements of the Flux into Iterables and then flattens these Iterables into a new Flux. This change implies that the method now expects the elements of the Flux to be Iterables. Ensure that this change is compatible with the expected return types of the methods that will be invoked by this handler. If the methods are not returning Iterables, this could lead to aClassCastException
.- return Flux.from(invocation).flatMapIterable(e -> (Iterable) e).subscribeOn(scheduler); + return Flux.from(invocation).subscribeOn(scheduler);reactive/src/test/java/feign/reactive/ReactiveFeignIntegrationTest.java (6)
86-97: The
ReactorDecoder
is being used instead of theJacksonDecoder
. This change is in line with the PR's goal of handlingFlux
type responses in Feign clients. Ensure that theReactorDecoder
is compatible with all the places where this function is used.105-126: The test
testReactorTargetFull
has been updated to include tests forservice.usersFlux()
andservice.usersMono()
. This is a good practice as it ensures that the new methods are tested.134-139: The
RxJavaDecoder
is being used instead of theJacksonDecoder
. This change is in line with the PR's goal of handlingFlux
type responses in Feign clients. Ensure that theRxJavaDecoder
is compatible with all the places where this function is used.315-320: In all these instances, the
ReactorDecoder
orRxJavaDecoder
is being used instead of theDecoder.Default()
. This change is in line with the PR's goal of handlingFlux
type responses in Feign clients. Ensure that these decoders are compatible with all the places where these functions are used.329-338: The
TestReactorService
interface has been updated to includeusersFlux()
andusersMono()
. This is a good practice as it ensures that the new methods are included in the interface.346-354: The
TestReactiveXService
interface has been updated to includeusers()
. This is a good practice as it ensures that the new method is included in the interface.reactive/src/main/java/feign/reactive/RxJavaDecoder.java (1)
- 25-43: The
RxJavaDecoder
class is well implemented. It delegates the decoding to anotherDecoder
instance, which allows for flexibility in choosing the decoding strategy. Thedecode
method checks if the response type is assignable fromFlowable
, and if so, it resolves the last type parameter of theFlowable
and decodes the response using that type. This is a good approach to handleFlowable
types in the response. However, it would be beneficial to handle the case where thedelegate.decode
method might throw an exception. Wrapping the decode calls in a try-catch block and handling the exceptions appropriately would make the code more robust.@Override public Object decode(Response response, Type type) throws IOException, FeignException { Class<?> rawType = Types.getRawType(type); if (rawType.isAssignableFrom(Flowable.class)) { Type lastType = Types.resolveLastTypeParameter(type, Flowable.class); try { return delegate.decode(response, lastType); } catch (IOException | FeignException e) { // handle exception } } try { return delegate.decode(response, type); } catch (IOException | FeignException e) { // handle exception } }reactive/README.md (4)
14-33: The
contributors
method has been split into two methods:contributorsFlux
andcontributorsMono
, returning aFlux
and aMono
respectively. This change provides more flexibility in handling the response, allowing for both a stream of contributors and a single emission of a list of contributors. However, ensure that all calls to the originalcontributors
method throughout the codebase have been updated to use one of the new methods.36-46: The
ExampleReactor
class has been updated to use the newReactorDecoder
in theReactorFeign.builder()
call. This change allows for reactive decoding of the response. ThecontributorsFlux
andcontributorsMono
methods are used to retrieve contributors, demonstrating the use of bothFlux
andMono
response types. Theblock()
method is used to subscribe to theFlux
andMono
and block until they emit their items, collecting them into a list. This is a good use of the reactive capabilities provided by the Reactor library.64-69: The
ExampleRxJava2
class has been updated to use the newRxJavaDecoder
in theRxJavaFeign.builder()
call. This change allows for reactive decoding of the response using RxJava. However, thecontributors
method has not been updated to match the changes in theGitHubReactor
interface. Please verify if this is intentional or if theGitHubReactiveX
interface should also be updated.90-94: The section on
Iterable
andCollections
responses has been updated to remove the information about manually convertingMono
orIterable
response types intoFlux
using thefromIterable
method. This is consistent with the changes in theGitHubReactor
interface, which now provides aFlux
response type directly. However, the statement "this limits the use ofFlux
as a response type" may no longer be accurate, as thecontributorsFlux
method does return aFlux
. Please verify if this statement should be updated or removed.
@RequestLine("GET /repos/{owner}/{repo}/contributors") | ||
Flowable<List<Contributor>> contributors(@Param("owner") String owner, @Param("repo") String repo); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The contributors
method is returning a Flowable<List<Contributor>>
. This means that it will emit multiple lists of contributors. If the API only returns a single list of contributors, consider changing the return type to Single<List<Contributor>>
to better reflect the expected response.
static class Contributor { | ||
|
||
private String login; | ||
private int contributions; | ||
|
||
void setLogin(String login) { | ||
this.login = login; | ||
} | ||
|
||
void setContributions(int contributions) { | ||
this.contributions = contributions; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Contributor
class is using package-private visibility for its fields and methods. This is generally not recommended as it can lead to issues with encapsulation. Consider changing the visibility to private
and providing public getter methods to access the fields.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review Status
Actionable comments generated: 7
Files selected for processing (9)
- reactive/README.md (3 hunks)
- reactive/src/main/java/feign/reactive/ReactiveDelegatingContract.java (1 hunks)
- reactive/src/main/java/feign/reactive/ReactorDecoder.java (1 hunks)
- reactive/src/main/java/feign/reactive/ReactorInvocationHandler.java (1 hunks)
- reactive/src/main/java/feign/reactive/RxJavaDecoder.java (1 hunks)
- reactive/src/test/java/feign/reactive/ReactiveFeignIntegrationTest.java (12 hunks)
- reactive/src/test/java/feign/reactive/examples/ConsoleLogger.java (1 hunks)
- reactive/src/test/java/feign/reactive/examples/ReactorGitHubExample.java (1 hunks)
- reactive/src/test/java/feign/reactive/examples/RxJavaGitHubExample.java (1 hunks)
Additional comments (Suppressed): 16
reactive/src/main/java/feign/reactive/ReactiveDelegatingContract.java (1)
- 55-59: The new hunk has removed the explicit setting of the return type to the first actual type (
actualTypes[0]
). Ensure that thetype
variable being used inmetadata.returnType(type);
is correctly set and represents the intended return type.reactive/src/main/java/feign/reactive/RxJavaDecoder.java (2)
33-42: The
decode
method has been overridden to handle decoding based on the type of the response. If the type isFlowable
, it resolves the last type parameter and delegates the decoding to the underlying decoder. This is a good approach to handle different types of responses in a reactive context. However, it's important to ensure that the underlying decoder can handle the resolved type correctly.29-31: The constructor takes a
Decoder
as a parameter and assigns it to thedelegate
field. This allows theRxJavaDecoder
to delegate the actual decoding to anotherDecoder
, which can be any implementation of theDecoder
interface. This is a good example of the Delegation pattern and promotes code reusability and flexibility.reactive/src/test/java/feign/reactive/examples/ReactorGitHubExample.java (1)
- 32-53: The use of
.block()
in a reactive stream is generally discouraged as it defeats the purpose of using a non-blocking reactive stream. It would be better to use.subscribe()
or.doOnNext()
to handle the results of theFlux
andMono
streams. However, this might be acceptable in a simple main method for demonstration purposes. Please verify if this is the intended usage.reactive/src/test/java/feign/reactive/examples/RxJavaGitHubExample.java (2)
31-36: The
RxJavaDecoder
is being used here, which is a good choice for handling reactive types. However, it's important to ensure that the rest of the codebase is compatible with this change, especially if it was previously using a non-reactive decoder.48-50: The
contributors
method returns aFlowable<List<Contributor>>
. This is a good use of RxJava'sFlowable
for handling potentially large lists of data. However, ensure that the API endpoint/repos/{owner}/{repo}/contributors
supports streaming responses, asFlowable
is designed to handle backpressure in streaming scenarios.reactive/README.md (4)
14-33: The
contributors
method in theGitHubReactor
interface has been split into two methods:contributorsFlux
andcontributorsMono
. This change allows for differentiation betweenFlux
andMono
responses. Ensure that all calls to these methods throughout the codebase have been updated to match the new method names. Also, theContributor
class no longer has a constructor and instead uses getter and setter methods for thelogin
field. Make sure this change doesn't affect the instantiation ofContributor
objects in the codebase.35-47: The
ExampleReactor
class now uses aReactorDecoder
with aJacksonDecoder
for decoding responses. This change provides reactive decoding capabilities. ThecontributorsFlux
andcontributorsMono
methods are used to retrieve contributors, and the responses are collected into lists usingcollectList()
. This is a more efficient way of collecting responses compared to the previous method of usingcollect(Collectors.toList())
.62-69: The
ExampleRxJava2
class now uses aRxJavaDecoder
with aJacksonDecoder
for decoding responses. This change provides reactive decoding capabilities for RxJava. Ensure that theRxJavaDecoder
works as expected and doesn't introduce any issues.90-94: The section on
Iterable
andCollections
responses has been updated to remove the mention of manual conversion fromMono
orIterable
toFlux
using thefromIterable
method. This is because the newReactorDecoder
handles the conversion automatically. Ensure that this change doesn't introduce any issues with handlingFlux
responses.reactive/src/test/java/feign/reactive/ReactiveFeignIntegrationTest.java (6)
86-97: The
ReactorDecoder
is being used instead of theJacksonDecoder
. This change is likely due to the need to handleFlux
type responses in Feign clients. Ensure that theReactorDecoder
is compatible with the rest of the codebase and that it correctly handles all expected response types.105-126: The test method
testReactorTargetFull
has been updated to include tests forFlux
andMono
responses. This is a good addition as it ensures that the new functionality is being properly tested.134-139: The
RxJavaDecoder
is being used instead of theJacksonDecoder
. This change is likely due to the need to handleFlux
type responses in Feign clients. Ensure that theRxJavaDecoder
is compatible with the rest of the codebase and that it correctly handles all expected response types.315-320: In each of these instances, the
ReactorDecoder
orRxJavaDecoder
is being used instead of theDecoder.Default()
. This change is likely due to the need to handleFlux
type responses in Feign clients. Ensure that these decoders are compatible with the rest of the codebase and that they correctly handle all expected response types.329-338: The
TestReactorService
interface has been updated to include methods for handlingFlux
andMono
responses. This is a good addition as it allows for testing of the new functionality.346-354: The
TestReactiveXService
interface has been updated to include a method for handlingFlowable<List<User>>
responses. This is a good addition as it allows for testing of the new functionality.
import feign.Logger; | ||
|
||
public class ConsoleLogger extends Logger { | ||
@Override | ||
protected void log(String configKey, String format, Object... args) { | ||
System.out.println(String.format(methodTag(configKey) + format, args)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ConsoleLogger
class extends Logger
and overrides the log
method to print logs to the console. This is a simple and straightforward implementation. However, consider using a proper logging framework like Log4J or SLF4J for more robust logging capabilities, including log levels, log file rotation, and asynchronous logging.
- System.out.println(String.format(methodTag(configKey) + format, args));
+ // Assuming a logger instance is available
+ logger.info(String.format(methodTag(configKey) + format, args));
public Object decode(Response response, Type type) throws IOException, FeignException { | ||
Class<?> rawType = Types.getRawType(type); | ||
if (rawType.isAssignableFrom(Mono.class)) { | ||
Type lastType = Types.resolveLastTypeParameter(type, Mono.class); | ||
return delegate.decode(response, lastType); | ||
} | ||
if (rawType.isAssignableFrom(Flux.class)) { | ||
Type lastType = Types.resolveLastTypeParameter(type, Flux.class); | ||
Type listType = Types.parameterize(List.class, lastType); | ||
return delegate.decode(response, listType); | ||
} | ||
|
||
return delegate.decode(response, type); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The decode
method has been updated to handle Mono
and Flux
types. It checks the raw type of the response and if it's Mono
or Flux
, it resolves the last type parameter and delegates the decoding to the underlying decoder. This is a good approach to handle reactive types in Feign clients. However, for Flux
types, it's creating a List
type to decode the response. This might not be the best approach as it could lead to memory issues for large responses. Consider using a streaming approach to handle Flux
types.
- Type listType = Types.parameterize(List.class, lastType);
- return delegate.decode(response, listType);
+ return Flux.from(delegate.decode(response, lastType));
protected Publisher invoke(Method method, MethodHandler methodHandler, Object[] arguments) { | ||
Publisher<?> invocation = this.invokeMethod(methodHandler, arguments); | ||
if (Flux.class.isAssignableFrom(method.getReturnType())) { | ||
return Flux.from(invocation).subscribeOn(scheduler); | ||
return Flux.from(invocation).flatMapIterable(e -> (Iterable) e).subscribeOn(scheduler); | ||
} else if (Mono.class.isAssignableFrom(method.getReturnType())) { | ||
return Mono.from(invocation).subscribeOn(scheduler); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The change from subscribeOn
to flatMapIterable
for Flux
types is a significant one. This change ensures that the elements emitted by the Flux
are processed sequentially on the scheduler. However, it also assumes that the emitted items are of type Iterable
. This might not always be the case and could lead to a ClassCastException
if the items are not Iterable
. Consider adding a type check before casting to Iterable
.
- return Flux.from(invocation).flatMapIterable(e -> (Iterable) e).subscribeOn(scheduler);
+ return Flux.from(invocation).flatMapIterable(e -> e instanceof Iterable ? (Iterable) e : Collections.singletonList(e)).subscribeOn(scheduler);
interface GitHub { | ||
@RequestLine("GET /repos/{owner}/{repo}/contributors") | ||
Flux<Contributor> contributorsFlux(@Param("owner") String owner, @Param("repo") String repo); | ||
|
||
@RequestLine("GET /repos/{owner}/{repo}/contributors") | ||
Mono<List<Contributor>> contributorsMono(@Param("owner") String owner, @Param("repo") String repo); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The GitHub
interface has two methods contributorsFlux
and contributorsMono
that seem to be doing the same thing but returning different types (Flux<Contributor>
and Mono<List<Contributor>>
). This might be confusing for users of the interface. Consider consolidating these methods into one or clearly documenting the difference in their behaviors.
static class Contributor { | ||
|
||
private String login; | ||
private int contributions; | ||
|
||
void setLogin(String login) { | ||
this.login = login; | ||
} | ||
|
||
void setContributions(int contributions) { | ||
this.contributions = contributions; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Contributor
class is using manual setters for its fields. Consider using Lombok's @Data
or @Setter
annotations to generate these methods automatically, which would make the code cleaner and more maintainable.
System.out.println("Let's fetch and print a list of the contributors to this library."); | ||
List<Contributor> contributorsFromFlux = github.contributors("OpenFeign", "feign") | ||
.blockingLast(); | ||
for (Contributor contributor : contributorsFromFlux) { | ||
System.out.println(contributor.login + " (" + contributor.contributions + ")"); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The blockingLast()
method is being used to convert the Flowable
to a List
. This is a blocking operation and may not be ideal in a reactive context. Consider using non-blocking operations to fully leverage the benefits of reactive programming.
private String login; | ||
private int contributions; | ||
|
||
void setLogin(String login) { | ||
this.login = login; | ||
} | ||
|
||
void setContributions(int contributions) { | ||
this.contributions = contributions; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Contributor
class is mutable, as it provides setters for its fields. This could potentially lead to issues in a multi-threaded environment. Consider making this class immutable if it's safe to do so.
* Refactoring: Move resolveLastTypeParameter from Util to Types * Add ReactiveDecoder * Update code as per suggestions * Update code as per suggestions * Refactoring * Add tests
* Refactoring: Move resolveLastTypeParameter from Util to Types * Add ReactiveDecoder * Update code as per suggestions * Update code as per suggestions * Refactoring * Add tests
Fixes: #1869
Summary by CodeRabbit
ReactiveDecoder
,ReactorDecoder
, andRxJavaDecoder
classes to support reactive decoding capabilities for Feign clients, enhancing the ability to handleMono
andFlux
types from the Reactor library andFlowable
type from RxJava.resolveLastTypeParameter
method fromUtil
class toTypes
class.README.md
to reflect changes in theGitHubReactor
interface and usage examples for Reactor and RxJava2.ReactiveFeignIntegrationTest
to cover new features and changes, providing better test coverage.ConsoleLogger
for improved logging during testing.ReactorGitHubExample
andRxJavaGitHubExample
classes to demonstrate the usage of Feign with Reactor and RxJava respectively.