掲示板

Resource export and ViewScoped bean

9年前 に antonio perez によって更新されました。

Resource export and ViewScoped bean

New Member 投稿: 15 参加年月日: 13/02/07 最新の投稿
Hi,

I'm trying to implement the jsf2-export-pdf-portlet but in our project we don't want to send the parameters in the url. We are trying to get the parameters from a bean of type ViewScoped, but the object bean always is null.

If we trying to get the parameter from url we don't have any problem.

Someone have any idea?

This is our code.

public class ExpedDocsExportResource extends Resource {

   protected LGFicheroPropiedades getLGFicheroPropiedades() {

        FacesContext facesContext = FacesContext.getCurrentInstance();
        Map<string, object> viewMap = facesContext.getViewRoot().getViewMap();
        //bean is null
        GestionExpDocsBean bean = (GestionExpDocsBean) viewMap.get("gestionExpDocsBean");

        //param1 is ok
        String param1= facesContext.getExternalContext().getRequestParameterMap().get(PARAM_NAME_XXX);

   }
}
</string,>


Thanks.
thumbnail
9年前 に Juan Gonzalez によって更新されました。

RE: Resource export and ViewScoped bean

Liferay Legend 投稿: 3089 参加年月日: 08/10/28 最新の投稿
Hola Antonio,

usually isn't a good idea to use a @ViewScoped bean within a resource request. They both have different lifecycle.

In case of @ViewScoped bean a view should exist, and this will need session or a serialized View state.

Take into account that a resource request should be independent of any state in server, that's why you need to specify a state (parameters in the URL) if you want to take advantage of a dynamic request.
9年前 に antonio perez によって更新されました。

RE: Resource export and ViewScoped bean

New Member 投稿: 15 参加年月日: 13/02/07 最新の投稿
In our use case the file is related with a document. If we put the id of the document in the url then anybody can download any file.
thumbnail
9年前 に Juan Gonzalez によって更新されました。

RE: Resource export and ViewScoped bean

Liferay Legend 投稿: 3089 参加年月日: 08/10/28 最新の投稿
Did you read my previous post? I guess you should send the ID throught URL.
thumbnail
9年前 に Neil Griffin によって更新されました。

RE: Resource export and ViewScoped bean

Liferay Legend 投稿: 2655 参加年月日: 05/07/27 最新の投稿
This is actually a problem that we are going to have to solve when we develop the alloy:dataExporter component (see FACES-1910).

There is a limitation to the design of the JSF2 ResourceHandler that is something that we will probably need to consider.

Specifically, the ResourceHandler.handleResourceRequest(FacesContext) method is only able to figure out what data to return in the response by examining request parameters specified on the URL.

So when we consider the following (potential/future) usage of alloy:dataExporter:

<alloy:datatable id="tbl" value="#{myModelBean.cars}" var="car">
    ...
</alloy:datatable>
<alloy:dataexporter type="xls" for="tbl" fileName="cars" />


One big problem that is a consequence of this limitation is that the ResourceHandler delegation chain is invoked by the portlet bridge (or FacesServlet) without first running the JSF lifecycle. So the ExportResourceHandler will probably have to execute the RESTORE_VIEW phase in order to get access the component tree. This can probably be done by developing a PhaseListener that short-circuits the JSF lifecycle by calling facesContext.responseComplete() at the end of RESTORE_VIEW.

public class ResourcePhaseListener implements PhaseListener {

	public void afterPhase(javax.faces.event.PhaseEvent event) {
                FacesContext facesContext = event.getFacesContext();
                String libraryName = facesContext.getExternalContext().getRequestParameterMap("ln");
                if ("export".equals(libraryName)) {
			facesContext.responseComplete();
                }
	}

	public void beforePhase(javax.faces.event.PhaseEvent event) {
	}

	public javax.faces.event.PhaseId getPhaseId() {
		return PhaseId.RESTORE_VIEW;
	}
}


Here is how we could execute the JSF lifecycle from the ExportResourceHandler:


	// Get the lifecycle
	Lifecycle lifecycle = lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);

	// Execute only the RESTORE_VIEW phase by relying on the ResourcePhaseListener
	lifecycle.execute(facesContext);


