Sanka
Sanka

Reputation: 1324

AJAX JSON data retrieve (Portlet+Liferay+JSON+Spring)

What I want to do is, just post data to server and get data from server by using JSON & AJAX. I am converting legacy non AJAX project to AJAX. It is a liferay portlet spring ibatis jquery project. Form submission was success and I could not be able to retrieve data from server as JSON. I used spring-mvc-jquery-autocomplete-example sample to learn jackson for JSON. It was very easy no need me to even think about JSON. I just copy-paste two jar files in my build path and annotate @ResponseBody to my method. But still response is full html page. Why?

JSP code here

   <portlet:actionURL var="formAction">
        <portlet:param name="action" value="submit"/>
    </portlet:actionURL>


    <c:set var="formPortletNamespace">form<portlet:namespace/></c:set>

    <form:form method="post" action="${formAction}" commandName="uiState" id="${formPortletNamespace}" cssClass="travelInsurancePortletForm jqCustomStyle" autocomplete="off">
        <% /* Selected action as a parameter */ %>
        <input type="hidden" name="portletAction" id="portletAction"/>

        <form:hidden path="quote.quotingWebApp" />

JS code here.This code submit the form to server

function doPortletAction(actionName) {
   jQuery('form#form<portlet:namespace/> input#portletAction').val(actionName); 

   jQuery('form#form<portlet:namespace/> input#<portlet:namespace/>-posted').val('true');
//jQuery('form#form<portlet:namespace/>').submit();


jQuery.ajax({
    url: jQuery('#form<portlet:namespace/>').attr("action"),
    type: 'POST',
    datatype:'json',
    data: jQuery('#form<portlet:namespace/>').serialize(),
    success: onAjaxSubmitReturn
});

}

Controller coding

@Controller
@RequestMapping("VIEW")
public class MyController{

    @ActionMapping(params="portletAction=myAction")
    public @ResponseBody UiState myAction( 
            PortletSession session, 
            ActionResponse response, 
            @RequestParam(value="endDate", required=false) Date endDate,
            @ModelAttribute("uiState") UiState requestUiState,
            BindingResult errors,
            ModelMap mm) throws Exception {

    UiState uiState=new UiState ();
        return uiState;

}

Upvotes: 4

Views: 3404

Answers (1)

n1ckolas
n1ckolas

Reputation: 4440

First of all, Action phase does not produce any output. It always goes to Render phase. So this code wouldn't work anyway.

For second, as of Spring 4.1 it doesn't support @ResponseBody for portlets yet. It is planning in 4.2, but it might not be there as well.

So what you need is to use either @RenderMapping or @ResourceMapping (JSR-286/Portlet 2.0 only).

The most natural way is to use @ResourceMapping. Code will look like the following:

@ResourceMapping("myAction")
public void myAction(
        PortletSession session,
        ResourceResponse response,
        @RequestParam(value="endDate", required=false) Date endDate,
        @ModelAttribute("uiState") UiState requestUiState,
        BindingResult errors,
        ModelMap mm) throws Exception {

    UiState uiState = new UiState ();

    //TODO extra logic

    //explicitly set JSON as response type
    response.setContentType("application/json");

    //write JSON into output
    response.getWriter().write(serializeJSON(uiState));
}

Whereis serializeJSON is utility method by your choice.

Sample implementation is the following (based on Jackson serializer):

public static String serializeJSON(Object o) throws IOException {
    return new ObjectMapper().writeValueAsString(o);
}

Note: you need to use this snippet on your JSP(s):

<portlet:resourceURL var="formAction" id="myAction"/>

Upvotes: 2

Related Questions