How to show a dynamic image in PrimeFaces 6.1 [duplicate] - primefaces

I am using PrimeFaces 5.3 <p:fileUpload> to upload a PNG image and I would like to show a preview of it in <p:graphicImage> before saving in database.
Here's a MCVE:
<h:form enctype="multipart/form-data">
<p:fileUpload value="#{bean.uploadedFile}" mode="simple" />
<p:graphicImage value="#{bean.image}" />
<p:commandButton action="#{bean.preview}" ajax="false" value="Preview" />
</h:form>
private UploadedFile uploadedFile;
public UploadedFile getUploadedFile() {
return uploadedFile;
}
public void setUploadedFile(UploadedFile uploadedFile) {
this.uploadedFile = uploadedFile;
}
public void preview() {
// NOOP for now.
}
public StreamedContent getImage() {
if (uploadedFile == null) {
return new DefaultStreamedContent();
} else {
return new DefaultStreamedContent(new ByteArrayInputStream(uploadedFile.getContents()), "image/png");
}
}
No error occurring on the backing bean, and the image won't be load and display at front-end. The client mentions that the image returned a 404 not found error.

Your problem is two-fold. It failed because the uploaded file contents is request scoped and because the image is requested in a different HTTP request. To better understand the inner working, carefully read the answers on following closely related Q&A:
Display dynamic image from database with p:graphicImage and StreamedContent
How to choose the right bean scope?
To solve the first problem, you need to read the uploaded file contents immediately in the action method associated with the form submit. In your specific case, that would look like:
private UploadedFile uploadedFile;
private byte[] fileContents;
public void preview() {
fileContents = uploadedFile.getContents();
}
// ...
To solve the second problem, your best bet is to use the data URI scheme. This makes it possible to render the image directly in the very same response and therefore you can safely use a #ViewScoped bean without facing "context not active" issues or saving the byte[] in session or disk in order to enable serving the image in a different request. Browser support on data URI scheme is currently pretty good. Replace the entire <p:graphicImage> with below:
<ui:fragment rendered="#{not empty bean.uploadedFile}">
<img src="data:image/png;base64,#{bean.imageContentsAsBase64}" />
</ui:fragment>
public String getImageContentsAsBase64() {
return Base64.getEncoder().encodeToString(imageContents);
}
Note: I assume that Java 8 is available to you as java.util.Base64 was only introduced in that version. In case you're using an older Java version, use DatatypeConverter.printBase64Binary(imageContents) instead.
In case you happen to use JSF utility library OmniFaces, you can also just use its <o:graphicImage> component instead which is on contrary to <p:graphicImage> capable of directly referencing a byte[] and InputStream bean property and rendering a data URI.
<o:graphicImage value="#{bean.imageContents}" dataURI="true" rendered="#{not empty bean.imageContents}">

Related

Weird dataTable behaviour when combined with accordionPanel

I get a very strange behaviour when I combine the accordionPanel (dynamic tabs) together with a dataTable. In my project the total amount of dynamic tabs can get really big (>1000) so I really need the dynamic loading of the accordionPanel working, otherwise it is way too slow.
The problem
Instead of only loading the datatable for the currently selected tab, the getter method to load the elements from a list variable is being called 6 times the total amount of dynamic tabs. So if I have 300 dynamic tabs, the getter method is called 1800 times. If I however do not use a dataTable but i.e. just output text, the getter method is only called once like it should be.
Here is a small working example which produces the unwanted behaviour:
xhtml
<p:accordionPanel id="datasetHistoryAccordionTab" value="#{Bean.orderDatasets}" var="dataset" dynamic="true">
<p:tab title="Dataset ##{dataset.id}">
<p:tabView>
<p:tab title="All Processes">
<p:dataTable value="#{Bean.datasetProgressHistoryAll}" />
<!-- <h:outputText value="#{Bean.datasetProgressHistoryAll}" /> -->
</p:tab>
</p:tabView>
</p:tab>
</p:accordionPanel>
Bean
#ManagedBean
#ViewScoped
public class Bean implements Serializable
{
private List<DatasetBE> orderDatasets = new ArrayList<DatasetBE>(300);
private List<DatasetHistoryBE> datasetHistoryAll = new ArrayList<DatasetHistoryBE>();
public List<DatasetBE> getOrderDatasets() {
return orderDatasets;
}
public void setOrderDatasets(List<DatasetBE> orderDatasets) {
this.orderDatasets = orderDatasets;
}
public List<DatasetHistoryBE> getDatasetHistoryAll() {
log.debug("getDatasetHistoryAll() called...");
return datasetHistoryAll;
}
public void setDatasetProgressHistoryAll(List<DatasetHistoryBE> datasetHistoryAll) {
this.datasetHistoryAll = datasetHistoryAll;
}
}
The initial state is OK but as soon as I change to another tab the getter method is being called like crazy...
Is this a bug in PrimeFaces or am I doing something wrong? In my project I still use PF 3.5 but for testing purposes I also tried PF 4.0 but the same strange behaviour applies... Any help would be greatly appreciated!

