get HttpServletResponse from liferay portal - jsf

I am trying to get the HttpServletResponse from liferay portal. I am also working with icefaces.
PortletResponse response1 = (PortletResponse)FacesContext.getCurrentInstance().getExternalContext().getResponse();
HttpServletResponse response = (HttpServletResponse)response1;
I get the following Exception:
Caused by: java.lang.ClassCastException: com.liferay.portlet.RenderResponseImpl cannot be cast to javax.servlet.http.HttpServletResponse

Try PortalUtil.getHttpServletResponse(portletResponse)

May be this Helps
Generate PDF File in Portlet

FacesContext will return PortletRequest/Response objects if you are using the portlet bridge.
What are you trying to do with the HttpServletResponse?
If you are trying to generate binary content, this will only work in the Resource phase of a JSR 286 portlet (otherwise you cannot set headers). It will never work in a JSR 168 portlet. If you need to do this in a JSR 168 portlet, you need to use a helper servlet.
In any case, if you are trying to use a third party lib that requires HttpServletResponse for its API, you can use a PortletRequestDispatcher to dispatch to a JSP or a servlet and then use the HttpServletResponse that is available to you there.

Try getting the native response and then casting it:
FilterServletResponseWrapper filterResponse = (FilterServletResponseWrapper) RequestContextHolder.getRequestContext().getExternalContext().getNativeResponse();
HttpServletResponse response = (HttpServletResponse)filterResponse.getResponse();

Related

HttpSession is null (randomly) when retrieved from HttpServletRequest using ExternalContext

