Navegação Implicita
Antigamente as suas regras de navegação precisavem ser registradas no faces-config.xml assim:
<navegation-rule>
<from-view-id>/person/people.xhtml</from-view-id>
<navegation-case>
<from-outcome>edit</from-outcome>
<to-view-id>/person/edit.xhtml</to-view-id>
</navegation-case>
</navegation-rule>
Agora vc não precisa mais disso. Basta vc informar o cominho da view sem a extensão:
public String action() {
return "/person/edit";
}
Assim o JSF vai procurar por um arquivo chamado edit.xhtml dentro do diretório person. Se vc precisar redirecionar basta adicionar “&faces-redirect=true” no final da sua regra de navegação e pronto.
Navegação Condicional
Se vc estiver usando navegações declarativas (aquelas no faces-config) então vc pode fazer algo assim:
<navigation-rule>
<from-view-id>/page1.xhtml</from-view-id>
<navigation-case>
<from-outcome>edit</from-outcome>
<if>#{page1Bean.isEditionAllowed}</if>
<to-view-id>/edit.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
Onde a expressão passada no IF deve resolver à um método de um ManagedBean q retorne um boolean. Nesse caso a navegação só será executada se esse método retornar true.
Bookmarkable URLs
Antes o JSF só suportava requisições POST e as navegações aconteciam no servidor através de um mecanismo chamado forward. Isso causava dois problemas:
1 - as navegações post passam parâmetros “implicitamente”, ou seja, os parâmetros não apareciam na URL. Assim, se vc precisasse de um parâmetro p/ navegar à página certa, digamos o ID do produto do qual vc quer visualizar os detalhes, então não era possível p/ o usuário salvar a URL desse produto nos favoritos do seu browser.
2 - as URLs das views ficavam sempre atrasadas pois os posts do JSF eram sempre feitos de volta p/ a página original.
Agora é possível usar GETs p/ acessar páginas JSF.
<!-- Os componentes h:button e h:link usam GET. -->
<h:button outcome="/detail&p=15" />
<h:link outcome="/edit?p=15" />
<!-- Vc usa regras de navegação, mas essas regras são resolvidas já no momento em q a página é renderizada, ou seja, o URL já vai certa p/ o cliente.
Depois vc pega o parâmetros assim:
<!-- detail.xhtml -->
<f:metadata>
<f:viewParam name="p" value="#{detailBean.prodId} />
</f:metadata>
Vc pode inclusive adicionar converters e validators aos viewParams.
Suporte a AJAX
O suporte a ajax só era possível através uma espécie de hacking no ciclo de vida do JSF. E só era viável usando suites de componentes como o RichFaces. Agora o JSF2 suporta a tag f:ajax.
<h:form>
<h:inputText value="#{bean.in}">
<f:ajax event="keyup" execute="@this" listener="#{bean.doSth}" render="panel" />
</h:inputText>
<h:panelGroup id="panel">
</h:form>
Suporte a comportamentos plugaveis
A tag f:ajax é um comportamento plugavel. É possível vc escrever comportamentos (Behavior) e então adiciona-los à um componente do JSF p/ q sejam executados quando algum evento ocorrer. É ainda possível q esses comportamentos sejam apenas um javascript q será executado no cliente (é assim q funciona o f:ajax).
Facelets
Quando o JSF foi concebido era esperado q p/ fazer templates de páginas fosse usado JSP. Mais tarde se percebeu q a integração de duas tecnologias tão diferentes era difícil e causava muita dor de cabeça aos desenvolvedores. Então foi criado o framework Facelets q oferecia recursos avançados p/ reaproveitamento de html e uma arquitetura muito mais integrada ao JSF. P/ adicionar o Facelets em uma aplicação JSF1.x vc precisa de uma série de configurações adicionais. JSF2 tornou o Facelets a tecnologia de templates padrão, ou seja, nenhuma configuração adicional é necessária p/ se usar Facelets com JSF. E JSP foi descontinuado como tecnologia de templates do JSF.
Se vc ainda não conhece Facelets, então eu o aconselho a dar uma olhada nele.
Behavior já foram citados acima.
Componentes Compostos
Imagine q vc use uma certa configuração de componentes, por exemplo, um outputLabel e um inputText. Se vc tem muito formulários grandes no seu aplicativos fica meio difícil p/ vc primeiro ter q escrever esse monte de outputLabels e inputTexts e, também, se vc quizer mudar aparência vc precisará visitar um por um. No JSF2 vc pode fazer algo assim:
<html xmlns:cc="http://java.sun.com/jsf/composite
xmlns:h="http://java.sun.com/jsf/html">
<cc:interface>
<cc:attribute name="label" />
<cc:attribute name="value" />
</cc:interface>
<cc:implementation>
<h:panelGroup>
<h:outputLabel for="#{clientId:input}" value="#{cc.attrs.label}" />
<h:inputText id="#{clientId:input}" value="#{cc.attrs.value}" />
</h:panelGroup>
</cc:implementation>
</html>
Vc, então pode salvar esse arquivo em um diretório “/resources/ezcomp” dentro de WebContent com o nome “inputText.xhtml” e usa-lo assim:
<html xmlns:ez="http://java.sun.com/jsf/composite/ezcomp">
<ez:inputText label="Test:" value="#{testBean.value}" />
</html>
Callbacks do Ciclo de Vida
Digamos q vc queira modificar a sub-árvore de um componente específico dinâmicamente, tipo em código. Agora vc pode adicionar um callback no processo de construção da árvore de componentes:
<h:form>
<f:event type="javax.faces.event.PostAddToViewEvent" listener="#{bean.callback}" />
</h:form>
E no bean:
public void callback(ComponentSystemEvent e) {
// aqui vc pode construir dinâmicamente a árvore de componentes do h:form.
}
Ainda existem dois outros recursos q eu esqueci de citar. Gerênciamento de recursos e passagem de parâmetros p/ actions.
Gerênciamento de Recursos
Basta vc adicionar os recursos em um diretório “/resources” no seu WebContent e substituir as tags head e body do html por h:head e h:body. Ai, p/ vc adicionar recursos como css, javascript e imagens:
<h:outputStyle name="estilos.css" target="head" />
<h:outputScript name="jquery.js" target="head" />
<h:outputImage name="smile.jpg" />
O target indica em q parte (h:head ou h:body) vc deseja ecoar esses recursos. Isso evita de vc fique escrevendo full-path urls p/ acessar esses recursos.
Parâmetros nos actions
Isso é muito legal!! Agora vc pode passar parâmetros em métodos action dos beans gerenciados. Tipo, digamos q vc tenha um dataTable com botões editar p/ cada linha. Vc quer q quando o usuário clicar ele seja direcionado p/ um página com os dados dessa linha p/ q possam ser editados. No JSF1.x vc precisava de componentes f:setPropertyActionListener p/ isso (q saco). Mas com JSF2 vc pode:
<h:dataTable value="#{products}" var="p">
<!-- outras colunas -->
<h:column>
<f:facet name="header">Actions</f:facet>
<h:commandLink value="Edit" action="#{productEditor.edit(p)}" />
</h:column>
</h:dataTable>
E no seu ManagedBean:
public String edit(Product product) {
this.product = product;
return "/product/edit";
}
Ademais existem algumas pequenas melhorias como vc não precisar mais de objetos SelectItem p/ construir um selectOneMenu, mas os principais são esses ai.