Displaying images from MySQL database in JSF datatable [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 9 years ago.
I have MySQL database which stores images in a blob column. I would like to show them in a PrimeFaces <p:dataTable>. How can I achieve this?
You can use <p:graphicImage> to display images stored in a byte[], regardless of the byte[] source (DB, disk file system, network, etc). Simplest example is:
<p:graphicImage value="#{bean.streamedContent}" />
which refers a StreamedContent property.
This has however a pitfall, particularly when used in an iterating component such as a data table: the getter method will be invoked twice; the first time by JSF itself to generate the URL for <img src> and the second time by webbrowser when it needs to download the image content based on the URL in <img src>. To be efficient, you should not be hitting the DB in the first getter call. Also, to parameterize the getter method call so that you can use a generic method wherein you pass a specific image ID, you should be using a <f:param> (please note that EL 2.2 feature of passing method arguments won't work at all as this doesn't end up in URL of <img src>!).
Summarized, this should do:
<p:dataTable value="#{bean.items}" var="item">
<p:column>
<p:graphicImage value="#{imageStreamer.image}">
<f:param name="id" value="#{item.imageId}" />
</p:graphicImage>
</p:column>
</p:dataTable>
The #{item.imageId} obviously returns the unique idenfitier of the image in the DB (the primary key) and thus not the byte[] content. The #{imageStreamer} is an application scoped bean which look like this:
#ManagedBean
#ApplicationScoped
public class ImageStreamer {
#EJB
private ImageService service;
public StreamedContent getImage() throws IOException {
FacesContext context = FacesContext.getCurrentInstance();
if (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) {
// So, we're rendering the HTML. Return a stub StreamedContent so that it will generate right URL.
return new DefaultStreamedContent();
} else {
// So, browser is requesting the image. Return a real StreamedContent with the image bytes.
String imageId = context.getExternalContext().getRequestParameterMap().get("imageId");
Image image = imageService.find(Long.valueOf(imageId));
return new DefaultStreamedContent(new ByteArrayInputStream(image.getBytes()));
}
}
}
The Image class is in this particular example just an #Entity with a #Lob on bytes property (as you're using JSF, I of cource assume that you're using JPA to interact with the DB).
#Entity
public class Image {
#Id
#GeneratedValue(strategy = IDENTITY) // Depending on your DB, of course.
private Long id;
#Lob
private byte[] bytes;
// ...
}
The ImageService is just a standard #Stateless EJB, nothing special to see here:
#Stateless
public class ImageService {
#PersistenceContext
private EntityManager em;
public Image find(Long id) {
return em.find(Image.class, id);
}
}
See also:
Display dynamic image from database with p:graphicImage and StreamedContent
If you are using Richfaces, you can use a4j:mediaOutput component to stream the blob from a bean.
If that's not the case, I'm afraid I'm not familiar with Primefaces. If it doesn't provide any component for that you need a way of generating a URL that points to a servlet that returns the blob. That way you can use h:graphicImage with that auto-generated URL.

not able to integrate gauge.js with jsf page(primefaces)

I want to use gauge.js with my jsf(primefaces) application. I dealt with primefaces components (for which, doesn't require integration) so far. Now, I want to access class property (probably through Json response) from jsf page for generating gauage. I read a solution which suggests to generate json Response but I didn't get it properly. jsFiddle by bernii shows that it requires a dynamic value for creating gauge.
<------sampleClass------>
public int func(){
return aValue; }
<-----JSF----->
<canvas id="gauge"></canvas>
<------Script----->
var gaugeTarget = document.getElementById('gauge');
var gauge = new Gauge(gaugeTwoTarget);
gaugeTwo.maxValue = 100;
gaugeTwo.set(); //how can i get value return by func() here...........
Also BalusC wrote awesome article on it(Java/JSP/JSF and JavaScript). Again m not able to implement it.
Thanks
I missed that part in your question regarding the other solution...
Anyway you can also solve it with a hidden field in your page...
Bean (your bean clas)
int theValue;//add getter and setter
#PostConstruct
public void init(){
theValue = func();
}
Page (your xhtml)
<h:inputText id="myFuncValueId" value="#{myBean.theValue}" style="display:none"/>
js
gaugeTwo.set(document.getElementById('myFuncValueId').value);

How to use KEYGEN html 5 tag in a JSF app?

I want to use the KEYGEN html 5 tag to generate certificates from a Firefox browser.
In my facelet i have a form with the tag and a commandbutton that will submit the form to my backing bean called clientCertificateBean in this case. What I cant figure out is how I get the byteArray public key argument sent by the browser. Can i bind the keygen to a field in my backing bean or send it as an argument in the backing bean method?
<h:form>
<keygen name="RSA public key" challenge="123456789" KEYTYPE="RSA"/>
<h:commandButton value="Generate" action="#{clientCertificateBean.generate}" />
</h:form>
Seems support for keygen will come in JSF 2.2 in the meanwhile i solved it like this:
#Named("clientCertificateBean")
public class ClientCertificateBean {
public void generate() {
HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
String publicKey = request.getParameter("RSA public key");
}
}
Hope it can help someone.

ASP.NET Javascript Converter does not seem to be invoked

I have an ASP.NET 3.5 SP1 web application that uses a custom JavaScriptConverter. The code used to work at some time in the past, but has stopped working. I do not know what changes have happened in the middle server side. The problem we are seeing now is that the converter is not being invoked, so we are getting errors that System.Data.DataRow cannot be serialized.
The following is the relevant portion of web.config:
<system.web.extensions>
<scripting>
<webServices>
<jsonSerialization>
<converters>
<add name="DataSetConverter" type="Microsoft.Web.Preview.Script.Serialization.Converters.DataSetConverter, Microsoft.Web.Preview" />
<add name="DataRowConverter" type="WebUI.DataRowConverter, WebUI.DataRowConverter, Version=1.1.0.323, Culture=neutral" />
<add name="DataTableConverter" type="Microsoft.Web.Preview.Script.Serialization.Converters.DataTableConverter, Microsoft.Web.Preview" />
</converters>
</jsonSerialization>
</webServices>
</scripting>
</system.web.extensions>
A trimmed version of the class is as follows (trimmed only to avoid wasting space on unnecesary implementation):
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data;
using System.Web.Script.Serialization;
namespace WebUI {
public class DataRowConverter : JavaScriptConverter {
private ReadOnlyCollection<Type> _supportedTypes = new ReadOnlyCollection<Type>(new Type[] { typeof(DataRow) });
public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer) {
// stuff
return dr;
}
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer) {
// stuff
return dictionary;
}
public override IEnumerable<Type> SupportedTypes {
get {
return this._supportedTypes;
}
}
}
}
What seems to happen is that the class is indeed being loaded (if we take it out of web.config and the project references, no breakpoints are available; put it back into web.config and copy the DLL/PDB by hand or add it to the project, breakpoints are available), but it's not being used propertly. No breakpoint anywhere in the class is hit, and no exceptions (including one thrown in a constructor added to see what happens) are thrown. It seems like the class is being loaded but never called.
This is on IIS 7.5 and IIS 7.0 in Integrated mode, if it matters.
Anyone have any ideas?
OK, just in case anyone else hits this, when calling web services through the automatically generated test pages, the custom serializers are not invoked - they are bypassed. This is apparently by design.