Wednesday, February 24, 2016

Modify / Add Request parameter values in Liferay

Generally request parameter values are immutable once the request process is started. Some time we may get some requirement that force you to add or modify the request parameter values. Assume scenario once we submit the form to the controller we would like to modify or add the parameter values before it reach the controller.

Http Servlet Request Wrapper is the way to modify the request parameter values. We will use Http Servlet Request Wrapper with servlet filter combination so that we can modify or add new parameter values.

Example Scenario

Assume the example scenario that when user login into the Liferay portal before it reach struts controller we would like to change the redirect parameter value.

Note:

This just scenario I chosen to explain the concept.
We will use Http Servlet Request Wrapper with servlet filter combination to achieve this concept. In Liferay we will use Hook plugin to implement the concept.

In Liferay login mechanism when user submit the user name and password then it will submitted to /login/login struts controller path. Before it reach struts controller (LoginAction.java) we would like to change the redirect parameter value in the filter using Http Servlet Request Wrapper concept.

Steps to Implementation
  1. Create Liferay Hook
  2. Create Custom Http Servlet Request Wrapper
  3. Create Servlet Filter Class and modify the request parameter values
  4. Configure Servlet Filter in liferay-hook.xml
  5. Configure Struts path in liferay-hook.xml
  6. Create Struts Action Hook for Login Action and observe the modified parameter value

Create Liferay Hook

Creating hook using Liferay IDE is very straight forward way and its easy. Follow below articles to create Liferay hook plugin.


Create Custom Http Servlet Request Wrapper

We need to create custom Http Servlet Request Wrapper and the following is custom Http Servlet Request Wrapper. This class is responsible for modify or add request parameters.


package com.liferaysavvy.requestwrapper;

import java.util.Collections;
import java.util.Enumeration;
import java.util.Map;
import java.util.TreeMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

public class AddModifyRequestParamValueWrappedRequest extends HttpServletRequestWrapper
{
private final Map<String, String[]> modifiableParameters;
private Map<String, String[]> allParameters = null;

/**
* Create a new request wrapper that will merge additional parameters into
* the request object without prematurely reading parameters from the
* original request.
*
* @param request
* @param additionalParams
*/
public AddModifyRequestParamValueWrappedRequest(final HttpServletRequest request,
final Map<String, String[]> additionalParams)
{
super(request);
modifiableParameters = new TreeMap<String, String[]>();
modifiableParameters.putAll(additionalParams);
}

@Override
public String getParameter(final String name)
{

String[] strings = getParameterMap().get(name);
if (strings != null)
{
return strings[0];

}

return super.getParameter(name);
}

@Override
public Map<String, String[]> getParameterMap()
{
if (allParameters == null)
{
allParameters = new TreeMap<String, String[]>();
allParameters.putAll(super.getParameterMap());
allParameters.putAll(modifiableParameters);
}
//Return an unmodifiable collection because we need to uphold the interface contract.
return Collections.unmodifiableMap(allParameters);
}

@Override
public Enumeration<String> getParameterNames()
{
return Collections.enumeration(getParameterMap().keySet());
}

@Override
public String[] getParameterValues(final String name)
{
return getParameterMap().get(name);
}
}


Create Servlet Filter Class and modify the request parameters

Now we will implement servlet filter and we will Custom Servlet Request Wrapper to modify parameter values or we can also add new parameters. Once request parameters are modifies then we will give this object to doFilter(--) method to do subsequent process.


package com.liferaysavvy.requestwrapper;

import java.io.IOException;
import java.util.Map;
import java.util.TreeMap;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.util.ParamUtil;

