Skip to content
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

Merged
merged 5 commits into from
Oct 27, 2023
Merged

Add typed response #2206

merged 5 commits into from
Oct 27, 2023

Conversation

gromspys
Copy link
Contributor

@gromspys gromspys commented Oct 18, 2023

Issue: #1627

Summary by CodeRabbit

  • New Feature: Introduced TypedResponse class to handle different types of HTTP responses, enhancing the flexibility of the Feign library.
  • Improvement: Updated the toString() method in the Response class for more accurate string representation of HTTP responses.
  • Test: Added a new test method typedResponse() to validate the functionality of the new TypedResponse 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.

@coderabbitai
Copy link

coderabbitai bot commented Oct 18, 2023

Walkthrough

The changes introduce a new class TypedResponse to handle typed responses in the Feign library, enhancing flexibility. The InvocationContext class has been updated to accommodate this new type. The Response class now uses dynamic protocol versioning. New tests have been added to validate these changes.

Changes

File Summary
.../feign/InvocationContext.java Updated proceed() method to handle TypedResponse. Added a new decode() method for response decoding.
.../feign/TypedResponse.java Introduced a new class TypedResponse to handle typed responses. It includes a builder pattern and getter methods.
.../feign/Response.java Modified toString() method to use dynamic protocol versioning.
.../feign/FeignTest.java Added new test method typedResponse() to validate the changes. Added a new method getWithTypedResponse() to the TestInterface.

🐇
"In the land of code, changes are afoot,
A new class is born, and it's quite astute.
With typed responses, we now can play,
And dynamic versioning is now in the fray.
Tests are written, to keep us in check,
Celebrate these changes, they're quite tech!" 🎉


Tips

Chat with CodeRabbit Bot (@coderabbitai)

  • If you reply to a review comment from CodeRabbit, the bot will automatically respond.
  • To engage with CodeRabbit bot directly around the specific lines of code in the PR, mention @coderabbitai in your review comment
  • Note: Review comments are made on code diffs or files, not on the PR overview.
  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai help to get help.

Note: For conversation with the bot, please use the review comments on code diffs or files.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • The JSON schema for the configuration file is available here.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/coderabbit-overrides.json

Copy link

@coderabbitai coderabbitai bot left a 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

Commits Files that changed from the base of the PR and between 25c419d and 80e0f0b.
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 the TestInterface returns a TypedResponse<String>. Ensure that the implementation of this method in the actual class correctly wraps the response in a TypedResponse object. Also, verify that the generic type String 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 a TypedResponse object. This is a significant change in the behavior of the proceed() method. Ensure that all parts of the codebase that use this method are compatible with this change. Also, verify that the TypedResponse 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 the proceed() method. Specifically, verify that exceptions thrown by the decode() method are caught and handled correctly in the proceed() method.

Comment on lines 91 to 101
@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());
}
Copy link

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());

Comment on lines +96 to +98
checkNotNull(request, "request is required");
this.request = request;
return this;
Copy link

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;
    }

Comment on lines 163 to 176
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();
}
Copy link

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();
  }

Copy link

@coderabbitai coderabbitai bot left a 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

Commits Files that changed from the base of the PR and between 80e0f0b and e71b886.
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 the TestInterface interface. This method returns a TypedResponse<String>, which is the new functionality being tested. Ensure that this method is implemented in the classes that implement this interface.

Comment on lines +33 to +40
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;
}
Copy link

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)
Suggested change
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;
}

Comment on lines +87 to +90
public Builder body(T body) {
this.body = body;
return this;
}
Copy link

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)
Suggested change
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;
}

@velo velo merged commit bc8b4b1 into OpenFeign:master Oct 27, 2023
@gromspys gromspys deleted the add-typed-response branch October 27, 2023 08:03
ghost referenced this pull request in camunda/camunda Nov 15, 2023
15205: deps(maven): Update dependency io.github.openfeign:feign-bom to v13.1 (main) r=github-actions[bot] a=renovate[bot]

