JSF Java Server Faces

Introductie

JSF, de JavaServer Faces technologie biedt de mogelijkheid om web pagina’s te maken.
Dit is gebaseerd op HTML en JSP. Er wordt gebruik gemaakt van web page componenten, net als HTML , maar dan een uitgebreidere set met uitgebreidere mogelijkheden.
JSF pagina’s worden vanaf JEE6 / JSF 2 opgeslagen met de extensie .xhtml
Via de servlet redirection in web.xml wordt er , net als bij .jsp pages voor gezorgd dat een .jsf extensie wordt doorgestuurd naar overeenkomende .xhtml file die naar een servlet, in dit geval FacesServlet wordt verzonden.
Een belangrijk concept van JSF, behalve het vormgeven van schermen, is het gebruik van zgn Backing Beans of Managed Beans. Elke JSF page kan koppelingen hebben met één of meer van deze backing beans voor de opslag van form data en het uitvoeren van acties.
Het refereren naar backing beans vindt plaats met de zgn Expression Language (EL).
EL maakt gebruik van #{….} haken om te refereren naar Backing Beans en de properties en methods daarin.

JSF Page

Een JSF Page bestaat, net als een HTML pagina, uit de initiele DOCTYPE en de tags.
In de HTML tag worden t.b.v. JSF verschillende namespaces met bijbehorende taglibraries gedefinieerd. Deze namespaces definieren elk een JSF specifieke letter of lettercombinatie waarmee JSF tags worden gemaakt. Zo wordt de letter h gebruikt voor JSF uitbreidingen van standaard html tags. De letter ‘f’ wordt gebruikt voor de daaraan toegevoegde JSF core tags.
Zie onder een voorbeeld van een basic 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://java.sun.com/jsf/html">

    <h:head>
    	<title>JSF 2.0 Hello World</title>
    </h:head>
    <h:body bgcolor="white">
    	<h3>JSF 2.0 Hello World Example - welcome.xhtml</h3>
    	<h4>Welcome #{helloBean.name}</h4>
    </h:body>
</html>

Facelets

Facelets technologie maakt het mogelijk om gebruik te maken van templates en custom components. Bij gebruik van Facelets wordt de ui namespace toegevoegd en komen altijd de tags, waarbinnen de feitelijke inhoud komt.

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

    <ui:composition template="/templates/template.xhtml">
        <h1>Departments</h1>
	<h:form id="frmListDepartments">
	</h:form>
    </ui:composition>
</html>

In de <ui:composition> tag wordt gerefereerd naar een template.xhtml bestand. In dat template bestand worden de generieke definities en stuctuur van de pages gedefinieerd.

JSF Template

Het JSF Template bestand wordt gerefereerd in elke JSF page in de tag. Het template bevat de generieke definities en structuur opzet die hiermee op één plek wordt gedefinieerd en beheerd. Hieronder een voorbeeld van het template bestand.

<!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"
      xmlns:mycomps="http://java.sun.com/jsf/composite/components">
    <h:head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>
            <ui:insert name="pageTitle">
                <h:outputText value="Title"></h:outputText>
            </ui:insert>
        </title>
        <h:outputScript     library="js" name="menu.js" target="head"/>
        <h:outputStylesheet library="css" name="table.css"  />
    </h:head>
    <h:body>
		<div align="left">
		<h:panelGrid  width="990">
			<mycomps:menu/>
			<h:form id="navigationBar">
				<div class="navBarClass">
					<ui:insert name="navigationBar"></ui:insert>
				</div>
			</h:form>
			<h:panelGrid columns="1"  headerClass="tableHeader" footerClass="tableFooter" cellpadding="0" cellspacing="0">
				<ui:insert name="content"></ui:insert>
			</h:panelGrid>
			<h:panelGroup>
				<ui:include src="./footer.xhtml" />
			</h:panelGroup>
		</h:panelGrid>
		</div>
   </h:body>
</html>

Typisch generieke content vormt de <HEAD> tag met o.a. alle links naar JavaScript en CSS bestanden. In de template worden met <ui:insert> placeholders gedefinieerd die in de verschillende pages worden vervangen door actuele inhoud middels de <ui:define> tag. Zo zien we in het voorbeeld de <ui:insert> met naam “pageTitle” met een default waarde “Title”. Deze inhoud wordt in de actuele page vervangen met een tag, bijv:

	<ui:define name="pageTitle">
		<h:outputText value="Departments"></h:outputText>
	</ui:define>

In voorbeeld hierboven wordt dus de value vervangen door “Departments”. Op deze wijze wordt bijv. de pagina titel in elke page ingevuld. De <body> tag staat hier ook in de template, met vervolgens een algemene layout gemaakt met panelGrid elementen. In de kern van deze layout vinden we de <ui:insert> “content”. Dat is de plek waar verder alle concrete inhoud van elke page terecht komt. Elke page zal met een <ui:define> de werkelijke content voor die plek gaan definieren.

Custom Components

in het template zien we als namespace ook de definitie :

xmlns:mycomps="http://java.sun.com/jsf/composite/components

Deze definieert een custom tag “mycomps”. Daarmee is het mogelijk om eigen gemaakte componenten te gebruiken. In het voorbeeld worden deze gedefinieerd met de tekst “mycomps”. Verderop in de template zien we ook dat deze custom tag wordt gebruikt : <mycomps:menu/> Deze definieert op die plek de eigen gemaakte component “menu”. Deze menu component is opgeslagen in het bestand menu.xhtml in de directory /resources/components. In deze directory bevindt zich voor elk component een .xhtml file. In onderstaand voorbeeld de structuur van een custom component:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html …>

    <composite:interface>
        <composite:attribute name="image"/>
    </composite:interface>

    <composite:implementation>
    </composite:implementation>
</html>

In het <composite:interface> tag worden de eventuele input parameters middels tag attributen gedefinieerd. Deze attributen zoals hier “image” kunnen worden gebruikt in de rest van de custom component binnen de <composite:implementation> tags.

JSF Backing Bean (Managed Bean)

In onderstaand voorbeeld zien we een form in een JSF Page. Binnen het form wordt een <h:dataTable> component gedefinieerd waarvan de inhoud is gekoppeld aan een backing bean die de inhoud bevat. In het value attribuut van de dataTable wordt met de EL constructie #{departmentBean.departments} gerefereerd naar de backing bean “departmentBean” en daarin naar departments wat de List bevat met elementen van de Entity bean “Department”. Een 2e attribuut “var” definieert een variabele “d”, die weer een instantie van de Department lijst bevat. Deze variabele wordt weer gebruikt in EL constructies binnen de tabel kolom definities. Daarin worden de attributen van Department instantie per kolom gekoppeld. We zien in dit geval een bijzondere constructie waarin als backing bean een Session Bean wordt gebruikt. Dit is eigenlijk niet zo mooi, want nu wordt in de Session Enterprise Bean kennis opgenomen van de schermen. Maar het voorkomt wel weer een extra laag Classes.

<h:form id="frmListDepartments">
       <h:dataTable value="#{departmentBean.departments}" var="d"
                  title="Departments"
                  id="dtDepartments"
                  styleClass="datatable"
    			  headerClass="datatableHeader"
    			  rowClasses="datatableRow1, datatableRow2"
                  >
         <h:column>
         	<f:facet name="header">Id</f:facet>
         	#{d.departmentId}
         </h:column>
         <h:column>
         	<f:facet name="header">Name</f:facet>
         	#{d.name}
         </h:column>
         <h:column>
         	<f:facet name="header">Address</f:facet>
         	#{d.address}
         </h:column>
         <h:column>
          	<f:facet name="header">Budget</f:facet>
        	#{d.budget}
         </h:column>
       </h:dataTable>
</h:form>

Een algemene JSF Backing Bean wordt gedefinieerd met de @ManagedBean annotatie. Aanvullend wordt de annotatie @SessionScoped of @RequestScoped gebruikt om de scope van de state te bepalen. Bijv:

ManagedBean(name="customer")
@SessionScoped
public class CustomerBean implements Serializable{
…
}

In het voorbeeld wordt echter i.p.v. de managed bean een Session Enterprise Bean gebruikt. Dit betreft het onderstaande voorbeeld. Daarin zien we de property “departments” die op table niveau werd gerefereerd.

@Stateless
@LocalBean
@Named
public class DepartmentBean {

    private List departments;

    public List getDepartments() {
    ………
    }
}

Als standaard naamgeving in backing bean referenties geldt de backing bean naam , maar dan beginnend met een kleine letter. Met de EL referentie “#{departmentBean.departments}” en de “var=”d”” gedefinieerde variabele “d” worden in de JSF page navigatie mogelijk naar de lijst gekoppelde Department Beans:

#{d.departmentId} , #{d.name} , #{d.address} , #{d.budget}

Die elk weer een referentie opleveren naar de Department Bean :

@Entity
public class Department implements Serializable {
	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private int departmentId;

	@Lob
	private String address;

	private int budget;

	@Lob
	private String name;

Behalve koppeling van Form data in backing bean properties is het ook nodig om actieve elementen zoals buttons te kunnen koppelen aan methods in de backing beans. Hieronder een voorbeeld van column definities, in dit geval niet van een standaard JSF table component, maar van een PrimeFaces component.

<p:column headerText="Actions">
   <p:commandLink id="selectButton" update=":form-createupdate:panelgrid"
       title="Edit" oncomplete="dlg.show()" process="@this">
       <h:outputText value="Edit" />
      	<f:setPropertyActionListener value="#{d}"
              target="#{departmentBean.selectedDepartment}" />
   </p:commandLink >
   |
   <p:commandLink  id="showDialogButton" update=":form-delete:confirmDialog"
     title="Delete" oncomplete="confirmation.show()"
     process="@this">
  	<h:outputText value="Delete" />
  	<f:setPropertyActionListener value="#{d}"
              target="#{departmentBean.selectedDepartment}" />
   </p:commandLink >
</p:column>

De PrimeFaces table component ziet er als volgt uit, met in de kolom “Actions” 2 links naar de Edit en Delete akties die hierboven staan gedefinieerd:

De commandLink definieert de teksten Edit en Delete met de ingesloten outputText tags. Als actie wordt met oncomplete de actie “dlg.show()” en “confirmation.show()” uitgevoerd. Dit betreft weer PrimaFaces dialog componenten die hiermee worden geopend. Met <f:setPropertyActionListener> wordt #{departmentBean.selecredDepartment} gerefereerd. Dat is de gekozen rij uit de tabel. Hieronder een voorbeeld van de confirmation dialog component uit dezelfde JSF Page die voor de delete actie wordt geopend.

<h:form id="form-delete">
   <p:confirmDialog id="confirmDialog" header="Confirm Delete"
                    severity="alert" widgetVar="confirmation">
	<f:facet name="message">
		<h:outputText value="Delete?" />
	</f:facet>

	<p:commandButton id="confirm" value="Yes" oncomplete="confirmation.hide()"
                         update=":form-table:datatable,:form-table:growlmessages"
	                 actionListener="#{departmentBean.deleteDepartment}"/>
       <p:commandButton id="decline" value="No" onclick="confirmation.hide()"
type ="button" />
   </p:confirmDialog>
</h:form>

Hierin zien we hoe met de commandButton “confirm” de callback method deleteDepartment() wordt aangeroepen. Dat is een speciale eventhandler method met de ActionEvent als parameter:

public void deleteDepartment(ActionEvent event)

Mapping FacesServlet

In de web.xml deployment constructor wordt de FacesServlet gedefinieerd en de mapping regels opgenomen naar de .xhtml bestanden. Hieronder het betreffende fragment uit web.xml :

  <servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.jsf</url-pattern>
  </servlet-mapping>
 <welcome-file-list>
  <welcome-file>welcome.xhtml</welcome-file>
 </welcome-file-list>

In dit geval worden de .xhtml bestanden in de browser gerefereerd met .jsf extensie.

JSF Page Navigatie

Klassiek wordt navigatie tussen JSF schermen geconfigureerd in het faces-config.xml bestand, zie onderstaand voorbeeld:

<navigation-rule>
   <from-view-id>page1.xhtml</from-view-id>
   <navigation-case>
       <from-outcome>page2</from-outcome>
       <to-view-id>/page2.xhtml</to-view-id>
   </navigation-case>
</navigation-rule>

In JEE6 / JSF 2.0 kan echter ook gebruik worden gemaakt van “implicit navigation”. Dit houdt in dat de outcome direct wordt gespecificeerd als de naam van de .xhtm page. Bijv navigeren van een page1.xhtml naar page2.xhtml via een commandButton gaat als volgt:

<h:form>
    <h:commandButton action="page2" value="Move to page2.xhtml" />
</h:form>

Er kan ook worden gekozen voor navigatie via de returnwaarde van methods in de backing bean. Hieronder een fragment uit de eerder getoonde PrimeFaces tabel met in de kolom “Details” een link van Departments Page naar de Employees Page.

<p:column headerText="Details">
   <p:commandLink id="employeesButton" update=":center"
    action="#{departmentBean.showEmployees}"
    value="Employees->" process="@this">
        <f:setPropertyActionListener value="#{d}"
        target="#{departmentBean.selectedDepartment}" />
   </p:commandLink>
</p:column>

Aan de commandLink is hier de method showEmployees() gekoppeld. Tegelijkertijd wordt met f:setPropertyActionListener de geselecteerde rij opgeslagen in #{departmentBean.selectedDepartment}.

Hieronder de method showEmployees() die niets ander doet dan als returnwaarde de link naar de employeeslistpf.xhtml teruggeven.

    public String showEmployees(){
	    return "/employee/employeelistpf";
    }

JSF Library concept

JSF Libary is bedoeld voor opslag van javascript, css bestanden, plaatjes etc. De library is standaard opgeslagen in directory /resources waaronder subdirectories

/resources/components : voor de custom components
/resources/css : voor de css bestanden
/resources/images : voor de plaatjes
/resources/js : voor de javascript bestanden

Voorbeeld verwijzingen:

        <h:outputScript     library="js" name="menu.js"/>
        <h:outputStylesheet library="css" name="appBlueSkin.css"/>

Directe Database toegang in Managed Beans

De managed bean kan direct een database benaderen met resource injectie. Daarvoor wordt gebruik gemaakt van de @Resource annotatie. Dit is handig voor opzet van kleinere ad-hoc database applicaties zonder EJB en JPA. Voorbeeld van de Backing Bean opzet :

@ManagedBean(name="employee")
@SessionScoped
public class EmployeeBean implements Serializable{

	@Resource(name="jdbc/employeedb")
	private DataSource ds;

	public List getCustomerList() throws SQLException{

		if(ds==null)
		  throw new SQLException("Can't get data source");

		Connection con = ds.getConnection();

		if(con==null)
                  throw new SQLException("Can't get database connection");

		PreparedStatement ps
			= con.prepareStatement(
			   "select employeeId, name, address,
			    from customer");

		ResultSet result =  ps.executeQuery();

		List list = new ArrayList();

		while(result.next()){
			Employee emp = new Employee();

			emp.setEmployeeID(result.getLong("employeeId"));
			emp.setName(result.getString("name"));
			emp.setAddress(result.getString("address"));
			//store all data into a List
			list.add(cust);
		}

		return list;
	}
}

Voorbeeld van de JSF Page die de backing bean gebruikt in een dataTable :

<h:dataTable value="#{customer.getCustomerList()}" var="c"
    	styleClass="order-table"
    	headerClass="order-table-header"
    	rowClasses="order-table-odd-row,order-table-even-row">