public class ChangeRequestParamFilter implements Filter {

@Override
public void destroy() {
logger.info("ChangeRequestParamFilter");
}

@Override
public void doFilter(ServletRequest servletRequest,
ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {

logger.info("inside ChangeRequestParamFilter doFilter ");
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;

/*Getting actual Redirect Param Value*/
String actuallRedirectValue = ParamUtil.getString(httpServletRequest,"redirect");
logger.info("Actual Redirect Param Value:" + actuallRedirectValue);

/* Modifying redirect param value and also adding new parameter to request object*/
Map<String, String[]> modifyAddParamValueMap = new TreeMap<String, String[]>();
String[] redirectParamArray = new String[1];
redirectParamArray[0] = "http://localhost:8080/web/guest/custom-portlet-workflow";
modifyAddParamValueMap.put("redirect", redirectParamArray);
modifyAddParamValueMap.put("newParam",new String[]{"Hello I am New Param value"});
HttpServletRequest wrappedRequest = new AddModifyRequestParamValueWrappedRequest(
httpServletRequest, modifyAddParamValueMap);
filterChain.doFilter(wrappedRequest, servletResponse);
}

@Override
public void init(FilterConfig filterConfig) {

logger.debug("Called ChangeRequestParamFilter init(" + filterConfig + ")");
}

private static final Log logger = LogFactoryUtil
.getLog(ChangeRequestParamFilter.class);

}


Configure Servlet Filter in liferay-hook.xml

Use following configuration in liferay-hook.xml file


<servlet-filter>
<servlet-filter-name>ChangeRequestParamFilter</servlet-filter-name>
<servlet-filter-impl>com.liferaysavvy.requestwrapper.ChangeRequestParamFilter</servlet-filter-impl>
<init-param>
<param-name>hello</param-name>
<param-value>world</param-value>
</init-param>
</servlet-filter>
<servlet-filter-mapping>
<servlet-filter-name>ChangeRequestParamFilter</servlet-filter-name>
<url-pattern>/web/guest/home/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</servlet-filter-mapping>


Note:

From the above configuration Filter will be execute when we request server with /web/guest/home/* path.

Configure Struts path in liferay-hook.xml

We are going to see resulted values in Custom Login Action struts action for /login/login path so we need to configure the path in liferay-portlet.xml file.


<struts-action>
<struts-action-path>/login/login</struts-action-path>
<struts-action-impl>com.liferaysavvy.requestwrapper.CustomLoginStrutsPortletAction</struts-action-impl>
</struts-action>


Create Struts Action Hook for Login Action and observe the modified parameter value

Finally we will see the modified or newly added parameter values in Custom Login Action Struts action class.


package com.liferaysavvy.requestwrapper;

import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.PortletConfig;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.ResourceRequest;
import javax.portlet.ResourceResponse;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;

import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.struts.BaseStrutsPortletAction;
import com.liferay.portal.kernel.struts.StrutsPortletAction;
import com.liferay.portal.kernel.util.ParamUtil;
import com.liferay.portal.util.PortalUtil;

public class CustomLoginStrutsPortletAction extends BaseStrutsPortletAction {

@Override
public void processAction(StrutsPortletAction originalStrutsPortletAction,
PortletConfig portletConfig, ActionRequest actionRequest,
ActionResponse actionResponse) throws Exception {
ServletRequest servletRequest = PortalUtil.getOriginalServletRequest(PortalUtil.getHttpServletRequest(actionRequest));
String modifiedRedirectValue = servletRequest.getParameter("redirect");
String newParamValue = servletRequest.getParameter("newParam");
logger.info("Modified Redirect Value:"+modifiedRedirectValue);
logger.info("Nee Parameter Value:"+newParamValue);
originalStrutsPortletAction.processAction(portletConfig, actionRequest,
actionResponse);
}

@Override
public String render(StrutsPortletAction originalStrutsPortletAction,
PortletConfig portletConfig, RenderRequest renderRequest,
RenderResponse renderResponse) throws Exception {
return originalStrutsPortletAction.render(portletConfig, renderRequest,
renderResponse);
}

@Override
public void serveResource(StrutsPortletAction originalStrutsPortletAction,
PortletConfig portletConfig, ResourceRequest resourceRequest,
ResourceResponse resourceResponse) throws Exception {

originalStrutsPortletAction.serveResource(portletConfig,
resourceRequest, resourceResponse);
}


private static Log logger = LogFactoryUtil
.getLog(CustomLoginStrutsPortletAction.class);
}


Observation

Deploy hook into Liferay portal server

Drag and Drop Liferay sign in portlet in home page

Site page URL should be as follows http://localhost:8080/web/guest/home

The following screen shows home page with sign in portlet



I have used /web/guest/home is filter path that is why Sign In portlet should be placed into home page so that filter will be executed when you login into portal.

Once you have done sign in process in Liferay portal then filter gets called and we can see redirect param value is empty later Custom Login Action will be executed there you can see redirect value that is modified in the filter. These are all will be printed in the server console.

This how we can observed modified parameter values in Login Action class.

Server Console


20:52:30,377 INFO  [http-bio-8080-exec-159][ChangeRequestParamFilter:31] inside ChangeRequestParamFilter doFilter
20:52:30,378 INFO  [http-bio-8080-exec-159][ChangeRequestParamFilter:36] Actual Redirect Param Value:
20:52:30,396 INFO  [http-bio-8080-exec-159][CustomLoginStrutsPortletAction:29] Modified Redirect Value: http://localhost:8080/web/guest/custom-portlet-workflow
20:52:30,396 INFO  [http-bio-8080-exec-159][CustomLoginStrutsPortletAction:30] New Parameter Value: Hello I am New Param value


Server Console




Note:

I just showed this example to understand how to modify or add new parameters in request object. This may or may not be the real time scenario but we can understand the concept from the example.


Author

Recent Posts

Recent Posts Widget

Popular Posts