3

my intention is to process a ResourceRequest that serves a resource (A dinamically generated PDF). If something goes wrong generating this file, the whole portal with a failure message in the portlet should be rendered.

Is it possible to forward a ResourceRequest to a request that renders the complete portal? I am also considering a redirect, but I will like to be able to pass some attributes/parameters along.

I hope I explained my problem clear enough. Thank you.

Related/Duplicate: How to make the ResourceResponse to forward the request to error page in liferay portlet

Example

This is an example that works and does something similar to what I want to achieve. I uses the utility class SessionErrors of Liferay: The serveResource() saves an object in the session and does a redirection to a render URL. The doView() method is called during the subsequent request and can read the contents saved in the session.

import com.liferay.portal.kernel.servlet.SessionErrors;
import javax.portlet.GenericPortlet;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.ResourceRequest;
import javax.portlet.ResourceResponse;
import javax.portlet.PortletException;
import javax.portlet.PortletException;
import javax.portlet.PortletRequestDispatcher;

public class ResourceRequestForwardPortlet extends GenericPortlet {

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

        SessionErrors.add(resourceRequest, "resourcerequest.error", "ERROR " + errorText);

        resourceResponse.setProperty(ResourceResponse.HTTP_STATUS_CODE, "302");
        resourceResponse.addProperty("Location", resourceResponse.createRenderURL().toString());
    }

    public void doView(RenderRequest renderRequest, RenderResponse renderResponse)
        throws IOException, PortletException {

        String error = (String)SessionErrors.get(renderRequest, "resourcerequest.error");
        SessionErrors.clear(renderRequest);
            
        renderRequest.setAttribute("errorMsg", error);

        PortletRequestDispatcher portletRequestDispatcher = getPortletContext().getRequestDispatcher("view.jsp");
        include(viewTemplate, renderRequest, renderResponse);
        portletRequestDispatcher.include(renderRequest, renderResponse);
    }
}

What I want to achieve is the same, but preventing the browser from doing two requests. For that, I would like to do a forward and I should write the error message as a request attribute.

I uploaded a project with this example to GitHub: https://github.com/adrianrm/poc-forward-portlet/tree/master/src/main/java/arm/requestforward

Community
  • 1
  • 1
AdrianRM
  • 2,622
  • 2
  • 25
  • 42
  • Did you manage to find a solution? – Maciej Ziarko Oct 17 '12 at 08:03
  • Nothing. I think we used a workaround in which an ActionRequest is sent, and, if successful, the shown page triggers the download with Javascript. – AdrianRM Oct 23 '12 at 10:05
  • 1
    `ResourceRequest` is used mostly with ajax. So to refresh the whole portal is not the job of `ResourceRequest`, at best you can display a failure message in your portlet through ajax if that is what you want to do. Or else you can return some flag to trigger a refresh on the whole portal through javascript. – Prakash K Dec 12 '12 at 09:31
  • OK, but if ResourceRequest is to be used only with Ajax, is there an alternative way to produce a dynamic download from a portlet? --> http://stackoverflow.com/questions/13862722/produce-a-dynamic-download-from-a-portlet – AdrianRM Dec 13 '12 at 15:10
  • Can you use the ResourceResponse.createRenderUrl() method and pass in a url that will map to a render method?http://portlet-container.java.net/apidocs/portlet2/javax/portlet/ResourceResponse.html#createRenderURL%28%29 – Victor Apr 15 '13 at 03:09

1 Answers1

0

The following is an attempt to do it using a servlet forward, and it seems to work. Still, I think it is a workaround for a feature not present in the portlet specification:

public class ResourceRequestForwardPortlet extends GenericPortlet {

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

        HttpServletRequest request = PortalUtil.getOriginalServletRequest(PortalUtil.getHttpServletRequest(portletRequest));
        PortletURL renderURL = portletResponse.createRenderURL();
        try {
            request.setAttribute("error", errorText);

            String forwardURL = renderURL.toString().replace("http://localhost:8080", "");//The generation of the forwardURL could be done nicer
            RequestDispatcher rd = request.getRequestDispatcher(forwardURL);
            rd.forward(request, PortalUtil.getHttpServletResponse(portletResponse));
        } catch (ServletException e) {
            throw new PortletException(e);
        }
    }
}

On top of that, when the forward occurs, Liferay shows a warning on the console:

14:33:51,048 WARN  [http-apr-8080-exec-112][code_jsp:128] {code="404", msg="/poc-forward-portlet/web/guest/home", uri=/web/guest/home}
X-Requested-With null
AdrianRM
  • 2,622
  • 2
  • 25
  • 42