Thursday, May 31, 2007

A simple way to make DWR able to see portlet session

Note: If you are running tomcat 5.5, there is way to configure tomcat 5.5 that will allow sharing session between portlet and servlet, google for "emptySessionPath".

If you are still interesting, then read on.

DWR is a servlet that normally not able to see portlet session when running in portal. The reason is the way use dwr in jsp page:
<script src="/myapp/dwr/interface/dwrTest.js"></script>

Because it goes to "/myapp" directly and by pass the usual "/portal" context, then all java code invoked by dwr won't able to see the portlet session.

One solution I found is to override the dwr internal javascript variable "_path" to a portlet path, then in the portlet, reassemble the request path and invoke the dwr servlet within the portlet.

Original dwr path:
/myapp/dwr/exec/dwrTest.getZipcode

Modified dwr path which will invoke dwr within portal:
/portal/xxxx-portal-specified-param&servletName=dwr& execName=/exec/dwrTest.getZipcode


Here is a sample that I created for Vignette 7.x portal runs in tomcat 5.

First, create a jsp page to be included by other jsp that use DWR.

sample DwrPortlet.jsp (partial listing)
....
//1. create a portlet url that points to the portlet that invoke the dwr
<portlet:renderurl var="dwrPortletUrl" windowstate="RAW">
<portlet:param name="servletName" value="/dwr">
</portlet:param>

//2. over ride the internal _path to point to the portlet
<script><br /> var dwrPortletPath = "${dwrPortletUrl}";<br /> if (window.dwrTest) {dwrTest._path = dwrPortletPath ;}<br /></script>

//3. must use post and iframe method
if (window.DWREngine) { DWREngine._verb = "POST";DWREngine._method = DWREngine.IFrame; }

===== end sample DwrPortlet.jsp ====</portlet:renderurl>


Now in your portlet java code, do this to invoke the dwr:
String servletName = (String)request.getParameter("servletName");
if (StringUtils.isNotBlank(servletName)) {
if ("/dwr".equals(servletName)) {
servletName = servletName + request.getParameter("execName");
}
request.getPortletSession().getPortletContext(). getRequestDispatcher(servletName).include(request, response);
}


In the dwr code i.e. the DwrTest.java, use this code to get the portlet request or response:

PortletRequest portletRequest = (PortletRequest)WebContextFactory.get().getHttpServletRequest(). getAttribute("javax.portlet.request");