I have following code to retrieve HttpSession from HttpServletRequest using ExternalContext in our Icefaces(1.8.2) & JSF(1.2) based Liferay environment :
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
HttpServletRequest httpServletRequest = (HttpServletRequest) (externalContext.getRequestMap().get("com.liferay.portal.kernel.servlet.PortletServletRequest");
HttpSession httpSession = httpServletRequest.getSession();
The above code snippet is working fluently for Liferay 6_1_0_CE_GA1 as httpSession is always populated.
But, the same code in Liferay 6_2_1_CE_GA2, I am randomly getting httpSession as null. Couldn't figure out, what the difference can be!
I have also, tried to get httpServletRequest using PortalUtil.getOriginalServletRequest and then getting httpSession from it, but that doesn't resolve the issue.
When I need access to HttpServletRequest from a Liferay portlet, I have to use this:
HttpServletRequest httpServletRequest = PortalUtil.getOriginalServletRequest(PortalUtil.getHttpServletRequest(renderRequest));
renderRequest is an object extended from the PortletRequest class. From your code, you can get the PortletRequest object this way:
PortletRequest portletRequest = (PortletRequest) externalContext.getRequest();
So, the resulting code should be:
PortletRequest portletRequest = (PortletRequest) externalContext.getRequest();
HttpServletRequest httpServletRequest = PortalUtil.getOriginalServletRequest(PortalUtil.getHttpServletRequest(portletRequest));
Hope this helps. Regards!
First of all: Please also try this on 6.2 GA6, which is out for a month now. In case this is a bug it might already be fixed during one of the later versions - the version you're using is almost 2 years old now.
Further, there's nothing that I'm aware of in the specification that allows access to the underlying HttpServletRequest. That's not to say that this is impossible (because it obviously is possible) but to say that behaviour might change, because you're outside of the specs.
I'd recommend to inspect the objects you get with a debugger and check if they're wrappers around the original servlet container's request or the actual container's objects. Also, compare if these requests are directed to the portal (check the URL) or to the portlet itself - as they're deployed in different contexts, they'll have different sessions (or one might have sessions while the other doesn't)

Liferay Portlet Response: how to set status code?

I have a simple method accepting PortletResponse and PortletRequest in my liferay portlet
public void remove(PortletResponse response, PortletRequest request) {
}
I want to set response status to 404, like I can do with HttpServletResponse by httpResponse.sendError(HttpServletResponse.SC_BAD_REQUEST)
Can you tell me how I can do it?
What does Portlet Specification 2.0 have to say - you can set the response status only when handling resource request:
If the portlet want to set a response status code it should do this
via setProperty with the key ResourceResponse.HTTP_STATUS_CODE.
That means, you can set the response status code this way when serving resources:
resourceResponse.setProperty(ResourceResponse.HTTP_STATUS_CODE,
Integer.toString(HttpServletResponse.SC_BAD_REQUEST));
With Liferay, you can get instance of the underlying HttpServletResponse and set status code there. The portal will return it to the client. This way, you can set the response status for any portal request, not only resource request.
HttpServletResponse httpServletResponse = PortalUtil.getHttpServletResponse(portletResponse);
httpServletResponse.setStatus(HttpServletResponse.SC_BAD_REQUEST);
However, such practice is strongly discouraged as well explained in Olaf Kock's answer. See it to get the bigger picture.
In addition to Tomas Pinos' answer (please accept his answer): Note that a portlet is never delivered directly by an HttpServletRequest - it's embedded in a page which is generated by the portal. Thus the HTTP response codes don't have any meaning (for portlets) in the portal world: The page might still be there, just contain or not contain the portlet in question - it's the business of the portal to show whatever it likes then.
The only exception to this rule is what Tomas describes correctly: When handling a resource request, you're serving exclusive content - thus you have the option to do more to the request than just piping HTML that would otherwise be embedded in a page generated by someone else (the portal, together with other unknown portlets)

Writing plain HTML in a JSF based web application

I have this use case in a JSF application.
Supposed in a JSF web application, I have a button that calls an external service that returns a complete HTML response then how can I show that HTML response to my users browsers?
The sequence of events are like this.
In user browser, my application is displayed. A button is there that user can click.
Clicking the button will call an external service. The external service will return information about a certain HTML tags. The HTML is complete with both head/body and with javascript. Currently the service can be implemented thru REST service or a plain DB call then
How can I display that HTML tag in my user browser?
Is this possible to write non-JSF output in a JSF web application?
Just to add, I think my problem is how to write an HTML in my backing bean and write it back to the users browser.
Just write it outright to the HTTP response body whereafter you instruct JSF that the response is manually completed. The principle is not much different from How to provide a file download from a JSF backing bean?, except that you need to set content disposition to inline (which is already the default anyway).
public void writeHtmlResponse() throws IOException {
FacesContext fc = FacesContext.getCurrentInstance();
ExternalContext ec = fc.getExternalContext();
ec.setResponseContentType("text/html;charset=UTF-8");
ec.setResponseCharacterEncoding("UTF-8");
ec.getResponseOutputStream().write(html.getBytes("UTF-8"));
fc.responseComplete(); // Important! Otherwise JSF will attempt to render the response which obviously will fail since it's already written with a file and closed.
}

Error Rendering View: java.lang.IllegalStateException: getOutputStream() has already been called for this response

I am creating a project in JSF and spring whose main only purpose is to generate PDF file in the browser. Everything seems fine and pdf generated too but on console i am getting this exception.Anyone have idea about this? I have searched and found that many peoples had that problem but i didn't find any solution for mine one.
SEVERE: Error Rendering View[/WebPages/SearchPages/index.xhtml]
java.lang.IllegalStateException: PWC3991: getOutputStream() has already been called for this response
I am getting this error while creating my outputstream object
HTTPServletResponse response = (HTTPServletResponse)FacesContext.getCurrentInstance().getExternalContext().getResponse();
ServletOutputStream out = response.getOutputStream();
Is there any problem while my creation or anyother reason? Any help would be greatly appreciable
You need to tell JSF that you've already completed the HTTP response yourself, otherwise JSF will still continue doing the default RENDER_RESPONSE job after the action method is finished, which would result in exactly this exception, because the response is already committed.
You can do that by calling FacesContext#responseComplete() in the action method.
responseComplete
public abstract void responseComplete()
Signal the JavaServer Faces implementation that the HTTP response for this request has already been generated (such as an HTTP redirect), and that the request processing lifecycle should be terminated as soon as the current phase is completed.
See also:
How to provide a file download from a JSF backing bean?

JSF PhaseListener viewId always one behind

Im trying to prevent users to access special pages with a phaselistener. for that reason im trying to figure out on which page they try to access.
but my problem is, i only get the page they where before. not the actual page.
public void afterPhase(PhaseEvent event)
{
FacesContext fc = event.getFacesContext();
System.out.println("test1" + fc.getViewRoot().getViewId());
}
and same here
public void afterPhase(PhaseEvent event)
{
FacesContext fc = event.getFacesContext();
HttpServletRequest request = (HttpServletRequest) fc.getExternalContext().getRequest();
String uri = request.getRequestURI();
System.out.println("uri: " + uri);
}
why is that, and how do i get the pagename the user is trying to access? Not that one that they required one step before, or better the page they are coming from.
It is one step behind because that is the way sequence of HTTP POST request behaves. When you are navigating in JSF application via command buttons each request goes as a post request.
Since you are protecting some resources make sure they are accessed via HTTP GET than you will get exact view id, this can be achieved as
User directly hits the url from address bar of browser.
After a post of jsf app redirect it to the resource instead of simple JSF navigation. POST-REDIRECT-GET pattern falls into this have a look here.
If you are showing some messages after each POST, you might need Flash map for that, which is new feature in JSF2, if you are on JSF1.x hard luck, you can implement flash if you want to.
To conclude catch the view ids on HTTP GET request.
Hope this helps...

Resources