Forums de discussion

Calling a servlet in JSF

Gaurav Sharma, modifié il y a 11 années.

Calling a servlet in JSF

Junior Member Publications: 39 Date d'inscription: 01/11/12 Publications récentes
I have a JSF portlet and I'd like to point to a servlet. How would I generate the link to it?
thumbnail
Neil Griffin, modifié il y a 11 années.

RE: Calling a servlet in JSF

Liferay Legend Publications: 2655 Date d'inscription: 27/07/05 Publications récentes
You can call PortalUtil.getPortalURL() and then append PortletRequest.getContextPath() in order to get a URL to the webapp context. After than you can append the servlet-mapping in order to invoke the servlet.

However, I would recommend that you consider writing a JSF2 ResourceHandler rather than a servlet. Could you provide a description of your use-case? Are you trying to generate an image or something like that?
Gaurav Sharma, modifié il y a 11 années.

RE: Calling a servlet in JSF

Junior Member Publications: 39 Date d'inscription: 01/11/12 Publications récentes
I'm actually integrating with Pentaho. I'm using the API that Pentaho provides to dynamically generate a report in PDF, HTML or Excel format. I'm then displaying this report in an iFrame in a portlet.

To dynamically choose the report and report type(PDF, HTML, etc) I'm using JSF. To generate the actual report, I'm using a servlet. That's the best way I could think of for the job. If you have a better suggestion, I'd really appreciate it.
thumbnail
Neil Griffin, modifié il y a 11 années.

RE: Calling a servlet in JSF (Réponse)

Liferay Legend Publications: 2655 Date d'inscription: 27/07/05 Publications récentes
Hitting a servlet is fine, but the problem is that it bypasses the portal and therefore operates outside the portlet lifecycle. So it's very difficult to get the servlet to be able to participate in the security/permissions system offered by the portal, and impossible to get access to portal objects like ThemeDisplay, etc.).

The Portlet 2.0 way of delivering up dynamic binary content would be to use a <portlet:resourceURL> to invoke a RESOURCE_PHASE of the portlet lifecycle. So at a minimum I would recommend that, which could be done by extending GenericFacesPortlet.

But the JSF 2 + Portlet 2 way of doing this would be to use a JSF 2 ResourceHandler. It's really nice because the bridge provides a JSF way of invoking the RESOURCE_PHASE without the page author knowing if the code is for a webapp or a portlet. We have some examples of how to do this if you are interested.
Gaurav Sharma, modifié il y a 11 années.

RE: Calling a servlet in JSF

Junior Member Publications: 39 Date d'inscription: 01/11/12 Publications récentes
I'd prefer to do it the JSF2 + Portlet way, but could not find any articles in my quick google search. Any examples would be appreciated.
Gaurav Sharma, modifié il y a 11 années.

RE: Calling a servlet in JSF

Junior Member Publications: 39 Date d'inscription: 01/11/12 Publications récentes
I'm looking at http://www.primefaces.org/showcase/ui/dynamicImage.jsf. Is this what you mean?
thumbnail
Neil Griffin, modifié il y a 11 années.

RE: Calling a servlet in JSF

Liferay Legend Publications: 2655 Date d'inscription: 27/07/05 Publications récentes
Actually no, the p:graphicImage component has a vendor-specific PrimeFaces feature that is not based on a ResourceHandler.

I would recommend that you look at the source code for the jsf2-export-pdf-portlet demo. The following files show how to develop a JSF2 ResourceHandler mechanism for serving up a PDF:

Also, the customers.xhtml composition shows how to generate a JSF 2 URL that the bridge will automatically convert into a Portlet 2.0 ResourceURL:

<h:outputlink target="_blank" value="#{customer.exportResourceURL}">
	<h:outputtext value="#{i18n['export']}" />
</h:outputlink>
Gaurav Sharma, modifié il y a 11 années.

RE: Calling a servlet in JSF

Junior Member Publications: 39 Date d'inscription: 01/11/12 Publications récentes
Is there an explanation of the code provided somewhere? I'm struggling to understand how
value="#{customer.exportResourceURL}"
knows that it needs to call CustomerResourceHandler to output a PDF. Basically I'm lost regarding the flow of the application.
thumbnail
Neil Griffin, modifié il y a 11 années.

RE: Calling a servlet in JSF

Liferay Legend Publications: 2655 Date d'inscription: 27/07/05 Publications récentes
CustomersDataModel.java is responsible for creating an instance of CustomerExportResource.java

The CustomerExportResource.getRequestPath() method is responsible for generating the URL to the resource, and gets called during the JSF lifecycle.

The CustomerExportResource.getInputStream() method is called when the user clicks on the URL that was generated.
Gaurav Sharma, modifié il y a 11 années.

