RestTemplate get with body
Asked Answered
S

4

5

How to make get with body using rest template?

Based on question from: POST request via RestTemplate in JSON, I tried make GET with body via HttpEntity (just check if it is possible), but it failed receiving:

Required request body is missing

For HttpMethod.POST: localhost:8080/test/post body is added correctly, but for HttpMethod.GET localhost:8080/test/get it is not mapped. My code is, as below:

@RestController
@SpringBootApplication
public class DemoApplication {

  public static void main(String[] args) {
    SpringApplication.run(DemoApplication.class, args);
  }

  private final RestTemplate restTemplate = new RestTemplate();

  @GetMapping("/test/{api}")
  public SomeObject test(@PathVariable("api") String api) {
    String input = "{\"value\":\"ok\"}";

    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    HttpEntity<String> entity = new HttpEntity<>(input, headers);

    HttpMethod method = "get".equals(api) ? HttpMethod.GET : HttpMethod.POST;
    String url = "http://localhost:8080/" + api;
    return restTemplate.exchange(url, method, entity, SomeObject.class).getBody();
  }

  @GetMapping("/get")
  public SomeObject getTestApi(@RequestBody(required = false) SomeObject someObject) {
    return new SomeObject() {{ setValue(someObject != null ? "ok" : "error"); }};
  }

  @PostMapping("/post")
  public SomeObject postTestApi(@RequestBody(required = false) SomeObject someObject) {
    return new SomeObject() {{ setValue(someObject != null ? "ok" : "error"); }};
  }

  @Data
  public static class SomeObject {
    private String value;
  }

}

Here is the repo with full example: https://gitlab.com/bartekwichowski/git-with-body

I wonder, what is wrong with code? Also accorging to: HTTP GET with request body GET with body is possible, but just not good practice.

Stalnaker answered 10/6, 2020 at 17:31 Comment(2)
As a summary, localhost:8080/test/get does not receive a body which is sent by your RestTemplate code?Nozicka
Yes, this is the caseStalnaker
E
5

I found this can't remeber where. Not a good practice, but if in your enviroment you have no other chance:

private static final class HttpComponentsClientHttpRequestWithBodyFactory extends HttpComponentsClientHttpRequestFactory {
    @Override
    protected HttpUriRequest createHttpUriRequest(HttpMethod httpMethod, URI uri) {
        if (httpMethod == HttpMethod.GET) {
            return new HttpGetRequestWithEntity(uri);
        }
        return super.createHttpUriRequest(httpMethod, uri);
    }
}

private static final class HttpGetRequestWithEntity extends HttpEntityEnclosingRequestBase {
    public HttpGetRequestWithEntity(final URI uri) {
        super.setURI(uri);
    }

    @Override
    public String getMethod() {
        return HttpMethod.GET.name();
    }
}

and when you get your restTemplate object

restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestWithBodyFactory());
Ean answered 22/4, 2021 at 3:27 Comment(1)
My guess is from here: mekaso.rocks/…Bedstraw
T
1

JdkClientHttpRequestFactory can fix it since Spring framework 6.1.

        var restTemplate = new RestTemplate(new JdkClientHttpRequestFactory());

This class dependes on java.net.http.HttpClient internally.

Therron answered 14/1 at 18:5 Comment(0)
C
0

I was facing the same issue with Spring 6.x - in this case solution provided by demian does no longer compile (as the API has changed). However I was able to overcome this - and the solution in this case isn't much more complicated.

First, Apache HttpClient must be added directly as a dependency:

<dependency>
    <groupId>org.apache.httpcomponents.client5</groupId>
    <artifactId>httpclient5</artifactId>
    <version>5.2.1</version>
</dependency>

Then, just use HttpComponentsClientHttpRequestFactory during creating RestTemplate instance:

RestTemplate restTemplate = new RestTemplate(new HttpComponentsClientHttpRequestFactory());
Condition answered 9/8, 2023 at 20:17 Comment(0)
L
-2

i had the same issue with RestTemplate and GET.

Tried to switch to Unirest but that also did not allow to use body with GET method.

Changing GET to POST is successful.

Making a call from postman after deploying in Liberty works fine and body did get accepted and expected response is generated.

i believe its something with the embedded tomcat server used.

Lactate answered 1/9, 2020 at 5:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.