Primefaces fileupload resets on ajax update - ajax

I'm doing a multiple record editing in primefaces datatable, in the record editing there is file upload, which resets when the user presses the "add" button
The jsf code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:p="http://primefaces.org/ui">
<h:head></h:head>
<h:body>
<h:form enctype="multipart/form-data">
<p:dataTable var="file" value="#{fileUpload.files}" id="uploadTable">
<p:column>
<p:inputText value="#{file.id}"/>
<p:inputText value="#{file.name}"/>
<p:fileUpload value="#{file.file}" mode="simple"/>
</p:column>
</p:dataTable>
<p:commandButton value="Add" action="#{fileUpload.add}" update="uploadTable" />
<p:commandButton action="#{fileUpload.submit}" value="Submit" ajax="false" />
</h:form>
</h:body>
</ui:composition>
Here's the controller:
#ManagedBean(name = "fileUpload")
#ViewScoped
public class DummyFileUpload implements Serializable {
private static final long serialVersionUID = 1L;
private List<File> files;
#PostConstruct
public void init() {
files = new ArrayList<DummyFileUpload.File>();
}
public void submit() {
// submit
}
public void add() {
files.add(new File());
}
public List<File> getFiles() {
return files;
}
public void setFiles(List<File> files) {
this.files = files;
}
public class File implements Serializable{
private static final long serialVersionUID = 2685385696849425824L;
private String id;
private String name;
private UploadedFile file;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public UploadedFile getFile() {
return file;
}
public void setFile(UploadedFile file) {
this.file = file;
}
}
}
The file upload control is reset when I do ajax call, I know it's a normal behavior but I'm asking if there's a known workaround for this situation and what could be the best practices for a complex business like this ?

This can be avoided by changing the file upload tag to the following:
<p:fileUpload fileUploadListener="#{fileUpload.add}" mode="advanced" />
This way the Add and Submit buttons as well as the AJAX update are not needed as the advanced version of the file upload will provide the same functionality.
In addition, in your DummyFileUpload bean you wall have to change the add function:
public void add(FileUploadEvent event) {
files.add(event.getFile());
}

Related

How enforce a p:inputText value to be set through p:ajax if the JSR 303 validation constraint is violated?

