Given a <p:dataTable>
rendering images in one of the columns.
<p:dataTable id="dataTable" var="row" value="#{bean}"
lazy="true"
skipChildren="true">
<p:column headerText="Image">
<p:cellEditor>
<f:facet name="output">
<p:graphicImage value="#{imageBean.image}" stream="true" cache="true">
<f:param name="id" value="#{row.id}"/>
<f:param name="width" value="100"/>
<f:param name="height" value="100"/>
</p:graphicImage>
</f:facet>
<f:facet name="input">
<p:graphicImage value="#{imageBean.image}" stream="true" cache="true">
<f:param name="id" value="#{row.id}"/>
<f:param name="width" value="100"/>
<f:param name="height" value="100"/>
</p:graphicImage>
<!-- <p:overlayPanel> here for file upload -->
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Edit">
<p:rowEditor/>
</p:column>
</p:dataTable>
The data table may contain other essential commonly used attributes and columns as and when needed.
When this table is (Ajaxically) updated, all images are fetched from the database (or disk file system, if used) as if they are not cached by the browser at all even though cache
is explicitly set to true
(which is the default value). This was working well previoulsly with PrimeFaces 5.3 final.
The migration guide states nothing about it but apparently something has been changed about caching <p:graphicImage>
.
Any suggestion to fix the problem?
In the example above, if the table contains 5 images in 5 rows, for example, the database will be queried 10 times on every single update made to the <p:dataTable>
(except inline row editing which defaults to the current row) which should not happen as getting images especially from a database is very costly.
Request / response headers using PrimeFaces 6.0 final (running on WildFly 10.0.0 final), when an initial request is made to the server to serve an image (does not work - images are not cached).
General
Request URL:https://localhost:8443/ContextRoot/javax.faces.resource/dynamiccontent.properties.xhtml?ln=primefaces&v=6.0&pfdrid=aed903cc-daba-4822-a62b-888b9a0ef2ac&pfdrt=sc&id=14&width=100&height=100&pfdrid_c=true
Request Method:GET
Status Code:200 OK
Remote Address:127.0.0.1:8443
Response Headers
Cache-Control:max-age=29030400
Connection:keep-alive
Date:Sat, 23 Jul 2016 06:59:54 GMT
Expires:Sun, 23 Jul 2017 06:59:54 GMT
Server:WildFly/10
Transfer-Encoding:chunked
X-Powered-By:Undertow/1
Request Headers
Accept:image/webp,image/*,*/*;q=0.8
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Cookie:JSESSIONID=4AoRGa1IAPTB4KssnikbO9uUetcQpMupli8BkGga.om-f6b0ea3ad206; __utma=111872281.616526714.1454485589.1468749319.1468751735.4; __utmz=111872281.1454485589.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)
Host:localhost:8443
Referer:https://localhost:8443/ContextRoot/admin/Brand
User-Agent:Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36
Query String Parameters
ln:primefaces
v:6.0
pfdrid:aed903cc-daba-4822-a62b-888b9a0ef2ac
pfdrt:sc
id:14
width:100
height:100
pfdrid_c:true
Request / response headers using PrimeFaces 5.3 final (running on GlassFish 4.1), when an initial request is made to the server to serve an image (works as intended - images are cached).
General
Request URL:https://localhost:8181/ContextRoot/javax.faces.resource/dynamiccontent.properties.xhtml?ln=primefaces&v=5.3&pfdrid=aAPHlxcQ2lcqfvzacYoCC6iUxLU1VVFp&pfdrt=sc&id=11&width=100&height=100&pfdrid_c=true
Request Method:GET
Status Code:200 OK
Remote Address:127.0.0.1:8181
Response Headers
Cache-Control:max-age=29030400
Date:Sat, 23 Jul 2016 07:15:03 GMT
Expires:Sun, 23 Jul 2017 07:15:04 GMT
Pragma:No-cache
Server:GlassFish Server Open Source Edition 4.1
Transfer-Encoding:chunked
X-Powered-By:Servlet/3.1 JSP/2.3 (GlassFish Server Open Source Edition 4.1 Java/Oracle Corporation/1.8)
Request Headers
Accept:image/webp,image/*,*/*;q=0.8
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Cookie:JSESSIONID=69b5070218cfe0fc6eaac2141c13; __utma=111872281.616526714.1454485589.1468749319.1468751735.4; __utmz=111872281.1454485589.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)
Host:localhost:8181
Referer:https://localhost:8181/ContextRoot/admin/Brand
User-Agent:Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36
Query String Parameters
ln:primefaces
v:5.3
pfdrid:aAPHlxcQ2lcqfvzacYoCC6iUxLU1VVFp
pfdrt:sc
id:11
width:100
height:100
pfdrid_c:true
Headers look good. This suggests that something in query string parameters changes from request to request. This would also be interpreted as a brand new resource and thus bust the caching even though the base URI (the part before URL query string separator ?
) is exactly the same.
And indeed, PrimeFaces 6.0 has changed the way how the pfdrid
query string parameter is generated. It has become a completely random UUID
which changes every time when the HTML <img src>
is rendered. See also line 59 of PF 6.0 source code. In PrimeFaces 5.3, it was encrypted based on EL expression string and thus guaranteed to be the same across requests as long as the EL expression string is the same. See also line 53 of PF 5.3 source code.
The change was introduced by Cagatay without a reference to an issue ticket. So it remains unclear why exactly this change was done. But after all it doesn't offer the client the opportunity anymore to cache the dynamic content and would thus actually decrease performance in both ends. This is definitely worth an issue ticket at PrimeFaces, so I created one: issue 1765.
I'm not seeing a clean way to solve this other than hacking the PrimeFaces source code. Your best bet is to replace the <p:graphicImage>
by a <h:graphicImage>
with a "plain vanilla servlet", or if you happen to use JSF utility library OmniFaces, then the <o:graphicImage>
with a simple bean. Those approaches are already detailed in this related Q&A: Show image as byte[] from database as graphic image in JSF page.
Update: as per issue 1765, it has been fixed for PrimeFaces 6.1.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With