RE: Calling a servlet in JSF

Junior Member Publications: 39 Date d'inscription: 01/11/12 Publications récentes
Neil,

I've tried to implement my code along the lines of the example but I get an error stating

The requested resource was not found. 

http://localhost:8080/javax.faces.resource/export?ln=pdfReports


Here is the code : https://gist.github.com/sharmanaetor/28b33c7a2cfd8f5a4679

Am I making any obvious errors?
thumbnail
Neil Griffin, modifié il y a 11 années.

RE: Calling a servlet in JSF

Liferay Legend Publications: 2655 Date d'inscription: 27/07/05 Publications récentes
Looks like the URL is not getting encoded by the bridge. Are you using h:outputLink for the user to click on, or a plain HTML <a href="..."></a> anchor tag?
Gaurav Sharma, modifié il y a 11 années.

RE: Calling a servlet in JSF

Junior Member Publications: 39 Date d'inscription: 01/11/12 Publications récentes
Actually, there was no link for the user to click on and that was the problem. I modified view.xhtml to:

<!--?xml version="1.0"?-->

<f:view xmlns="http://www.w3.org/1999/xhtml" xmlns:c="http://java.sun.com/jsp/jstl/core" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:p="http://primefaces.org/ui" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:aui="http://alloy.liferay.com/tld/aui">
	<h:head />
	<h:body>
		<h:form>

			<h:outputlink target="theFrame" value="#{myReport.reportResourceURL}">
				<h:outputtext value="#{i18n['export']}" />
			</h:outputlink>
			
			<iframe id="theFrame"></iframe>

		</h:form>
	</h:body>
</f:view>


and it works fine now. Thanks!
thumbnail
Neil Griffin, modifié il y a 11 années.

RE: Calling a servlet in JSF

Liferay Legend Publications: 2655 Date d'inscription: 27/07/05 Publications récentes
Hi Gaurav,

My pleasure -- BTW when the link is provided as the value attribute of h:outputLink, the JSF runtime (Mojarra/MyFaces) will automatically invoke the bridge's implementation of ExternalContext.encodeResourceURL(String) which does the encoding.

When you get it all working, would you consider publishing an open source JSF+Pentaho type of project at GitHub?

Best Regards,

Neil
Gaurav Sharma, modifié il y a 11 années.

RE: Calling a servlet in JSF

Junior Member Publications: 39 Date d'inscription: 01/11/12 Publications récentes
Will do Neil. I'll update this thread when the project is created.
Gaurav Sharma, modifié il y a 10 années.

RE: Calling a servlet in JSF

Junior Member Publications: 39 Date d'inscription: 01/11/12 Publications récentes
It took a little longer than I expected, but I finally got a chance to upload my code on GitHub at https://github.com/sharmanaetor/liferay-pentaho-reports-portlet.

If anyone has any questions on the code, I'd be more than happy to help.
Bivas Nath, modifié il y a 10 années.

RE: Calling a servlet in JSF

New Member Envoyer: 1 Date d'inscription: 10/01/12 Publications récentes
Thanks to both Neil and Gaurav - This thread was really helpful!
But whether I use ResourceHandler or extend the FacesPortlet (I need to generate PDF dynamically using data entered by the user in the UI), the challenge remains in passing the request parameters to the Resource or to the serveResource() method of the custom portlet. Passing parameters through the URL is OK if you have a limited set of params but when the user entered params is a long (or dynamic) list, this is cumbersome. Is there any other way to pass request params from the UI when I need to generate a resource? Thanks Again!
Gaurav Sharma, modifié il y a 10 années.

RE: Calling a servlet in JSF

Junior Member Publications: 39 Date d'inscription: 01/11/12 Publications récentes
Neil,

How do I add permissions and security to these dynamically generated resources? Like if I want to allow only logged in user to be able to access these reports. Or maybe only users with a specific role.
thumbnail
Neil Griffin, modifié il y a 10 années.

RE: Calling a servlet in JSF

Liferay Legend Publications: 2655 Date d'inscription: 27/07/05 Publications récentes
Now that you have implemented the ResourceHandler mechanism, your code is being invoked by a thread associated with a Liferay ResourceRequest.

In order to find out if the user has permission to access the resource, you need to get an instance of the Liferay PermissionChecker. You can do that like this:
FacesContext facesContext = FacesContext.getCurrentInstance();
PortletRequest portletRequest = (PortletRequest) facesContext.getExternalContext().getRequest();
ThemeDisplay themeDisplay = (ThemeDisplay) portletRequest.getAttribute(WebKeys.THEME_DISPLAY);
PermissionChecker permissionChecker = themeDisplay.getPermissionChecker();