-
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
Add typed response #2206
Add typed response #2206
Conversation
WalkthroughThe changes introduce a new class 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: 4
Files selected for processing (3)
- core/src/main/java/feign/InvocationContext.java (2 hunks)
- core/src/main/java/feign/TypedResponse.java (1 hunks)
- core/src/test/java/feign/FeignTest.java (2 hunks)
Additional comments (Suppressed): 3
core/src/test/java/feign/FeignTest.java (1)
- 1216-1217: The new method
getWithTypedResponse()
in theTestInterface
returns aTypedResponse<String>
. Ensure that the implementation of this method in the actual class correctly wraps the response in aTypedResponse
object. Also, verify that the generic typeString
is appropriate for the response body.core/src/main/java/feign/InvocationContext.java (2)
80-91: The new code checks if the return type is assignable to
TypedResponse
. If true, it decodes the response and wraps it in aTypedResponse
object. This is a significant change in the behavior of theproceed()
method. Ensure that all parts of the codebase that use this method are compatible with this change. Also, verify that theTypedResponse
class and its builder method are implemented correctly and tested thoroughly.112-121: The decoding logic has been moved to a new private method
decode()
. This improves the modularity and readability of the code. However, ensure that this change does not affect the error handling logic in theproceed()
method. Specifically, verify that exceptions thrown by thedecode()
method are caught and handled correctly in theproceed()
method.
@Test | ||
public void typedResponse() throws Exception { | ||
server.enqueue(new MockResponse().setBody("foo")); | ||
|
||
TestInterface api = new TestInterfaceBuilder().target("http://localhost:" + server.getPort()); | ||
|
||
TypedResponse response = api.getWithTypedResponse(); | ||
|
||
assertEquals(200, response.status()); | ||
assertEquals("foo", response.body()); | ||
} |
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 new test typedResponse()
is well written and covers the new feature of handling typed responses. It checks the status and body of the response, which are the most critical parts of an HTTP response. However, it would be beneficial to add assertions for other fields of the TypedResponse
object to ensure they are correctly populated. This will provide a more comprehensive test of the new feature.
assertEquals("HTTP/1.1", response.protocolVersion());
assertNotNull(response.headers());
assertNotNull(response.request());
checkNotNull(request, "request is required"); | ||
this.request = request; | ||
return this; |
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 request()
method in the Builder
class checks if the request
argument is null. However, similar checks are not performed for other setter methods like status()
, headers()
, and body()
. It's a good practice to validate method arguments to prevent invalid or unexpected values.
public Builder status(int status) {
+ checkArgument(status >= 100 && status < 600, "status code must be valid");
this.status = status;
return this;
}
...
public Builder headers(Map<String, Collection<String>> headers) {
+ checkNotNull(headers, "headers must not be null");
this.headers = headers;
return this;
}
...
public Builder body(T body) {
+ checkNotNull(body, "body must not be null");
this.body = body;
return this;
}
public String toString() { | ||
StringBuilder builder = new StringBuilder("HTTP/1.1 ").append(status); | ||
if (reason != null) | ||
builder.append(' ').append(reason); | ||
builder.append('\n'); | ||
for (String field : headers.keySet()) { | ||
for (String value : valuesOrEmpty(headers, field)) { | ||
builder.append(field).append(": ").append(value).append('\n'); | ||
} | ||
} | ||
if (body != null) | ||
builder.append('\n').append(body); | ||
return builder.toString(); | ||
} |
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 toString()
method constructs a string representation of the TypedResponse
object. However, it assumes that the protocol version is always HTTP/1.1
, which might not be the case. Consider using the protocolVersion
field to reflect the actual protocol version.
public String toString() {
- StringBuilder builder = new StringBuilder("HTTP/1.1 ").append(status);
+ StringBuilder builder = new StringBuilder(protocolVersion.toString()).append(' ').append(status);
if (reason != null)
builder.append(' ').append(reason);
builder.append('\n');
for (String field : headers.keySet()) {
for (String value : valuesOrEmpty(headers, field)) {
builder.append(field).append(": ").append(value).append('\n');
}
}
if (body != null)
builder.append('\n').append(body);
return builder.toString();
}
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: 2
Configuration used: CodeRabbit UI
Files selected for processing (3)
- core/src/main/java/feign/Response.java (1 hunks)
- core/src/main/java/feign/TypedResponse.java (1 hunks)
- core/src/test/java/feign/FeignTest.java (3 hunks)
Files skipped from review due to trivial changes (1)
- core/src/main/java/feign/Response.java
Additional comments: 3
core/src/test/java/feign/FeignTest.java (3)
52-52: The import
import static junit.framework.TestCase.assertNotNull;
is added. Ensure that this import is used in the test cases and is not redundant.92-105: A new test case
typedResponse()
is added. This test case is testing the new functionality of handling typed responses. It checks the status, body, protocol version of the response, and also verifies that headers and request are not null. The test case seems to be well written and covers the necessary assertions for the new functionality.1220-1222: A new method
getWithTypedResponse()
is added to theTestInterface
interface. This method returns aTypedResponse<String>
, which is the new functionality being tested. Ensure that this method is implemented in the classes that implement this interface.
checkState(builder.request != null, "original request is required"); | ||
this.status = builder.status; | ||
this.request = builder.request; | ||
this.reason = builder.reason; // nullable | ||
this.headers = caseInsensitiveCopyOf(builder.headers); | ||
this.body = builder.body; | ||
this.protocolVersion = builder.protocolVersion; | ||
} |
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 constructor of TypedResponse
still lacks validation for essential fields like status
and headers
. This could lead to the creation of invalid TypedResponse
objects. Please consider adding checks for these fields.
private TypedResponse(Builder<T> builder) {
checkState(builder.request != null, "original request is required");
+ checkState(builder.status >= 100 && builder.status < 600, "status code must be valid");
+ checkState(builder.headers != null, "headers must not be null");
this.status = builder.status;
this.request = builder.request;
this.reason = builder.reason; // nullable
this.headers = caseInsensitiveCopyOf(builder.headers);
this.body = builder.body;
this.protocolVersion = builder.protocolVersion;
}
Committable suggestion (Beta)
checkState(builder.request != null, "original request is required"); | |
this.status = builder.status; | |
this.request = builder.request; | |
this.reason = builder.reason; // nullable | |
this.headers = caseInsensitiveCopyOf(builder.headers); | |
this.body = builder.body; | |
this.protocolVersion = builder.protocolVersion; | |
} | |
private TypedResponse(Builder<T> builder) { | |
checkState(builder.request != null, "original request is required"); | |
checkState(builder.status >= 100 && builder.status < 600, "status code must be valid"); | |
checkState(builder.headers != null, "headers must not be null"); | |
this.status = builder.status; | |
this.request = builder.request; | |
this.reason = builder.reason; // nullable | |
this.headers = caseInsensitiveCopyOf(builder.headers); | |
this.body = builder.body; | |
this.protocolVersion = builder.protocolVersion; | |
} |
public Builder body(T body) { | ||
this.body = body; | ||
return this; | ||
} |
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 setter methods in the Builder
class (status()
, headers()
, body()
) still lack validation for their arguments. This could lead to the creation of invalid TypedResponse
objects. Please consider adding checks for these methods.
public Builder status(int status) {
+ checkArgument(status >= 100 && status < 600, "status code must be valid");
this.status = status;
return this;
}
...
public Builder headers(Map<String, Collection<String>> headers) {
+ checkNotNull(headers, "headers must not be null");
this.headers = headers;
return this;
}
...
public Builder body(T body) {
+ checkNotNull(body, "body must not be null");
this.body = body;
return this;
}
Committable suggestion (Beta)
public Builder body(T body) { | |
this.body = body; | |
return this; | |
} | |
public Builder status(int status) { | |
checkArgument(status >= 100 && status < 600, "status code must be valid"); | |
this.status = status; | |
return this; | |
} | |
... | |
public Builder headers(Map<String, Collection<String>> headers) { | |
checkNotNull(headers, "headers must not be null"); | |
this.headers = headers; | |
return this; | |
} | |
... | |
public Builder body(T body) { | |
checkNotNull(body, "body must not be null"); | |
this.body = body; | |
return this; | |
} |
15205: deps(maven): Update dependency io.github.openfeign:feign-bom to v13.1 (main) r=github-actions[bot] a=renovate[bot] [](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [io.github.openfeign:feign-bom](https://togithub.com/openfeign/feign) | `13.0` -> `13.1` | [](https://docs.renovatebot.com/merge-confidence/) | [](https://docs.renovatebot.com/merge-confidence/) | [](https://docs.renovatebot.com/merge-confidence/) | [](https://docs.renovatebot.com/merge-confidence/) | --- > [!WARNING] > Some dependencies could not be looked up. Check the Dependency Dashboard for more information. --- ### Release Notes <details> <summary>openfeign/feign (io.github.openfeign:feign-bom)</summary> ### [`v13.1`](https://togithub.com/OpenFeign/feign/releases/tag/13.1): OpenFeign 13.1 [Compare Source](https://togithub.com/openfeign/feign/compare/13.0...13.1) ##### What's Changed - Support Conditional Parameter Expansion by [`@​gromspys](https://togithub.com/gromspys)` in [https://github.com/OpenFeign/feign/pull/2216](https://togithub.com/OpenFeign/feign/pull/2216) - Add typed response by [`@​gromspys](https://togithub.com/gromspys)` in [https://github.com/OpenFeign/feign/pull/2206](https://togithub.com/OpenFeign/feign/pull/2206) - Allow to ignore methods on provided interface by [`@​gromspys](https://togithub.com/gromspys)` in [https://github.com/OpenFeign/feign/pull/2218](https://togithub.com/OpenFeign/feign/pull/2218) - support method option and add UT by [`@​TaoJing96](https://togithub.com/TaoJing96)` in [https://github.com/OpenFeign/feign/pull/1881](https://togithub.com/OpenFeign/feign/pull/1881) - Do not decode URL encoding while setting up RequestTemplate by [`@​Breina](https://togithub.com/Breina)` in [https://github.com/OpenFeign/feign/pull/2228](https://togithub.com/OpenFeign/feign/pull/2228) *** <details> <summary>List of PRs that updated libraries versions</summary> <br /> * build(deps): bump jakarta.xml.ws:jakarta.xml.ws-api from 4.0.0 to 4.0.1 by `@​dependabot` in OpenFeign/feign#2211 * build(deps-dev): bump org.glassfish.jersey.core:jersey-client from 2.40 to 2.41 by `@​dependabot` in OpenFeign/feign#2210 * build(deps-dev): bump org.glassfish.jersey.inject:jersey-hk2 from 2.40 to 2.41 by `@​dependabot` in OpenFeign/feign#2209 * build(deps): bump jakarta.xml.soap:jakarta.xml.soap-api from 3.0.0 to 3.0.1 by `@​dependabot` in OpenFeign/feign#2208 * build(deps): bump com.sun.xml.bind:jaxb-impl from 2.3.8 to 2.3.9 by `@​dependabot` in OpenFeign/feign#2207 * build(deps): bump io.sundr:sundr-maven-plugin from 0.101.0 to 0.101.1 by `@​dependabot` in OpenFeign/feign#2213 * build(deps): bump maven-surefire-plugin.version from 3.1.2 to 3.2.1 by `@​dependabot` in OpenFeign/feign#2212 * build(deps): bump io.sundr:sundr-maven-plugin from 0.101.1 to 0.101.2 by `@​dependabot` in OpenFeign/feign#2215 * build(deps): bump kotlin.version from 1.9.10 to 1.9.20 by `@​dependabot` in OpenFeign/feign#2219 * build(deps): bump io.sundr:sundr-maven-plugin from 0.101.2 to 0.101.3 by `@​dependabot` in OpenFeign/feign#2220 * build(deps): bump org.mockito:mockito-core from 5.6.0 to 5.7.0 by `@​dependabot` in OpenFeign/feign#2221 * build(deps): bump org.moditect:moditect-maven-plugin from 1.0.0.Final to 1.1.0 by `@​dependabot` in OpenFeign/feign#2224 * build(deps): bump io.dropwizard.metrics:metrics-core from 4.2.21 to 4.2.22 by `@​dependabot` in OpenFeign/feign#2222 * build(deps): bump org.junit:junit-bom from 5.10.0 to 5.10.1 by `@​dependabot` in OpenFeign/feign#2223 * build(deps): bump org.apache.maven.plugins:maven-javadoc-plugin from 3.6.0 to 3.6.2 by `@​dependabot` in OpenFeign/feign#2226 * build(deps): bump maven-surefire-plugin.version from 3.2.1 to 3.2.2 by `@​dependabot` in OpenFeign/feign#2225 </details> ##### New Contributors * `@​TaoJing96` made their first contributi[https://github.com/OpenFeign/feign/pull/1881](https://togithub.com/OpenFeign/feign/pull/1881)l/1881 * `@​Breina` made their first contributi[https://github.com/OpenFeign/feign/pull/2228](https://togithub.com/OpenFeign/feign/pull/2228)l/2228 **Full Changelog**: OpenFeign/feign@13.0...13.1 </details> --- ### Configuration 📅 **Schedule**: Branch creation - "every weekday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/camunda/zeebe). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40Ni4wIiwidXBkYXRlZEluVmVyIjoiMzcuNDYuMCIsInRhcmdldEJyYW5jaCI6Im1haW4ifQ==--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
* Add typed response * Update code as per suggestions --------- Co-authored-by: Marvin Froeder <velo@users.noreply.github.com>
* Add typed response * Update code as per suggestions --------- Co-authored-by: Marvin Froeder <velo@users.noreply.github.com>
Issue: #1627
Summary by CodeRabbit
TypedResponse
class to handle different types of HTTP responses, enhancing the flexibility of the Feign library.toString()
method in theResponse
class for more accurate string representation of HTTP responses.typedResponse()
to validate the functionality of the newTypedResponse
class.These changes provide a more flexible and accurate way to handle and represent HTTP responses, improving the overall user experience with the Feign library.