Comparison method violates its general contract while using Spring Rest Template
Asked Answered
G

2

6

One of our application is invoking another application via a Spring Rest Template.

HttpEntity<Object> httpEntity = new HttpEntity<>(null);
restTemplate.exchange(URL, HttpMethod.GET, httpEntity,String.class)

We haven't set any headers explicitly for the request. We are encountering the below exception:

Caused by: java.lang.IllegalArgumentException: Comparison method violates its general contract!
    at java.util.TimSort.mergeHi(TimSort.java:895)
    at java.util.TimSort.mergeAt(TimSort.java:512)
    at java.util.TimSort.mergeCollapse(TimSort.java:437)
    at java.util.TimSort.sort(TimSort.java:241)
    at java.util.Arrays.sort(Arrays.java:1512)
    at java.util.ArrayList.sort(ArrayList.java:1454)
    at java.util.Collections.sort(Collections.java:175)
    at org.springframework.http.MediaType.sortBySpecificity(MediaType.java:441)
    at org.springframework.web.client.RestTemplate$AcceptHeaderRequestCallback.doWithRequest(RestTemplate.java:691)
    at org.springframework.web.client.RestTemplate$HttpEntityRequestCallback.doWithRequest(RestTemplate.java:743)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:567)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:530)
    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:448)

The Java version we are using is: 1.8.0_45 and Spring: 4.1.6

If anyone could help that would be really great. I will be happy to provide any more details on this if required.

Thanking in anticipation.

Gurl answered 20/12, 2017 at 8:5 Comment(4)
Interesting. You should put a breakpoint at MediaType.sortBySpecificity(MediaType.java:441) and see what values are being sorted and how they implement Comparable. This might be a bug in MediaType.Keratin
See this question and its answers for more details.Dulciana
There doesn't seem to be any changes in the comparators between 4.1.6 and 4.2.0, so you need to get a list of the Accept header values that are being sorted for more help.Keratin
Looking at that comparator, the whole premise seems flawed, specifically at lines 484 and 494. You can't treat distinct parents as equal and then differentiate between children of the same parent. That breaks transitivity.Homophile
C
0

I guess this is a known issue when using String.class instead of a custom class. I managed to circumvent this by defining my own custom rest template

<bean id="customRestTemplate" class="org.springframework.web.client.RestTemplate">
  <property name="messageConverters">
    <list>
      <bean class="org.springframework.http.converter.StringHttpMessageConverter">
        <property name="writeAcceptCharset" value="false" />
      </bean>
    </list>
  </property>
</bean>
Crystallize answered 9/1, 2019 at 16:45 Comment(0)
C
1

I had this issue while migrating spring boot from 2.2.X to 2.5.6.

It happened when my other service was returning String from a @RestController method, but without any specified MediaType.

Specifying the media type in produces in the @GetMapping solved it for me:

@GetMapping("/this-returns-string", produces = MediaType.TEXT_PLAIN_VALUE)
Copyright answered 22/11, 2021 at 14:10 Comment(0)
C
0

I guess this is a known issue when using String.class instead of a custom class. I managed to circumvent this by defining my own custom rest template

<bean id="customRestTemplate" class="org.springframework.web.client.RestTemplate">
  <property name="messageConverters">
    <list>
      <bean class="org.springframework.http.converter.StringHttpMessageConverter">
        <property name="writeAcceptCharset" value="false" />
      </bean>
    </list>
  </property>
</bean>
Crystallize answered 9/1, 2019 at 16:45 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.