2

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");
}
Parkash Kumar
  • 4,710
  • 3
  • 23
  • 39
A D
  • 307
  • 3
  • 21

3 Answers3

3

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.

jstuartmilne
  • 4,398
  • 1
  • 20
  • 30
  • thx for the suggestion Sudakatux. Cf my edit following some tests. – A D Oct 25 '15 at 22:35
  • I suppose that in this second case, I need to remove the ,url parameter. I tried it: I receive the success message which should mean that some controller code must have been executed before returning to the JS. However, the code never entered the serveResource method: I set a System.out in serveResource which never displayed. I m really puzzled... – A D Oct 26 '15 at 06:54
2

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");
    }
}
Community
  • 1
  • 1
Parkash Kumar
  • 4,710
  • 3
  • 23
  • 39
1

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?
Olaf Kock
  • 46,930
  • 8
  • 59
  • 90
  • alert(rat.nom + portletURL); works too. Nothing in the logs. This portlet is the only one on the page. – A D Oct 25 '15 at 20:34
  • Any other taglibs than these that should be included? <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %> <%@ taglib uri="http://alloy.liferay.com/tld/aui" prefix="aui" %> <%@ taglib uri="http://liferay.com/tld/ui" prefix="liferay-ui" %> <%@ taglib uri="http://liferay.com/tld/theme" prefix="theme" %> – A D Oct 25 '15 at 20:37
  • The libraries look good. You'll have to include all of the ones that you're using, no more, no less. And, of course, they have to be deployed and available to the web application as well. Also, note the edited ?strip=0 hint in the updated answer. – Olaf Kock Oct 27 '15 at 10:17