Archive

Posts Tagged ‘bookmarking’

URLs amigáveis no JSF 2.0

May 27th, 2009

Hoje vou falar de mais uma novidade do JSF 2, cuja falta era motivo de muita reclamação: URLs amigávies, bookmarking, método GET e outros nomes que podemos dar. O suporte a essa nova funcionalidade é dado por dois pares de componentes, de um lado h:button e h:link e do outro f:metadata e f:viewParam.

Os componentes h:button e h:link servem para originar as ações jsf assim como os componentes h:command{Button|Link}, porém usando GET em vez de POST. Esses componentes possuem um atributo chamado outcome, que representa a regra de navegação do JSF, assim como seria colocar uma String diretamente na action do h:command{Button|Link}. Para passar parâmetros colocamos a tag f:param dentro do h:link ou h:button.

Como exemplo vamos ver uma aplicaçãozinha que tem uma tela de listagem e outra de visualização de Pessoas. A seguir um trecho da página de listagem de pessoas, listarPessoas.xhtml:

<h:form>
	<h:dataTable value="#{pessoaController.pessoas}" var="pessoa">
		<h:column>
			#{pessoa.nome}
		</h:column>
		<h:column>
			<h:link outcome="/verPessoa" value="Editar">
				<f:param name="pessoa" value="#{pessoa.nome}"/>
			</h:link>
		</h:column>
	</h:dataTable>
</h:form>

Nesse exemplo, no outcome eu já estou usando o esquema novo de navegação comentado no post passado. O link acima vai gerar uma url parecida com http://localhost:8080/exemplojsf2/verPessoa.jsf?pessoa=fulano_0.

Agora do lado da página que recebe a requisição temos os componentes f:metadata e f:viewParam. A primeira é apenas uma tag que engloba as f:viewParam. Já as tags f:viewParam se comportam de forma muito parecida com um h:inputText, podemos dizer que praticamente a única diferença é no input a gente digita em um formulário, enquanto na f:viewParam escrevemos na URL.

A tag f:viewParam possue os seguintes atributos: converter, converterMessage, required, requiredMessage, validator, validatorMessage, value, valueChangeListener, maxlength e for (este último voltado para o novo esquema de component composition do Facelets). Como podemos ver, é praticamente um h:inputText.

Vamos ver então um trecho do código da página que recebe a requisição, verPessoa.xhtml:

<f:view>
	<f:metadata>
	    	<f:viewParam name="pessoa" value="#{pessoaController.pessoaSelecionada}" />
   	</f:metadata>
<h:head>
    <title>Ver Pessoa</title>
</h:head>
<h:body>
	<h:form>
		Nome: #{pessoaController.pessoaSelecionada.nome}
	</h:form>
</h:body>
</f:view>

Não precisei colocar um converter no f:viewParam pois configurei um converter “forClass” como veremos mais a frente.

Agora a nossa classe

public class Pessoa {
 
	private String nome;
 
	public Pessoa() {
	}
	public Pessoa(String nome) {
		this.nome = nome;
	}
 
	//getter e setter suprimido
}

Isso mesmo, a classe é complexa desse jeito  :D

Como o intuito é só um exemplo, eu nem me preocupei com banco de dados ou algum mecanismo mais interessante, apenas criei um conversor para mostrar que o novo esquema não permite apenas o uso de Strings. Segue o código do conversor:

@FacesConverter(forClass=Pessoa.class)
public class PessoaConverter implements Converter {
 
	@Override
	public Object getAsObject(FacesContext context, UIComponent component, String string) {
 
		return new Pessoa(string);
	}
 
	@Override
	public String getAsString(FacesContext context, UIComponent component, Object object) {
 
		return ((Pessoa)object).getNome();
	}
 
}

E agora nosso managed bean que recebe não uma String, e sim objetos do nosso domínio. Eu falo isso o tempo todo pois preciso deixar isso bem claro, senão eu fico doido de ver uma aplicação usando JSF passando String e Integer de um lado pro outro :(

Mas tudo bem, deixando o desabafo pra lá vamos ao código:

@ManagedBean(name="pessoaController")
@RequestScoped
public class PessoaController {
 
	private Pessoa pessoaSelecionada;
	private List<pessoa> pessoas;
 
	@PostConstruct
	public void init()
	{
		pessoas = new ArrayList<pessoa>();
		for (int i = 0; i < 10; i++) {
			pessoas.add(new Pessoa("fulano_" + i));
		}
	}
 
	//getters e setters suprimidos
}

Acredito que por hoje seja suficiente. Vou ver se em breve escrevo algo mais específico sobre facelets.

JSF, JavaEE , , ,