I have a Java Web 7 project in which I want to write JSF component values directly on an entity instance managed in a backing bean on every p:ajax event. That works fine as long as I add a JSR 303 validation constraint, like #Size(min=5) on one of the entity properties. The value is not longer set on the property with the constraint as long as the constraint is violated. The setter isn't called according to NetBeans debugger; the other property works just fine which leads me to believe that I've isolated the problem. I would like to perform validation when I want and thus get and invalid value set if I want. How to acchieve that?
In my minimal reproducible example I have the entity MyEntity (JPA and JSR 303 annotations)
#Entity
public class MyEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
private Long id;
#Size(min = 5)
private String property1;
private String property2;
public MyEntity() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getProperty1() {
return property1;
}
public void setProperty1(String property1) {
this.property1 = property1;
}
public String getProperty2() {
return property2;
}
public void setProperty2(String property2) {
this.property2 = property2;
}
}
a JSF page
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:form>
<p:inputText value="#{myManagedBean.myEntity.property1}">
<p:ajax/>
</p:inputText>
<p:inputTextarea value="#{myManagedBean.myEntity.property2}">
<p:ajax/>
</p:inputTextarea>
<p:commandButton value="Save">
<p:ajax listener="#{myManagedBean.onSaveButtonClicked}"/>
</p:commandButton>
</h:form>
</h:body>
</html>
and a backing bean
#ManagedBean
#SessionScoped
public class MyManagedBean {
private String value;
private String textAreaValue;
private MyEntity myEntity = new MyEntity();
public MyManagedBean() {
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getTextAreaValue() {
return textAreaValue;
}
public MyEntity getMyEntity() {
return myEntity;
}
public void setMyEntity(MyEntity myEntity) {
this.myEntity = myEntity;
}
public void setTextAreaValue(String textAreaValue) {
this.textAreaValue = textAreaValue;
}
public void onSaveButtonClicked(AjaxBehaviorEvent event) {
System.out.println("value: "+value);
System.out.println("textAreaValue: "+textAreaValue);
System.out.println("myEntity: "+myEntity);
}
}
The example can be found at https://github.com/krichter722/jsf-skip-entity-validation. I'm using Primefaces 6.0.
It is working as it is supposed to work. If the validation fails the setter shouldn't be called. If you want you can disable bean validations with this:
<f:validateBean disabled="true"/>

OrderList <p:ajax> Unable to attach behavior to non-ClientBehaviorHolder parent

I got stuck with a problem which seems to have been solved here.
I want to use order list as it's in an example here.
But it doesn't work at all. I have nested <p:ajax> in order list like in an example.
Namely, I have got an error:
javax.servlet.ServletException: /resources/abc/rankingAnswer.xhtml #21,85<p:ajax> Unable to attach behavior to non-ClientBehaviorHolder parent
My Primefaces config in pom.xml is
<!-- prime faces -->
<primefaces.version>5.1</primefaces.version>
<primefaces.themes.version>1.0.10</primefaces.themes.version>
My view is
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:composite="http://java.sun.com/jsf/composite"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html">
<composite:interface>
<composite:attribute name="question" />
</composite:interface>
<composite:implementation>
<ui:decorate template="answerDecorator.xhtml">
<ui:define name="component">
<p:orderList value="#{cc.attrs.question.possibleAnswers}" var="answer" itemLabel="#{answer.text}" itemValue="#{answer}" controlsLocation="left" editable="true" >
<f:facet name="caption">#{msg['survey.default.makeOrder']}</f:facet>
<p:ajax event="reorder" listener="#{cc.attrs.question.onReorder}" />
<p:column>
<h:outputText value="#{answer.text}" />
</p:column>
</p:orderList>
</ui:define>
</ui:decorate>
</composite:implementation>
</html>
My model is
public class RankingQuestionDTO extends AbstractQuestionDTO implements Serializable {
private ArrayList<RankingAnswerDTO> possibleAnswers;
private boolean randomizeAnswers;
private String text;
public RankingQuestionDTO() {
super(QuestionType.RANKING);
this.text = MessageUtils.getBundle("survey.default.text");
this.possibleAnswers = new ArrayList<>();
this.possibleAnswers.add(new RankingAnswerDTO(MessageUtils.getBundle("survey.default.text")));
this.possibleAnswers.add(new RankingAnswerDTO(MessageUtils.getBundle("survey.default.text")));
this.randomizeAnswers = true;
}
public void onSelect(SelectEvent event) {
System.out.print(event.getObject().toString());
}
public void onUnselect(UnselectEvent event) {
System.out.print(event.getObject().toString());
}
public void onReorder() {
}
public void addEmptyPossibleAnswer()
{
this.possibleAnswers.add(new RankingAnswerDTO(MessageUtils.getBundle("survey.default.text")));
}
public ArrayList<RankingAnswerDTO> getPossibleAnswers() {
return possibleAnswers;
}
public String getText() {
return text;
}
public void setPossibleAnswers(ArrayList<RankingAnswerDTO> possibleAnswers) {
this.possibleAnswers = possibleAnswers;
}
public void setRandomizeAnswers(boolean randomizeAnswers) {
this.randomizeAnswers = randomizeAnswers;
}
public boolean getRandomizeAnswers() {
return randomizeAnswers;
}
public void setText(String text) {
this.text = text;
}
}
The PrimeFaces Showcase has the answer (emphasis mine):
Pojo Support with Clip Effect, Captions, Custom Content, Reorder Controls and Events (since v5.1.5)
As does issue 4501 (emphasis mine):
Added
select
unselect
reorder
Target is 5.1.5 Elite and 5.2 Community.

polling using f:ajax:: Hi Have been using setInterval and f:ajax to poll below is the code kindly advise what is wrong here:

Have used setInterval to call ajax method which will render the value on page or probably keep updating the page. But in debug the control does not comes to ajax method in bean. please advise the issue in below code
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<h:body>
<script>
setInterval(function() {
document.getElementById("changeme").click();
}, 3000);
</script>
<h3>JSF 2.0 + Ajax Hello World Example</h3>
<h:form>
<h:inputText id="name" value="#{helloBean.name}"></h:inputText>
<h:commandButton value="Welcome Me">
<f:ajax execute="name" render="output" />
</h:commandButton>
<h2><h:outputText id="output" value="#{helloBean.sayWelcome}" /></h2>
<h2><h:outputText id="countsee" value="#{helloBean.name}" /></h2>
<h:commandButton id="changeme" style="display:none">
<f:ajax execute="#this" listener="#{helloBean.updates}" render="countsee" ></f:ajax>
</h:commandButton>
</h:form>
</h:body>
</html>
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.event.AjaxBehaviorEvent;
import java.io.Serializable;
#ManagedBean
#SessionScoped
public class HelloBean implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private static int count;
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSayWelcome(){
//check if null?
if("".equals(name) || name ==null){
return "";
}else{
return "Ajax message : Welcome " + name;
}
}
public void getUpdates(ActionBehaviorEvent event){
System.out.println("Printing"+count);
this.name=name+"agdam";
}
}
Try giving the below:
public void updates(ActionBehaviorEvent event)
The method name and name given in the listener should be same.

