Saturday, March 26, 2022

How to send JSON via POST request using RestTemplate in Spring | PostForObject, PostForEntity, and PostLocation Example in Java

Hello guys, if you are wondering how to send a Post request with Json in Java application using Spring framework then you have come to the right place. Earlier, I have shown how to consume JSON from a RESTful API and In this tutorial, we are going to discuss how to send POST requests via RestTemplate in JSON. We will have an example project which is having POST API and then test it by sending request body along with request headers using postEntry(). POST requests can be made using the RestTemplate class's postForObject(), postForEntity(), and postForLocation() template methods. The first two techniques are fairly similar to what I covered in the GET request lesson for RestTemplate. Instead of returning the whole resource, the last method returns the location of the newly formed resource.


How to send JSON with POST request in Java RESTful API using Spring RestTempalte

So let's start our example application where you will learn how to send JSON to the server using a POST request using RestTemplate and its various post methods like PostForObject, PostForEntity, andPostForLocation with having the pom.xml file updated.


1. Add maven dependencies to your project.

To allow loading of the spring text context, bean initialization, and dependency management, include the spring-boot-starter-test dependency in the project.


<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>




2. Setting up an example project.

Let's start our project by having the Student model class represent the data.

package com.school.model;

public class Student {

    private String firstName;
    private String lastName;
    private int age;

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}


Here we are using the h2 database to store our data. The StudentRepository class looks like below.


import org.springframework.data.jpa.repository.JpaRepository;

public interface StudentRepository extends JpaRepository < Student, Integer > {

    Student findById(int id);

}



To add the students and update them, we use the IStudentService interface and implementation of them as below

import java.util.List;

public interface IStudentService {
    Student saveStudent(Student student);
    Student getStudentById(Integer id);
}


So we are going to implement these services in the StudentServiceImpl class in the project.


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


@Service
public class StudentServiceImpl implements IStudentService {

    @Autowired
    StudentRepository studentRepository;

    //add a new student to h2 database
    @Override
    public String saveStudent(Cards card) {
        try {
            studentRepository.save(card);
            return "Saved to database successfully !";
        } catch (Exception e) {
            e.printStackTrace();
            return "Error in saving the value";
        }
    }

    //get the specific student from the h2 database
    @Override
    public Student getStudentById(String cardNumber) {
        return studentRepository.findById(cardNumber);
    }
}

So let's define the REST APIs for these services in the StudentController class.


@Controller
public class StudentController {

    @Autowired
    StudentServiceImpl studentService;

    @PostMapping(
        value = "/addstudent", consumes = "application/json", produces = "application/json")
    public Person createPerson(@RequestBody Student student) {
        return studentService.saveStudent(student);
    }

    @PostMapping(
        value = "/updatestudent", consumes = "application/json",
        produces = "application/json")
    public Student updateStudent(@RequestBody Student student, 
               HttpServletResponse response) {
        response.setHeader("Location", ServletUriComponentsBuilder.fromCurrentContextPath()
            .path("/findStudent/" + student.getId()).toUriString());

        return studentService.saveStudent(student);
    }

}


For both approaches, we used the @RequestBody annotation on the Student argument. This instructs
Spring to bind the student object to the body of the HTTP request. And also we added the consumes
attribute in the @PostMapping annotation with the value of "application/json" for both methods.




3. RestTemplate Example

Here, we will try to send POST requests to the person API by using the POST methods provided
by the RestTemplate. We are using the postForObject, postForEntity, and postForLocation methods in this example. Before, going into the implementation of our unit tests, let's define a setup method to initialize the objects.

@BeforeClass
public static void runBeforeAllTestMethods() {
    createPersonUrl = "http://localhost:8080/addstudent";
    updatePersonUrl = "http://localhost:8080/updatestudent";

    restTemplate = new RestTemplate();
    headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    JsonObjectStudent = new JSONObject();
    JsonObjectStudent.put("id", 1);
    JsonObjectStudent.put("name", "John");
}


As we want the post data in JSON format, we can add the Content-Type header to our request with
APPLICATION_JSON media type.




4. PostForEntity Example 

This is returning the response as a ResponseEntity object. Let's get an example as the POST
request to the Student API to create a new Student object and return the response as a ResponseEntity.


@Test
public void postforEnityMethod()
throws IOException {
    HttpEntity < String > request =
        new HttpEntity < String > (.toString(), headers);

    ResponseEntity < String > responseEntityStr = restTemplate.
    postForEntity(JsonObjectStudent, request, String.class);
    JsonNode root = objectMapper.readTree(responseEntityStr.getBody());

    assertNotNull(responseEntityStr.getBody());
    assertNotNull(root.path("name").asText());
}


