Spring Rest:Jackson’s JsonNode for Payload unaware request Handling

Generally, while creating a Rest application using Spring one would leverage Jackson’s message converter to convert the received JSON onto domain object in java i.e typically a POJO.

Example: Let’s say there is a request which we need to send to the service then that has to be de-serialized to a Java object.Java object would be this:

package com.example.demo;public class Request {
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;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append(“Request [firstName=”);
builder.append(firstName);
builder.append(“, lastName=”);
builder.append(lastName);
builder.append(“, age=”);
builder.append(age);
builder.append(“]”);
return builder.toString();
}
}

And this has to be received at the Spring Controller method with annotation @RequestBody like this:

package com.example.demo.controller;import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.Request;
@RestController
public class HomeController {

@RequestMapping("/submitRequest")
public String processRequest(@RequestBody Request request) {
System.out.println("Request:"+request);
return "Response of processed request!";
}
}

But,there would be few cases where the rest service will just be used as a proxy i.e when the Rest service is used to forward the request on to another 3rd party service or to a service present in another application and to receive the response payload back to the requester.In this scenario,we may not require to know the request and response Payload structure i.e the structure of the JSON to map it onto domain model object.So,how would we deal with this situation?

One solution for this is Spring netflix zuul proxy which can be used to just forward the request and send the response received from the 3rd party service back to the requester.But,it requires the application to be a Spring Boot application.It just does not work with Spring MVC.

The other solution and that which works For application which is not a Spring boot application is,we can just use JSONNode object present in Jackson module, to de-serialize the request JSON even if we are unaware or does not need to know of the request and response payload structure.

Example:

package com.example.demo.controller;import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.fasterxml.jackson.databind.JsonNode;@RestController
public class DemoController {

@RequestMapping(value="/ping",method = RequestMethod.POST)
public JsonNode index(@RequestBody JsonNode jsonNode) {
System.out.println("Received JSON:"+jsonNode.toString());
return jsonNode;
}
}

Let’s test this by sending a sample request from a REST client:

Let us have a look at what we received at the controller:

We just received the JSON object without having to know the request payload structure and without having to use the Java domain object.

We can also modify the payload structure at the REST client without having to make any modifications at Spring Controller.Let’s test this by sending a request with different payload structure and still the request will be processed at Spring Controller.

Request received at controller:

As you can see the benefit of JSONNode is that the request payload can be changed and still can be processed at Controller.

The real benefit of using JsonNode comes when the rest service controller is just used as a proxy i.e when the rest service is used to just forward the request to another rest service ,forward the response from another rest service back to the requester.Let’s see this with an example.

Let us assume we have another rest service which is consumed from the Controller.Example of this kind of rest service.

@RequestMapping(“/submitRequest”)
public Response processRequest(@RequestBody Request request) {
System.out.println(“Request:”+request);
Response response = new Response();
response.setResponseMessage(“Processed Successfully”);
response.setResponseStatus(“Success”);
return response;
}

And this service would be consumed from the controller we have.

@RequestMapping(value=”/ping”,method = RequestMethod.POST)
public JsonNode index(@RequestBody JsonNode jsonNode) {
//System.out.println(“Received JSON:”+jsonNode.toString());

RestTemplate restTemplate = new RestTemplate();
HttpEntity<JsonNode> request = new HttpEntity<>(jsonNode);

String url = “http://localhost:8080/submitRequest”
ResponseEntity<JsonNode> response =
restTemplate.exchange(url,
HttpMethod.POST,
request,
JsonNode.class);
JsonNode responsePayload = response.getBody();
return responsePayload;
}

Let’s test this by sending the request from rest client:

Please visit my YouTube channel https://youtube.com/channel/UC-8tqCyhtt6Lt5-n2UMZB_A