Disable inputText Primefaces depending selectOneMenu

I have a form with a selectOneMenu with two option and one inputText that which must be disabled if user choose the second option. I think that I should use ajax with update of inputText and is what I did, but don't work. Here is my code, please help me. Thanks
<h:outputText value="Modalita"></h:outputText>
<p:selectOneMenu value="#{vociCostoBean.selected.modalita}" immediate="true">
<f:selectItem itemLabel="Importo" itemValue="0"/>
<f:selectItem itemLabel="Quantita" itemValue="1"/>
<p:ajax update="uc" />
</p:selectOneMenu>
<h:outputText value="Costo Unitario"></h:outputText>
<p:inputText id="uc" disabled="#{vociCostoBean.selected.modalita !='1'}" value="#{vociCostoBean.selected.CUnitario}" />
<br></br>
and this vociCostoBean:
#ManagedBean
#SessionScoped
public class VociCostoBean {
#EJB
private CostoBeanRemote cust;
private List<VociCosto> list;
private VociCosto selected= new VociCosto();
private boolean UcDisabled=true;
#PostConstruct
public void init(){
setList(new ArrayList<VociCosto>());
setList(cust.getAll());
//selected.setModalita("0");
}
public String newCosto(){
return "editCosto";
}
public void onRowSelect(){
FacesContext fc = FacesContext.getCurrentInstance();
System.out.println("|||||"+ getSelected().getNome());
try {
fc.getExternalContext().redirect("editCosto.jsf");
} catch (IOException e) {
}
}
public VociCosto getSelected() {
return selected;
}
public void setSelected(VociCosto selected) {
this.selected = selected;
}
public void setCust(CostoBeanRemote cust) {
this.cust = cust;
}
public List<VociCosto> getList() {
return list;
}
public void setList(List<VociCosto> list) {
this.list = list;
}
public boolean isUcDisabled() {
return UcDisabled;
}
public void setUcDisabled(boolean ucDisabled) {
this.UcDisabled = ucDisabled;
}
}
and this is VociCosto.java
package it.bway.timerep.entities;
import java.io.Serializable;
import javax.persistence.*;
import java.util.Set;
/**
* The persistent class for the VOCI_COSTO database table.
*
*/
#Entity
#Table(name="VOCI_COSTO")
public class VociCosto implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="ID_COSTO", unique=true, nullable=false)
private int idCosto;
#Column(name="C_UNITARIO")
private int cUnitario;
#Column(length=1)
private String modalita;
#Column(length=50)
private String nome;
//bi-directional many-to-one association to NoteSpese
#OneToMany(mappedBy="vociCosto", fetch=FetchType.EAGER)
private Set<NoteSpese> noteSpeses;
public VociCosto() {
}
public int getIdCosto() {
return this.idCosto;
}
public void setIdCosto(int idCosto) {
this.idCosto = idCosto;
}
public int getCUnitario() {
return this.cUnitario;
}
public void setCUnitario(int cUnitario) {
this.cUnitario = cUnitario;
}
public String getModalita() {
return this.modalita;
}
public void setModalita(String modalita) {
this.modalita = modalita;
}
public String getNome() {
return this.nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public Set<NoteSpese> getNoteSpeses() {
return this.noteSpeses;
}
public void setNoteSpeses(Set<NoteSpese> noteSpeses) {
this.noteSpeses = noteSpeses;
}
#Override
public boolean equals(Object obj) {
try{
VociCosto toCompare = (VociCosto) obj;
if (idCosto==toCompare.getIdCosto()) return true;
return false;
} catch (Exception e){
return false;
}
}
#Override
public int hashCode(){
return idCosto;
}
}
You are doing exacly the opposite of what you are expecting. You should change
#{vociCostoBean.selected.modalita != '1'}
to
#{vociCostoBean.selected.modalita == '1'}
Working test case
View :
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
<h:form>
<h:outputText value="Modalita"></h:outputText>
<p:selectOneMenu value="#{selectMenuActions.value}" immediate="true">
<f:selectItem itemLabel="Importo" itemValue="0"/>
<f:selectItem itemLabel="Quantita" itemValue="1"/>
<p:ajax update="uc" />
</p:selectOneMenu>
<h:outputText value="Costo Unitario"></h:outputText>
<p:inputText id="uc" disabled="#{selectMenuActions.value == '1'}" value="#{vociCostoBean.selected.CUnitario}" />
<br></br>
</h:form>
</h:body>
</html>
Bean :
#ManagedBean
#ViewScoped
public class SelectMenuActions
{
private String m_sValue;
public void setValue(String p_sValue)
{
m_sValue = p_sValue;
}
public String getValue()
{
return m_sValue;
}
}

