235

I want to convert the following (working) curl snippet to a RestTemplate call:

curl -i -X POST -d "email=first.last@example.com" https://app.example.com/hr/email

How do I pass the email parameter correctly? The following code results in a 404 Not Found response:

String url = "https://app.example.com/hr/email";

Map<String, String> params = new HashMap<String, String>();
params.put("email", "first.last@example.com");

RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.postForEntity( url, params, String.class );

I've tried to formulate the correct call in PostMan, and I can get it working correctly by specifying the email parameter as a "form-data" parameter in the body. What is the correct way to achieve this functionality in a RestTemplate?

pramodc84
  • 1,576
  • 2
  • 25
  • 33
sim
  • 3,552
  • 5
  • 23
  • 23

4 Answers4

492

The POST method should be sent along the HTTP request object. And the request may contain either of HTTP header or HTTP body or both.

Hence let's create an HTTP entity and send the headers and parameter in body.

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

MultiValueMap<String, String> map= new LinkedMultiValueMap<String, String>();
map.add("email", "first.last@example.com");

HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(map, headers);

ResponseEntity<String> response = restTemplate.postForEntity( url, request , String.class );

http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html#postForObject-java.lang.String-java.lang.Object-java.lang.Class-java.lang.Object...-

Tharsan Sivakumar
  • 6,351
  • 3
  • 19
  • 28
  • 1
    You may refer this link as well for more info http://techie-mixture.blogspot.com/2016/07/spring-rest-template-sending-post.html – Tharsan Sivakumar Sep 28 '16 at 13:59
  • 2
    `ResponseEntity response = new RestTemplate().postForEntity(url, request, String.class);` I am getting `org.springframework.http.converter.HttpMessageNotWritableExc‌​eption: Could not write content: No serializer found for class java.util.Collections$3` – Shivkumar Mallesappa Aug 28 '17 at 13:14
  • How to pass body parameter when others are Strings but one of them is of type String[], as in below request data `args` is an array of String `curl -X POST --data '{"file": "/xyz.jar", "className": "my.class.name", "args": ["100"]}' -H "Content-Type: application/json" localhost:1234/batches` – khawarizmi Mar 22 '18 at 15:43
  • Any server side snippet available for this ? – Chetan May 05 '18 at 09:33
  • 2
    So this works only for strings... What if I want to send a java object in payload? – devssh May 31 '18 at 07:24
  • No, you can pass objects as well, only thing you have to adjust your map accordingly. MultiValueMap map= new LinkedMultiValueMap(); – Tharsan Sivakumar May 31 '18 at 09:17
  • @ShivkumarMallesappa :- I was also getting same error in spring boot application. we need to set below property in 'application.properties' spring.jackson.serialization.FAIL_ON_EMPTY_BEANS=false – Suraj Patil Oct 16 '18 at 07:26
  • @ShivkumarMallesappa @SurajPatil When I try making the `MultiValueMap`, It is being received at the client as null (i.e all the values are null, except for one auto generated field). Also, name of the key and the parameter is same. any idea? – Nisarg Patil Feb 11 '19 at 11:10
  • I'm getting java.lang.reflect.InvocationTargetException – Sumanth Varada May 29 '19 at 11:48
  • You have to add new FormHttpMessageConverter() to your RestTemplate's message converters to avoid non-suitable parser found error. – FilipR Jun 14 '19 at 17:57
  • This is a good answer, but in my case did not fully work because the parameters were not inserted in the URI. I've managed to make it work following this + the suggestions in https://stackoverflow.com/questions/8297215/spring-resttemplate-get-with-parameters to use `UriComponentsBuilder` or other methods to manipulate the URI in the RestTemplate. – WinterBoot Nov 12 '21 at 19:51
37

How to POST mixed data: File, String[], String in one request.

You can use only what you need.

