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.

Rahul
  • 198
  • 4
  • 10
  • 3
    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`. – Kayaman Dec 20 '17 at 08:10
  • See [this question and its answers](https://stackoverflow.com/questions/8327514/comparison-method-violates-its-general-contract) for more details. – MC Emperor Dec 20 '17 at 08:16
  • 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. – Kayaman Dec 20 '17 at 08:21
  • 2
    Looking at that comparator, the whole premise seems flawed, specifically at lines [484](http://grepcode.com/file/repo1.maven.org/maven2/org.springframework/spring-core/4.1.6.RELEASE/org/springframework/util/MimeType.java#484) and [494](http://grepcode.com/file/repo1.maven.org/maven2/org.springframework/spring-core/4.1.6.RELEASE/org/springframework/util/MimeType.java#494). You can't treat distinct parents as equal and then differentiate between children of the same parent. That breaks transitivity. – shmosel Dec 20 '17 at 08:28

2 Answers2

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)
Léo Schneider
  • 2,085
  • 3
  • 15
  • 28
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>
Paul Roub
  • 36,322
  • 27
  • 84
  • 93
Lyle Dcruz
  • 18
  • 1