A D
A D

Reputation: 307

Ajax not triggered in my Liferay portlet

I have a MVCPortlet and I try to call ajax in a jsp page.

My jsp is as follows:

<%@include file="/html/init.jsp"%>

<portlet:resourceURL var="updateRatAjax" id="updateRatAjax" ></portlet:resourceURL>


<script type="text/javascript">

function selectRat(){

    var rat = new Object();
    rat.nom = $('#ratsList').val();

    alert(rat.nom + ' '/* + portletURL*/);


    $.ajax({

        url: "${updateRatAjax}" ,
        type: 'POST',
        dataType: 'json',
        data: JSON.stringify(article),
        contentType: 'application/json',
        mimeType: 'application/json',

        success: function (data) {
            alert('ajax' + article.nom);
            }
    });

    alert('end of function');
}
</script>
....

    <select  class="offset2 span4 form-control"  name=ratsList id = ratsList onchange="selectRat()">
        <option>1</option>
        <option>2</option>
        <option>3</option>
    </select>

    <input  name = "selectedRat" id ="selectedRat"></input>

My controler portlet resource is as folliws:

public class MainControllerPortlet extends  MVCPortlet {
...
    public void updateRatAjax( ResourceRequest request, ResourceResponse response)
            throws IOException, PortletException {
        System.out.println(" updateRatAjax");

    }
}

I also tried to call the url this way into the js function:

  url:"<%= updateRatAjax %>",

and

 var portletURL = "<%= updateRatAjax %>";
   url: portletURL,

no chance. alert(rat.nom + ' '/* + portletURL*/); oes display but then nothing so the js method must be stopping when $.ajax({...}) is called.

The issue might have to do with the application not being able to map the resourceURL with the updateRatAjax method. In this project, the actionURL are correctly mapped to the controller's methods without I map them in web.xml nor I use any allocations. I took it that I don't need to map the portlet:resourceURL either, but I might be wrong there. First time I use portlet:resourceURL so I have no knowledge about them.

thx in advance for your assistance.

EDIT: following Sudakatux's answer, I changed the JS function to : ...

 var portletURL = "${updateRatAjax}"; // "<%= updateRatAjax %>";//working  // 
  alert(rat.nom + '\n ' +   portletURL); //portletURL displays correctly with both options on previous line

    $.ajax({

        url: portletURL ,
        type: 'POST',
        dataType: 'text',
        cache: false,
        success: function (data) {
            alert('success ajax' );
            }, 
        error: function(http, message, exc) { 
           alert('error ajax'); 
       }

    });

Strangely enough, I get the success message but the controller method is never called :

public void updateRatAjax( ResourceRequest request, ResourceResponse response)
        throws IOException, PortletException {
//public void updateRatAjax(ActionRequest request, ActionResponse response)        throws  PortalException, SystemException {
    System.out.println("MainController portlet : updateRatAjax");
}

Upvotes: 2

Views: 1624

Answers (3)

Olaf Kock
Olaf Kock

Reputation: 48087

Looks good to me - some sanity checks:

  • anything in the logs?
  • you mention alert(rat.nom + ' '/* + portletURL*/); but not alert(rat.nom + portletURL); (of course with an initial var portletURL = "<%= updateRatAjax %>";)
  • Does your init.jsp include the portlet taglib and is it available? You might want to just include on your page, so that it's printed and you can inspect it
  • alternatively: What's the HTML code that this JSP generates? (In order to work around Liferay's minifier, add ?strip=0 to the URL - that makes it easier to read.
  • This is a portlet which shares the page with other portlets. Are you sure that the IDs that you use are not interfering with any other portlet's IDs?

Upvotes: 1

Parkash Kumar
Parkash Kumar

Reputation: 4730

Yes, you are right, your AJAX call (resourceURL) is not getting mapped with appropriate listener in action class.

The problem is that you are highly focusing on linking AJAX call to specific method of the controller based on the its var attribute for default MVC portlet, like we have feasibility to do in Spring MVC portlet using @ResourceMapping("xxx") annotation.

See following lines taken from the Multiple Ajax calls liferay portlets:

Adding more in this. We can not use the serveResource method like processAction. There can be multiple processAction in single Liferay portlet(Which is not Spring MVC portlet), while in case of serveReource it will be single.

Now, simply override serveResource as following:

public void serveResource( ResourceRequest request, ResourceResponse response)
    throws IOException, PortletException {
    System.out.println(" updateRatAjax");
}

Moreover, if you have multiple AJAX calls, you have two options:

1. Filter requests using resourceRequest.getResourceID() in serveResource after adding id attribute to <portlet:resourceURL> tag, like:

<portlet:resourceURL id="updateRatAjax" ></portlet:resourceURL>

public void serveResource( ResourceRequest request, ResourceResponse response)
    throws IOException, PortletException {

    if(resourceRequest.getResourceID().equals("updateRatAjax")){
        System.out.println(" updateRatAjax");
    }
}

2. Filter requests using additional parameter through <portlet:resourceURL> or AJAX data:

<portlet:resourceURL>
    <portlet:param name="action" value="updateRatAjax" />
</portlet:resourceURL>

OR

data: {
    article: JSON.stringify(article),
    action: 'updateRatAjax'
},

Controller:

public void serveResource( ResourceRequest request, ResourceResponse response)
    throws IOException, PortletException {

    String action = ParamUtil.getString(request , "action", "");

    if(action.equals("updateRatAjax")){
        String article = ParamUtil.getString(request , "article", "");
        System.out.println(" updateRatAjax");
    }
}

Upvotes: 2

jstuartmilne
jstuartmilne

Reputation: 4508

Give This a try

<portlet:resourceURL var="timeSyncURL" id="serverTimeSync" />

<script type="text/javascript">
var serverTimeFunction = function serverTime() { 
var time = null; 
    $.ajax({url: '<%=timeSyncURL.toString() %>', 
 async: false, dataType: 'text', 
 success: function(text) { 
    console.log("updated time "+ text);
     time = new Date(Number(text)); 
     console.log("time is "+time);
 }, error: function(http, message, exc) { 
     time = new Date(); 
}}); 

So here im calling a service which does have the same signature as your updateRatAjax method. and is working fine for me

This is a less elegant option but it should certainly work Override the serveResource method

@Override
        public void serveResource(ResourceRequest resourceRequest,
                ResourceResponse resourceResponse)
            throws  IOException, PortletException {

if(resourceRequest.getResourceID().equals("serverTimeSync")){
                 PrintWriter out = resourceResponse.getWriter();

                 out.println(new Date().getTime());
}

The serveResource is for AJAX calls so this will certainly work.

Upvotes: 3

Related Questions