Here, there is a responseType parameter to convert the response body to the requested java type.
Here we were able to return the response body as a ResponseEntity.


5. PostForObject Example

Here, first, we are going to make the HttpEntity based on the HttpEntity on studentJsonObject containing headers of Content-Type.


@Test
public void postJsonObject()
throws IOException {
    HttpEntity < String > request =
        new HttpEntity < String > (studentJsonObject.toString(), headers);

    String personResultAsJsonStr =
        restTemplate.postForObject(createStudentUrl, request, String.class);
    JsonNode root = objectMapper.readTree(personResultAsJsonStr);

    assertNotNull(studentResultInJsonUrl);
    assertNotNull(root);
    assertNotNull(root.path("name").asText());
}


This method will return the requested body as a string. postForObject() may automatically convert the response body to the Java type given in the responseType argument (e.g. String, Person).




6. PostForLocation Example 

The postForLocation() method, like the postForObject() and postForEntity methods,
generates a new resource by publishing the provided object to the specified URI. The only difference is that the value of the Location header is returned. 

So think if you want to return the LocationHeader of the response after updating the student object we posted.


@Test
public void postJsonLocationObject()
throws JsonProcessingException {
    HttpEntity < String > request = new HttpEntity <String> (studentJsonObject.toString(),
                                                       headers);
    URI locationHeader = restTemplate.postForLocation(updateStudentUrl, request);

    assertNotNull(locationHeader);
}



So let's discuss a question that may arise from using the POST request via RestTemplate in JSON.

In here, the RestTemplate is used like below

restTemplate = new RestTemplate();
List<HttpMessageConverter<?>> list = new ArrayList<HttpMessageConverter<?>>();
list.add(new MappingJacksonHttpMessageConverter());
restTemplate.setMessageConverters(list);
...
Payment payment= new Payment("Aa4bhs");
Payment res = restTemplate.postForObject("http://localhost:8080/aurest/rest/payment",
                    payment, Payment.class);


So everytime using this method, will get an error like below.
org.springframework.web.client.HttpClientErrorException: 415 Unsupported Media Type
How to send JSON via POST request using RestTemplate in Spring  - Example Tutorial





How to fix org.springframework.web.client.HttpClientErrorException: 415 Unsupported Media Type exception in Spring

If you are using Spring 3.0, an easy way to avoid the org.springframework.web.client.HttpClientErrorException: 415 Unsupported Media Type exception, is to include the Jackson jar files in your classpath, and use mvc:annotation-driven config element.

Underneath the covers, Spring MVC delegates to a HttpMessageConverter to perform the serialization. In this case, Spring MVC invokes a MappingJacksonHttpMessageConverter built on the Jackson JSON processor.

This implementation is enabled automatically when you use the mvc:annotation-driven configuration element with Jackson present in your classpath.

So this method below works fine.

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

HttpEntity<String> entity = new HttpEntity<String>(requestJson, headers);
ResponseEntity<String> response = restTemplate.put(url, entity);


and another method of solving the above error is given below.

So here used a basic example using Spring's RestTemplate class to make a POST request. This way is also good to implement as the particular JSON parser of the rest endpoint was using needed double quotes around field names.


RestTemplate restTemplate = new RestTemplate();
 
String url = "endpoint url";
String requestJson = "{\"queriedQuestion\":\"Is there pain in your hand?\"}";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
 
HttpEntity < String > entity = new HttpEntity < String > (requestJson, headers);
String answer = restTemplate.postForObject(url, entity, String.class);
System.out.println(answer);

You can use this code to send post requests to your Java application and verify the result on the backend. 



That's all about how to send Post requests via RestTempalte in Java using Spring Framework. You can use this method to send JSON to the server. So in this tutorial, we discussed how to send POST requests via RestTemplate in JSON. The three methods postForEntity, postForObject, and postForLocation are used the send POST request via RestTemplate in JSON. 

Hope you understand this tutorial well and hope to see you in the next tutorial. Until then bye.

Other Spring Framework articles you may like to explore 


    Thanks for reading this article so far. If you find this Spring Boot and Hiberante example tutorial useful, please share them with your friends and colleagues. If you have any questions or feedback, then please drop a note.


    1 comment:

    1. Have you ever considered about adding a little bit more than just your
      articles? I mean, what you say is important and everything.
      But think about if you added some great images or video clips to give your posts more, "pop"!
      Your content is excellent but with pics and videos, this site could certainly be one of the greatest in its niche.
      Great blog!

      ReplyDelete