Skip to main content

Spring MVC with JSON, Using jQuery and Jackson

Hello everyone, how are you? I was developing a cms system using spring mvc and hibernate, and I want to add ajax functionality, but I faced a lot of problems and they took me a whole day to solve.

1、Add Jackson dependency to Spring MVC

Add following code in to your pom.xml:

<dependency>
 <groupId>org.codehaus.jackson</groupId>
 artifactId>jackson-mapper-asl</artifactId>
 <version>1.9.12</version>
</dependency>

2、Spring MVC configuration file:

There must be “<annotation-driven />” in the file, these will automatically register a json message converter, so you can covert json object to java object or conversely  in @RequestBody and @ResponseBody.

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
 http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

    <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->

    <!-- Enables the Spring MVC @Controller programming model -->
    <annotation-driven />

    <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
    <resources mapping="/resources/**" location="/resources/" />

    <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
    <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <beans:property name="prefix" value="/WEB-INF/views/" />
        <beans:property name="suffix" value=".jsp" />
    </beans:bean>

    <context:component-scan base-package="com.zxuqian.cms.web.controllers" />

3、Jackson with Hibernate, recursion issue

I didn’t use jackson-hibernate-module, I just using get instead of load in hibernate. That’s not enough, we must add an ignore annotation on the property that we shouldn’t convert to json.

package com.zxuqian.cms.domain;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;

import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonProperty;

@Entity
public class Category {
    
    private Long id;
    
    @NotNull(message="category name should not be empty")
    @Pattern(message="category name is not valid", regexp="^[\\w\\s\\u4e00-\\u9fa5\\-\\|]+$")
    private String cateName;
    private String cateType;
    @Pattern(message="description string has illegal characters", regexp="^[^<>]*$")
    private String description;
    private List childCategories;
    private Category category;
    
    public Category() {
        childCategories = new ArrayList();
    }
    
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    
    @ManyToOne
    @JoinColumn(name="parent_id", referencedColumnName="id")
    @JsonIgnore
    public Category getCategory() {
        return category;
    }

    @JsonProperty
    public void setCategory(Category category) {
        this.category = category;
    }

    public String getCateName() {
        return cateName;
    }
    public void setCateName(String cateName) {
        this.cateName = cateName;
    }
    public String getCateType() {
        return cateType;
    }
    public void setCateType(String cateType) {
        this.cateType = cateType;
    }
    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    @OneToMany(mappedBy = "category")
    public List getChildCategories() {
        return childCategories;
    }
    
    public void setChildCategories(List childCategories) {
        this.childCategories = childCategories;
    }

    @Override
    public String toString() {
        return "Category [id=" + id + ", cateName=" + cateName + ", cateType="
                + cateType + ", description=" + description + "]";
    }
    
}

4、Mapping JSON object to POJO

We must write correct JSON string in ajax request. Use JSON.stringify({“cateName”: “abc”}), the double quote around “cateName” is required. Then, in the POJO, we use @jsonignore annotation igored “category” property on its getter method, you should take close care of this, you need to add @jsonproperty on its setter method, or you will get a 400 bad request error, and cannot mapping to the @RequestBody variable.

$(document).ready(function () {

    $("#addcate_form").submit(function (event) {

        jQuery.ajax({
            url: 'addCategory',
            data: JSON.stringify({ "cateName": "on", "description": "aaaa", "category": { "id": 7 } }),
            type: 'post',
            dataType: 'text',
            contentType: 'application/json; charset=UTF-8',
            success: function (data) {
                alert(32423234);
                alert($(data).success);
            },
            error: function () {
                alert(111111111);
            }
        });

        return false;

    });

});

Controllers:

@RequestMapping(value = "/addCategory", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody String saveOrUpdateCategory(@RequestBody Category category){
    logger.info(category.toString());
    logger.info(category.getCateName());
    logger.info(category.getDescription());

    Long parent_id = category.getCategory().getId();
    logger.log(Level.INFO, parent_id);
    if (parent_id == null) {
        category.setCategory(null);
    }

    return "{'success':true}";
}

These seemed to be simple problems, but I’m new to it, so it took a long time to solve them, but thank god, anyway, I succeed!