1
votes

I'm working with portlets and was working through the sample on liferay's wiki: https://www.liferay.com/documentation/liferay-portal/6.1/development/-/ai/writing-the-my-greeting-portl-4

I'm having some issues with the portlet redirecting back to the init jsp after processing a form. My Java class is:

import java.io.IOException;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.PortletException;
import javax.portlet.PortletPreferences;
import com.liferay.util.bridges.mvc.MVCPortlet;

public class Directory extends MVCPortlet {

    @Override
    public void processAction(
        ActionRequest actionRequest, ActionResponse actionResponse)
        throws IOException, PortletException {
        PortletPreferences prefs = actionRequest.getPreferences();
        String greeting = actionRequest.getParameter("greeting");

        if (greeting != null) {
            prefs.setValue("greeting", greeting);
            prefs.store();
        }

        super.processAction(actionRequest, actionResponse);
    }
}

I have two jsps. view.jsp:

<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
<%@ page import="javax.portlet.PortletPreferences" %>

<portlet:defineObjects />

<%
PortletPreferences prefs = renderRequest.getPreferences();
String greeting = (String)prefs.getValue(
"greeting", "Hello! Welcome to our portal.");
%>

<p><%= greeting %></p>

<portlet:renderURL var="editGreetingURL">
   <portlet:param name="mvcPath" value="/edit.jsp" />
</portlet:renderURL>

<p><a href="<%= editGreetingURL %>">Edit greeting</a></p>

And edit.jsp:

<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
<%@ taglib uri="http://liferay.com/tld/aui" prefix="aui" %>

<%@ page import="com.liferay.portal.kernel.util.ParamUtil" %>
<%@ page import="com.liferay.portal.kernel.util.Validator" %>
<%@ page import="javax.portlet.PortletPreferences" %>

<portlet:defineObjects />

<%
    PortletPreferences prefs = renderRequest.getPreferences();
    String greeting = (String)prefs.getValue(
    "greeting", "Hello! Welcome to our portal.");
%>

<portlet:actionURL var="editGreetingURL">
 <portlet:param name="mvcPath" value="/edit.jsp" />
</portlet:actionURL>

<aui:form action="<%= editGreetingURL %>" method="post">
    <aui:input label="greeting" name="greeting" type="text 
       value="<%=greeting%>
    <aui:button type="submit" />
</aui:form>

<portlet:renderURL var="viewGreetingURL">
    <portlet:param name="mvcPath" value="/view.jsp" />
</portlet:renderURL>

<p><a href="<%= viewGreetingURL %>">&larr; Back</a></p>

On the form submit of the edit.jsp, it's supposed to re-render that page. When I just use portlet:renderUrl instead of portlet:actionUrl, it does it correctly, but actionUrl isn't re-rendering. The tutorial says that it IS supposed to render edit.jsp again, so I'm not sure what I'm missing. Note: It is saving all my parameters correctly.

1
Are you using Liferay 6.1 or Liferay 6.2? And what happens instead of rendering edit.jsp? It returns to view.jsp, right?Andrea Di Giorgi
We are using Liferay 6.1.2. Yes, it returns to view.jsp. I added the code actionResponse.setRenderParameter("mvcPath","/edit.jsp") to my java class, which directed it correctly, but that still doesn't seem like the right way to do it. my init parameter in portlet.xml is the view.jsp, so it's almost like it's re-initializing the whole portlet.jordaniac89

1 Answers

3
votes

According to the JSR 286 (aka Portlet Specification 2.0), PLT.11.1.1.2:

The portlet-container must not propagate parameters received in an action or event request to subsequent render requests of the portlet.

This is what happens when the user clicks the Submit button on the browser page:

  1. The browser sends an Action request to Liferay, which contains, as its parameters, "name" and "mvcPath".
  2. The portlet is now in Action phase, and so it executes the processAction method.
  3. When the processAction method terminates without errors, Liferay is still responding to the Action request and the browser is still waiting for a response, which will be the HTML of the current page.
  4. Because Liferay now has to respond the browser with the HTML of the page, it calls the render method for every portlet in page. That is, if makes a Render request to these portlets.
  5. For your portlet, which is a MVCPortlet, the render method reads the "mvcPath" parameter to find out which JSP page it has to render.

But now, the JSR 286 says that there's no parameter passing between the Action and the Render phases, so the mvcPath, which was part of the Action request, is not copied by Liferay to the Render request that Liferay makes to your portlet.

Now, solutions:

  • As you suggested, at the end of the processAction method (but usually you don't change the processAction method, instead you create different methods for different actions, they'll tell you how to do in the tutorials... have a look to http://dev.liferay.com), you can set actionResponse.setRenderParameter("mvcPath","/edit.jsp"). This is perfectly normal.
  • If you want that your Action parameters are always copied to the subsequent Render request that Liferay makes to your portlet, you can set the copy-request-parameters init parameter to true (have a look here)
  • But you'll see that usually Liferay portlets go back to the view after executing an "edit" action (passing a "redirect" parameter in the Action request), so it's up to you.

Sorry, there's a lot to say about this subject, hope what I wrote can be useful to you!