Foros de discusión

Resource export with ResourceHandlerBridge

Gaël Paruta, modificado hace 9 años.

Resource export with ResourceHandlerBridge

New Member Mensajes: 13 Fecha de incorporación: 5/05/14 Mensajes recientes
Hello,

First of all, sorry for my poor english ^^

I downloaded the jsf2-export-pdf-portlet example but I cannot make it work in my own portlet.
Actually, I don't even undersantd why in the example there is several instanciation of the resource.
- return new CustomerExportResource(); // In the CustumerResourceHandler.createResource
- CustomerExportResource customerExportResource = new CustomerExportResource(customer); // In the CustumerDataModel

I have to pass some parameter to the resource, so I tried to make backingBean similar to CustumerDataModel.
To do that I added a CustomerExportResource(param) constructor in CustomerExportResource. This is the constructor I call from my backingbean, doing that I can get my resource from my back end and set a string into my backingbean with the requestPath without problem.
BUT, once I click on my link in my xhtml file, the bridge call for a new CustomerExportResource() using the CustumerResourceHandler.
-> The CustomerExportResource previously created is not used
-> I go through the getCustumer method again (but without my parameter)

What is the correct way to instanciate the Resource and then use it with the ResourceHandler declared into the face-config file ?

Thanx
thumbnail
Neil Griffin, modificado hace 9 años.

RE: Resource export with ResourceHandlerBridge

Liferay Legend Mensajes: 2655 Fecha de incorporación: 27/07/05 Mensajes recientes
First, let me say thanks for referencing the jsf2-export-pdf-portlet in order to solve your problem. We knew that exporting a resource was going to be a common use-case, so we wanted to develop a demo that was helpful to developers.

Second, I need to point out a bug that we recently fixed in FACES-1891. The "Fix Version" for FACES-1891 is 3.2.5-ga6 so you would need to reference the source code from the 3.2.x branch at GitHub rather than the source code code that accompanies the war file at Maven Central.

Third, I also wanted to point out that the primefaces3-users-portlet also has a resource handler that shows how to display the avatar/image of the selected user. We tried very hard to add meaningful comments to the UserPortraitResource.java and UserPortraitResourceHandler.java source files in order to explain how to use resource handlers correctly.

Please let us know whether or not this information was helpful, so that we know how to improve the demos in order to improve the developer experience. emoticon
Gaël Paruta, modificado hace 9 años.

RE: Resource export with ResourceHandlerBridge

New Member Mensajes: 13 Fecha de incorporación: 5/05/14 Mensajes recientes
Thank you for your answers, they helped me a lot.

1) I modified the ResourceHandler as specified in your comment, the Primefaces.js file is now loaded properly.
BUT, I still have troubles with my web components. (<p:datable> pagination not working, <p:panel> toggle not working, etc...)
In the browser console I can see : Uncaught TypeError: undefined is not a function

2) I used the primefaces3-users-portlet to implement a file download fonctionnality but I stiil can't make it work. I have several error line like :

15:22:55,432 ERROR [MissingResourceImpl:78] Resource handler=[com.liferay.faces.bridge.application.ResourceHandlerOuterImpl@ed3e7d9] was unable to create a resource for resourceName=[fichierExportResourceLibrary] libraryName=[null] contentType=[null]

The class ResourceHandlerOuterImpl is not the one I declared into the faces-config.xml

