out 15

CDI no Websphere 8 com JSF 2

Voltando aos posts de tecnologia, nas duas semanas que se passaram estive com um grande problema no trabalho:

Estávamos desenvolvendo uma aplicação utilizando CDI, com JSF 2, rodando no JBOSS  AS 7, tudo funcionando as mil maravilhas. Mas, porém, contudo, no entanto, como diz Joseph Climber –  “Mas a vida é uma caixinha de surpresas” – nosso servidor de desenvolvimento roda Websphere 8 (WAS 8) , que apesar de adotar praticamente as mesmas especificações do JAVA do JBOSS 7, utiliza em sua maioria as implementações  da APACHE(Myfaces para JSF, OpenWebBeans para CDI), enquanto que o JBOSS utiliza as implementações de referência, por exemplo o WELD para CDI e o mojarra para JSF.

Então como fazer funcionar nos 2 ambientes sem ter problemas de compatibilidade? Alguns passos são necessário, primeiro para o JSF:

  • Adicionar ao web.xml :
 
<context-param>
	<param-name>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</param-name>
	<param-value>false</param-value>
</context-param>

Agora para o CDI é mais complicado, inicialmente, todas as suas classes elegíveis a injeção, por exemplo, todas as classes que você anotou com @named, devem ser serializáveis, enquanto que no JBOSS não é obrigatório, eu diria até que é uma boa prática fazer isso. Além disso, o beans.xml deve ficar dentro de WEB-INF, obrigatoriamente. No JBOSS basta estar em algum lugar do classpath, no WAS 8 não, tem que estar ao lado do web.xml, abaixo de WEB-INF.

Porém isso não é tudo, no nosso caso aqui, nada estava sendo injetado pelo container, só conseguimos resolver isso incluindo a biblioteca de CDI do myfaces no classpath da aplicação, o Myfaces CODI . Um extra sobre o CODI é que ele também possui uma implementação similar ao ViewScope do JSF que funciona para CDI (CDI padrão não possui essa anotação), que é a @ViewAccessScoped

Você pode escolher quais módulos do CODI você deseja utilizar, aqui abaixo segue o código do pom para inserir o CODI completo, na wiki do CODI você encontra esses módulos.

 
    <dependency>
	<groupId>org.apache.myfaces.extensions.cdi.bundles</groupId>
	        <artifactId>myfaces-extcdi-bundle-jsf20</artifactId>
		<version>1.0.5</version>
		<scope>compile</scope>
    </dependency>

 

ago 03

Conversor em JSF2 com Servlet 3.0

Neste post falarei de como criar um converter para uma classe do meu modelo e também como utilizá-lo com um componente selectOneMenu.

Primeiramente, precisamos sobrescrever o método equals lá do nosso bean ( ex: MeuBean.java) para o qual será feito o converter.  Caso eu o identifique por um atributo específico, por exempo um id, o nosso equals ficaria da seguinte maneira:

 
        @Override
        public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Conta other = (Conta) obj;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		return true;
	}

Em seguida criamos uma nova classe chamada meuBeanConverter que irá implementar a interface Converter do pacote  javax.faces.convert , vamos anotá-la com a seguinte annotation: @FacesConverter, setando o atributo forClass da anotação com a nossa classe MeuBean.class .

Essa interface Converter possui 2 métodos que precisamos implementar:

  1. public Object getAsObject(FacesContext arg0, UIComponent arg1, String texto)
  2. public String getAsString(FacesContext arg0, UIComponent arg1, Object obj)

Onde o primeiro será acessado na fase do jsf : apply request values, quando o formulário for submitado, convertendo o atributo value  da tag option do html no objeto correspondente da nossa classe MeuBean. E o segundo no caminho inverso, quando queremos a partir de um objeto da nossa classe MeuBean,  mostrar no selectBox html o nosso objeto.

 
@FacesConverter(forClass = MeuBean.class)
public class ContaConverter implements Converter {

	@Override
	public Object getAsObject(FacesContext arg0, UIComponent arg1, String texto) {
		if (texto == null || texto.equals("")) {
			return null;
		}

		Long longId = Integer.valueOf(texto).longValue();
		MeuBean bean = //alguma maneira de recuperar o bean pelo atributo id
		return bean;

	}

	@Override
	public String getAsString(FacesContext arg0, UIComponent arg1, Object obj) {
		// TODO Auto-generated method stub
		if (obj == null || obj.toString().equals("")) {
			return "";
		}
		return ((MeuBean) obj).getId().toString();
	}

}

Por fim no nosso html teremos no value do h:selectOneMenu  a propriedade que receberá o valor escolhido que será convertido para um objeto da classe MeuBean, e na listagem de f:selectItems uma lista de objetos MeuBean ( Ex: List<MeuBean> meusBeans ).

<h:selectOneMenu id="meuBean" value="#{meuMB.meuBean}">
	<f:selectItems value="#{meuMB.meusBeans}" ></f:selectItems>
</h:selectOneMenu>

Apenas um detalhe a mais, não setando o atributo itemLabel do f:selectItems, será necessário sobrescrever o toString do MeuBean, caso contrário será impresso a representação do objeto.

