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.
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.
– Why can’t I get the json data from AJAX in MVC resource command?
– What am I doing wrong?
2
Answers
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:
The resulting code can be seen below.
main.js
In the main.js file the value of the data key of the AJAX function has been modified.
Before
Current
The final code can be seen below.
Additional information
This issue has also been resolved by following a code template obtained from the following web page.
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).