This question already has an answer here:
JSF returns blank/unparsed page with plain/raw XHTML/XML/EL source instead of rendered HTML output
(1 answer)
Closed 7 years ago.
i cannot find out what i am doing wrong, so that my dataTable is not shown on the webpage.
The User class i created is not really complicated but has more than these three properties which i try to set in the bean.
The only thing that is displayed is the facet Text "Test Header"
What am i missing?
Testmonitor .xhtml
<?xml version="1.0" encoding="UTF-8"?>
<!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"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<head>
<title>Test Monitor</title>
<meta content='text/html; charset=UTF-8' http-equiv="Content-Type"/>
</head>
<body onload="#{testdata.createUsers()}">
<p:dataTable id="overviewTable" var="collector" sortOrder="descending" value="#{testdata.userList}">
<f:facet name="header">
Test Header
</f:facet>
<p:column headerText="IP">
<h:outputText value="#{collector.ip}" />
</p:column>
<p:column headerText="CollectorID">
<h:outputText value="#{collector.collectorId}" />
</p:column>
<p:column headerText="ID">
<h:outputText value="#{collector.id}" />
</p:column>
</p:dataTable>
</body>
</html>
Bean:Testdata.java
package MonitorTest;
import UserAndPosition.User;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import java.util.List;
#ManagedBean
#SessionScoped
public class Testdata {
private List<User> UserList;
private User aUser=new User();
public void createUsers() {
aUser.setCollectorId("AnyCollectorID");
aUser.setId("WND9L320NDUD");
aUser.setIp("192.168.2.1");
UserList.add(aUser);
//System.out.println("Post Construct durchgelaufen");
}
/**
* Regular Getter- and Setter Methods.
*/
public Testdata() {
}
public List<User> getUserList() {
return UserList;
}
public void setUserList(List<User> UserList) {
this.UserList = UserList;
}
}
Thanks in advance
I haven't tested, but you definitely need h:head and h:body instead.
Also in onload you can use only script (not Expression Language), annotate createUsers() with #PostConstruct instead - then the method will run whenever the bean is being created.
I found the solution: Before the error I changed the project properties in Netbeans so that not the index.xhtml would show up as initial page. i just entered "/Testmonitor.xhtml" as relative path. the "/faces" path of the url was then missing an all JSF or primefaces components did not show up (even though i did not get any error message or so..)
I dont know why this "/faces" in the url is so important, but obviously it is!
Can someone explain what /faces causes?
Related
i have a requirement like i need to show/hide datatable upon button click . I tried implementing it , but its not working . below is the code .
please let me know if we can do with ajax . It is possible only if i set ajax to false .
<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>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>hello world</title>
</h:head>
<h:body>
<h:form>
<p:outputPanel id="panel" rendered="#{bye1.showtable}">
<p:dataTable value="#{bye1.carmodel}" var="cartypes">
<p:column headerText="Model">
<h:outputText value="#{cartypes.carname}">
</h:outputText>
</p:column>
<p:column headerText="Location">
<h:outputText value="#{cartypes.location}"></h:outputText>
</p:column>
<p:column headerText="Price">
<h:outputText value="#{cartypes.rate}"></h:outputText>
</p:column>
</p:dataTable>
</p:outputPanel>
<p:commandButton value="show" action="#{bye1.enabletable}" update="panel">
</p:commandButton>
</h:form>
</h:body>
</html>
package lifecycle;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
public class bye {
private String output;
private Boolean showtable;
private List<cars> carmodel;
public List<cars> getCarmodel() {
System.out.println("cars populated...........");
return carmodel;
}
#PostConstruct
public void bye1() {
System.out.println("constructor called");
carmodel = new ArrayList<cars>();
output = "hai";
carmodel.add(new cars("ford","chennai","4 laks"));
carmodel.add(new cars("AUDI","chennai","44 laks"));
}
public String getOutput() {
return output;
}
public Boolean getShowtable() {
return showtable;
}
public String enabletable() {
showtable = true;
return "";
}
}
Any help ?
Thanks in Advance
Use an actionListener on your commandbutton instead of action.
"A return value of an empty string or the same view ID will also return to the same page, but recreate the view scope and thus destroy any currently active view scoped beans and, if applicable, recreate them:"
Differences between action and actionListener
Also consider the use of Boolean vs boolean.
It also seems like your class is missing the #ManagedBean and scope annotations?
I think the update="panel" is not working properly, and the panel component is not getting updated. When you disable ajax, the whole page gets update, and maybe this is why the update works only with ajax="false".
Can you try this and tell me if it works now ? :
<p:commandButton value="show" actionListener="#{bye1.enabletable}" ajax="true" update=":#{p:component('panel')}">
</p:commandButton>
i found this solution .
i did a change like this
<p:outputPanel id="panel" >
<p:dataTable value="#{bye1.carmodel}" var="cartypes"
rendered="#{bye1.showtable}">
..............
</p:dataatble>
</p:outputPanel>
set the rendered attribute to the datatable rather to the outputpanel .
This question already has answers here:
How to dynamically add JSF components
(3 answers)
Closed 6 years ago.
A click on a commandButton should trigger an action in a ManagedBean: to add a new "outputText" component to the current page.
The overall idea is to have the page changed dynamically with user action, with server side action because new elements added to the page need data from a db to be laid out.
-> How do I add a component to the page from a managed bean in jsf / primefaces? Let's say that the elements should be added in an existing div like:
<div id="placeHolder">
</div>
(this div could be changed to a jsf panel if needs be)
Note: if alternative methods are better to achieve the same effect I'd be glad to learn about them.
I'll provide you another solution apart from the one you posted. Basically it has a List of given outputs, which is increased everytime the button is pushed. That should render exactly the same DOM tree as the solution you stated:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<title>Tiles</title>
<h:outputStylesheet name="css/320andup_cle.css" />
</h:head>
<h:body>
<h:form>
<h:commandButton actionListener="#{bean.createNewTile}" title="new"
value="new" />
</h:form>
<h:panelGroup layout="block" id="tiles">
<ui:repeat var="str" value="#{bean.strings}">
<h:panelGroup>
<h:outputText styleClass="tile" value="#{str}" />
</h:panelGroup>
</ui:repeat>
</h:panelGroup>
</h:body>
</html>
#ManagedBean
#SessionScoped
public class Bean {
List<String> strings = new ArrayList<String>();
public List<String> getStrings() {
return strings;
}
public void createNewTile() {
strings.add("output");
}
}
Apart from being much simpler IMHO, it has a main advantage: it doesn't couple your server side code to JSF implicit API. You can change the #ManagedBean annotation for #Named if you want it to be a CDI managed bean.
The solution:
This is a jsf page with a button creating a new div each time it is clicked:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>Tiles</title>
<h:outputStylesheet name="css/320andup_cle.css" />
</h:head>
<h:body>
<h:form>
<h:commandButton actionListener="#{bean.createNewTile()}" title="new" value="new"/>
</h:form>
<h:panelGroup layout="block" id="tiles">
</h:panelGroup>
</h:body>
</html>
The Managed Bean:
#Named
#SessionScoped
public class Bean implements Serializable {
private UIComponent found;
public void createNewTile() {
HtmlPanelGroup div = new HtmlPanelGroup();
div.setLayout("block");
HtmlOutputText tile = new HtmlOutputText();
tile.setValue("heeeeeRRRRRRRRRRRRRR ");
tile.setStyleClass("tile");
div.getChildren().add(tile);
doFind(FacesContext.getCurrentInstance(), "tiles");
found.getChildren().add(div);
}
private void doFind(FacesContext context, String clientId) {
FacesContext.getCurrentInstance().getViewRoot().invokeOnComponent(context, clientId, new ContextCallback() {
#Override
public void invokeContextCallback(FacesContext context,
UIComponent component) {
found = component;
}
});
}
}
See this app built with this logic of dynamically generated components: https://github.com/seinecle/Tiles
This question already has answers here:
How to ajax-refresh dynamic include content by navigation menu? (JSF SPA)
(3 answers)
Closed 6 years ago.
I'm working on a schoolproject and encountered a problem with dynamic ui insert.
I'm currently working in JSF2.0 / Primefaces 3 M1.
The main problem is that I want to have a Primefaces dialog with dynamic content which is changed through means of a menubar.
The dialog component contains a ui:include tag with src set to a managed bean property.
The menuitems are linked to bean methods that change this property.
The main problem is that the variable is not changing at all, I'm currently using alerts to show this variable.
Currently working with remoteCommand but I've also already tried with action/actionlistener in the menuitem component. Any help would be appreciated.
This is the main page with the menubar and the dialog.
<?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:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.prime.com.tr/ui"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<title>KunstInHuis: Main</title>
</h:head>
<h:body style="font-size: 12px;">
<h:form id="mainForm">
<f:metadata>
<f:event type="preRenderView" listener="#{login.verifyAccess}"/>
</f:metadata>
<p:remoteCommand name="lazyANew" actionListener="#{main.goToAboNew}" onsuccess="alert('test')"/>
<p:remoteCommand name="lazyAList" actionListener="#{main.goToAboList}" onsuccess="alert('test')" />
<p:remoteCommand name="lazyASearch" actionListener="#{main.goToAboSearch}" onsuccess="alert('test')" />
<p:menubar autoSubmenuDisplay="true">
<p:submenu label="Abonnementen">
<p:menuitem value="Nieuw" onclick="lazyANew()" onsuccess="alert('#{main.goToPage}')"/>
<p:menuitem value="Lijst" onclick="lazyAList()" onsuccess="alert('#{main.goToPage}')" />
<p:menuitem value="Zoek" onclick="lazyASearch()" onsuccess="alert('#{main.goToPage}')"/>
</p:submenu>
<p:submenu label="Klanten">
<p:menuitem value="Nieuw" url="#" />
<p:menuitem value="Lijst" url="#"/>
</p:submenu>
<p:submenu label="Kunstwerken">
<p:menuitem value="Nieuw" url="#" />
<p:menuitem value="Lijst" url="#"/>
</p:submenu>
</p:menubar>
</h:form>
<p:dialog id="mainDialog" header="Abonnement aanmaken" widgetVar="dlg0" minHeight="300" minWidth="450"
resizable="true" modal="false" >
<ui:include src="#{main.goToPage}" />
</p:dialog>
</h:body>
And this is my backing bean.
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.page.beans;
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.event.ActionEvent;
/**
*
* #author wezlee
*/
#ManagedBean(name = "main")
#ViewScoped
public class mainMenuBean implements Serializable {
private boolean panelRender=false;
private String goToPage = "./includes/forms/abboCreate.xhtml";
/** Creates a new instance of mainMenuBean */
public mainMenuBean() {
}
public void goToAboNew(ActionEvent e){
goToPage="./includes/forms/abboCreate.xhtml";
}
public void goToAboNew(){
goToPage="./includes/forms/abboCreate.xhtml";
}
public void goToAboList(ActionEvent e){
goToPage="./includes/forms/abboList.xhtml";
}
public void goToAboList(){
goToPage="./includes/forms/abboList.xhtml";
}
public void goToAboSearch(ActionEvent e){
goToPage="./includes/forms/abboSearch.xhtml";
}
public void goToAboSearch(){
goToPage="./includes/forms/abboSearch.xhtml";
}
/**
* #return the goToPage
*/
public String getGoToPage() {
return goToPage;
}
public void setGoToPage(String src){
this.goToPage=src;
}
}
Actually, I think the methods to update the backing value look like they work just fine. The issue is probably in how you are trying to display it. When the page is initially rendered, the value for goToPage is evaluated and placed into the content of the page returned to the user's browser. Once this value is set on the user's side, it will not re-synchronize with the backing bean until that part of the page is re-rendered.
I believe a prime faces remoteCommand allows you to do this with AJAX using update="client side id". I'm not a prime faces guy though, so I put together this little test. First change your remoteCommands:
<p:remoteCommand name="lazyANew" actionListener="#{main.goToAboNew}" update="testOutput" />
<p:remoteCommand name="lazyAList" actionListener="#{main.goToAboList}" update="testOutput" />
<p:remoteCommand name="lazyASearch" actionListener="#{main.goToAboSearch}" update="testOutput" />
Then add a simple text field to your page content with the appropriate Id:
Page target: <h:outputText value="#{main.goToPage}" id="testOutput" />
Your output text should start synchronizing. As long as that works, you can simply re-target the update from testOutput to mainDialog and you should be in business.
I think I have run into a bug in Mojarra 2.1.0. Maybe I missed something but damned if I can see it.
I rely a lot of #ViewScoped beans to save state whilst the browser does a lot of AJAX to the server. I find when I use certain tags, the #ViewScoped bean starts getting re-instantiated when it shouldn't be. Here is my test case backing bean:
/*
* TestStuff.java
*/
package test;
import java.io.Serializable;
import java.util.Arrays;
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 javax.faces.event.ActionEvent;
/**
* Backing bean for test.xhtml -- working out AJAX/SVG connection
*
*/
#ManagedBean
#ViewScoped
public class TestStuff implements Serializable {
private int counter = 0;
public TestStuff() {
log("TestStuff(): {0}", this);
}
public String getRandomNumber() {
int i = (int) (Math.random() * 1000000.0);
return String.format("%d", i);
}
public int getCounter() { return counter; }
public List<String> getStuff() {
return Arrays.asList("big", "bad", "wolf");
}
public void pushButton(ActionEvent evt) {
log("TestStuff.pushButton({0}): {1}",
new Object[] { evt, ++counter });
}
}
And here is the JSF Facelets page that uses it:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.prime.com.tr/ui"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:head>
<title>Test Page</title>
</h:head>
<h:body>
<h1>Test Page</h1>
<p>If you are reading this text, the server
is not properly configured.</p>
<ui:composition id="compRoot" template="/template5.xhtml">
<ui:define name="content">
<h1>Test</h1>
<h:form id="formTest">
<p:commandButton value="Do Me"
actionListener="#{testStuff.pushButton}"
update="testUpdate" />
<p:panel id="testUpdate" >
<h:outputText value="Random output is: " />
<h:outputText
value="#{testStuff.randomNumber}"
/>
<h:outputText value=" Counter is: "/>
<h:outputText
value="#{testStuff.counter}"
/>
</p:panel>
<h:panelGrid columns="5" border="1" >
<c:forEach items="#{testStuff.stuff}" var="x">
<h:outputText value="#{x}" />
</c:forEach>
</h:panelGrid>
</h:form>
</ui:define>
</ui:composition>
</h:body>
</html>
So here is what goes wrong. When you click on the "Do Me" command button, a new instance of the backing bean gets created each time, just as if it were a #RequestScoped bean. I can see this via the log() call in the constructor.
If you change the bean to #SessionScoped, this doesn't happen. You get one instance of the bean no matter how many times the button is clicked.
HOWEVER -- if you leave it as #ViewScoped, and you take out the c:foreach element and its content, it now no longer re-instantiates the bean each click. In other words it now works as expected.
Is this a mojarra bug or am I doing something wrong here?
This is a known "bug": issue 1665. It's a chicken-egg issue with regard to partial state saving.
In your case, however, you could also just use <ui:repeat>.
<ui:repeat value="#{testStuff.stuff}" var="x">
<h:outputText value="#{x}" />
</ui:repeat>
Your best bet is to try to avoid JSTL tags when using #ViewScoped. The only alternative is to disable partial state saving by a context param in web.xml:
<context-param>
<param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
<param-value>false</param-value>
</context-param>
But it makes the views more memory hogging.
I have a listing page that goes to an add page. The add page has a name textbox whose value is bound to a session scoped bean.
The listing page has an add button that goes via an action method to the add page. This action method clears the object that the name textbox is bound to.
I also have a cancel button on the add page, which is bound to an action method that again clears the value that the name textbox is bound to.
If nothing is set to immediate, this all works fine.
However, if I set the cancel button to immediate, if I enter values in the name field, and then click cancel, the action method is fired and clears the object in the backing bean and goes to the listing page. If I then click add, the action method clears the object again (ignore if it's best method or not) and then goes to the add page. I would now expect the add page's name textbox to be empty, but it's not?! Surely, since the add button is not immediate, the values should be re-bound and empty?
Below is the relevant XHTML for the add button on the listing page
<h:commandButton id="addButton"
value="Add"
action="#{myBean.gotoAdd}"/>
Below is the relevant XHTML for the input box on the add page (myBean is session scoped), followed by that of the cancel button on the add page.:
<h:inputText id="newName"
value="#{myBean.newObject.name}"
binding="#{myBean.newNameInput}"
styleClass="name" />
<h:commandButton id="cancelButton"
value="Cancel" immediate="true"
action="#{myBean.cancelAdd}"
onclick="return confirm('You sure?');"/>
I almost never use the binding property of tags, except for when I need to identify which item of a list has had an action fired on it, so I am not particularly well-informed about its uses. But I know that without using binding your code would most likely work as you expected, so my expectation is that whatever javax.faces.component.UIxxx object you are binding to isn't getting reset correctly.
I'm having very similar problems right now.
Besides removing the binding and/or immediate attribute, try calling setSubmittedValue() on component with binding from action called upon click on 'add' button.
Alas, even if it helps you, you would still have to do it in any action that can lead to displaying same component after cancel.
That's why I'm still trying to figure out some better solution...
If you use immediate="true" then the value will be kept, this is how the parameter works. You should take a look at the following links:
http://wiki.apache.org/myfaces/How_The_Immediate_Attribute_Works
http://wiki.apache.org/myfaces/ClearInputComponents
Ok, here's an example that I did from scratch. I have two cancel buttons, one that is immediate, and one that isn't. Example of steps to reproduce:
Go to james-list page and click Add
The add page displays with empty fields. Enter values for all fields and click Add.
The listing page displays and is updated to include the new person. Click Add.
The add page displays with empty fields. Enter values for all fields and Click Cancel (Immediate)
The listing page displays and is unchanged. Click Add.
The add page displays however the fields are not empty as I would expect. Click Cancel.
The listing page displays and is unchanged. Click Add.
The add page displays and NOW the fields are not empty.
James.java:
package com.jamiebarrow;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.component.UIComponent;
#ManagedBean
#SessionScoped
public class James {
private UIComponent idComponent;
private UIComponent firstNameComponent;
private UIComponent lastNameComponent;
public UIComponent getIdComponent() {
return idComponent;
}
public void setIdComponent(UIComponent idComponent) {
this.idComponent = idComponent;
}
public UIComponent getFirstNameComponent() {
return firstNameComponent;
}
public void setFirstNameComponent(UIComponent firstNameComponent) {
this.firstNameComponent = firstNameComponent;
}
public UIComponent getLastNameComponent() {
return lastNameComponent;
}
public void setLastNameComponent(UIComponent lastNameComponent) {
this.lastNameComponent = lastNameComponent;
}
private List<Person> personResults;
private Person person;
public James() {
personResults = new ArrayList();
personResults.add(new PersonBuilder(1, "Bob", "Uncle").build());
personResults.add(new PersonBuilder(2, "Jack", "Black").build());
}
public List<Person> getPersonResults() {
return personResults;
}
public void setPersonResults(List<Person> personResults) {
this.personResults = personResults;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
private void clearPerson() {
person = new PersonBuilder().build();
}
public String gotoList() {
return "james-list";
}
public String gotoAdd() {
clearPerson();
return "james-add";
}
public String cancelAdd() {
clearPerson();
return gotoList();
}
public String addPerson() {
personResults.add(person);
return gotoList();
}
}
james-list.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-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>list page</title>
</h:head>
<body>
<div class="container">
<div class="content">
<h:messages showSummary="true" showDetail="false" errorClass="error" infoClass="info"
warnClass="warn"/>
<h:form>
<h:dataTable value="#{james.personResults}" var="person">
<h:column>
<f:facet name="header">Id</f:facet>
<h:outputText value="#{person.id}"/>
</h:column>
<h:column>
<f:facet name="header">Name</f:facet>
<h:outputText value="#{person.firstName}"/>
</h:column>
<h:column>
<f:facet name="header">Surname</f:facet>
<h:outputText value="#{person.lastName}"/>
</h:column>
</h:dataTable>
<h:panelGroup layout="block">
<h:commandButton value="Add" action="#{james.gotoAdd}"/>
</h:panelGroup>
</h:form>
</div>
</div>
<ui:debug hotkey="L" rendered="true"/>
</body>
</html>
james-add.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-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>add page</title>
</h:head>
<body>
<div class="container">
<div class="content">
<h:messages showSummary="true" showDetail="false" errorClass="error" infoClass="info"
warnClass="warn"/>
<h:form>
<fieldset>
<legend>Add Person</legend>
<h:panelGrid columns="2">
<h:outputLabel for="PersonId" value="Id:"/>
<h:inputText id="PersonId" value="#{james.person.id}" binding="#{james.idComponent}"/>
<h:outputLabel for="PersonFirstName" value="First Name:"/>
<h:inputText id="PersonFirstName" value="#{james.person.firstName}" binding="#{james.firstNameComponent}"/>
<h:outputLabel for="PersonLastName" value="Last Name:"/>
<h:inputText id="PersonLastName" value="#{james.person.lastName}" binding="#{james.lastNameComponent}"/>
</h:panelGrid>
<h:panelGroup layout="block">
<h:commandButton value="Add" action="#{james.addPerson}"/>
<h:commandButton value="Cancel (immediate)" action="#{james.cancelAdd}" immediate="true"/>
<h:commandButton value="Cancel" action="#{james.cancelAdd}"/>
</h:panelGroup>
</fieldset>
</h:form>
</div>
</div>
<ui:debug hotkey="L" rendered="true"/>
</body>
</html>