O que é JSF ?
Quais os "módulos" que compõem o JSF?
Divisão de papéis com JSF ?
O que JSF trás de bom?
O que temos de diferente com JSF ?
Curiosidade
Como a especificação do JSF se ajusta
O que tenho que saber para começar a discutir e implementar aplicações usando o
faces ?
UIComponents e core tags
Regras de navegação:
<navigation-rule> <from-view-id>/greeting.jsp</from-view-id> <navigation-case> <from-outcome>success</from-outcome> <to-view-id>/response.jsp</to-view-id> </navigation-case> <navigation-case> <from-outcome>fail</from-outcome> <to-view-id>/fail.jsp</to-view-id> </navigation-case> </navigation-rule>
BackBean:
JSP: <h:inputText id="email" value="#{checkoutFormBean.email}" size="25" maxlength="125" validator="#{checkoutFormBean.validateEmail}"/>
Backbean: public void validateEmail(FacesContext context, UIInput toValidate) { String message = ""; String email = (String) toValidate.getValue(); if (email.indexOf('@') == -1) { toValidate.setValid(false); message = CoffeeBreakBean.loadErrorMessage(context, CoffeeBreakBean.CB_RESOURCE_BUNDLE_NAME,"EMailError"); context.addMessage(toValidate.getClientId(context),new FacesMessage(message, "")); } else { toValidate.setValid(true); } }
Action Event Handler Method: métodos que recebem um ActionEvent e são void (não procuram nenhuma regra de negação, voltam para a mesma página).
- Apenas os componentes que implementam ActionSource podem usar esse método.
- UICommand e UIButton
JSP: <h:commandLink id="NAmerica" action="bookstore" actionListener="#{localeBean.chooseLocaleFromLink}">
Backbean: public void chooseLocaleFromLink(ActionEvent event) { String current = event.getComponent().getId(); FacesContext context = FacesContext.getCurrentInstance(); context.getViewRoot().setLocale((Locale) locales.get(current)); }
JSP: <h:inputText id="name" size="50" value="#{cashier.name}" required="true" valueChangeListener="#{cashier.processValueChange}" /> </h:inputText>
Backbean: public void processValueChange(ValueChangeEvent event) throws AbortProcessingException { if (null != event.getNewValue()) { FacesContext.getCurrentInstance(). getExternalContext().getSessionMap(). put("name", event.getNewValue()); } }
Navigation handling methods
(Action methods): métodos que retornam uma String que deve casar com as regras de navegação:JSP: <h:commandButton value="#{bundle.Submit}" action="#{cashier.submit}" />
Backbean: public String submit() { ... if(cart().getTotal() > 100.00 && !specialOffer.isRendered()) { specialOfferText.setRendered(true); specialOffer.setRendered(true); return null; } else if (specialOffer.isRendered() && !thankYou.isRendered()){ thankYou.setRendered(true); return null; } else { clear(); return ("receipt"); } }
Arquivo de configuração do faces:
<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN" "http://java.sun.com/dtd/web-facesconfig_1_1.dtd"> <faces-config> <managed-bean> <managed-bean-name>tabularBB</managed-bean-name> <managed-bean-class>com.groundside.jsf.backing.Tabular</managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean> <managed-bean> <managed-bean-name>neighbors</managed-bean-name> <managed-bean-class>com.groundside.jsf.Neighbors</managed-bean-class> <managed-bean-scope>session</managed-bean-scope> </managed-bean> <managed-bean> <managed-bean-name>editBB</managed-bean-name> <managed-bean-class>com.groundside.jsf.backing.Edit</managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean> <managed-bean> <managed-bean-name>editContact</managed-bean-name> <managed-bean-class>com.groundside.jsf.Contact</managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean> <navigation-rule> <from-view-id>/tabular.jsp</from-view-id> <navigation-case> <from-outcome>drilldown</from-outcome> <to-view-id>/edit.jsp</to-view-id> </navigation-case> </navigation-rule> <navigation-rule> <from-view-id>/edit.jsp</from-view-id> <navigation-case> <from-outcome>return</from-outcome> <to-view-id>/tabular.jsp</to-view-id> </navigation-case> </navigation-rule> </faces-config>
Entendendo o ciclo de vida
em todo jsp temos que ter: // tags dos tlds ... <f:view> // as tags do faces e tags que não são do faces também </f:view>
Exemplo comentado:
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> <html> <f:view> <body> <h:form> <table> <tr> <td> <h:outputText value="Login"/> </td> <td> <h:inputText id="login" binding="#{cadastroBean.loginComponente}" required="true"/> <h:message for="login"/> </td> </tr> <tr> <td> <h:outputText value="Senha"/> </td> <td> <h:inputSecret id="senha" value="#{cadastroBean.senha}" required="true"/> <h:message for="senha"/> </td> </tr> <tr> <td> <h:outputText value="E-mail" /> </td> <td> <h:inputText id="mail" value="#{cadastroBean.mail}" required="true"/> <h:message for="mail"/> </td> </tr> <tr> <td> <h:commandButton action="#{cadastroBean.cadastraUsuarioAction}" value="Enviar Dados"/> </td> </tr> </table> </h:form> <h:form id="removeUsuario"> <h:dataTable var="usuario" value="#{cadastroBean.usuariosCadastrados}" border="1"> <h:column> <f:facet name="header"> <h:outputText value="Login"/> </f:facet> <h:outputText value="#{usuario.login}"></h:outputText> <f:facet name="footer"> <h:outputText value="Login"/> </f:facet> </h:column> <h:column> <f:facet name="header"> <h:outputText value="E-mail"/> </f:facet> <h:outputText value="#{usuario.mail}"></h:outputText> <f:facet name="footer"> <h:outputText value="E-mail"/> </f:facet> </h:column> <h:column> <f:facet name="header"> <h:outputText value="Ação"/> </f:facet> <h:commandLink value="#{usuario.id}" actionListener="#{cadastroBean.removeUsuarioAction}"> <h:outputText value="Excluir"></h:outputText> </h:commandLink> <f:facet name="footer"> <h:outputText value="Ação"/> </f:facet> </h:column> </h:dataTable> </h:form> <body> </f:view> <html>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib
uri="http://java.sun.com/jsf/html" prefix="h" %>
<h:inputSecret
id="senha" value="#{cadastroBean.senha}"
required="true"/> <h:message for="senha"/>
<h:form id="removeUsuario"> <h:dataTable var="usuario" value="#{cadastroBean.usuariosCadastrados}" border="1"> <h:column> <f:facet name="header"> <h:outputText value="Login"/> </f:facet> <h:outputText value="#{usuario.login}"></h:outputText> <f:facet name="footer"> <h:outputText value="Login"/> </f:facet> </h:column> <h:column> <f:facet name="header"> <h:outputText value="E-mail"/> </f:facet> <h:outputText value="#{usuario.mail}"></h:outputText> <f:facet name="footer"> <h:outputText value="E-mail"/> </f:facet> </h:column> <h:column> <f:facet name="header"> <h:outputText value="Ação"/> </f:facet> <h:commandLink value="#{usuario.id}" actionListener="#{cadastroBean.removeUsuarioAction}"> <h:outputText value="Excluir"></h:outputText> </h:commandLink> <f:facet name="footer"> <h:outputText value="Ação"/> </f:facet> </h:column> </h:dataTable> </h:form>
package daca.bean; public class Usuario { private int id ; private String login=""; private String senha=""; private String mail=""; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getLogin() { return login; } public void setLogin(String login) { this.login = login; } public String getSenha() { return senha; } public void setSenha(String senha) { this.senha = senha; } public String getMail() { return mail; } public void setMail(String mail) { this.mail = mail; } }
package daca.dao; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import org.springframework.jdbc.datasource.DriverManagerDataSource; import daca.bean.Usuario; /* * TODO To change the template for this generated type comment go to * Window - Preferences - Java - Code Style - Code Templates */ public class GerenteBanco{ private DriverManagerDataSource dataSource; public GerenteBanco(){ } /* (non-Javadoc) * @see daca.service.PersistenteIF#save(daca.business.Usuario) */ public void save(Usuario usuario) { try { Connection conn = dataSource.getConnection() ; PreparedStatement statement = conn.prepareStatement("insert into usuario (login,senha,mail) values (?,?,?)"); statement.setString(1,usuario.getLogin()); statement.setString(2,usuario.getSenha()); statement.setString(3,usuario.getMail()); statement.execute(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } /* (non-Javadoc) * @see daca.service.PersistenteIF#remove(java.lang.String) */ public void remove(String id) { try { Connection conn = dataSource.getConnection(); PreparedStatement statement = conn.prepareStatement("delete from usuario where id=?"); statement.setString(1,id); statement.execute(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } /* (non-Javadoc) * @see daca.service.PersistenteIF#selectTodos() */ public List selectTodos() { Connection conn = null; List lista = new ArrayList(); try { conn = dataSource.getConnection(); ResultSet rs = conn.createStatement().executeQuery("select * from usuario"); while(rs.next()){ Usuario u = new Usuario(); u.setId(rs.getInt(1)); u.setLogin(rs.getString(2)); u.setSenha(rs.getString(3)); u.setMail(rs.getString(4)); lista.add(u); } conn.close(); } catch (SQLException e) { e.printStackTrace(); } return lista; } /** * @return Returns the dataSource. */ public DriverManagerDataSource getDataSource() { return dataSource; } /** * @param dataSource The dataSource to set. */ public void setDataSource(DriverManagerDataSource dataSource) { this.dataSource = dataSource; } }
package daca.service; import javax.servlet.ServletContext; import org.springframework.context.ApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; import daca.dao.GerenteBanco; import daca.util.DCContants; import daca.util.FacesUtils; /** * The implementation of <code>ServiceLocator</code>. * <p> * This class is managed by the JSF managed bean facility, * and is set with application scope. * * @see ServiceLocator */ public class ServiceLocator { //the Spring application context private ApplicationContext appContext; //the cached user service private GerenteBanco persistentService; /** * Constructor. * <p> * The following steps being done: * <ul> * <li>retrieve Spring application context from servlet context. * <li>look up <code>UserService</code> from Spring applicatino context. * </ul> */ public ServiceLocator() { ServletContext context = FacesUtils.getServletContext(); this.appContext = WebApplicationContextUtils.getRequiredWebApplicationContext(context); persistentService = (GerenteBanco)this.lookupService(DCContants.PERSISTENT_SERVICE_BEAN_NAME); } /** * Lookup service based on service bean name. * * @param serviceBeanName the service bean name * @return the service bean */ public Object lookupService(String serviceBeanName) { return appContext.getBean(serviceBeanName); } public GerenteBanco getPersistentService() { return persistentService; } public void setPersistentService(GerenteBanco persistentService) { this.persistentService = persistentService; } }
package daca.util; import javax.faces.context.FacesContext; import javax.servlet.ServletContext; /** * Utility class for JavaServer Faces. */ public class FacesUtils { /** * Get servlet context. * * @return the servlet context */ public static ServletContext getServletContext() { return (ServletContext)FacesContext.getCurrentInstance().getExternalContext().getContext(); } }
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"><beans> <!-- ========================= Start of PERSISTENCE DEFINITIONS ========================= --> <!-- DataSource Definition --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" destroy-method="close"> <property name="driverClassName"> <value>com.mysql.jdbc.Driver</value> </property> <property name="url"> <value>jdbc:mysql:///daca</value> </property> <property name="username"> <value>root</value> </property> <property name="password"> <value></value> </property> </bean> <!-- PErsistent Service Defintion --> <bean id="servicoPersistencia" class="daca.dao.GerenteBanco"> <property name="dataSource"><ref local="dataSource"/></property> </bean> </beans>
<?xml version="1.0"?> <!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN" "http://java.sun.com/dtd/web-facesconfig_1_0.dtd"> <faces-config> <application> <locale-config> <default-locale>br</default-locale> </locale-config> <message-bundle>daca.bundle.Messages</message-bundle> </application> </faces-config>
<?xml version="1.0"?> <!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN" "http://java.sun.com/dtd/web-facesconfig_1_0.dtd"> <faces-config> <managed-bean> <description> Service locator of the business services </description> <managed-bean-name>serviceLocatorBean</managed-bean-name> <managed-bean-class>daca.service.ServiceLocator</managed-bean-class> <managed-bean-scope>application</managed-bean-scope> </managed-bean> <managed-bean> <description> </description> <managed-bean-name>cadastroBean</managed-bean-name> <managed-bean-class>daca.view.CadastroBean</managed-bean-class> <managed-bean-scope>session</managed-bean-scope> <managed-property> <property-name>service</property-name> <value>#{serviceLocatorBean}</value> </managed-property> </managed-bean> </faces-config>
<?xml version="1.0"?> <!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN" "http://java.sun.com/dtd/web-facesconfig_1_0.dtd"> <faces-config> <navigation-rule> <from-view-id>*</from-view-id> <navigation-case> <description> </description> <from-outcome>sucesso</from-outcome> <to-view-id>/index.jsp</to-view-id> </navigation-case> </navigation-rule> <!-- <from-view-id>/algumaPagina.jsp</from-view-id> <navigation-case> <description> </description> <from-outcome>nomeLugar</from-outcome> <to-view-id>/umaPagina.jsp</to-view-id> </navigation-case> </navigation-rule> --> </faces-config>
<?xml version="1.0"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> <display-name>Daca</display-name> <description> Aplicação Exemplo DACA </description> <welcome-file-list> <welcome-file>index.jsf</welcome-file> </welcome-file-list> <!-- JavaServer Faces --> <context-param> <param-name>javax.faces.STATE_SAVING_METHOD</param-name> <param-value>server</param-value> </context-param> <context-param> <param-name>javax.faces.CONFIG_FILES</param-name> <param-value>/WEB-INF/faces-config.xml,/WEB-INF/faces-managed-beans.xml,/WEB-INF/faces-navigation.xml</param-value> </context-param> <context-param> <param-name>com.sun.faces.validateXml</param-name> <param-value>true</param-value> </context-param> <listener> <listener-class>com.sun.faces.config.ConfigureListener</listener-class> </listener> <!-- Faces Servlet --> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <!-- Spring Servlet--> <servlet> <servlet-name>SpringContextServlet</servlet-name> <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <!-- Faces Servlet Mapping --> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.jsf</url-pattern> </servlet-mapping> <!-- Tomcat 4.1 can not read tld file from jar for jstl1.0 jarkata implementation. It's a workaround here. --> <taglib> <taglib-uri>http://java.sun.com/jstl/core</taglib-uri> <taglib-location>/WEB-INF/c.tld</taglib-location> </taglib> </web-app>
package daca.view; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; import javax.faces.component.html.HtmlCommandLink; import javax.faces.component.html.HtmlInputText; import javax.faces.event.ActionEvent; import org.apache.commons.beanutils.BeanUtils; import daca.bean.Usuario; import daca.dao.GerenteBanco; import daca.service.ServiceLocator; import daca.util.DCContants; public class CadastroBean { private HtmlInputText loginComponente; private String login=""; private String senha=""; private String mail=""; private int idParaRemocao; private ServiceLocator service; private List usuariosCadastrados = new ArrayList(); public String cadastraUsuarioAction(){ setLogin((String) getLoginComponente().getValue()); service.getPersistentService().save(createUsuarioBussiness()); return DCContants.PAGINA_CADASTRO; } public void removeUsuarioAction(ActionEvent event){ HtmlCommandLink link = (HtmlCommandLink) event.getSource(); getService().getPersistentService().remove( ((Integer)link.getValue()).toString() ); } /** * cria um usuario do model * @return usuario, o usuário criado com os dados do form */ public Usuario createUsuarioBussiness(){ //TODO usar uma factory, tirar os printStackTrace Usuario u = new Usuario(); try { BeanUtils.copyProperties(u, this); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } reset(); return u ; } public void reset() { setLoginComponente(new HtmlInputText()); setMail(""); setSenha(""); } public HtmlInputText getLoginComponente() { return loginComponente; } public void setLoginComponente(HtmlInputText loginComponente) { this.loginComponente = loginComponente; } public String getLogin() { return login; } public void setLogin(String login) { this.login = login; } public String getMail() { return mail; } public void setMail(String mail) { this.mail = mail; } public String getSenha() { return senha; } public void setSenha(String senha) { this.senha = senha; } public List getUsuariosCadastrados() { usuariosCadastrados = service.getPersistentService().selectTodos(); return usuariosCadastrados; } public void setUsuariosCadastrados(List usuariosCadastrados) { this.usuariosCadastrados = usuariosCadastrados; } public ServiceLocator getService() { return service; } public void setService(ServiceLocator service) { this.service = service; } }
Finalizando
Chamar na página <h:outputText id=version value="#{initParam.versionNo}" web.xml file <context-param> <param-name>versionNo</param-name> <param-value>1.05</param-name> </context-param>
<h:inputText id="userNo" value="#{UserNumberBean.userNumber}" validator="#{UserNumberBean.validate}"/>
<h:inputText id="userNo" value="#{UserNumberBean.userNumber}"> <f:validateLength maximum="6" minimum="2"/> </h:inputText>
Método validate que deve ser implementado no bean: public void validateEmail(FacesContext context,UIInput toValidate) { String message = ""; String email = (String) toValidate.getValue(); if (email.indexOf('@') == -1) { toValidate.setValid(false); message = CoffeeBreakBean.loadErrorMessage(context, CoffeeBreakBean.CB_RESOURCE_BUNDLE_NAME,"EMailError"); context.addMessage(toValidate.getClientId(context),new FacesMessage(message, "")); } else { toValidate.setValid(true); } }
na sua página jsp chamar o método de validação: <h:inputText id="email" value="#{checkoutFormBean.email}" size="25" maxlength="125" validator="#{checkoutFormBean.validateEmail}"/>
<f:loadBundle basename="carstore.bundles.Resources" var="bundle"/> <h:outputText value="bundle.key"/>
Finalmente: