Strange display of p:fileUpload component - jsf

I am trying to use the fileUpload component of PrimeFaces and everything is working BUT an empty error message is displayed when the component appeared with no content and i do not understand why.
And if i add a file to the component is disappeared well but it is still not pretty to have it when the component loads.
// View
<h:form>
<p:fileUpload fileUploadListener="#{bean.handleFileUpload}" />
</h:form>
// ManagedBean
public void handleFileUpload(FileUploadEvent event) {
UploadedFile file = event.getFile();
System.out.println("handleFileUpload : " + file);
}
The managed bean function is well called when I click on the upload button.
Hope some could understand my problem !
Thanks in advance

Related

Display p:fileupload image in p:graphicImage preview without saving it

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}">

Display total files uploaded on file upload complete

I know my question is quite basic but I couldn't find anything on SO or Google regarding this.
I am using PrimeFaces and their p:fileUpload component. It is working fine, files are being uploaded. The problem is, after these files are uploaded, I need to show user how many files are uploaded, and not using JavaScript. I need this number in my Backing Bean.
There is one oncomplete attribute but that is for client side callback (which again is JavaScript).
Following is my humble code :)
<p:fileUpload required="true" requiredMessage="No files selected."
mode="advanced"
multiple="true"
dragDropSupport="true"
allowTypes="/(\.|\/)(gif|jpe?g|png)$/"
update="growlMessage"
fileUploadListener="#{mainForm.fileUploadListener}">
</p:fileUpload>
And here is backing bean:
#ManagedBean
#SessionScoped
public class MainForm {
private int totalImageFiles;
public MainForm() {
this.totalImageFiles = 0;
}
public void fileUploadListener(FileUploadEvent event) {
UploadedFile uploadedFile = event.getFile();
ReaderWriter.ReadWrite(uploadedFile, yourName, yourHomeAddress, totalImageFiles);
totalImageFiles++;
}
}
totalImageFiles is the number that I want to show user. It has the correct values but I don't know how to send another request to retrieve this number.
Just reference it in some output component and ajax-update it.
<p:fileUpload ... update="growlMessage totalImageFiles" />
<h:outputText id="totalImageFiles" value="#{mainForm.totalImageFiles}" />

How can I render a file cached in a managed bean?

Current versions: JSF 2.1, RichFaces 4.5.2
I got into the following problem:
I have an upload component in one of my web-pages which is going to upload images:
<h:graphicImage id="uploadedPict" value="__WHAT__?" alt="picture />
<rich:fileUpload id="imageStartUploadComponent"
fileUploadListener="#{MyBean.uploadStartImage}"
acceptedTypes="png,jpg"
immediateUpload="false">
<a4j:ajax event="uploadcomplete" render="uploadedPict" />
</rich:fileUpload>
and the manged bean itself:
public class MyBean{
private UploadedFile detailsImage;
public void uploadStartImage(){
//SETTING detailsImage here
}
//GET, SET, OTHER STUFF
}
I could invoke UploadedFile::getData() method to retrieve binary image data. But how can I render it into the web-page? value attribute is supposed to be assigned with an actual picture's URL. So it seems I'm going to have to write my own servlet...
QUESTION: Is there a way to avoid writing a servlet and render the picture right from managed bean's method returning its binary data?
UPDATE: I need to do this for showing uploaded picture's preview. Maybe there is another way to do that correctly?
You can use <a4j:mediaOutput>:
<a4j:mediaOutput element="img" mimeType="image/jpeg"
createContent="#{bean.paint}" value="#{bean.file}">
</a4j:mediaOutput>
and the paint method:
public void paint(OutputStream stream, Object object) throws IOException {
stream.write(((UploadedFile) object).getData());
stream.close();
}
(check the showcase example)

show FacesMessage when invoking wizard.getOldStep()