But in order for the RESTORE_VIEW phase to work, the viewId and the viewState would need to be present in the URL:

public class ExportResourceHandler {

...
public String getRequestPath() {
    // Need to add javax.portlet.faces.Bridge.FACES_VIEW_ID_PARAMETER "_jsfBridgeViewId" with the target viewId
    // Need to add javax.faces.render.ResponseStateManager.VIEW_STATE_PARAM "javax.faces.ViewState" with the viewState
}
...

}


Getting the value of "javax.faces.ViewState" might prove to be very very difficult. The way we currently do it in the bridge is that we have ResponseWriterBridgeImpl.java intercept it. The problem is that Mojarra/MyFaces doesn't write it out until just before the closing </form> element rendered by the h:form tag. That means it happens too late -- after the Resouce.getRequestPath() method has been called. Again, a very very difficult problem.

But we might also need to provide a way for the JSF Lifecycle to determine the target viewId. In order to do this, we could provide an ExternalContextFactory implementation [4] that "wraps" the others in the ExternalContext delegation chain. Something like this:

public class ExternalContextResourceImpl extends ExternalContextWrapper {

	public String getRequestPathInfo() {
		// return the viewId from the URL request parameter
		// BUT MAKE SURE THAT THE viewId HAS VALID CHARACTERS
		// (meaning, it does not contain a colon (:) character)
		// See: https://issues.liferay.com/browse/FACES-1917
	}
}


Anyway, all of this code is just an example of some ideas that I have. Not sure it will work, since we haven't developed alloy:dataExporter yet.
9年前 に antonio perez によって更新されました。

RE: Resource export and ViewScoped bean

New Member 投稿: 15 参加年月日: 13/02/07 最新の投稿
thank you very much.

We'll have to wait for the version that incorporates these features.
9年前 に Gaël Paruta によって更新されました。

RE: Resource export and ViewScoped bean

New Member 投稿: 13 参加年月日: 14/05/05 最新の投稿
Hi,

I had a similar issue.
To solve it (int a dirty way I think), I injected into my @ViewSopedBean another bean with @SessionScope annotation.
In this second bean I manage a Map with parameters.

When I construct the first bean, I set parameters to the second bean.
Then in my Resource file, I can access to the second bean (SessionScoped) and then get the parameters from the Map.
9年前 に antonio perez によって更新されました。

RE: Resource export and ViewScoped bean

New Member 投稿: 15 参加年月日: 13/02/07 最新の投稿
It is the same solution that I developed.
thumbnail
9年前 に Neil Griffin によって更新されました。

RE: Resource export and ViewScoped bean

Liferay Legend 投稿: 2655 参加年月日: 05/07/27 最新の投稿
Technically @ViewScoped managed-beans are already stored in the PortletSession (an abstraction over HttpSession) by Mojarra/MyFaces. It's just that we can't get access to them easily unless the RESTORE_VIEW phase of the JSF lifecycle is executed. This has been a helpful discussion, and I just wanted to let you all know that we (the Liferay Faces team) are very much aware of the need for an alloy:dataExporter type of component to solve this problem. We have it on the roadmap, but it will be later this year before it would be available. I'm sorry that we don't have a shorter-term solution for you. :-(
thumbnail
9年前 に Neil Griffin によって更新されました。

RE: Resource export and ViewScoped bean

Liferay Legend 投稿: 2655 参加年月日: 05/07/27 最新の投稿
Hi Antonio (and all watching this thread),

I just attached liferay-faces-1513-patch-SNAPSHOT.jar to FACES-1513. This patch should make it possible to use p:fileDownload and p:dataExporter in a portlet without doing any portlet-specific coding in your own code.

However, there are two limitations:

p:fileDownload - the PrimeFaces.monitorDownload(start, stop) JavaScript API doesn't call the "stop" function due to cookie issues in a portlet environment.

p:dataExporter - unable to get type="xml" working but I tried "csv", "pdf", and "xls" and they worked fine.

Please give the patch a try and let me know if it works for you. Simply copy it to tomcat/webapps/yourportlet/WEB-INF/lib and restart Tomcat.

Thanks,

Neil