private String doPOST(File file, String[] array, String name) {
    RestTemplate restTemplate = new RestTemplate(true);

    //add file
    LinkedMultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
    params.add("file", new FileSystemResource(file));

    //add array
    UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("https://my_url");
    for (String item : array) {
        builder.queryParam("array", item);
    }

    //add some String
    builder.queryParam("name", name);

    //another staff
    String result = "";
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.MULTIPART_FORM_DATA);

    HttpEntity<LinkedMultiValueMap<String, Object>> requestEntity =
            new HttpEntity<>(params, headers);

    ResponseEntity<String> responseEntity = restTemplate.exchange(
            builder.build().encode().toUri(),
            HttpMethod.POST,
            requestEntity,
            String.class);

    HttpStatus statusCode = responseEntity.getStatusCode();
    if (statusCode == HttpStatus.ACCEPTED) {
        result = responseEntity.getBody();
    }
    return result;
}

The POST request will have File in its Body and next structure:

POST https://my_url?array=your_value1&array=your_value2&name=bob 
sebnukem
  • 8,143
  • 6
  • 38
  • 48
Yuliia Ashomok
  • 8,336
  • 2
  • 60
  • 69
  • I tried this method but did not work for me. I am facing an issue making a POST request with the data in multipart format. Here's my question if you could guide me with a solution https://stackoverflow.com/questions/54429549/spring-boot-multipart-content-type-http-request-using-resttemplate – Deep Lathia Feb 01 '19 at 11:12
13

here is the full program to make a POST rest call using spring's RestTemplate.

import java.util.HashMap;
import java.util.Map;

import org.springframework.http.HttpEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import com.ituple.common.dto.ServiceResponse;

   public class PostRequestMain {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        MultiValueMap<String, String> headers = new LinkedMultiValueMap<String, String>();
        Map map = new HashMap<String, String>();
        map.put("Content-Type", "application/json");

        headers.setAll(map);

        Map req_payload = new HashMap();
        req_payload.put("name", "piyush");

        HttpEntity<?> request = new HttpEntity<>(req_payload, headers);
        String url = "http://localhost:8080/xxx/xxx/";

        ResponseEntity<?> response = new RestTemplate().postForEntity(url, request, String.class);
        ServiceResponse entityResponse = (ServiceResponse) response.getBody();
        System.out.println(entityResponse.getData());
    }

}
Piyush Mittal
  • 1,860
  • 1
  • 21
  • 39
  • 7
    That posts application/json instead of form data – Maciej Stępyra Aug 02 '17 at 13:08
  • `ResponseEntity> response = new RestTemplate().postForEntity(url, request, String.class);`. I am getting `org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: No serializer found for class java.util.Collections$3` – Shivkumar Mallesappa Aug 28 '17 at 13:01
  • could you please share your whole program or let me know i'll share some sample sample program @ShivkumarMallesappa – Piyush Mittal Aug 29 '17 at 09:36
  • 2
    If you replace `application/json` content type by the `application/x-www-form-urlencoded` you'll get _org.springframework.web.client.RestClientException: No HttpMessageConverter for java.util.HashMap and content type "application/x-www-form-urlencoded"_ - see https://stackoverflow.com/q/31342841/355438 – Ilya Serbis Aug 06 '19 at 19:25
2

Client.java

@PostMapping(value = "/employee", consumes = "application/json")
public Employee createProducts(@RequestBody Employee product) {
    HttpHeaders headers = new HttpHeaders();
    headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
    HttpEntity<Employee> entity = new HttpEntity<Employee>(product,headers);

    ResponseEntity<Employee> response = restTemplate.exchange(
            "http://hello-server/rest/employee", HttpMethod.POST, entity, Employee.class);

    return response.getBody();
}

Server.java

private static List<Employee> list = new ArrayList<>();

@PostMapping(path="rest/employee", consumes = "application/json")
public Employee createEmployee(@RequestBody Employee employee)

{
    list.add(employee);
    return employee;
}
static
{
    list.add(new Employee(1, "albert", "Associate", "mphasis"));
    list.add(new Employee(2, "sachin", "software engineer", "mphasis"));
    list.add(new Employee(3, "dhilip", "Lead engineer", "IBM"));
}

Employee.java

public class Employee {

private Integer id;
private String name;
private String Designation;
private String company;
 // generate getter setter and toString()
}

1. post request enter image description here

anand krish
  • 4,281
  • 4
  • 44
  • 47