Spring MVC ModelAttribute Fields Are Null Instead of Form Input Values

AForsberg picture AForsberg · Aug 1, 2013 · Viewed 12.3k times · Source

I'm trying to make a form that will post a CardRequestResource:

public class CardRequestResource extends ResourceSupport{
    private Long cardRequestId;
    private String deliveryMethod;
    private String address;
    private boolean isHomeDelivery;
    private String requestDate;
    private String expectedDate;
    private String comments;
    private Long statusId;
    private PersonResource person;

    //Getters and Setters
}

In my controller, I first load the JSP and add an empty CardRequestResource to the ModelMap:

@RequestMapping(value = { "", "/approval" }, method = RequestMethod.GET)
public String getApproval(ModelMap map) {
    map.put("cardRequestResource", new CardRequestResource());       
    return "cardoffice/approval";
}

My JSP builds the form with the cardRequestResource model attribute:

<form:form id="detailForm" name="detailForm" modelAttribute="cardRequestResource">
    <form:input path="statusId" type="hidden" id="statusId" name="statusId" />
    <form:textarea path="comments" name="comments" id="commentTextarea" rows="7" cols="81" style="font-style: normal;"/>
</form:form>

A Javascript function makes an AJAX call to populate the form values:

function getCardRequestDetails(cardRequestUrl) {
    $.ajax({
        type : "GET",
        url : cardRequestUrl,
        dataType : "json",
        success : function(response) {
            loadCardRequestDetails(response);
        },
        error : function(response) {}
    });
};

function loadCardRequestDetails(cardRequest) {
    $("#statusId").attr("value", cardRequest.statusId);
    $("#commentTextarea").val(cardRequest.comments);
}

At this point a user may update the comment text area, and the hidden input may change conditionally on what the user enters in the field. Then when the form is submitted, I call the following Javascript function:

function postCardRequest(url) {
    var serialized = $("#detailForm").serialize();
    alert(serialized);
    $.ajax({
        type: "POST",
        url: url,
        data: serialized,
        contentType: "application/json",
        dataType: "json"                
    });
}

The alert shows that the fields are populated correctly with the data that was either originally loaded by AJAX/Javascript, or by the user. However when I get to the handler in my controller that processes the post, the CardRequestResource is non-null, but EVERY SINGLE field in it is NULL!

Handler code:

@RequestMapping(value = "/approval/submit", method = RequestMethod.POST)
public @ResponseBody Map<String, Object> postCardRequest(@ModelAttribute(value = "cardRequestResource") CardRequestResource cardRequestResource) {
    Map<String, Object> responseMap = new HashMap<String, Object>();
    final String success = "success";
    Boolean isSuccessful = Boolean.FALSE;

    if(cardRequestResource != null){
        isSuccessful = Boolean.TRUE;
    }
    //TODO

    System.out.println("Status: " + cardRequestResource.getStatusId() + ", Comments: " + cardRequestResource.getComments());

    responseMap.put(success, isSuccessful);
    return responseMap;
}

Answer

AForsberg picture AForsberg · Aug 2, 2013

So I think I found the perp!

This lil' guy right here in the POST AJAX call:

contentType: "application/json",

I was originally sending JSON to my controller, then I learned that Spring MVC had that nifty ModelAttribute annotation, so I wouldn't have to worry about converting to/from JSON during my POST. Unfortunately, I didn't think to remove that contentType line, and one would think that it would throw an error or something with it still in there... apparently not. Just NULL values in the binding and hours of fruitless debugging...

After I removed that line, I started getting data in the CardRequest attributes instead of NULLs!