   <h:column>
    	<f:facet name="header">
    		Customer ID
    	</f:facet>
    	#{c.customerID}
   </h:column>

   <h:column>
    	<f:facet name="header">
    		 Name
	</f:facet>
    	#{c.name}
   </h:column>

   <h:column>
    	<f:facet name="header">
    		 Address
	</f:facet>
    	#{c.address}
   </h:column>

</h:dataTable>

JSF HTML <h:> en <f:> Componenten

De JSF componenten bevatten de JSF kern functies, die verder worden uitgebreid met de componenten voor verrijking van HTML elementen componenten voor facelets technologie zoals gebruik van templates. Hierna worden een aantal veelgebruikte standaard JSF en componenten toegelicht.

Form met <h:inputText> en <h:commandButton>

Backing Bean:

@ManagedBean
@SessionScoped
public class UserBean implements Serializable {

	private String userName;

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}
}

form.xhtml :

<h:inputText> value wordt gekoppeld aan backing bean property userName.
<h:commandButton> action wordt gekoppeld aan page user.xhtml.

    <h:body>
    	<h1>JSF 2 textbox example</h1>

	  <h:form>
    		<h:inputText value="#{userBean.userName}" />
    		<h:commandButton value="Submit" action="user" />
    	  </h:form>

    </h:body>

In form.xhtml wordt met de action attribuut de user.xhtml aangeroepen.

user.xhtml :

    <h:body>
    	<h1>JSF 2 textbox example</h1>

	Submitted value : <h:outputText value="#{userBean.userName}" />

    </h:body>

HTML Analogie

<input type="text" name="j_idt6:j_idt7" />
<input type="submit" name="xxx" value="submit" />

Plain text <h:outputText>

De <h:outputText> component laat alleen de tekst zien. Genereert verder geen HTML constructs.

<h:outputText value="#{user.text}" />

Images <h:graphicImage>

De <h:graphicImage> component laat een plaatje zien.

<h:graphicImage value="resources/images/header.png" />

Dit genereert de HTML code:

<img src="resources/images/sofa.png;" alt="" />

Er kan ook gebruik worden gemaakt van het JSF library concept :

<h:graphicImage library="images" name="header.png" />

Wat de volgende HTML genereert:

<img src="/JavaServerFaces/faces/javax.faces.resource/header.png?ln=images" alt="" />

Layout Tables met <h:panelGrid> en <h:panelGroup>

<h:panelGrid>
De gebruikelijke HTML table constructies om een indeling voor een Page te maken wordt eenvoudiger met <h:panelGrid>.
Onderstaand voorbeeld maakt een tabel met 3 kolommen. De componenten binnen het panelGrid worden achtereenvolgens elk in een volgende kolom geplaatst.
Dus de eerste 3 componenten : outputLabel, inputText en message komen in de 3 kolommen.
De volgende 3, dezelfde soort componenten, komen nu in de volgende rij weer in de 3 kolommen.

<h:panelGrid id="grid" columns="3">
            <h:outputLabel value="Username" />
            <h:inputText id="username" required="true" />
            <h:message for="username" errorClass="error" />
            <h:outputLabel value="Password" />
            <h:inputSecret id="password" required="true" />
            <h:message for="password" errorClass="error" />
            <h:commandButton id="submit" value="Verzend" />
</h:panelGrid>

<h:panelGroup>
Met de component <h:panelGroup> kunnen verschillende componenten worden gegroepeerd en zich als één component voordoen aan het parent component waarin het zich bevindt.
Onderstaande JSF structuur geeft daarmee (bijna) hetzelfde resultaat als hierboven. Met nu 1 kolom komen beide panelGroups vervolgens elk in een aparte rij terecht.

