ViewScoped CDI bean recreated after some AJAX requests - ajax

I have a CDI ViewScoped bean and a JSF page. After a couple of AJAX requests the bean somehow recreated.
Here is the full code of the application:
index.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
Hello from Facelets
<h:form>
<h:inputText value="#{questionBean.newTag}"></h:inputText>
<h:commandButton value="Add Tag">
<f:ajax listener="#{questionBean.addTag()}" execute="#form" render="#form"></f:ajax>
</h:commandButton>
<ui:repeat value="#{questionBean.tagsOfQuestion}" var="tag">
<h:outputLabel value="#{tag}"></h:outputLabel>
<h:commandButton value="X">
<f:ajax event="click" listener="#{questionBean.removeTag(tag)}" render="#form" execute="#form"/>
</h:commandButton>
</ui:repeat>
</h:form>
</h:body>
</html>
Here is the backing CDI bean
QuestionBean.java
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
#Named
#ViewScoped
public class QuestionBean {
private String newTag;
private List<String> tagsOfQuestion = new ArrayList<String>();
private Date dateCreated = new Date();
public QuestionBean(){
System.out.println("Date Created : "+dateCreated);
}
public void addTag(){
if(!newTag.isEmpty()){
getTagsOfQuestion().add(newTag);
}
newTag = "";
}
public void removeTag(String tagToRemove){
getTagsOfQuestion().remove(tagToRemove);
}
public String getNewTag() {
return newTag;
}
public void setNewTag(String newTag) {
this.newTag = newTag;
}
public List<String> getTagsOfQuestion() {
return tagsOfQuestion;
}
public void setTagsOfQuestion(List<String> tagsOfQuestion) {
this.tagsOfQuestion = tagsOfQuestion;
}
}

Well I had the same problem when I tried it - Netbeans 8 and JSF 2.2.0 too.
Works for me after I updated Glassfish - grab javax.faces.jar from here - I took the very newest, 2.2.8-02, and replaced the one in glassfish/glassfish/modules.
Don't know what the error was or exactly when it was fixed though.
Hope it works for you too.

Related

Can't get values from jsf page

