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

UriTemplateRequestEntity doesn't override hashCode() and equals() #27531

Closed
abryantsev opened this issue Oct 7, 2021 · 3 comments
Closed

UriTemplateRequestEntity doesn't override hashCode() and equals() #27531

abryantsev opened this issue Oct 7, 2021 · 3 comments
Assignees
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: bug A general bug
Milestone

Comments

@abryantsev
Copy link

abryantsev commented Oct 7, 2021

Affects: 5.3.8


Hi developers!

To fix a memory leak caused by the micrometer metrics used in the RestTemplate I need to switch to the usage of the uri template to build a RequestEntity instance. To test the produced instance from one of the internal implementation in my project I use assertThat from the Asserj library.

The problem is that the test is failing because of the not overridden equals() method in the UriTemplateRequestEntity class that is used internally by the Assertj. In fact both calls - equals() and hashCode() throws an exception on the instances of the UriTemplateRequestEntity that should never be the case if the instance of the latter is built correctly.

The following test fails because of the mentioned issue.

    @Test
    void test() {
        final Map<String, Object> vars = new HashMap<>();
        vars.put("id", 1);

        final RequestEntity<Void> requestEntity1 =
            RequestEntity.method(HttpMethod.GET, "http://test.api/path/{id}", vars).build();

        final RequestEntity<Void> requestEntity2 =
            RequestEntity.method(HttpMethod.GET, "http://test.api/path/{id}", vars).build();

        org.assertj.core.api.Assertions.assertThat(requestEntity1)
            .isEqualTo(requestEntity2);
    }

with the following stack trace

java.lang.UnsupportedOperationException
	at org.springframework.http.RequestEntity.getUrl(RequestEntity.java:165)
	at org.springframework.http.RequestEntity.equals(RequestEntity.java:198)
	at java.base/java.util.Arrays.deepEquals0(Arrays.java:4654)
	at java.base/java.util.Objects.deepEquals(Objects.java:90)
	at org.assertj.core.internal.StandardComparisonStrategy.areEqual(StandardComparisonStrategy.java:77)
	at org.assertj.core.internal.Objects.areEqual(Objects.java:361)
	at org.assertj.core.internal.Objects.assertEqual(Objects.java:337)
	at org.assertj.core.api.AbstractAssert.isEqualTo(AbstractAssert.java:359)

Could you please have a look? To workaround this issue I need to implement a very cumbersome test accessing internal fields one by one.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Oct 7, 2021
@jhoeller jhoeller self-assigned this Oct 8, 2021
@jhoeller jhoeller added in: web Issues in web modules (web, webmvc, webflux, websocket) type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Oct 8, 2021
@jhoeller jhoeller added this to the 5.3.11 milestone Oct 8, 2021
@sbrannen
Copy link
Member

sbrannen commented Oct 8, 2021

Good catch, @abryantsev.

Thanks for opening your first issue for the Spring Framework! 👍

We'll get this fixed in 5.3.11.

@nytro77
Copy link

nytro77 commented Oct 10, 2021

@jhoeller Seems this fix violates the hashCode contract?
Two RequestEntity with the same uriTemplate but with different uriVarsArray and/or uriVarsMap are not equal, but the hashCode function will return the same value as that only takes uriTemplate into account?

EDIT: Sorry my bad. It seems that is OK after all. I just never had a reason to do so, but i do not doubt that you have :)

If two objects are unequal according to the equals(java.lang.Object) method, calling the hashCode method on each of the two objects doesn't need to produce distinct integer results. However, developers should be aware that producing distinct integer results for unequal objects improves the performance of hash tables

@jhoeller
Copy link
Contributor

Well spotted, that's a tradeoff we make in quite a few classes: hashCode doesn't need to be as specific as equals, it is sufficient to only take core attributes into account there. In particular in case of competing/alternate attributes such as the uriVars variants here, we tend to simply omit them from hashCode.

Thanks for reviewing the change, in any case :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: bug A general bug
Projects
None yet
Development

No branches or pull requests

5 participants