[![Mend Renovate logo banner](https://app.renovatebot.com/images/banner.svg)](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` | [![age](https://developer.mend.io/api/mc/badges/age/maven/io.github.openfeign:feign-bom/13.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/io.github.openfeign:feign-bom/13.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/io.github.openfeign:feign-bom/13.0/13.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/io.github.openfeign:feign-bom/13.0/13.1?slim=true)](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 [`@&#8203;gromspys](https://togithub.com/gromspys)` in [https://github.com/OpenFeign/feign/pull/2216](https://togithub.com/OpenFeign/feign/pull/2216)
-   Add typed response by [`@&#8203;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 [`@&#8203;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 [`@&#8203;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 [`@&#8203;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 `@&#8203;dependabot` in OpenFeign/feign#2211
* build(deps-dev): bump org.glassfish.jersey.core:jersey-client from 2.40 to 2.41 by `@&#8203;dependabot` in OpenFeign/feign#2210
* build(deps-dev): bump org.glassfish.jersey.inject:jersey-hk2 from 2.40 to 2.41 by `@&#8203;dependabot` in OpenFeign/feign#2209
* build(deps): bump jakarta.xml.soap:jakarta.xml.soap-api from 3.0.0 to 3.0.1 by `@&#8203;dependabot` in OpenFeign/feign#2208
* build(deps): bump com.sun.xml.bind:jaxb-impl from 2.3.8 to 2.3.9 by `@&#8203;dependabot` in OpenFeign/feign#2207
* build(deps): bump io.sundr:sundr-maven-plugin from 0.101.0 to 0.101.1 by `@&#8203;dependabot` in OpenFeign/feign#2213
* build(deps): bump maven-surefire-plugin.version from 3.1.2 to 3.2.1 by `@&#8203;dependabot` in OpenFeign/feign#2212
* build(deps): bump io.sundr:sundr-maven-plugin from 0.101.1 to 0.101.2 by `@&#8203;dependabot` in OpenFeign/feign#2215
* build(deps): bump kotlin.version from 1.9.10 to 1.9.20 by `@&#8203;dependabot` in OpenFeign/feign#2219
* build(deps): bump io.sundr:sundr-maven-plugin from 0.101.2 to 0.101.3 by `@&#8203;dependabot` in OpenFeign/feign#2220
* build(deps): bump org.mockito:mockito-core from 5.6.0 to 5.7.0 by `@&#8203;dependabot` in OpenFeign/feign#2221
* build(deps): bump org.moditect:moditect-maven-plugin from 1.0.0.Final to 1.1.0 by `@&#8203;dependabot` in OpenFeign/feign#2224
* build(deps): bump io.dropwizard.metrics:metrics-core from 4.2.21 to 4.2.22 by `@&#8203;dependabot` in OpenFeign/feign#2222
* build(deps): bump org.junit:junit-bom from 5.10.0 to 5.10.1 by `@&#8203;dependabot` in OpenFeign/feign#2223
* build(deps): bump org.apache.maven.plugins:maven-javadoc-plugin from 3.6.0 to 3.6.2 by `@&#8203;dependabot` in OpenFeign/feign#2226
* build(deps): bump maven-surefire-plugin.version from 3.2.1 to 3.2.2 by `@&#8203;dependabot` in OpenFeign/feign#2225
</details>

##### New Contributors
* `@&#8203;TaoJing96` made their first contributi[https://github.com/OpenFeign/feign/pull/1881](https://togithub.com/OpenFeign/feign/pull/1881)l/1881
* `@&#8203;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>
velo added a commit that referenced this pull request Oct 7, 2024
* Add typed response

* Update code as per suggestions

---------

Co-authored-by: Marvin Froeder <velo@users.noreply.github.com>
velo added a commit that referenced this pull request Oct 8, 2024
* Add typed response

* Update code as per suggestions

---------

Co-authored-by: Marvin Froeder <velo@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants