Spring 4 Web MVC – JSON Handling

Introduction

The JavaScript AJAX call is described in terms of request headers and request data formatting.

Spring uses Jackson for JSON parsing. Jackson is configured to ignore extra JSON properties that do not match properties of the bean being populated at the @Controller request end-point method.

This blog demonstrates populating complex objects n levels deep thus overcoming some difficulties encountered as per many of the comments in this blog.

Unlike Spring 3 MVC – Adding Objects to a List element on the fly at form submit – (Generic method) a generic JavaScript library is not provided. Populating JSON objects is easily achieved with JavaScript. For that reason, the difficulties of the HTML form implementation described (and partially solved) in that blog do not arise in the first place. Therefore it is hugely favorable to use JSON over conventional HTML forms for complex objects (and in general).

This demonstration conforms to a useful and popular design pattern. Specifically, the form is submitted asynchronously, the response is handled by the client JavaScript.

This provides for:

A far better user experience as there is no page load. Feedback is immediate.

Ease of development

Ease of validation handling

Support for complex forms

Code portability (think HTML5 clients and single page applications)

Goal

Send this complex object to Spring for processing.

Setup

Create a Spring 4 Web MVC with Java configuration application as described in this previous blog.

Add Jackson to the POM

POM - Jackson

XHTML

1

2

3

4

5

6

7

.

<dependency>

<groupId>com.fasterxml.jackson.core</groupId>

<artifactId>jackson-databind</artifactId>

<version>2.3.3</version>

</dependency>

.

Java – DTO Box Object

Create this DTO object. It will be populated with JSON data. Package it in com.outbottle.model.

BoxDto.java

Java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

packagecom.outbottle.model;

importcom.fasterxml.jackson.annotation.JsonIgnoreProperties;

importjava.util.LinkedList;

importjava.util.List;

/**

*

*/

@JsonIgnoreProperties(ignoreUnknown=true)

publicclassBoxDto{

privateStringname;

privateList<BoxDto>boxArray=newLinkedList<BoxDto>();

publicBoxDto(){

}

publicStringgetName(){

returnname;

}

publicvoidsetName(Stringname){

this.name=name;

}

publicList<BoxDto>getBoxArray(){

returnboxArray;

}

publicvoidsetBoxArray(List<BoxDto>boxArray){

this.boxArray=boxArray;

}

}

Jackson – Ignoring extra properties

Be sure to add the following annotation to BoxDto in order to have Jackson ignore properties that do not match the DTO. For example, AngularJS adds the property “$$hashKey”. Without this annotation, the request would not succeed due to Jackson throwing an exception.

@JsonIgnoreProperties

Java

1

2

3

*/

@JsonIgnoreProperties(ignoreUnknown=true)

publicclassBoxDto{

Request Object

Pop the BoxDto into the request object. It’s always good practice to use request and response objects rather than passing model objects directly.

BoxRequest.java

Java

1

2

3

4

5

6

7

8

9

10

11

12

publicclassBoxRequest{

privateList<BoxDto>boxDtoList=newLinkedList<BoxDto>();

publicList<BoxDto>getBoxDtoList(){

returnboxDtoList;

}

publicvoidsetBoxDtoList(List<BoxDto>boxDtoList){

this.boxDtoList=boxDtoList;

}

}

JavaScript

This JavaScript which is here as a JSFiddle is used to populate the BOX DTO object. Each box can have a list of boxes.

To add a box, simply enter a name and hit the button. Select a box to add a child box to it.

This code is for demonstration purposes. Its purpose is simply to populate a BoxDto object recursively in order to demonstrate the nature of JSON and how Spring/Jackson can handle it. If it’s a little off-putting, just note that it simply populates a BoxDto object.

$Http AJAX Module

Note the content-type header.;”application/json” should be specified in order to allow Spring to be aware of the JSON payload thus handle accordingly. For example, as per the REST specification, XML could be specified here and Spring could adapt to handle/parse XML instead of JSON,

JavaScript - AJAX

JavaScript

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

$scope.sendBox=function(){

varreq={

method:'POST',

url:$attrs.contextPath+"/box",

headers:{

'Content-Type':'application/json'

},

data:JSON.stringify({boxDtoList:$scope.boxArray}),

};

$http(req).

success(function(data,status,headers,config){

console.log(data);

alert('Success, see browser log for returned object');

}).

error(function(jqXHR,textStatus,errorThrown){

alert('Woops something wen wrong with the AJAX call');

});

};

Java – AJAX End point handler @Controller method

@Controller AJAX Handler

Java

1

2

3

4

5

@RequestMapping(value="/box",method=RequestMethod.POST)

public@ResponseBodyObjectbox(@RequestBodyBoxRequest boxRequest){

//Do stuff here

returnboxRequest.getBoxDtoList();

}

The @RequestBody and @ResponseBody are responsible for initiating the JSON marshalling. The request header ‘Accept: application.json’ which is delivered by the JavaScript indicates JSON rather than XML.

Conclusion

The following has been demonstrated

Setting up the necessary AJAX request headers to facilitate asynchronous communication with Spring.

Configuring Spring Web MCV / Jackson to ignore extra properties in the request thus making it easier to integrate with AngularJS.

Delivering complex objects from the client to the Server and vice versa using AJAX and JSON.