I'm trying to show a FacesMessage built in onFlowProcess of a primefaces wizard.
public String onFlowProcess(FlowEvent event) {
if (event.getOldStep().equalsIgnoreCase("otherTab")){
if (!hasImage){
FacesUtils.addMessage(null, "Error", "image is required", FacesMessage.SEVERITY_ERROR);
return event.getOldStep();
}
}
return event.getNewStep();
}
The message should be send to the growl but I believe that by invoking getOldStep(), the message is lost along the way.
My growl is declared as :
<p:growl life="2500" showDetail="true" globalOnly="true"/>
and the wizard contains flowListener="#{bean.onFlowProcess}".
I tried to keep my FacesMessage with
FacesContext.getCurrentInstance().getExternalContext().getFlash().setKeepMessages(true);
but this seems to work only for page redirect...
If anybody has any idea... Thx
I solved the problem by updating the <p:growl> from the bean:
RequestContext.getCurrentInstance().update("form:growl");

JSF - p:ajax listener asking for parameters netBeans/primefaces

Versions:
NetBeans: 7.2.1
PrimeFaces: 3.5.3
GlassFish: 3.1.2
JDK 1.6
I've been trying to find related issues and have found topics that are close, but not quite what I'm looking for. I'm trying to do something similar to the p:schedule demo from PrimeFaces ShowCase where I want a dialog to appear showing the details of the event clicked.
I think the issue is coming from calling the listener method from the backing bean. When I go to type in the listener method in the p:ajax tag, NetBeans forces me to pass in a parameter like:
listener="#{cmodel.onEventSelect(e)}"
which I don't think is necessary as I don't have a value to pass in anyways.
I'm thinking either:
Something is up with NetBeans that doesn't recognize the method as a listener. (Since i keep seeing multiple examples of people calling the method without needing to pass a parameter.)
or
I'm not registering the method as a listener properly in the Model.
Also, I have directly copied and pasted the demo from the ShowCase into a project and it didn't work which is making me lean more towards an issue with NetBeans. (that is, the dialog appears but with no information on the event that was selected)
So to summarize; events are showing up as they should on the schedule itself, I just cant get the dialog to show the event details of the event that was selected.
Any help would be greatly appreciated!
View Layer:
<h:form>
<p:schedule id="nelsonsSchedule" value="#{cmodel.scheduleModel}" showHeader="true"
leftHeaderTemplate="none" rightHeaderTemplate="prev, next today"
draggable="false" timeZone="UTC" styleClass="schedule">
<p:ajax event="eventSelect" listener="#{cmodel.onEventSelect}"
update="eventDialog eventDetails" oncomplete="eventDialog.show()"/>
</p:schedule>
<p:dialog id="eventDialog" widgetVar="eventDialog" header="EventDetails">
<p:panel id="eventDetails">
<h:outputLabel value="#{cmodel.selectedEvent.title}" />
</p:panel>
</p:dialog>
</h:form>
Backing Bean:
#ManagedBean(name = "cmodel")
#SessionScoped
public class CalendarModel implements Serializable {
private ScheduleModel scheduleModel;
private List<ScheduleEvent> allScheduledGames;
private DefaultScheduleEvent gameEvent;
public ScheduleEvent selectedEvent;
List<Game> allGames;
#PersistenceContext
private EntityManager em;
public CalendarModel() {
}
#PostConstruct
public void init() {
allScheduledGames = new ArrayList<ScheduleEvent>();
allGames = new ArrayList<Game>();
allGames = em.createNamedQuery("Game.findAll").getResultList();
/*create list of games to put into the ScheduleModel*/
for (int i = 0; i < allGames.size(); i++) {
gameEvent = new DefaultScheduleEvent(allGames.get(i).getOpponent() +
"\n\n\n" + allGames.get(i).getTimeOfGame(),
allGames.get(i).getDateOfGame(),
allGames.get(i).getDateOfGame());
if(allGames.get(i).getHomeAway().equals("away")){
gameEvent.setStyleClass("away");
} else{
gameEvent.setStyleClass("home");
}
gameEvent.setData(allGames.get(i));
allScheduledGames.add(gameEvent);
}/*end for*/
scheduleModel = new DefaultScheduleModel(allScheduledGames);
}/*end init()*/
public void onEventSelect (SelectEvent e) {
selectedEvent = new DefaultScheduleEvent();
selectedEvent = (ScheduleEvent) e.getObject();
}
In case anyone runs into the same issue - It was NetBeans. I upgraded to 7.3 and don't have the problem anymore. Although another has come up where itellisense doesn't recognize a hashmap from the backing bean, but that's for another question.

Resources