    <h:panelGrid id="grid" columns="1">
        <h:panelGroup>
            <h:outputLabel value="Username" />
            <h:inputText id="username" required="true" />
            <h:message for="username" errorClass="error" />
        </h:panelGroup>
        <h:panelGroup>
            <h:outputLabel value="Password" />
            <h:inputSecret id="password" required="true" />
            <h:message for="password" errorClass="error" />
        </h:panelGroup>
        <h:commandButton id="submit" value="Verzend" />
    </h:panelGrid>

Zoals is te zien is het resultaat bijna hetzelfde maar niet helemaal. In het eerste voorbeeld worden de 3 kolommen netjes uitgelijnd. In het 2e voorbeeld niet.

Databound Tables

Onderstaande voorbeeld betreft een dataTable die itereert over de orderList property van de backing bean. De orderList property wordt gekoppeld aan de variabele “o”.
De verschillende inliggende <h:column> componenten specificeren een facet met de headernaam en referen met de variabele o naar de attributen van een instantie uit de orderList.

<h:dataTable value="#{orderBean.orderList}" var="o"
    		styleClass="order-table"
    		headerClass="order-table-header"
    		rowClasses="order-table-odd-row,order-table-even-row">

    <h:column>
    	<!-- column header -->
	<f:facet name="header">Order No</f:facet>
    	<!-- row record -->
    	#{o.orderNo}
    </h:column>

    <h:column>
    	<f:facet name="header">Product Name</f:facet>
    	#{o.productName}
    </h:column>

    <h:column>
    	<f:facet name="header">Price</f:facet>
    	#{o.price}
    </h:column>

    <h:column>
    	<f:facet name="header">Quantity</f:facet>
    	#{o.qty}
    </h:column>
</h:dataTable>

De dataTable specificeert een 4-tal CSS style classes :

.order-table{
	border-collapse:collapse;
}

.order-table-header{
	text-align:center;
	background:none repeat scroll 0 0 #E5E5E5;
	border-bottom:1px solid #BBBBBB;
	padding:16px;
}

.order-table-odd-row{
	text-align:center;
	background:none repeat scroll 0 0 #FFFFFFF;
	border-top:1px solid #BBBBBB;
}

.order-table-even-row{
	text-align:center;
	background:none repeat scroll 0 0 #F9F9F9;
	border-top:1px solid #BBBBBB;
}

Links <h:outputLink>, <h:commandLink>, <h:link>

De component <h:outputLink> maakt een gewone url link zoals het HTML anchor element.

<h:outputLink value="login.xhtml" >Login page</h:outputLink>

Genereert HTML output

<a href="login.xhtml">Login page</a>

Er kunnen ook teksten en parameters worden meegegeven:

<h:outputLink value="login.xhtml">
	<h:outputText value="Login page" />
	<f:param name="username" value=”Jan" />
</h:outputLink>

Genereert HTML output

<a href="login.xhtml?username=Jan">Login page</a>

<h:commandLink>
De <h:commandLink> component maakt een url link die werkt als een submit button.

<h:commandLink action="#{user.goLoginPage}" value="Login page" />		

Dit wordt gegeneerd naar HTML en Javascript die zorgt voor de aanroep van de backing bean method.

<h:link>
De <h:link> component is nieuw in JSF 2 en maakt een url link naar een andere .xhtml JSF Page.

<h:link value="Login page" outcome="login" />

Genereert HTML output

<a href="/JavaServerFaces/faces/login.xhtml">Login page</a>

Hierop kunnen ook parameters worden toegevoegd, net als bij de outputLink.

Checkboxen

selectBooleanCheckbox
Eenvoudigste optie is selectBooleanCheckbox voor één CB :

<h:selectBooleanCheckbox value="#{user.rememberMe}" /> Remember Me

Dit genereert als HTML output:

<input type="checkbox" name="j_idt6:j_idt8" /> Remember Me

Maakt gebruik van backing bean boolean property:

public boolean rememberMe;

selectManyCheckbox
Met selectManyCheckbox wordt een groep checkboxen gebruikt, en dat genereert een HTML constructie waarbij de verschillende CB’s in een HTML table worden opgenomen.

Onderstaand voorbeeld maakt gebruik van hard-coded selectie items:

<h:selectManyCheckbox value="#{user.favNumber1}">
   	<f:selectItem itemValue="1" itemLabel="Number1 - 1" />
   	<f:selectItem itemValue="2" itemLabel="Number1 - 2" />
   	<f:selectItem itemValue="3" itemLabel="Number1 - 3" />
</h:selectManyCheckbox>

Maakt gebruik van backing bean property:

public String[] favNumber1;
public String getFavNumber1InString() {
		return Arrays.toString(favNumber1);
}

Onderstaand voorbeeld maakt gebruik van selectie items uit de backing bean:

<h:selectManyCheckbox value="#{user.favNumber2}">
   	<f:selectItems value="#{user.favNumber2Value}" />
</h:selectManyCheckbox>

Maakt gebruik van backing bean property:

public String[] favNumber2;
	public String[] getFavNumber2Value() {

		favNumber2 = new String[5];
		favNumber2[0] = "Number2 - 1";
		favNumber2[1] = "Number2 - 2";
		favNumber2[2] = "Number2 - 3";
		favNumber2[3] = "Number2 - 4";
		favNumber2[4] = "Number2 - 5";

		return favNumber2;
	}

