skip to Main Content

I am unable to get the JSON data from AJAX in MVC Resource Command because I am getting null value in the request parameter.

I have searched for several Stackoverflow answers to solve the problem, and I am not clear where I am going wrong.

Code snippet and screenshots will be provided below.

Controller portlet

@Component(
    immediate = true,
    property = {
        "com.liferay.portlet.display-category=Demo",
        "com.liferay.portlet.header-portlet-css=/css/main.css",
        "com.liferay.portlet.footer-portlet-javascript=/js/main.js",
        "com.liferay.portlet.instanceable=true",
        "javax.portlet.display-name=Empleado",
        "javax.portlet.init-param.template-path=/",
        "javax.portlet.init-param.view-template=/view.jsp",
        "javax.portlet.name=" + EmpleadoPortletKeys.EMPLEADO,
        "javax.portlet.resource-bundle=content.Language",
        "javax.portlet.security-role-ref=power-user,user",
        "javax.portlet.version=3.0"
    },
    service = Portlet.class
)
public class EmpleadoPortlet extends MVCPortlet {
    
    public void render(RenderRequest renderRequest, RenderResponse renderResponse) throws IOException, PortletException {
        
        List<Empleado> empleados = EmpleadoLocalServiceUtil.getEmpleados(-1, -1);
        
        renderRequest.setAttribute(EmpleadoPortletKeys.EMPLEADO_ID_TABLE_HEADER, EmpleadoPortletKeys.EMPLEADO_ID_TABLE_HEADER);
        renderRequest.setAttribute(EmpleadoPortletKeys.DNI_TABLE_HEADER, EmpleadoPortletKeys.DNI_TABLE_HEADER);
        renderRequest.setAttribute(EmpleadoPortletKeys.NOMBRE_TABLE_HEADER, EmpleadoPortletKeys.NOMBRE_TABLE_HEADER);
        renderRequest.setAttribute(EmpleadoPortletKeys.APELLIDOS_TABLE_HEADER, EmpleadoPortletKeys.APELLIDOS_TABLE_HEADER);
        renderRequest.setAttribute(EmpleadoPortletKeys.CARGO_TABLE_HEADER, EmpleadoPortletKeys.CARGO_TABLE_HEADER);
        renderRequest.setAttribute(EmpleadoPortletKeys.ACCIONES_TABLE_HEADER, EmpleadoPortletKeys.ACCIONES_TABLE_HEADER);
        renderRequest.setAttribute(EmpleadoPortletKeys.EMPLEADOS, empleados);
        
        super.render(renderRequest, renderResponse);
    }
    
}

view.jsp

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

<portlet:resourceURL id="empleado-resource" var="empleadoResourceURL"/>

<div id="empleado-portlet">
    <div class="container">
        <table class="table table-hover">
            <thead>
                <tr>
                    <th scope="col">${fn:toUpperCase(dni)}</th>
                    <th scope="col">${nombre}</th>
                    <th scope="col">${apellidos}</th>
                    <th scope="col">${cargo}</th>
                    <th scope="col" class="text-center">${acciones}</th>
                </tr>
            </thead>
            <tbody>
                <c:forEach var="employee" items="${employees}"> 
                    <tr>
                        <td>${employee.dni}</td>
                        <td>${employee.nombre}</td>
                        <td>${employee.apellidos}</td>
                        <td>${employee.cargo}</td>
                        <td>
                            <div class="btn-actions d-flex justify-content-center">
                                <div class="mr-1">
                                    <button type="button" id="${employee.empleadoId}" class="btn btn-primary btn-update">
                                        <i class="icon-pencil"></i>
                                    </button>
                                </div>
                                <div class="ml-1">
                                    <button type="button" id="${employee.empleadoId}" class="btn btn-danger btn-remove">
                                        <i class="icon-remove"></i>
                                    </button>
                                </div>
                            </div>
                        </td>
                    </tr>
                </c:forEach> 
            </tbody>
        </table>
    </div>
</div>

<script>
    let empleadoResourceURL = '${empleadoResourceURL}';
</script>

main.js

function ajaxCall(data) {

    $.ajax({
        beforeSend : function() {
            /*showSpinner();*/
        },
        url: empleadoResourceURL,
        type: "POST",
        data: JSON.stringify(data),
        contentType: "json",
        success: function(data) {
            console.log("Respuesta de la solicitud: " + data);
            
            switch(data){
            
                case 'updateEmployee':
                    console.log('Empleado actualizado: OK');
                break;
            
            }   
        },
        error: function(xhr, status) {
            console.log("La solicitud ha fallado: " +  status);
        },
        complete: function(xhr, status) {
            /*hideSpinner();*/
        }
    });

}

$(document).ready(function(){
  
    $('#empleado-portlet .btn-actions').on('click','.btn-update',function() {
        var data = {};
        
        data.action = 'updateEmployee';
        data.selectedEmployee = $(this).attr('id');
        
        console.log(data);
        console.log('JSON.stringfy: ' + JSON.stringify(data));
        
        ajaxCall(data);
    });
  
});

MVC Resource Command

@Component(
    property = {
        "javax.portlet.name=" + EmpleadoPortletKeys.EMPLEADO,
        "mvc.command.name=empleado-resource",
        "javax.portlet.version=3.0"
    },
    service = MVCResourceCommand.class
)
public class EmpleadoResource extends BaseMVCResourceCommand{