jul 05

Upload de arquivos com primefaces

Quem usa JSF sabe que ele não tem tag nativa para upload de arquivos, para fazer funcionar , é preciso usar a tag html input e utilizar uma biblioteca da apache a commons-fileupload.

Porém algumas suites de componentes como richfaces , trinidad e tobago , e primefaces possuem essas tags. Nesse post vou focar no primefaces, pois considero a melhor dentre as apresentadas.

Antes é necessário que você baixe as seguintes bibliotecas e as adicione no classpath do seu projeto:

Em seguida você deve configurar seu web.xml caso você esteja usando Servlet 2.5, no caso do Servlet 3 eu não testei, mas acredito que não precise (quem usar, teste e comente por favor), adicionando o seguinte código abaixo:

        
	
        <filter>
                <filter-name>PrimeFaces FileUpload Filter</filter-name>
                <filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
        </filter>
        <filter-mapping>
                <filter-name>PrimeFaces FileUpload Filter</filter-name>
                <servlet-name>Faces Servlet</servlet-name>
        </filter-mapping>

No sua página você deve usar a tag  p:fileUpload , ela possui vários atributos que podem ser setados, mas os principais são :

  • mode – que pode ser simple ou advanced, onde o simple ele renderiza um input file html comum; e o advanced (que é o default) ele renderiza apenas o botão de pesquisar e ao selecionar o arquivo ele já o valida, além de oferecer as opções de upload ou descartar.
  • allowTypes – lista-se as extensões que deverão ser aceitas
  • sizeLimit – tamanho máximo do arquivo
  • fileUploadListener – método do managed bean que quando for escolhido o mode advanced , trata o evento de upload( explicarei em seguida )
  • value – propriedade do tipo UploadedFile do managed bean que será feito o upload do arquivo, utiliza-se no caso do mode = simple

Exemplo:

    
<p:fileUpload fileUploadListener="#{mb.upload}"
     allowTypes="png,gif,jpg,jpeg" sizeLimit="10000"
     value="#{mb.arquivo}" mode="advanced"  />

Por fim deve-se no managed bean criar o método para o fileUploadListener :

     
private UploadedFile arquivo;
public void upload(FileUploadEvent event) {
    arquivo = event.getFile();
   /* implementação*//
}

E pronto. No labs do primefaces tem alguns exemplos de utilização, e usando você também descobre outras funcionalidades.

fev 14

Por que não usar richfaces

Em um outro post meu eu vim explicar como fazer funcionar richfaces 4 com jsf2, mas simplesmente não funciona. Na verdade eu estou exagerando, funcionar funciona, porém faltam muitos componentes que quem está acostumado a utilizar a versão 3.X do richfaces sente uma falta muito grande, quem usa primefaces então, esse chora de doer.
Tudo bem que ainda não é a release final do richfaces 4, mas sinceramente está muito capenga ainda. Componentes básicos como ordenar uma tabela, filtrar, sem contar os a4j:commandButton que são um parto para funcionar, eu mesmo desisti de os usar.
No final das contas migrei tudo para primefaces, agora com a versão 2.2 estável, não tem comparação, simplesmente é o melhor framework existente para jsf2.

jan 18

Richfaces 4 com jsf 2 e tomcat 6

Lá vou eu me aventurar a utilizar o richfaces 4, que ainda está em versão de milestone 5. Mas vamo que vamo para ver o que ele tem de melhor ou pior que o primefaces.
Primeiro problema dele é a documentação falha, pois a última versão do richfaces vem com mais jars do que a documentação diz que precisa, e além disso são necessários outros 3 jars para conseguir rodar.

Assim é necessário baixar o richfaces e também os seguintes jars cssparser-0.9.5.jar, guava-r07.jar and sac1-3.jar e adicioná-los ao seu classpath para só então conseguir rodar sua aplicação jsf 2 com richfaces. A é claro que são necessárias também as bibliotecas do jsf 2 né.

Assim que tiver novidades postarei aqui, mas só para fazer rodar já me levou um tempinho, portanto fica aí a dica.

out 14

Biblioteca de componentes para JSF 2

Venho aqui neste post recomendar apenas, para quem quer utilizar JSF 2, e estava acostumado a utilizar richfaces, que para a versão 2 do JSF não está ainda com versão estável, recomendo o primefaces , que é uma suite de componentes muito completa, de muito fácil utilização. Bastando apenas baixar o jar do primefaces, e adicionar a suas páginas o namespace xmlns:p=”http://primefaces.prime.com.tr/ui”. No site, há um livedemo, que mostra cada componente, e o código de sua utilização.


Um problema apenas que eu tive em utilizá-lo, foi quando tive que usar outro componente que utilizava jquery em mesma página que estivesse utilizando o primefaces, pois como ele utiliza o jquery embutido no jar, ele acaba referenciando o arquivo jquery errado, o que faz com que os componentes não funcionem.

Mas se você não for usar outro componente que utilize jquery também, é uma ótima pedida o primefaces.