JSF 2.1 SelectOneMenu toggling automatically to init values

I have 2 SelectOneMenu as follows in the index.xhtml. The menu1 essentially chooses a language(sp or en) and menu2 displays the possible serial numbers(0 to 3). I have the init constructor(post constructor) which initialises the default values on the two Menus. However for some strange reason, if I select a serial number other than the default serial number for the language other than the default language, somehow the language gets reset to init default :(
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title>My page</title>
</h:head>
<h:body>
<div>
<h4>Change Existing Description</h4>
</div>
<h:form id="myForm">
<h:panelGrid columns="4">
<h:outputLabel value="Language:" />
<h:selectOneMenu value="#{myBean.language}">
<f:selectItems value="#{myBean.languages}" />
<f:ajax listener="#{myBean.doUpdate}" render ="myForm" />
</h:selectOneMenu>
<h:outputLabel value="SerialID:" />
<h:selectOneMenu value="#{myBean.serialID}">
<f:selectItems value="#{myBean.serialIDs}" />
<f:ajax listener="#{myBean.doUpdate}" render ="myForm" />
</h:selectOneMenu>
</h:panelGrid>
</h:form>
</h:body>
</html>
Here is my Bean code. Where is the problem?? please advise!
package bean;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.ejb.Stateful;
import javax.enterprise.context.RequestScoped;
import javax.faces.bean.ManagedBean;
#ManagedBean(name = "myBean")
//#Stateless
#Stateful
#RequestScoped
public class MyBean {
public static final int PERMISSIONS = 2;
private List<String> languages;
private String language;
private int serialID;
private List<Integer> serialIDs;
/**
* init() method for initializing the bean. Is called after constuction.
*/
#PostConstruct
private void init() {
//public MyBean () {
languages = getAllLanguages();
language = "en"; //defaultLanguage
serialID = 3;
serialIDs = getSerialIDsFromOverview();
}
public List<String> getLanguages() {
System.out.println("getLanguages, language " +language);
return languages;
}
public int getPERMISSIONS() {
return PERMISSIONS;
}
public String getLanguage() {
System.out.println("getLanguage " +language);
return language;
}
public void setLanguage(String language) {
System.out.println("setLanguage " +language);
this.language = language;
}
public int getSerialID() {
System.out.println("getSerialID " +serialID);
return serialID;
}
public void setSerialID(int serialID) {
System.out.println("setSerialID " +serialID);
this.serialID = serialID;
}
public List<Integer> getSerialIDs() {
System.out.println("getSerialIDs language = "+language );
return serialIDs;
}
public List<String> getAllLanguages() {
List<String> results = new ArrayList<String>();
results.add("sp");
results.add("en");
if(results != null){
System.out.println("getting all languages");
}
return results;
}
public void doUpdate() {
System.out.println("doUpdate language " +language);
System.out.println("doUpdate serialID " +serialID);
}
/**
* Returns a list of all serialIDs present in the overview.
* #return
*/
private List<Integer> getSerialIDsFromOverview() {
List<Integer> results = new ArrayList<Integer>();
results.add(0);
results.add(1);
results.add(2);
results.add(3);
return results;
}
}
UPDATES:
After taking suggestions from cubbuk, I sat down and corrected my code with #ViewScoped annotation and making the bean implement Serializable. THIS WORKS. However, the next thing I had to do was include an #EJB annotation to call a stateless bean which calls the Entity manager to fetch the serialIDs from a database instead of "hardcoding" it. That is when I encounter the problem: Not serializable exception "java.io.NotSerializableException: bean.__EJB31_Generated__. How do I solve this? When I made myBean back to RequestScope and remove Serializable, I could run the code without problems however there the toggling of the menu to init values :(
By the way I check this post: #EJB in #ViewScoped managed bean causes java.io.NotSerializableException and set my STATE SAVING METHOD to server but that gives me "empy response from server" pop up message :(
Please help!
Since you are using #RequestScoped bean as your backing bean after each request your init method is getting called and your values are getting reset. To avoid that you need to use #ViewScoped bean as your backing bean. I updated your bean accordingly note that your backing bean now implements Serializable interface. This is needed as this bean will be stored in your servlet and it needs to be flushed to disk if the content can not be hold in the memory. For learning the details of #ViewScoped beans please check the following post:
http://balusc.blogspot.com/2010/06/benefits-and-pitfalls-of-viewscoped.html
Apart from these, for naming conventions I renamed your getAllLanguages and getSerialIDsFromOverview methods to initAllLanguages and initSerialIds as methods starting with get and set can be confusing because they are mostly used for getters and setters.
Lastly when you use f:ajax command by default the UIInput the ajax command is bind to is rendered and executed. Since you don't refresh the h:selectOneMenu menus according to the values of each other you don't need to render the whole form. The following will be enough for this case:
<h:form id="myForm">
<h:panelGrid columns="4">
<h:outputLabel value="Language:" />
<h:selectOneMenu value="#{myBean.language}">
<f:selectItems value="#{myBean.languages}" />
<f:ajax listener="#{myBean.doUpdate}"/>
</h:selectOneMenu>
<h:outputLabel value="SerialID:" />
<h:selectOneMenu value="#{myBean.serialID}">
<f:selectItems value="#{myBean.serialIDs}" />
<f:ajax listener="#{myBean.doUpdate}"/>
</h:selectOneMenu>
</h:panelGrid>
</h:form>
#ManagedBean
#ViewScoped
public class MyBean implements Serializable
{
public static final int PERMISSIONS = 2;
private List<String> languages;
private String language;
private int serialID;
private List<Integer> serialIDs;
/**
* init() method for initializing the bean. Is called after constuction.
*/
#PostConstruct
protected void init()
{
//public MyBean () {
System.out.println("lang: " + language);
System.out.println("serialId: " + serialID);
System.out.println("init is called");
initAllLanguages();
initSerialIds();
language = "en"; //defaultLanguage
serialID = 3;
}
public List<String> getLanguages()
{
return languages;
}
public int getPERMISSIONS()
{
return PERMISSIONS;
}
public String getLanguage()
{
return language;
}
public void setLanguage(String language)
{
this.language = language;
}
public int getSerialID()
{
return serialID;
}
public void setSerialID(int serialID)
{
this.serialID = serialID;
}
public List<Integer> getSerialIDs()
{
return serialIDs;
}
private void initAllLanguages()
{
languages = new ArrayList<String>();
languages.add("sp");
languages.add("en");
}
public void doUpdate()
{
System.out.println("doUpdate language " + language);
System.out.println("doUpdate serialID " + serialID);
}
/**
* Returns a list of all serialIDs present in the overview.
*
* #return
*/
private void initSerialIds()
{
serialIDs = new ArrayList<Integer>();
serialIDs.add(0);
serialIDs.add(1);
serialIDs.add(2);
serialIDs.add(3);
}
}
Cheers

Resources