ViewScoped bean reconstructs when using AJAX rendering one of its parent elements - ajax

I have a ViewScoped CDI bean (javax.faces.view.ViewScoped). It reconstructs (calls a #PostConstruct method) when an ajax render its parent element. What should I do?
Bean:
import javax.annotation.PostConstruct;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
#Named("test")
#ViewScoped
public class TestBean implements Serializable {
private List<Integer> items;
#PostConstruct
private void postConstruct() {
Logger.getLogger("asd").log(Level.INFO, "construct");
items = new ArrayList<Integer>();
items.add(0);
items.add(1);
items.add(3);
items.add(4);
items.add(7);
items.add(10);
}
public List<Integer> getItems() {
return items;
}
public void setItems(List<Integer> items) {
this.items = items;
}
}
View:
<?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"
xmlns:pt="http://xmlns.jcp.org/jsf/passthrough">
<h:head>
<title>Simple JSF Facelets page</title>
</h:head>
<h:body>
<h:form>
<h:commandButton value="No reconstructing">
<f:ajax render=":panel" />
</h:commandButton>
</h:form>
<h:panelGrid id="panel">
<h:panelGroup>
<h:form>
<h:commandButton value="Strange reconstructing occurs">
<f:ajax render=":panel" />
</h:commandButton>
</h:form>
<ui:repeat value="#{test.items}" var="i">
#{i}
</ui:repeat>
</h:panelGroup>
</h:panelGrid>
</h:body>
</html>
Firstly click on the first button.

Related

f:ajax does not render the outputPanel until I refresh

Every time I debug the application and type something in the Textbox, the Controller remember only when I refresh the page.
Without the ajax Tag it's working fine. So my guess: the rendering of the outputPanel does not Work. I set Breakpoints (ajax listener and field setter are both called) and tested it many times and the outcome was the controller only works when i clicked the button and then refreshed the page. Referring JSF, I work with Eclipse for Java EE and Tomcat v.9.0 and earlier.
Strange thing is that the execute attribute only has the id for the name input in its execute attribute and still the listener is called (sysout is printed), this is not to be expected accordimg to #9 in commandButton/commandLink/ajax action/listener method not invoked or input value not set/updated. But changing it to #form does not change it
new.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:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
>
<h:head>
</h:head>
<h:body>
<h:form id="formID">
<h:inputText id="name" value="#{LayoutController.name}"></h:inputText>
<h:commandButton value="Welcome Me">
<f:ajax event="click" listener="#{LayoutController.listen}" execute=":formID:name" render=":formID:output"/>
</h:commandButton>
<h:panelGroup id="output">
<h:outputText value="#{LayoutController.name}"/>
</h:panelGroup>
</h:form>
</h:body>
</html>
LayoutController.java:
package Template;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.event.AjaxBehaviorEvent;
#ManagedBean(name="LayoutController")
#SessionScoped
public class LayoutController{
private String name;
public LayoutController() {
this.name="";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void listen (AjaxBehaviorEvent event) {
this.name = this.name + " ! ";
System.out.println("Clicked");
}
}

#ViewScoped #PostContruct is called upon every ajax request

Using Primefaces 5.0, JSF 2.2.7, deployed on EAP 6.1.
I have this Managed Bean below.
import hh.bean.Service;
import hh.dao.ServiceDao;
import hh.dao.impl.ServiceDaoImpl;
import java.io.Serializable;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean
#ViewScoped
public class View1 implements Serializable {
private static final long serialVersionUID = 1L;
private ServiceDao serviceDao = new ServiceDaoImpl();
#PostConstruct
public void init() {
System.out.println(View1.class.getName() + ": init() " + this);
}
public List<Service> getServices(){
return serviceDao.getAllServices();
}
}
I'm calling it from the xhtml below.
<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"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>Home Web</title>
<f:facet name="first">
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type"
content="text/html; charset=UTF-8" />
<meta name="viewport"
content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<meta name="apple-mobile-web-app-capable" content="yes" />
</f:facet>
</h:head>
<h:body>
<h:outputStylesheet library="css" name="newcss.css" />
<p:dataTable var="service" value="#{view1.services}">
<p:column style="width:16px">
<p:rowToggler />
</p:column>
<p:column headerText="Id">
<h:outputText value="#{service.id}" />
</p:column>
<p:column headerText="xxxx">
<h:outputText value="#{service.description}" />
</p:column>
<p:rowExpansion>
<p:dataTable var="sv" value="#{view1.services}">
<p:column headerText="Id">
<h:outputText value="#{sv.id}" />
</p:column>
</p:dataTable>
</p:rowExpansion>
</p:dataTable>
</h:body>
</html>
I noticed every time I expand the row my init() gets called. I thought #ViewScoped lives on when the request stays on the same page.
When I switch to #SessionScoped, init() does not get called when I expand a row.
Edit 1: Put the entire xhtml in, specify jsf version/impl
Edit 2: Fixed this issues by surrounding the p:dataTable with h:form. Not sure why that fixed it...
Fixed this issues by surrounding the p:dataTable with h:form. Not sure why that fixed it...
The JSF view state is maintained by javax.faces.ViewState hidden input field of the <h:form>. If you don't use a <h:form>, then PrimeFaces won't be able to find that hidden input field in order to pass its value along with the jQuery ajax request.
If this information is absent in the (ajax) request, then JSF will simply create a brand new view and inherently also all view scoped beans associated with it.

Why is this Ajax Call not Working?

Trying to use an ajax request to render a label without refreshing the entire page. So far every time I click the command button the whole page refreshes still and I can't seem to figure out what I am doing wrong.
Search By Title..
<h:commandButton class="addButton"
id="checkStatusButton"
value ="Check Status"
action = "#{itemWeb.findItem}">
<f:ajax execute="checkStatusForm"
event="click"
render="statusLabel"/>
</h:commandButton>
<h:outputText id="statusLabel"
value="#{itemWeb.foundItem.status}">
</h:outputText>
The page refresh because you do not use JSF Standard tags(h:head, h:body).
Thus, you should change the index.xhtml to below example.
<!--
Index.html setup
Holds the form for input data
-->
<!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:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<link href='http://fonts.googleapis.com/css?family=Roboto'
rel='stylesheet' type='text/css'></link>
<link href='resources/css/main.css'
rel='stylesheet' type='text/css'></link>
<title>
<ui:insert name="title"
Library Management System
</ui:insert>
</title>
<!--
Quick style setup..
-->
</h:head>
<h:body>
<h:form id="checkStatusForm">
<div class="group">
<h:inputText id="searchCheckInput"
value="#{itemWeb.searchString}">
</h:inputText>
<label>Search By Title..</label>
<span class="highlight"></span>
<span class="bar"></span>
</div>
<h:commandButton class="addButton"
id="checkStatusButton"
value ="Check Status"
action ="#{itemWeb.findItem}">
<f:ajax execute="checkStatusForm"
event="action"
render="statusLabel"/>
</h:commandButton>
<h:outputText id="statusLabel"
value ="#{itemWeb.foundItem.status}">
</h:outputText>
</h:form>
</h:body>
</html>
See also: Adding HTML Head and Body Tags
Try to process only the desired field rather than the whole form, in the execute attribute:
<h:commandButton class="addButton" id="checkStatusButton" value ="Check Status" action = "#{itemWeb.findItem}">
<f:ajax execute="searchCheckInput" event="click" render="statusLabel"/>
</h:commandButton>
You need to use event="action" instead of event="click". The event="action" is namely the default event the is listening on when nested in an h:commandButton component.
An example is shown below.
xhtml
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<f:view contentType="text/html">
<h:head>
<f:facet name="first">
<meta content='text/html; charset=UTF-8' http-equiv="Content-Type"/>
<title>ajax-call</title>
</f:facet>
</h:head>
<h:body>
<h:form id="checkStatusForm">
<h:inputText id="searchCheckInput"
value="#{itemWeb.searchString}">
</h:inputText>
<label>Search By Title..</label>
<br/>
<h:commandButton class="addButton"
id="checkStatusButtonListener"
value ="Check Status (Listener)"
actionListener="#{itemWeb.findItemListener}">
<f:ajax execute="checkStatusForm"
event="action"
render="statusLabel"/>
</h:commandButton>
<h:commandButton class="addButton"
id="checkStatusButton"
value ="Check Status"
action="#{itemWeb.findItem}">
<f:ajax execute="checkStatusForm"
event="action"
render="statusLabel"/>
</h:commandButton>
<br/>
<h:outputText id="statusLabel"
value ="#{itemWeb.foundItem.status}">
</h:outputText>
</h:form>
</h:body>
</f:view>
</html>
managedbean
package com.wittakarn.view;
import com.wittakarn.model.Item;
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.event.ActionEvent;
/**
*
* #author Wittakarn
*/
#ViewScoped
#ManagedBean(name = "itemWeb")
public class ItemWeb implements Serializable{
private String searchString;
private Item foundItem;
public ItemWeb(){
foundItem = new Item();
}
public String getSearchString() {
return searchString;
}
public void setSearchString(String searchString) {
this.searchString = searchString;
}
public Item getFoundItem() {
return foundItem;
}
public void setFoundItem(Item foundItem) {
this.foundItem = foundItem;
}
public void findItem(){
foundItem.setStatus("status A");
}
public void findItemListener(ActionEvent event){
foundItem.setStatus("status B");
}
}
domain
package com.wittakarn.model;
import java.io.Serializable;
/**
*
* #author Wittakarn
*/
public class Item implements Serializable{
private String status;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}

f:ajax listener not invoked

Whatever I do, I can't make sense of the listener attribute of the f:ajax tag. The method won't get invoked. I don't get any error messages. Here's an example:
test.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:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>
Example
</title>
</h:head>
<h:body>
<h:form>
<h:selectOneMenu value="#{testBean.value}">
<f:selectItem itemLabel="1" itemValue="1" />
<f:selectItem itemLabel="2" itemValue="2" />
<f:ajax render="messages" listener="#{testBean.processAjaxBehaviour}" onevent="test" />
</h:selectOneMenu>
<h:messages id="messages" />
</h:form>
<script type="text/javascript">
function test(event)
{
alert(event.status);
}
</script>
</h:body>
</html>
TestBean.java
package test;
import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.event.AjaxBehaviorEvent;
import javax.faces.event.AbortProcessingException;
#ManagedBean
#ViewScoped
public class TestBean implements Serializable
{
int value = 2;
public int getValue()
{
return value;
}
public void setValue(int value)
{
value = value;
}
#PostConstruct
public void init()
{
System.out.println("Done constructing testBean.");
}
public void processAjaxBehaviour(AjaxBehaviorEvent event) throws AbortProcessingException
{
System.out.println("Processing AJAX behaviour.");
}
}
The function test is called three times, as expected, and I get the status "success". The listener processAjaxBehaviour isn't called however.
The init method is called. The second option element rendered by the f:selectItem gets selected as expected.

JSF h:message or p:message does not work

My application runs in glassfish. I do not see any h:message or h:messages (or, the primefaces messages)... Is there any configuration, I have to specify either in web.xml or faces-config.xml ?
Currently I have no way to see if any validation fails, even, required="true" with requiredMessages="Some Value" does not work..
JSF
growl -> id="growl"
commandButton -> update="growl"
<?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:p="http://primefaces.prime.com.tr/ui"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:form>
<p:growl id="growl" showDetail="false" sticky="true" />
<p:commandButton value="Update" update="growl" actionListener="#{userPageBacking.updateUser}"/>
</h:form>
</h:body>
</html>
Backing Bean
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.event.ComponentSystemEvent;
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* #author ezehrt
*/
#ManagedBean
#RequestScoped
public class UserPageBacking {
public void updateUser() {
FacesContext fc = FacesContext.getCurrentInstance();
if (fc.isValidationFailed()) {
return;
}
FacesMessage msg = new FacesMessage("fehlermeldung", "fehlermeldung");
msg.setSeverity(FacesMessage.SEVERITY_ERROR);
fc.addMessage("fehlermeldung", msg);
fc.renderResponse();
}
}

Resources