Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to make Primefaces graphicImage work with Spring Web Flow
    text
    copied!<p>com.I have SWF app where user uploads image, and that image has to be displayed in the next flow state. The flow uses conversation-scoped bean (actually a JPA entity) that stores all user-entered data. I can upload the image, store it in the bean, but PrimeFaces graphicImage facelet will not render it. I did some research, and it appears that during rendering PF GI component stores the EL expression to be evaluated with the session, and subsequent call to ResourceHandler (made by IMG tag in rendered HTML) fetches the same EL expression and actually evaluates it. Problem is that ResourceHandler has no access to the flow variable where I store all my data and therefore cant render the image.</p> <p>I extended PF GI component to store actual image with the session instead of EL expression, but that has obvious performance implications: storing binary data in Session is not a good idea. Also, I would rather keep all data in flow/conversation scope instead of session for security reasons.</p> <p>Is there any clean way to make PF GI component access my flow variables?</p> <p>Snippets of my code below</p> <p>The Flow:</p> <pre><code>&lt;on-start&gt; &lt;evaluate expression="new my.models.Customers()" result="conversationScope.customer"&gt;&lt;/evaluate&gt; &lt;/on-start&gt; &lt;view-state id="scanImage" view="s1-scan.xhtml" model="customer" &gt; &lt;secured attributes="ROLE_WEB" /&gt; &lt;transition on="submit" to="verifyImage"&gt;&lt;/transition&gt; &lt;transition on="cancel" to="canceled"&gt;&lt;/transition&gt; &lt;/view-state&gt; &lt;view-state id="verifyImage" view="s2-verifyscan.xhtml" model="customer"&gt; &lt;secured attributes="ROLE_WEB" /&gt; &lt;transition on="submit" to="enterDetails"&gt;&lt;/transition&gt; &lt;transition on="back" to="scanImage"&gt;&lt;/transition&gt; &lt;transition on="cancel" to="canceled"&gt;&lt;/transition&gt; &lt;/view-state&gt; </code></pre> <p>Image rendering:</p> <pre><code>&lt;p:graphicImage value="#{customer.getImageSC()}"&gt;&lt;/p:graphicImage&gt; </code></pre> <p>Patched GraphicImageRenderer.getImageSrc()</p> <pre><code>protected String getImageSrc(FacesContext context, GraphicImage image) { String src = null; String name = image.getName(); if(name != null) { String libName = image.getLibrary(); ResourceHandler handler = context.getApplication().getResourceHandler(); Resource res = handler.createResource(name, libName); if(res == null) { return "RES_NOT_FOUND"; } else { String requestPath = res.getRequestPath(); return context.getExternalContext().encodeResourceURL(requestPath); } } else { Object value = image.getValue(); if(value == null) { return ""; } else if(value instanceof String) { src = getResourceURL(context, (String) value); } else if(value instanceof StreamedContent) { StreamedContent streamedContent = (StreamedContent) value; Resource resource = context.getApplication().getResourceHandler().createResource("dynamiccontent", "primefaces", streamedContent.getContentType()); String resourcePath = resource.getRequestPath(); String rid = createUniqueContentId(context); StringBuilder builder = new StringBuilder(resourcePath); builder.append("&amp;").append(Constants.DYNAMIC_CONTENT_PARAM).append("=").append(rid); for(UIComponent kid : image.getChildren()) { if(kid instanceof UIParameter) { UIParameter param = (UIParameter) kid; builder.append("&amp;").append(param.getName()).append("=").append(param.getValue()); } } src = builder.toString(); context.getExternalContext().getSessionMap().put(rid, value); // context.getExternalContext().getSessionMap().put(rid, image.getValueExpression("value").getExpressionString()); } if(!image.isCache()) { src += src.contains("?") ? "&amp;" : "?"; src += "primefaces_image=" + UUID.randomUUID().toString(); } src = context.getExternalContext().encodeResourceURL(src); } return src; } </code></pre> <p>Handler:</p> <pre><code>public void handleResourceRequest(FacesContext context) throws IOException { Map&lt;String,String&gt; params = context.getExternalContext().getRequestParameterMap(); String library = params.get("ln"); String dynamicContentId = params.get(Constants.DYNAMIC_CONTENT_PARAM); if(dynamicContentId != null &amp;&amp; library != null &amp;&amp; library.equals("primefaces")) { Map&lt;String,Object&gt; session = context.getExternalContext().getSessionMap(); StreamedContent streamedContent = null; try { Object dynamicContentEL = (Object) session.get(dynamicContentId); //String dynamicContentEL = (String) session.get(dynamicContentId); //ELContext eLContext = context.getELContext(); //ValueExpression ve = context.getApplication().getExpressionFactory().createValueExpression(context.getELContext(), dynamicContentEL, StreamedContent.class); //streamedContent = (StreamedContent) ve.getValue(eLContext); streamedContent = (StreamedContent) dynamicContentEL; ExternalContext externalContext = context.getExternalContext(); externalContext.setResponseStatus(200); externalContext.setResponseContentType(streamedContent.getContentType()); byte[] buffer = new byte[2048]; int length; InputStream inputStream = streamedContent.getStream(); while ((length = (inputStream.read(buffer))) &gt;= 0) { externalContext.getResponseOutputStream().write(buffer, 0, length); } externalContext.responseFlushBuffer(); context.responseComplete(); } catch(Exception e) { logger.log(Level.SEVERE, "Error in streaming dynamic resource. {0}", new Object[]{e.getMessage()}); } finally { //cleanup session.remove(dynamicContentId); if(streamedContent != null) { streamedContent.getStream().close(); } } } else { super.handleResourceRequest(context); } </code></pre> <p>}</p> <p>faces-config:</p> <pre><code> &lt;application&gt; &lt;el-resolver&gt;org.springframework.web.jsf.el.SpringBeanFacesELResolver&lt;/el-resolver&gt; &lt;resource-handler&gt;com.my.PrimeResourceHandler&lt;/resource-handler&gt; &lt;/application&gt; &lt;render-kit&gt; &lt;renderer&gt; &lt;component-family&gt;org.primefaces.component&lt;/component-family&gt; &lt;renderer-type&gt;org.primefaces.component.graphicimage.GraphicImageRenderer&lt;/renderer-type&gt; &lt;renderer-class&gt;com.my.GraphicImageRenderer&lt;/renderer-class&gt; &lt;/renderer&gt; &lt;/render-kit&gt; </code></pre> <p>I suspect it may be possible to store webflow context together with the EL in Session object, and make resource handler to use that context when evaluating the EL...</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload