The getOriginalRequest and getOriginalResponse methods return generic Object instances on purpose because we can't really know the details of what the request is going to look like beforehand. We've made it broad like this on purpose because each container handles it differently. So when you use getOriginalRequest, you could get something that's a PortletRequest, an HttpServletRequest, or even both APIs at the same time. How to handle the result is currently in the app developer's hands and corresponds to the container/version that they are running on.
In Liferay's case, it does indeed return a PortletRequest but the request does not implement the HttpServletRequest contract. It does provide a public method on the implementation to get at the raw HttpServletRequest. So you either have to use Liferay specific APIs or reflection to get at it. Here's a more detailed example for Liferay 6. If the original request is not an HttpServletRequest (which is perfectly valid) we can use reflection to get at the underlying HttpServletRequest through a Liferay API.
public Object getOriginalRequest(){
BridgeExternalContext bec = getBridgeExternalContext();
if( bec == null )
{
System.out.println("TestBean.getOriginalRequest: not BridgeExternalContext ");
return "[not a BridgeExternalContext]";
}
Object originalReq = bec.getOriginalRequest();
System.out.println("originalReq = " + originalReq);
if( originalReq instanceof HttpServletRequest)
{
//If the original request is already an HttpServletRequest, we're done. This is how certain
//portal containers implement their requests - as both PortletRequest and HttpServletRequests.
System.out.println("TestBean.getOriginalRequest: original request is HttpServletRequest");
return originalReq;
}
//Liferay does it differently. Using reflection, we can try and get/invoke the specific Liferay method
//that returns the raw HttpServletRequest.
try {
Method getHttpServletRequestMethod = originalReq.getClass().getMethod("getHttpServletRequest",null);
Object httpRequest = getHttpServletRequestMethod.invoke(originalReq,null);
if( httpRequest != null && httpRequest instanceof HttpServletRequest)
{
System.out.println("TestBean.getOriginalRequest: request from reflection = " + httpRequest);
return (HttpServletRequest)httpRequest;
}
} catch (Exception e)
{
e.printStackTrace();
}
//There may be other ways to get at the original HttpRequest depending on the portal vendor,
//the version, what APIs they expose, etc. They would need to be investigated individually.
return originalReq;
}
I've checked in a fix that allows developers access to the original request and response instances provided by the portlet or servlet container. The way to access this feature works something like this:
public HttpServletRequest getRequest(){
FacesContext fc = FacesContext.getCurrentInstance();
ExternalContext ec = fc.getExternalContext();
if( ec instanceof BridgeExternalContext ){
//The ICEfaces implementation of ExternalContext
BridgeExternalContext bec = (BridgeExternalContext)ec;
//BridgeExternalContext has two new methods:
// getOriginalRequest()
// getOriginalResponse()
Object originalReq = bec.getOriginalRequest();
//The implemenation returned here is container specific but will
//be an instance of HttpServletRequest or PortletRequest
//or, sometimes, both.
if( originalReq instanceof HttpServletRequest)
{ return (HttpServletRequest)originalReq; }PortletRequest portletReq = (PortletRequest)originalReq;
//Again, depending on the container, getting the HttpServletRequest
//from the PortletRequest is likely to be specific to the platform.
//For example on WebLogic Portal this could do the trick:
portletReq = (PortletRequest) portletReq.getAttribute("javax.portlet.request");
return (HttpServletRequest) portletReq.getAttribute("javax.servlet.request");
}
//If not ICEfaces, then just do it the plain JSF way.
return (HttpServletRequest)ec.getRequest();
}
I tested this on Liferay as well as WebLogic Portal 1.0.3 and WebSphere Portal 6.1 and it appears to do the trick. I made an effort to ensure that the references to the original request and response are not retained in the requestMap when the BridgeExternalContext is released as this previously caused memory issues.