    @Override
    public void doServeResource(ResourceRequest resourceRequest, ResourceResponse resourceResponse) throws Exception {
        System.out.println("I HAVE PASSED");
        
        ResourceParameters resourceParameters = resourceRequest.getResourceParameters();
        PrintWriter printWriter = resourceResponse.getWriter();
        
        //Alternative 1
        String action_1 = resourceParameters.getValue(EmpleadoPortletKeys.ACTION);
        System.out.println("ACTION_1: " + action_1);
        
        //Alternative 2
        String action_2 = ParamUtil.getString(resourceRequest, EmpleadoPortletKeys.ACTION);
        System.out.println("ACTION_2: " + action_2);
        
        printWriter.print(EmpleadoPortletKeys.ACTION_REMOVE_EMPLEADO);
        
    }

}

The problem

Once the portlet is deployed, the update button is selected in the table on the page.In the image below you can see through the browser console that the AJAX function makes the request and the response.

AJAX request/response

On the other hand, in the eclipse console, you can see that the MVC Resource Command "doServeResource" method is executed because it prints "I have passed" on the screen. However, the value of the "action" key is not obtained.

The first alternative prints "null" and the second alternative prints blank.

Eclipse IDE console

– Why can’t I get the json data from AJAX in MVC resource command?

– What am I doing wrong?

2

Answers


  1. Chosen as BEST ANSWER

    I will detail the steps I have taken to solve the problem. The second alternative proposed by @OlafKock detailed in the previous answer has been chosen, in addition to modifying the value of the data key of the AJAX function, data: JSON.stringify(data) to data: data.

    A code snippet will be provided below.

    Controller Portlet

    The following property has been added to the portlet controller:

    com.liferay.portlet.requires-namespaced-parameters=false

    The resulting code can be seen below.

    @Component(
        immediate = true,
        property = {
            "com.liferay.portlet.display-category=Demo",
            "com.liferay.portlet.header-portlet-css=/css/main.css",
            "com.liferay.portlet.footer-portlet-javascript=/js/main.js",
            "com.liferay.portlet.instanceable=true",
            "javax.portlet.display-name=Empleado",
            "javax.portlet.init-param.template-path=/",
            "javax.portlet.init-param.view-template=/view.jsp",
            "javax.portlet.name=" + EmpleadoPortletKeys.EMPLEADO,
            "javax.portlet.resource-bundle=content.Language",
            "javax.portlet.security-role-ref=power-user,user",
            "javax.portlet.version=3.0",
            "com.liferay.portlet.requires-namespaced-parameters=false"
        },
        service = Portlet.class
    )
    public class EmpleadoPortlet extends MVCPortlet {
        
        public void render(RenderRequest renderRequest, RenderResponse renderResponse) throws IOException, PortletException {
            
            List<Empleado> empleados = EmpleadoLocalServiceUtil.getEmpleados(-1, -1);
            
            renderRequest.setAttribute(EmpleadoPortletKeys.EMPLEADO_ID_TABLE_HEADER, EmpleadoPortletKeys.EMPLEADO_ID_TABLE_HEADER);
            renderRequest.setAttribute(EmpleadoPortletKeys.DNI_TABLE_HEADER, EmpleadoPortletKeys.DNI_TABLE_HEADER);
            renderRequest.setAttribute(EmpleadoPortletKeys.NOMBRE_TABLE_HEADER, EmpleadoPortletKeys.NOMBRE_TABLE_HEADER);
            renderRequest.setAttribute(EmpleadoPortletKeys.APELLIDOS_TABLE_HEADER, EmpleadoPortletKeys.APELLIDOS_TABLE_HEADER);
            renderRequest.setAttribute(EmpleadoPortletKeys.CARGO_TABLE_HEADER, EmpleadoPortletKeys.CARGO_TABLE_HEADER);
            renderRequest.setAttribute(EmpleadoPortletKeys.ACCIONES_TABLE_HEADER, EmpleadoPortletKeys.ACCIONES_TABLE_HEADER);
            renderRequest.setAttribute(EmpleadoPortletKeys.EMPLEADOS, empleados);
            
            super.render(renderRequest, renderResponse);
        }
        
    }
    

    main.js

    In the main.js file the value of the data key of the AJAX function has been modified.

    Before

    data: JSON.stringify(data)

    Current

    data: data

    The final code can be seen below.

    function ajaxCall(data) {
    
        $.ajax({
            beforeSend : function() {
                /*showSpinner();*/
            },
            url: empleadoResourceURL,
            type: "POST",
            data: data,
            contentType: "json",
            success: function(data) {
                console.log("Respuesta de la solicitud: " + data);
                
                switch(data){
                
                    case 'updateEmployee':
                        console.log('Empleado actualizado: OK');
                    break;
                
                }   
            },
            error: function(xhr, status) {
                console.log("La solicitud ha fallado: " +  status);
            },
            complete: function(xhr, status) {
                /*hideSpinner();*/
            }
        });
    
    }
    
    $(document).ready(function(){
      
        $('#empleado-portlet .btn-actions').on('click','.btn-update',function() {
            var data = {};
            
            data.action = 'updateEmployee';
            data.selectedEmployee = $(this).attr('id');
            
            console.log(data);
            
            ajaxCall(data);
        });
      
    });
    

    Additional information

    This issue has also been resolved by following a code template obtained from the following web page.


  2. My best guess: Portlet parameters typically need to be namespaced, so that it’s obvious, to which portlet they are targeted. (e.g. in a JSP, prepend <portlet:namespace/> to the parameter name)

    If you don’t want to do this this, you can either add the com.liferay.portlet.requires-namespaced-parameters=false property to your portlet, or you can access the raw HttpServletRequest for the raw parameter value (not recommended).

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search