My managed bean gets null values from a simple form in a jsf page. In reality I have a fairly developed interface but the problem is happening even with a simple form.
(JSF 2.1.0, java compiler 1.6, primefaces 6.0 and tomcat7)
It seems to be a duplicated question. But, 5 days ago I am looking for the solution to this strange problem. I found a lot of solutions, but it does not work for me. Maybe I did not quite understand them as the answer from BalusC (commandButton/commandLink/ajax action/listener method not invoked or input value not updated) .
The 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: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"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</h:head>
<h:body>
<h:form>
<h:inputText value="#{notification.typeSelected}"></h:inputText>
<p:commandButton value="Enregistrer"
actionListener="#{notificationBean.filtrer}" process="#this"
style="float:right">
</p:commandButton>
</h:form>
</h:body>
</html>
The managed bean:
package presentation;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.event.ActionEvent;
//import javax.faces.event.ValueChangeEvent;
import javax.faces.model.SelectItem;
import org.apache.log4j.Logger;
import entities.Contrainte;
import metier.ContrainteMetier;
import metier.ContrainteMetierImp;
#ManagedBean
#SessionScoped
public class NotificationBean implements java.io.Serializable{
private static final long serialVersionUID = 1L;
public static Logger log = Logger.getLogger(ProjetMODBean.class);
private ContrainteMetier contrainteM = new ContrainteMetierImp();
private List<Contrainte> contrainteL;
private List<Contrainte> filtreL;
private List<SelectItem> classificationL;
private String typeSelected;
//Constructeurs
public NotificationBean() {
}
public NotificationBean(ContrainteMetier contrainteM, List<Contrainte> contrainteL) {
super();
this.contrainteM = contrainteM;
this.contrainteL = contrainteL;
}
#PostConstruct
public void init() {
contrainteL = contrainteM.findAll();
classificationL = new ArrayList<SelectItem>();
for(Contrainte c:contrainteL)
{//Attention, il ne faut pas dupliquer les types dans la liste déroulante
classificationL.add(new SelectItem(c.getClassification()));
}
log.info(" dans init je filtre selon: " + getTypeSelected());
}
//Méthodes
public void filtrer(ActionEvent e)
{
setTypeSelected(typeSelected);
log.info("je filtre selon: " + getTypeSelected());
}
The console output:
2017-03-24 18:06:43 INFO ProjetMODBean:57 - dans init je filtre selon: null
2017-03-24 18:06:43 INFO ProjetMODBean:76 - je filtre selon: null
I tried to correct my error but a detail escapes me.
Imho your problem is process="#this" change it to process="#form" (it is default value so change it only if you have good reason) or add id to input and use process="#this idOfInputField".
See question.
Please post questions fully in english.
I will assume, that //Méthodes mean getter/setter for fields (JSF require getter/setter for inputs).
Also use injection for services.
Change method header from public void filtrer(ActionEvent e) to public void filtrer()

Primefaces: Ajax update with RequestContext running only once

I have a component on my view which i want to update from my bean.
It works only once. If i press the second button nothing happen, but the bean method in the actionlistener was called.
I checked the browser log with firebug and have no errors or something else which looks odd.
My Bean is in ViewScope. I'm using primefaces 3.5.
JSFPage:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:body>
<h:form id="myRootForm">
<p:inputText id="text1" styleClass="myChangeClass" disabled="true" />
</h:form>
<h:form>
<p:commandButton value="Activate Insert"
actionListener="#{controller.activate()}" update=":myRootForm" />
<p:commandButton value="Deactivate"
actionListener="#{controller.resetFields()}" update=":myRootForm" />
</h:form>
</h:body>
</html>
This is the EJB code:
import javax.faces.component.UIViewRoot;
import javax.faces.component.html.HtmlInputText;
import javax.faces.context.FacesContext;
import org.apache.myfaces.extensions.cdi.core.api.scope.conversation.ViewAccessScoped;
import java.io.Serializable;
import javax.inject.Named;
#ViewAccessScoped
#Named("controller")
public class Controller {
private UIViewRoot viewRoot = FacesContext.getCurrentInstance().getViewRoot();
public void activate() {
HtmlInputText text = (HtmlInputText)
viewRoot.findComponent("myRootForm:text1");
text.setDisabled(false);
RequestContext.getCurrentInstance().update(text.getClientId());
}
public void deactivate() {
HtmlInputText text = (HtmlInputText)
viewRoot.findComponent("myRootForm:text1");
text.setDisabled(true);
RequestContext.getCurrentInstance().update(text.getClientId());
}
}
** Update:
I made the example a bit better to read.
When i'm using the "RequestScope" it is working, but i need the viewScope to hold my information.
For a better understanding why i want to do it this way:
I have several input components which i want to be available in several mode's.
The mode is indicated in a StyleClass (i.e. myChangeClass).
When i press the button i go through the component tree of my form and searching for the styleclass and activiate the buttons. I don't want to do this by holding for every component an attribute in my bean.
I don't know exactly what you're trying to achieve. I've added example below to help you.
XHTML code
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>Test</title>
</h:head>
<h:body>
<h:form id="myRootForm">
<p:inputText id="text1" disabled="#{tBean.enabled}" />
<p:commandButton value="Activate Insert"
actionListener="#{tBean.enable}" update=":myRootForm" />
<p:commandButton value="Deactivate" actionListener="#{tBean.disable}"
update=":myRootForm" />
</h:form>
</h:body>
</html>
ManagedBean Code
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.event.ActionEvent;
#ManagedBean(name = "tBean")
#ViewScoped
public class TestBean {
private boolean enabled;
public void enable(ActionEvent e) {
enabled = false;
}
public void disable(ActionEvent e) {
enabled = true;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}
Try above and see if that helps.

JSF: strange iframe when using multipart/form-data and AJAX

UPD: this error is caused by installing PrimeFaces 4.0.
I have a problem with multipart/form-data and AJAX in JSF 2.2.4 (Glassfish 4.0.0). When I type something, a strange iframe is shown with id JSFFrameId that contains AJAX's responce. Something like this:
<iframe src="about:blank" id="JSFFrameId" name="JSFFrameId">
<partial-response id="j_id1"><changes><update id="j_id1:javax.faces.ViewState:0"><![CDATA[1204950170773864689:-3204770436768457110]]></update></changes></partial-response>
</iframe>
But the value is set. What's wrong? Is it a bug?
JSF form:
<h:form enctype="multipart/form-data">
<h:outputText value="#{foo.string}" id="asd" />
<h:inputText value="#{foo.string}">
<f:ajax event="change" render="asd" />
</h:inputText>
</h:form>
Bean:
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
#ManagedBean(name = "foo")
#RequestScoped
public class SomeBean {
private String string;
public String getString() {
return string;
}
public void setString(String string) {
this.string = string;
}
}
I think it could be this bug: JSF jira

Primefaces commandButton calls action method on page refresh

Completely edited:
Maybe I was mixing problems and misinterpreted. After simplifying my code the question simplifies to: How can I prevent the <p:commandButton> from executing it's action method on page refresh (like when you hit F5 inside browser window)?
JSF Code:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:body>
<h:form>
<h:outputText value="#{bugBean.number}" />
<h:outputText value="#{bugBean.isComplete()}" />
<p:commandButton id="entryCommand" value="add"
action="#{bugBean.increase()}" update="#form" oncomplete="#{bugBean.complete()}"/>
</h:form>
</h:body>
</html>
backing bean code:
package huhu.main.managebean;
import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
#Named
#SessionScoped
public class BugBean implements Serializable {
private static final long serialVersionUID = 1L;
private int number;
private boolean isComplete = false;
public void increase(){
number++;
}
public void complete(){
isComplete = true;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public boolean isComplete() {
return isComplete;
}
public void setComplete(boolean isComplete) {
this.isComplete = isComplete;
}
}
Update:
Even if I remove the oncomplete stuff like this an click the <p:commandButton> just once, the counter goes up on every page refresh.
<h:form>
<h:outputText value="#{bugBean.number}" />
<p:commandButton id="entryCommand" value="add"
action="#{bugBean.increase()}" update="#form"/>
</h:form>
The construct was lacking Ajax-support due to a missing head definition as it seems. In this case I just added <h:head/> right above the <h:body>-tag and everything worked fine.
Thanks to all contributors!
I think that the action method increase() is not called on each page refresh, but it's called the complete() method instead, and this is probably making you think that the action method has been called.
The oncomplete attribute inside the p:commandButton indicates a client side action, and so a JS method, and not a server action: the EL executes #{bugBean.complete()} when parses it on each page refresh.

Icefaces 3.0.1 FileEntry: FileEntryListener is never called

1.1, IceFaces 3.0.1 and JSF 2.1 and was trying to work with ace:fileentry. I can't understand why the listener is never called! Even the IDE sends me a warning "pruebaBean.sampleListener is an unknown property".
Here is a short example of what i'm doing. When click the submit button nothing happen.
Can someone help me ?? Could be some kind of bug?
prueba.xhtml:
<?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:ice="http://www.icesoft.com/icefaces/component"
xmlns:ace="http://www.icefaces.org/icefaces/components">
<h:head>
</h:head>
<h:body>
<ice:form id="usuarioForm">
<ice:panelGrid columns="2">
<ace:fileEntry id="fileEntryImage" absolutePath="c:\iTablero\imagenes"
useSessionSubdir="false" useOriginalFilename="false"
fileEntryListener="#{pruebaBean.sampleListener}"/>
<ice:commandButton type="submit" value="Subir archivo"/>
</ice:panelGrid>
<ice:messages/>
</ice:form>
</h:body>
PruebaBean.java:
package com.itablero.backingbeans;
import java.io.Serializable;
import javax.annotation.ManagedBean;
import javax.faces.bean.RequestScoped;
import org.icefaces.ace.component.fileentry.FileEntry;
import org.icefaces.ace.component.fileentry.FileEntryEvent;
import org.springframework.stereotype.Controller;
#ManagedBean
#Controller
#RequestScoped
public class PruebaBean implements Serializable {
public void sampleListener (FileEntryEvent e) {
System.out.println("it work!");
FileEntry fe = (FileEntry) e.getComponent();
//some others operations
}
}
Update 1
Thanks to #fischermatte I found the problem was replace ice:commandButton for h:commandButton. But when I applied this to the original complete form and didn't work. The fileEntryListener method is never called. Can someone see the error here?
Logically the previous example and the code below have the same web.xml, faces-config.xml, etc. Note the button to submit the file is h:commandButton, and there is a ice:commandButton for complete form. I already tried to change this por en h:cb.
Here is the original form (that is display in a popup/modal window) and bean:
usuariosList.xhtml
<ice:panelPopup rendered="#{usuariosBean.showPopup}"
visible="#{usuariosBean.showPopup}"
modal="true"
autoCentre="true">
<f:facet name="header">
<h:panelGroup>
<h:panelGroup style="float: left;">
Usuario
</h:panelGroup>
<h:panelGroup style="float: right;">
<ice:form>
<h:commandButton image="/resources/images/popup-close.png"
alt="Cerrar" title="Cerrar"
style="height: 11px; width: 11px; border: 0;"
action="#{usuariosBean.closePopup}"/>
</ice:form>
</h:panelGroup>
</h:panelGroup>
</f:facet>
<f:facet name="body">
<ice:form id="usuarioForm">
<ice:panelGrid columns="2">
<p>Nombre:</p>
<ice:inputText id="nombre" label="nombre" value="#{usuariosBean.usuario.nombre}" size="40" />
<p>Imagen:</p>
<ice:graphicImage value="#{usuariosBean.usuario.imagen}"/>
<ace:fileEntry id="fileEntryImage" absolutePath="c:\iTablero\imagenes"
useSessionSubdir="false" useOriginalFilename="false"
fileEntryListener="#{usuariosBean.formListener}"/>
<h:commandButton type="submit" value="Subir archivo"/>
</ice:panelGrid>
<ice:messages for="usuarioForm"/>
<ice:commandButton value="Guardar" action="#{usuariosBean.save()}" />
</ice:form>
</f:facet>
</ice:panelPopup>
UsuariosBean.java
package com.itablero.backingbeans;
import com.itablero.excepciones.DAOException;
import com.itablero.modelo.Usuario;
import com.itablero.servicios.AdminService;
import java.io.Serializable;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import org.icefaces.ace.component.fileentry.FileEntry;
import org.icefaces.ace.component.fileentry.FileEntryEvent;
import org.icefaces.ace.component.fileentry.FileEntryResults;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
#ManagedBean
#Controller
#ViewScoped
public class UsuariosBean implements Serializable {
#Autowired
private AdminBean adminBean;
#Autowired
private AdminService adminService;
private Usuario usuario = new Usuario();
private boolean showPopup;
//getter and setters
public boolean isShowPopup() {
return showPopup;
}
public void setShowPopup(boolean showPopup) {
this.showPopup = showPopup;
}
public void openPopup() {
this.showPopup = true;
}
public void closePopup() {
this.showPopup = false;
this.usuario = new Usuario();
}
public String edit(Usuario usuario) {
this.usuario = usuario;
this.showPopup = true;
return "usuariosList";
}
public String delete(Usuario usuario) {
adminService.delete(usuario);
return "usuariosList";
}
public String save() {
try {
usuario.setTutor(adminBean.getLoggedTutor());
adminService.save(usuario);
} catch (DAOException ex) {
Logger.getLogger(TutoresBean.class.getName()).log(Level.SEVERE, null, ex);
}
usuario = new Usuario();
this.showPopup = false;
return "usuariosList";
}
public void formListener(FileEntryEvent e) {
System.out.println("Entro");
FileEntry fe = (FileEntry)e.getComponent();
FileEntryResults results = fe.getResults();
//other stuff
}
}
Update 2
I think I figured out why is not working, but need some help with the fix. I made the corrections as #fischermatte advice me, but didn't work.
To reach this page with the form, first have to navigate throw a the main page /admin/admin.html, if a look the URL in the browser appears http://localhost:8084/iTablero/admin/admin.html. This page has a menu, one of this menu options bring me to the page with the problematic form. But, because is an AJAX call (if i'm not wrong) the URL in the browser does not change, it keeps the http://localhost:8084/iTablero/admin/admin.html. And the fileEntry never calls the listener.
Now, if I enter the URL by myself http://localhost:8084/iTablero/admin/usuariosList.html, the page is displayed correctly as before, but now THE FILEENTRY WORKS PERFECTLY!!!
I have no idea how to fix this, will have to use redirects? I think is something around AJAX.......help pls! :-D
Update 3
That is the menu, without redirect is not working.
<h:form>
<ice:menuBar orientation="horizontal">
<ice:menuItem value="Tutores" action="tutoresList"/>
<ice:menuItem value="Usuarios" action="usuariosList"/>
<ice:menuItem value="Tableros" action="tablerosList"/>
<ice:menuItem value="Simbolos" action="simbolosList"/>
<ice:menuItem value="Estadisticas" action="estadisticas"/>
<ice:menuItem value="Salir" action="#{adminBean.logout()}"/>
</ice:menuBar>
</h:form>
With action="usuariosList?faces-redirect=true" works fine.
Already test with forward navigation to a basic page form with only a FileEntry and doesn't work too. Again, if I use redirect, works fine. I think is some kind of issue with this component and forward navigation.
You have to use JSF's commandbutton instead of icefaces's: <h:commandButton type="submit" value="Subir archivo"/>. It is a known issue in ICEFaces, see ace:fileEntry wiki.
Update 1
Plus you either remove the rendered attribute in the popup or update the popup when opening it like here:
<h:form>
<h:commandButton value="Show Popup" action="#{usuariosBean.showPopupAction}">
<f:ajax render=":popupPanelGroup"/>
</h:commandButton>
</h:form>
<h:panelGroup id="popupPanelGroup">
<ice:panelPopup visible="#{usuariosBean.showPopup}" rendered="#{usuariosBean.showPopup}" modal="true" autoCentre="true">
...
</ice:panelPopup>
</h:panelGroup>

Resources