The version I have in ivy.xml for liferay-faces and JSF seem to be OK (I'm using Liferay 6.2) :
<dependency name="jboss-el" org="org.jboss.seam" rev="2.0.0.GA" />
<dependency name="jsf-api" org="com.sun.faces" rev="2.1.27" />
<dependency name="jsf-impl" org="com.sun.faces" rev="2.1.27" />
<dependency name="liferay-faces-bridge-api" org="com.liferay.faces" rev="3.2.4-ga5" />
<dependency name="liferay-faces-bridge-impl" org="com.liferay.faces" rev="3.2.4-ga5" />
<dependency name="liferay-faces-portal" org="com.liferay.faces" rev="3.2.4-ga5" />
<dependency name="liferay-faces-util" org="com.liferay.faces" rev="3.2.4-ga5" />
<dependency name="primefaces" org="org.primefaces" rev="3.5" />

Thank you for your help emoticon
thumbnail
Neil Griffin, modificado hace 9 años.

RE: Resource export with ResourceHandlerBridge

Liferay Legend Mensajes: 2655 Fecha de incorporación: 27/07/05 Mensajes recientes
When you get a chance, please upload/attach your Resource, ResourceHandler, and faces-config.xml source. Thanks.
Gaël Paruta, modificado hace 9 años.

RE: Resource export with ResourceHandlerBridge

New Member Mensajes: 13 Fecha de incorporación: 5/05/14 Mensajes recientes
Hi Neil,

I succeded to get rid of the Javascript errors, but I still have problems to get Resources.

I didn't find the way to upload files in the forum.
Here is my Resource class


public class MyExportResource extends Resource {

	// Public Constants
		public static final String CONTENT_TYPE = "application/text";
		public static final String RESOURCE_NAME = "fichierExportResourceLibrary";

		// Logger
		private static final Logger logger = LoggerFactory.getLogger(MyExportResource .class);

		// Private Data Members
		private String requestPath;
		private String md5;
		
		public MyExportResource (String md5) {
			this();
			this.md5 = md5;
		}
		
		public MyExportResource () {
			setLibraryName(MyResourceHandler.LIBRARY_NAME);
			setResourceName(RESOURCE_NAME);
		}

		/**
		 * This method returns a the URL of the resource. It is designed to be called during the JSF lifecycle. For the sake
		 * of speed this method uses lazy initialization for the return value.
		 */
		@Override
		public String getRequestPath() {

			if (requestPath == null) {
				StringBuilder buf = new StringBuilder();

				// Otherwise, return a JSF2 resource URL that will invoke the portlet RESOURCE_PHASE, and the resource
				// handler delegation-chain.
				buf.append(ResourceHandler.RESOURCE_IDENTIFIER);
				buf.append(StringPool.FORWARD_SLASH);
				buf.append(getResourceName());
				buf.append(StringPool.QUESTION);
				buf.append(MyResourceHandler.LIBRARY_NAME);
				buf.append(StringPool.EQUAL);
				buf.append(getLibraryName());
				buf.append(StringPool.AMPERSAND);
				buf.append(MyResourceHandler.PARAM_NAME_FILE);
				buf.append(StringPool.EQUAL);
				buf.append(md5);
				requestPath = buf.toString();
			}
			return requestPath;
		}

		@Override
		public InputStream getInputStream() throws IOException {

			byte[] byteArray = new byte[] {};
			try {
				if(StringUtils.isNotBlank(md5)){
					String fileContent = getFileContent();
					if(StringUtils.isNotBlank(fileContent)){
						byteArray = fileContent.getBytes();
					}
				}
			}
			catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
			return new ByteArrayInputStream(byteArray);
		}

		private String getFileContent() {
			MyService service = (MyService )FacesContext.getCurrentInstance().getApplication().getExpressionFactory().createValueExpression(
					FacesContext.getCurrentInstance().getELContext(), "#{myBean}", MyBean.class).getValue(FacesContext.getCurrentInstance().getELContext());

			FileDTO file = service.getFile(md5);
			if(file != null){
				return file.getFileContent();
			}
			return null;
		}
.....


My ResourceHandler class


public class MyResourceHandler extends ResourceHandlerBridgeImpl {

	public static final String LIBRARY_NAME = "myFileResource";
	public static final String PARAM_NAME_FILE = "param_file";
	
	public MyResourceHandler(ResourceHandler resourceHandler) {
		super(resourceHandler);
	}

	@Override
	public Resource createResource(String resourceName, String libraryName) {
		// If the specified library name is known by this resource handler, then
		if (LIBRARY_NAME.equals(libraryName) &amp;&amp; MyExportResource.RESOURCE_NAME.equals(resourceName)) {
			FacesContext facesContext = FacesContext.getCurrentInstance();
			Map<string, string> requestParameterMap = facesContext.getExternalContext().getRequestParameterMap();
			String md5 = requestParameterMap.get(PARAM_NAME_FILE);
			return new MyExportResource(md5);
		}
		return super.createResource(resourceName, libraryName);
	}

	@Override
	public void handleResourceRequest(FacesContext facesContext) throws IOException {
		ExternalContext externalContext = facesContext.getExternalContext();
		String libraryName = externalContext.getRequestParameterMap().get(ResourceConstants.LN);
		String resourceName = externalContext.getRequestParameterMap().get(ResourceConstants.JAVAX_FACES_RESOURCE);
		if (LIBRARY_NAME.equals(libraryName) &amp;&amp; MyExportResource.RESOURCE_NAME.equals(resourceName)) {
			Resource resource = createResource(resourceName, libraryName);
			handleResource(facesContext, resource);
		}
		else {
			// Otherwise, delegate creation of the resource to the delegation-chain.
			super.handleResourceRequest(facesContext);
                       // HERE I ALSO TRIED TO PUT THE getwrapper().doStuff()
		}
	}
</string,>


My face-config.xml file


<faces-config version="2.1" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_1.xsd">
	<application>
		<resource-bundle>
			<base-name>Language</base-name>
			<var>msg</var>
		</resource-bundle>
		<resource-handler>com.package.resource.MyResourceHandler</resource-handler>
	</application>
	
	<lifecycle>
		<phase-listener>com.liferay.faces.util.lifecycle.ViewScopePhaseListener</phase-listener>
	</lifecycle>
	
</faces-config>


The call for the Resource

In the xhtml file...

				        	<h:outputlink target="_blank" value="#{MyBean.getFichierLogStagingResourceUrl(logFileMd5)}"><h:outputtext value="Consulter" /></h:outputlink>


In the JSF Bean


public String getFichierLogStagingResourceUrl(String md5) {
		if(StringUtils.isNotBlank(md5)){
			FacesContext facesContext = FacesContext.getCurrentInstance();
			ExternalContext externalContext = facesContext.getExternalContext();
			MyExportResource fichierResource = new MyExportResource(md5);
			String requestPath = fichierResource .getRequestPath();
			Application application = facesContext.getApplication();
			ViewHandler viewHandler = application.getViewHandler();
			String resourceURL = viewHandler.getResourceURL(facesContext, requestPath);
			return externalContext.encodeResourceURL(resourceURL);
		}
		return null;
	}


Thanks
thumbnail
Neil Griffin, modificado hace 9 años.

RE: Resource export with ResourceHandlerBridge

Liferay Legend Mensajes: 2655 Fecha de incorporación: 27/07/05 Mensajes recientes
I took a look at the Java source code and I didn't see any obvious problems, aside from these values:

MyExportResource.RESOURCE_NAME = "fichierExportResourceLibrary"
MyResourceHandler.LIBRARY_NAME = "myFileResource"

It seems that instead, the values should be reversed like this:

MyExportResource.RESOURCE_NAME = "myFileResource"
MyResourceHandler.LIBRARY_NAME = "fichierExportResourceLibrary"

If you were to make that change, then in the XHTML I would recommend that you use the JSF2 "resource" EL keyword in order to get the URL:

<h:outputlink target="_blank" value="#{resource['fichierExportResourceLibrary:myFileResource']}">
    <f:param name="md5" value="#{logFileMd5}" />
    <h:outputtext value="Consulter" />
</h:outputlink>
Gaël Paruta, modificado hace 9 años.

RE: Resource export with ResourceHandlerBridge

New Member Mensajes: 13 Fecha de incorporación: 5/05/14 Mensajes recientes
Hi Neil,

Thanks for your advices but I still have a blank page when I tri to download the resource.

Error log :

 ERROR [MissingResourceImpl:78] Resource handler=[com.liferay.faces.bridge.application.ResourceHandlerOuterImpl@35bb28a0] was unable to create a resource for resourceName=[fichierAppairageResource] libraryName=[null] contentType=[null]
10:20:06,713 ERROR [MissingResourceImpl:136] Resource handler=[com.liferay.faces.bridge.application.ResourceHandlerOuterImpl@35bb28a0] was unable to create a resource for resourceName=[fichierAppairageResource] libraryName=[null] contentType=[null]
10:20:06,715 WARN  [ResourceImpl:166] Unable to determine if user agent needs update because resource URL was null for resourceName=[fichierAppairageResource].
10:20:06,715 ERROR [MissingResourceImpl:136] Resource handler=[com.liferay.faces.bridge.application.ResourceHandlerOuterImpl@35bb28a0] was unable to create a resource for resourceName=[fichierAppairageResource] libraryName=[null] contentType=[null]
10:20:06,724 WARN  [ResourceImpl:166] Unable to determine if user agent needs update because resource URL was null for resourceName=[fichierAppairageResource].
thumbnail
Neil Griffin, modificado hace 9 años.

RE: Resource export with ResourceHandlerBridge

Liferay Legend Mensajes: 2655 Fecha de incorporación: 27/07/05 Mensajes recientes
According to the error messages you posted, the library name for the request resource is null. That would seem to be the problem. The library name should be non-null. You need to examine the URL that the browser is requesting and make sure that the "ln" URL parameter is present, and that it has the correct value.
Gaël Paruta, modificado hace 9 años.

RE: Resource export with ResourceHandlerBridge

New Member Mensajes: 13 Fecha de incorporación: 5/05/14 Mensajes recientes
I inspected the URL called from the <h:outputLink ... />, it seems to be OK.


http://mysite/web/scef/tracking?p_p_id=trackingcommand_WAR_trackingcommandportlet&amp;p_p_lifecycle=2&amp;p_p_state=normal&amp;p_p_mode=view&amp;p_p_cacheability=cacheLevelPage&amp;p_p_col_id=&amp;p_p_col_count=0&amp;_trackingcommand_WAR_trackingcommandportlet_javax.faces.resource=fichierLogStagingExportResource&amp;_trackingcommand_WAR_trackingcommandportlet_trackingCommandResourceLibrary=trackingCommandResourceLibrary&amp;_trackingcommand_WAR_trackingcommandportlet_param_log_staging_file=3ADE88D3C30719D1242F6FE93E557202


With :
RESOURCE_NAME = "fichierLogStagingExportResource";
LIBRARY_NAME = "trackingCommandResourceLibrary";
thumbnail
Neil Griffin, modificado hace 9 años.

RE: Resource export with ResourceHandlerBridge

Liferay Legend Mensajes: 2655 Fecha de incorporación: 27/07/05 Mensajes recientes
The URL should contain:

&amp;ln=trackingCommandResourceLibrary


rather than:

&amp;trackingCommandResourceLibrary=trackingCommandResourceLibrary
thumbnail
Neil Griffin, modificado hace 9 años.

RE: Resource export with ResourceHandlerBridge

Liferay Legend Mensajes: 2655 Fecha de incorporación: 27/07/05 Mensajes recientes
(BTW, I forgot to mention that my examples above omit the portlet namespace prefix of trackingcommand_WAR_trackingcommandportlet for the sake of simplicity)
Gaël Paruta, modificado hace 9 años.

RE: Resource export with ResourceHandlerBridge

New Member Mensajes: 13 Fecha de incorporación: 5/05/14 Mensajes recientes
Thank Neil, it's a bit better emoticon

But I think there is a problem with <f:param

<h:outputlink target="_self" value="#{resource['trackingCommandResourceLibrary:fichierLogStagingResource']}">
	    						<f:param name="param_log_staging_file" value="#{log.logFileMd5}" />
								<h:outputtext value="bla bla bla bla" />
							</h:outputlink>



19:21:16,264 ERROR [BridgePhaseBaseImpl:248] Found render parameter name=[trackingcommandcom.liferay.faces.bridge.bridgeRequestScopeId] value=[trackingcommand:::5E586BDD1D11EF8872C1A17656C9E440:::1399915195335] BUT bridgeRequestScope is NOT in the cache
19:21:21,565 ERROR [URLUtil:93] Invalid name=value pair=[L[ln, trackingCommandResourceLibrary?param_log_staging_file, 3ADE88D3C30719D1242F6FE93E557202]] in URL=[/javax.faces.resource/fichierLogStagingResource?ln=trackingCommandResourceLibrary?param_log_staging_file=3ADE88D3C30719D1242F6FE93E557202]
19:21:21,628 ERROR [BridgeURLBaseImpl:143] invalid name/value pair: ln=trackingCommandResourceLibrary?param_log_staging_file=3ADE88D3C30719D1242F6FE93E557202
thumbnail
Neil Griffin, modificado hace 9 años.

RE: Resource export with ResourceHandlerBridge

Liferay Legend Mensajes: 2655 Fecha de incorporación: 27/07/05 Mensajes recientes
You have two question-marks (?) in the BridgeURL. The first question-mark is OK, but the second one should be an ampersand (&).
Gaël Paruta, modificado hace 9 años.

RE: Resource export with ResourceHandlerBridge

New Member Mensajes: 13 Fecha de incorporación: 5/05/14 Mensajes recientes
Yes, that's why I thougth there was a problem with the <f:param
The first "?" is given by the getRequestPath() methodand second is set by the "<f:param"

Is there a way to set the <f:param to make it put a "&" and not a "?" ?



public String getRequestPath() {
			if (requestPath == null) {
				StringBuilder buf = new StringBuilder();
				buf.append(ResourceHandler.RESOURCE_IDENTIFIER);
				buf.append(StringPool.FORWARD_SLASH);
				buf.append(getResourceName());
				buf.append(StringPool.QUESTION);
				buf.append(TrackingCommandResourceHandler.PARAM_LIBRARY_NAME);
				buf.append(StringPool.EQUAL);
				buf.append(getLibraryName());
				if(StringUtils.isNotBlank(md5)){
					buf.append(StringPool.AMPERSAND);
					buf.append(TrackingCommandResourceHandler.PARAM_NAME_APPAIRAGE_FILE);
					buf.append(StringPool.EQUAL);
					buf.append(md5);
				}
				requestPath = buf.toString();
			}
			return requestPath;
		}


I tried adding a <f:param with the library value and then delete the "question part" into the getRequestPath() method


					        <h:outputlink target="self" value="#{resource['trackingCommandResourceLibrary:fichierLogStagingResource']}" rendered="#{log.logFileMd5 != null}">
	    						<f:param name="param_log_staging_file" value="#{log.logFileMd5}" />
	    						<f:param name="ln" value="trackingCommandResourceLibrary" />
								<h:outputtext value="Consulter" />
							</h:outputlink>



				StringBuilder buf = new StringBuilder();
				buf.append(ResourceHandler.RESOURCE_IDENTIFIER);
				buf.append(StringPool.FORWARD_SLASH);
				buf.append(getResourceName());
				buf.append(StringPool.QUESTION);
//				buf.append(TrackingCommandResourceHandler.PARAM_LIBRARY_NAME);
//				buf.append(StringPool.EQUAL);
//				buf.append(getLibraryName());
//				if(StringUtils.isNotBlank(md5)){
//					buf.append(StringPool.AMPERSAND);
//					buf.append(TrackingCommandResourceHandler.PARAM_NAME_APPAIRAGE_FILE);
//					buf.append(StringPool.EQUAL);
//					buf.append(md5);
//				}
				requestPath = buf.toString();
			}
			return requestPath;



It doesn't seems to work either. The fact is I have no Exception nor message into the logs. The getInputStream() method is NEVER called..
The link generated by the "h:outputLink ":

<a href="http://mysite/web/scef/tracking?p_p_id=trackingcommand_WAR_trackingcommandportlet&amp;p_p_lifecycle=2&amp;p_p_state=normal&amp;p_p_mode=view&amp;p_p_cacheability=cacheLevelPage&amp;p_p_col_id=&amp;p_p_col_count=0&amp;_trackingcommand_WAR_trackingcommandportlet_javax.faces.resource=fichierLogStagingResource&amp;_trackingcommand_WAR_trackingcommandportlet_%3Fparam_log_staging_file=F7FFA3BA9505F2949764DCD1C966F76D&amp;_trackingcommand_WAR_trackingcommandportlet_ln=trackingCommandResourceLibrary" target="self">Consulter</a>
thumbnail
Neil Griffin, modificado hace 9 años.

RE: Resource export with ResourceHandlerBridge

Liferay Legend Mensajes: 2655 Fecha de incorporación: 27/07/05 Mensajes recientes
I was able to reproduce the problem and determined that the extra question mark is caused by the following bug in Mojarra: JAVASERVERFACES-3276.

If you can't wait for Mojarra to be fixed, then you can work-around the problem in your application.

1. In your WEB-INF/faces-config.xml descriptor, add the following:

<render-kit>
	<renderer>
		<description>Overrides the OutputLinkRenderer that comes with the JSF implementation</description>
		<component-family>javax.faces.Output</component-family>
		<renderer-type>javax.faces.Link</renderer-type>
		<renderer-class>com.mycompany.myproject.MyOutputLinkRenderer</renderer-class>
	</renderer>
</render-kit>


2. Then, add the following class to your project:

package com.mycompany.myproject;
public class MyOutputLinkRenderer extends Renderer {

	private Renderer delegationRenderer;
	
	public MyOutputLinkRenderer() {
		try {
			Class<!--?--> rendererClass = Class.forName("com.sun.faces.renderkit.html_basic.OutputLinkRenderer");
			this.delegationRenderer = (Renderer) rendererClass.newInstance();
		}
		catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public String convertClientId(FacesContext context, String clientId) {
		return delegationRenderer.convertClientId(context, clientId);
	}

	@Override
	public void decode(FacesContext context, UIComponent component) {
		delegationRenderer.decode(context, component);
	}

	@Override
	public void encodeBegin(FacesContext context, UIComponent component)
			throws IOException {
		
		ResponseWriter responseWriter = context.getResponseWriter();
		MyResponseWriter myResponseWriter = new MyResponseWriter(responseWriter);
		context.setResponseWriter(myResponseWriter);
		delegationRenderer.encodeBegin(context, component);
		context.setResponseWriter(responseWriter);
	}

	@Override
	public void encodeChildren(FacesContext context, UIComponent component)
			throws IOException {
		delegationRenderer.encodeChildren(context, component);
	}

	@Override
	public void encodeEnd(FacesContext context, UIComponent component)
			throws IOException {
		delegationRenderer.encodeEnd(context, component);
	}

	@Override
	public Object getConvertedValue(FacesContext context,
			UIComponent component, Object submittedValue)
			throws ConverterException {
		return delegationRenderer.getConvertedValue(context, component, submittedValue);
	}

	@Override
	public boolean getRendersChildren() {
		return delegationRenderer.getRendersChildren();
	}
	
	public class MyResponseWriter extends ResponseWriterWrapper {

		private ResponseWriter wrappedResponseWriter;
		
		public MyResponseWriter(ResponseWriter responseWriter) {
			this.wrappedResponseWriter = responseWriter;
		}
	
		@Override
		public void writeURIAttribute(String name, Object value, String property)
				throws IOException {
			
			if ((value != null) &amp;&amp; (value instanceof String)) {
				String valueAsString = (String) value;
				valueAsString = valueAsString.replaceAll("[?]", "&amp;");
				valueAsString = valueAsString.replaceFirst("[&amp;]", "?");
				value = valueAsString;
			}
			super.writeURIAttribute(name, value, property);
		}

		@Override
		public ResponseWriter getWrapped() {
			return wrappedResponseWriter;
		}
	}
}
thumbnail
Neil Griffin, modificado hace 9 años.

RE: Resource export with ResourceHandlerBridge

Liferay Legend Mensajes: 2655 Fecha de incorporación: 27/07/05 Mensajes recientes
Also wanted to mention that we developed a patch for Mojarra 2.x and Mojarra 2.1 and sent the patch to the Mojarra maintainers at Oracle. You might want to click on the "watch" link in JAVASERVERFACES-3276 for updates.
Gaël Paruta, modificado hace 9 años.

RE: Resource export with ResourceHandlerBridge

New Member Mensajes: 13 Fecha de incorporación: 5/05/14 Mensajes recientes
Neil thank you for your help, it was very useful.
I found another way to make it work.

My xhtml link :

					        <h:outputlink target="self" value="#{myCommandBean.getMyResourceUrl(log.logFileMd5)}" rendered="#{log.logFileMd5 != null}">
								<h:outputtext value="#{msg[tmyCommandBean.bu.concat('_portlet-mycommand-log-consulter')]}" />
							</h:outputlink>



My JSF bean :

public String geMyResourceUrl(String md5) {
		if(StringUtils.isNotBlank(md5)){
			FacesContext facesContext = FacesContext.getCurrentInstance();
			ExternalContext externalContext = facesContext.getExternalContext();
			MyExportResource fichierMyResource = new MyExportResource(md5);
			String requestPath = fichierMyResource.getRequestPath();
			String resourceURL = facesContext.getApplication().getViewHandler().getResourceURL(facesContext, requestPath);
			return externalContext.encodeResourceURL(resourceURL);
		}
		return null;
	}


My resource class :

public class MyExportResource extends Resource {

	// Public Constants
		public static final String CONTENT_TYPE = "application/text";
		public static final String RESOURCE_NAME = "fichierMyResource";

		// Logger
		private static final Logger logger = LoggerFactory.getLogger(MyExportResource.class);

		// Private Data Members
		private String requestPath;
		private String md5;
		private LogFileDTO logFile;
		
		public MyExportResource(String md5) {
			setLibraryName(MyCommandResourceHandler.LIBRARY_NAME);
			setResourceName(RESOURCE_NAME);
			setContentType(CONTENT_TYPE);
			this.md5 = md5;
		}
		
		public MyExportResource() {
			setLibraryName(MyCommandResourceHandler.LIBRARY_NAME);
			setResourceName(RESOURCE_NAME);
			setContentType(CONTENT_TYPE);
		}

		/**
		 * This method returns a the URL of the resource. It is designed to be called during the JSF lifecycle. For the sake
		 * of speed this method uses lazy initialization for the return value.
		 */
		@Override
		public String getRequestPath() {

			if (requestPath == null) {
				StringBuilder buf = new StringBuilder();
				buf.append(ResourceHandler.RESOURCE_IDENTIFIER);
				buf.append(StringPool.FORWARD_SLASH);
				buf.append(getResourceName());
				buf.append(StringPool.QUESTION);
				buf.append(MyCommandResourceHandler.PARAM_LIBRARY_NAME);
				buf.append(StringPool.EQUAL);
				buf.append(getLibraryName());
				buf.append(StringPool.AMPERSAND);
				buf.append(MyCommandResourceHandler.PARAM_NAME_LOG_STAGING_FILE);
				buf.append(StringPool.EQUAL);
				buf.append(md5);
				requestPath = buf.toString();
			}
			return requestPath;
		}

		@Override
		public InputStream getInputStream() throws IOException {

			byte[] byteArray = new byte[] {};
			try {
				if(StringUtils.isNotBlank(md5)){
					byteArray = getMyContent();
				}
			}
			catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
			return new ByteArrayInputStream(byteArray);
		}

		private byte[] getMyContent() {
			MyCommandService service = (MyCommandService)FacesContext.getCurrentInstance().getApplication().getExpressionFactory().createValueExpression(
					FacesContext.getCurrentInstance().getELContext(), "#{myService}", MyCommandService.class).getValue(FacesContext.getCurrentInstance().getELContext());
			logFile = service.getMy(md5);
			if(logFile != null){
				return logFile.getLogFileContent();
			}
			return null;
		}

		@Override
		public Map<string, string> getResponseHeaders() {
			Map<string, string> map = new HashMap<string, string>();
			map.put("Content-Disposition","attachment;filename="+ md5+".txt");
			return map;
		}

		@Override
		public URL getURL() {
			return null;
		}

		@Override
		public boolean userAgentNeedsUpdate(FacesContext arg0) {
			return true;
		}

</string,></string,></string,>


My ResourceHandler class :

public class MyCommandResourceHandler extends ResourceHandlerBridgeImpl {

	public static final String LIBRARY_NAME = "myCommandResourceLibrary";
	public static final String PARAM_NAME_LOG_STAGING_FILE = "param_log_staging_file";
	public static final String PARAM_LIBRARY_NAME = "ln";

	
	public MyCommandResourceHandler(ResourceHandler resourceHandler) {
		super(resourceHandler);
	}

	@Override
	public Resource createResource(String resourceName, String libraryName) {
		// If the specified library name is known by this resource handler, then
		FacesContext facesContext = FacesContext.getCurrentInstance();
		Map<string, string> requestParameterMap = facesContext.getExternalContext().getRequestParameterMap();
		if (LIBRARY_NAME.equals(libraryName) &amp;&amp; MyExportResource.RESOURCE_NAME.equals(resourceName)) {
			String md5 = requestParameterMap.get(PARAM_NAME_LOG_STAGING_FILE);
			return new MyExportResource(md5);
		}
		return super.createResource(resourceName, libraryName);
	}

	@Override
	public boolean libraryExists(String libraryName) {
		if (LIBRARY_NAME.equals(libraryName)) {
			return true;
		}
		else {
			return super.libraryExists(libraryName);
		}
	}
	
}</string,>


My faces-config.xml file :

<faces-config version="2.1" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_1.xsd">
	<application>
		<resource-bundle>
			<base-name>Language</base-name>
			<var>msg</var>
		</resource-bundle>
		<resource-handler>com.azenn.resource.MyCommandResourceHandler</resource-handler>
	</application>
	
	<lifecycle>
		<phase-listener>com.liferay.faces.util.lifecycle.ViewScopePhaseListener</phase-listener>
	</lifecycle>
	
</faces-config>


Hope this will be helpfull emoticon
thumbnail
Neil Griffin, modificado hace 9 años.

RE: Resource export with ResourceHandlerBridge

Liferay Legend Mensajes: 2655 Fecha de incorporación: 27/07/05 Mensajes recientes
Very nice solution! emoticon