	public String getFavNumber2InString() {
		return Arrays.toString(favNumber2);
	}

Radiobuttons

Met selectOneRadio genereert een HTML constructie waarbij de verschillende RB’s in een HTML table worden opgenomen.

Onderstaand voorbeeld maakt gebruik van hard-coded items:

<h:selectOneRadio value="#{user.favColor1}">
   <f:selectItem itemValue="Red" itemLabel="Color1 - Red" />
   <f:selectItem itemValue="Green" itemLabel="Color1 - Green" />
   <f:selectItem itemValue="Blue" itemLabel="Color1 - Blue" />
</h:selectOneRadio>

Maakt gebruik van backing bean property:

public String favColor1;

Onderstaand voorbeeld maakt gebruik van selectie items uit de backing bean:

<h:selectOneRadio value="#{user.favColor2}">
   <f:selectItems value="#{user.favColor2Value}" />
</h:selectOneRadio>

Maakt gebruik van backing bean property:

public String favColor2;

private static Map<String,Object> color2Value;
	static{
		color2Value = new LinkedHashMap<String,Object>();
		color2Value.put("Color2 - Red", "Red"); //label, value
		color2Value.put("Color2 - Green", "Green");
		color2Value.put("Color3 - Blue", "Blue");
	}

public Map<String,Object> getFavColor2Value() {
	return color2Value;
}

Listbox

Met selectOneListbox genereert een HTML constructie waarbij de verschillende LB items in een HTML table worden opgenomen.

Onderstaand voorbeeld maakt gebruik van hard-coded items:

<h:selectOneListbox value="#{user.favYear1}">
   <f:selectItem itemValue="2000" itemLabel="Year1 - 2000" />
   <f:selectItem itemValue="2010" itemLabel="Year1 - 2010" />
   <f:selectItem itemValue="2020" itemLabel="Year1 - 2020" />
</h:selectOneListbox>

Maakt gebruik van backing bean property:

public String favYear1;

Onderstaand voorbeeld maakt gebruik van selectie items uit de backing bean:

<h:selectOneListbox value="#{user.favYear2}">
   <f:selectItems value="#{user.favYear2Value}" />
</h:selectOneListbox>

Maakt gebruik van backing bean property:

public String favYear2;

private static Map<String,Object> year2Value;
static{
	year2Value = new LinkedHashMap<String,Object>();
	year2Value.put("Year2 - 2000", "2000"); //label, value
	year2Value.put("Year2 - 2010", "2010");
	year2Value.put("Year2 - 2020", "2020");
}

public Map<String,Object> getFavYear2Value() {
	return year2Value;
}

Validaties en Messages

Er zijn verschillende validator componenten, beginnend met <f:validate> die toegevoegd kunnen worden aan input componenten om de input te testen op het gevalideerde aspect.
Met de componentenen <h:message> en <h:messages> wordt een plek in de Page gedefinieerd waar messages getoond kunnen worden.

Onderstaand voorbeeld voegt een validator <f:validateLength> toe aan de inputText, welke controleert op minimum en maximum lengte. Ook is attribuut required toegevoed, wat ook een check en mogelijke messages oplevert.

<h:messages style="color:red;margin:8px;" />

<h:inputText id="username" value="#{user.username}" size="20"
		required="true" label="UserName" >
	<f:validateLength minimum="5" maximum="10" />
</h:inputText>

<h:message for="username" style="color:red" />

Met de <h:messages> component worden alle boodschappen op één centrale plek op de Page getoond.

Met de <h:message> component worden de foutboodschappen van één specifieke input component getoond, na de inputText. Deze component wordt met attribuut “for” gerelateerd aan de id van de inputText.

Andere standaard validators zijn:
f:validateLongRange
f:validateDoubleRange

Je kunt ook custom validators maken met component

<h:inputText id="email" value="#{user.email}"
	      size="20" required="true" label="Email Address">
	<f:validator validatorId="MyEmailValidator" />
</h:inputText>

De validator wordt als volgt geimplementeerd:

@FacesValidator("MyEmailValidator")
public class EmailValidator implements Validator{

   @Override
   public void validate(FacesContext context, UIComponent component,
			 Object value) throws ValidatorException {

        ….Test Logic op de inputparameter : value……

	if(…value not ok…){
	   FacesMessage msg = new FacesMessage("E-mail validation failed.",
						"Invalid E-mail format.");
	   msg.setSeverity(FacesMessage.SEVERITY_ERROR);
	   throw new ValidatorException(msg);
	}
   }
}

Met attribuut validatorId=”MyEmailValidator” wordt de <f:validator> component gekoppeld aan de implementatie class “EmailValidator” via de @FacesValidator annotatie.

De Validatie class implementeert de Validator interface en override de method “validate()”.
In deze method bevat de parameter “value” de te controleren input van de <h:inputText> component waarbinnen de <f:validator> component zich bevindt.
De validate method voert de controle daarop uit en zal, indien niet ok, een message aanmaken en vervolgens ValidatorException gooien.

Converters

De converters zijn nodig voor representatie van numerieke en data/time velden.

<f:convertNumber>

<h:outputText value="#{receipt.amount}" >
	<f:convertNumber minFractionDigits="2" />
</h:outputText>

Toont : 0.10

<h:outputText value="#{receipt.amount}" >
	<f:convertNumber pattern="#0.000" />
</h:outputText>

Toont : 0.100

<h:outputText value="#{receipt.amount}" >
	<f:convertNumber currencyCode="EUR" type="currency" />
</h:outputText>

Toont EUR0.10

<f:convertDateTime>

<h:inputText id="date" value="#{receipt.date}"
			size="20" required="true"
			label="Receipt Date" >
	<f:convertDateTime pattern="dd-MM-yyyy" />
</h:inputText>

<h:outputText value="#{receipt.date}" >
	<f:convertDateTime pattern="dd-MM-yyyy" />
</h:outputText>
This entry was posted in JEE, JSF and tagged , . Bookmark the permalink.

Geef een reactie

Je e-mailadres wordt niet gepubliceerd.

De volgende HTML tags en attributen zijn toegestaan: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>