mai 03

Remoção de um item de datatable sem dar update no form inteiro no primefaces

Bom o título é grande mas o assunto é confuso. Contextualizando, imagine que você queira permitir ao seu usuário incluir vários campos de telefone, porém ele pode inserir N telefones, para isso você precisa que sejam campos dinâmicos.

No JSF  você pode fazer isso criando uma coleção no seu managedBean e utilizando o componente datatable. Assim ao inserir um novo telefone você chama um método que acrescenta um novo item a sua coleção e da update no datatable.

Porém digamos que o usuário adicionou acidentalmente um outro campo de telefone e queira removê-lo. Para isso é necessário um botão que faça tal ação, chamando um método do managedBean para remover o item desejado da lista.

Mas, porém, contudo, no entanto dentro de um datatable o update de um p:commandButton só funciona passando o parâmetro @form, que faz um refresh do formulário inteiro, o que nem sempre é desejado, pois somente queremos dar update no datatable.

Depois de muito discutir com amigos e pesquisar uma solução, descobri uma forma de fazer isso utilizando o componente p:remoteCommand, da seguinte maneira:

No botão de remover você faz:


<p:commandButton value="remover" type="button"
     onclick="removeRC({param:#{row}})" ></p:commandButton>

ATENÇÂO, a solução acima não se aplica para a versão 3.5+ do primefaces, caso esteja utilizando-a faça da seguinte maneira:


<p:commandButton value="remover" type="button"
     onclick="removeRC([{name:'param',value:#{row}}])" ></p:commandButton>

Onde row é o nome do atributo rowIndexVar do p:dataTable.

Aí fora da datatable vc usa um p:remoteCommand:


<p:remoteCommand name="removeRC" 
    update="datatableID" actionListener="#{MB.remove}">

</p:remoteCommand>

E pronto, é só agora fazer seu MB com os métodos como o exemplo abaixo e você conseguirá contornar esse bug do primefaces

@ManagedBean(name = "MB")
@ViewScoped
public class MB {

	private List<String> telefones;	

	public MB() {

		telefones = new ArrayList();
		for (int i = 0; i < 3; i++) {
			telefones.add(new String());
		}
	}		

	public void addList() {
		telefones.add(new String());
	}

	public void remove(ActionEvent event) {
		FacesContext context = FacesContext.getCurrentInstance();
		Map map = context.getExternalContext().getRequestParameterMap();		
		int row = Integer.parseInt(map.get("param"));
		telefones.remove(row);
	}

	public List getTelefones() {
		return telefones;
	}

	public void setTelefones(List telefones) {
		this.telefones = telefones;
	}
}

dez 14

Codigo Java dentro do javascript

Esse post vai ser bem curto, é só para mostrar que é possível chamar código java direto do html através de javascript, para fazer da seguinte maneira:

<script type="text/javascript">
           var data = new java.util.Date();
           alert(data);

</script>

Este código mostrará uma janela de alert com a data e hora do momento da execução, ele demonstra que para chamar alguma classe java deve-se declarar todo o caminho da classe. No caso de classes do pacote java é só chamar direto, no caso de classes personalizadas deve-se utilizar da seguinte maneira:

<script type="text/javascript">
           var minhaClasse = new Packages.meuPacote.minhaClasse();
           var retorno = minhaClasse.meuMetodo();
</script>

Para isso funcionar você precisa estar com essa classe no classpath da sua aplicação web. Mais informações basta olhar na documentação do Rhino

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.

mar 22

Habilitar o java no firefox em linux

Para você que usa linux, no meu caso é ubuntu, e utiliza firefox, percebeu já que ao baixar uma nova versão do site da mozilla os applets java param de funcionar. Eu acabei de baixar o firefox 4, muito bom, visual mais limpo e a primeira impressão é que está mais rápida a navegação, e mais uma vez ( pois não anotei como fiz da última) tive que perder alguns minutinhos configurando o plugin do java,  já que o que acho na internet logo de cara é criar um link do plugin libjavaplugin_oji.so que se encontra em /jdkXXX/jre/plugin/i386/ns7 , porém achei em outro lugar que não é mais essa a biblioteca necessária e sim a libnpjp2.so que fica em /jdkXXX/jre/lib/i386.

Para fazer funcionar crie um diretório com o nome plugins na pasta onde possui o arquivo de execução do firefox e então crie um link da biblioteca libnpjp2.so e o coloque nesta pasta. Para criar tal link você tem duas opções (Eu fiz no ubuntu, portanto se em alguma outra distribuição for diferente, desculpe-me):

1) Visualmente, selecionando com o botão direito do mouse a lib e escolhendo a opção criar link, em seguida recortar e colá-lo na pasta plugins do firefox que você criou.

2) Via terminal com o comando ln -s [endereço fonte]/libnpjp2.so [endereço destino]    . Onde o endereço fonte é o citado anteriormente onde se encontra a biblioteca,  e o destino é a pasta plugins criada.

mar 11

Engatinhando com Android

Comecei agora a estudar para desenvolver minha dissertação de mestrado utilizando Android. A medida que for descobrindo coisas interessantes vou postando aqui, tanto para minha base de conhecimento como para informar a vocês.

Primeiramente, para você começar com Android é preciso saber JAVA, pois a programação dos aplicativos é nessa linguagem.

Segundo você precisa de um ambiente para desenvolver os aplicativos, eu andei pesquisando e a princípio tenho 2 opções:

1) Baixar eclipse + android SDK + plugin ADT

2) Baixar MOTODEV + android SDK

Vantagens e desvantagens:

O MOTODEV nada mais é do que um eclipse + plugin ADT , porém vem com mais opções, como por exemplo uma gui para o desenvolvimento dos layouts XML, os quais definem as interfaces. Fazendo um paralelo com SWING é como se fosse um jigloo ou VEP da vida. Além de outras coisas mais que ainda não tive tempo de fuçar. Devido a essa facilidade eu estou preferindo até o momento utilizar o MOTODEV (Uma observação a atentar, só porque é da motorola não significa que seus apps só rodarão em aparelhos motorola). Para baixá-lo basta se cadastrar no site, é gratuito.

Basicamente aplicativos do android são baseados em atividades (Activities) que é “um componente da aplicação que provê uma tela na qual os usuários podem interagir com intuito de fazer algo, tal como discar, tirar uma foto, mandar um email, ou visualizar um mapa.”( Android Dev Guide). Um aplicativo normalmente é composto de diversas atividades, pois cada atividade corresponde a uma tela da aplicação. Essas atividades são ligadas para se navegar pela aplicação, cada vez que uma nova atividade é aberta a anterior é fechada, mas é mantida empilhada conservando seu último estado. No link do Dev guide é melhor detalhado o que é, como funciona, o ciclo de vida de uma atividade, etc.

Isso é um resumo básico, a partir de agora começarei a postar coisas mais práticas, mais implementações, e sempre que possível colocarei as definições ou teorias, ou então o link para tais.

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 19

Utilizando Quartz para agendamento de tarefas

O Quartz é um serviço de agendamento de tarefas com diversas funcionalidades, como agendamento por período, com data marcada, etc.

Ele é livre para utilização e está sob a licença Apache 2.0. Agora neste post vou dar uma breve noção de como se agendar uma tarefa para ser executada em uma data específica.

Primeiramente criaremos a classe Tarefa.java que irá implementar a interface Job da biblioteca Quartz como no exemplo abaixo, e no método execute você desempenha a tarefa desejada.

public class Tarefa implements Job{

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {

        System.out.println("Trabalhando");
        //Resto das atividades

    }

}

Para se chamar essa tarefa, em algum lugar da sua aplicação é necessário agendar sua execução da seguinte maneira:

SchedulerFactory sf = new StdSchedulerFactory();
Scheduler sched = sf.getScheduler();

JobDetail job = new JobDetail("Nome do Job que voce quiser",Tarefa.class);

java.util.Calendar cal = new java.util.GregorianCalendar(2011, Calendar.MARCH, 17);
  cal.set(cal.HOUR, 10);
  cal.set(cal.MINUTE, 30);
  cal.set(cal.SECOND, 0);
  cal.set(cal.MILLISECOND, 0);

Date dtInicio = cal.getTime();

SimpleTrigger disparo = new SimpleTrigger("Disparo da tarefa",dtInicio);
sched.scheduleJob(job, disparo);

Pronto, agora sua tarefa será executada no dia 17 de março de 2011 às 10:30, mas é óbvio que para isso sua aplicação precisará estar rodando até lá!

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.

nov 08

Configurando JPA com Hibernate

Neste post vou mostrar o básico para fazer funcionar o JPA  com hibernate , utilizando o hsqldb, que é um banco de dados leve e muito bom para testes de desenvolvimento.

Inicialmente precisaremos das bibliotecas do hibernate que nesta versão já vem com as do JPA 2, porém isso não influenciará muito nessa configuração básica caso esteja usando o JPA. Agora crie uma pasta lib para colocar os .jar e adicione-os ao build path do projeto.

O segundo passo é criar a nossa Persistence Unit, que provê a definição do contexto de persistência, contendo os metadados relativos a tal.


Para isso deve ser criado um arquivo XML chamado persistence.xml e deve ser colocado dentro da pasta META-INF dentro da sua pasta de códigos fontes, no eclipse, utilizando a configuração default ficaria :  “src/META-INF/persistence.xml” . Este arquivo ficará com a seguinte configuração :

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
    <persistence-unit name="pu" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" />
            <property name="hibernate.connection.url" value="jdbc:hsqldb:hsql://localhost/nomedobanco" />
            <property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver" />

            <property name="hibernate.connection.password" value="senha" />
            <property name="hibernate.connection.username" value="usuario" />

            <property name="hibernate.archive.autodetection" value="class"/>
            <property name="hibernate.hbm2ddl.auto" value="update" />
            <property name="show_sql" value="true" />
            <property name="format_sql" value="true" />

        </properties>
    </persistence-unit>
</persistence>

Obs.: Caso esteja utilizando o JPA  troque a linha da tag <persistence> por:

<persistence version=”1.0″
xmlns=”http://java.sun.com/xml/ns/persistence” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=”http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd”>

Feito isso precisamos agora configurar como pegar o EntityManager, que é uma interface para interagir com o contexto de persistência.

Para isso criaremos um singleton que através da fábrica EntityManagerFactory pegaremos uma nova instância de EntityManager caso não tenha nenhuma aberta, ou retornará a que já está aberta. Será criada a classe JPAUtil:

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class JPAUtil {
      private static EntityManagerFactory emf = null;
      private static EntityManager em = null;

      public static EntityManagerFactory getEntityManagerFactory() {
            if (emf == null)
                 emf = Persistence.createEntityManagerFactory("pu");
            return emf;
      }

       public static EntityManager getEntityManager() {
             if (em != null && em.isOpen())
                   return em;
             else {
                   em = getEntityManagerFactory().createEntityManager();
                   return em;
             }
       }

}

Isso já basta para testar se está funcionando, a conexão com o banco. Para testar agora criaremos uma classe de testes utilizando o JUnit para verificar se está tudo ok. Criaremos a classe JPATest:

import static org.junit.Assert.*;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;

import org.junit.Test;

public class JPAtest {
	@Test
	public void testaConexaoJPA() {
		EntityManager em = JPAUtil.getEntityManager();
		EntityTransaction transaction = em.getTransaction();
		transaction.begin();
		transaction.commit();
		boolean isconectado = em.isOpen();
		em.close();
		assertTrue(isconectado);
	}
}

Pronto, se tudo estiver correto ficará verde o teste do JUnit. Em outro post mostrarei como implementar um DAO para JPA.

nov 03

Utilizando C3p0 para resolver problemas de falha na conexão com banco

Coloquei uma aplicação no servidor da DailyRazor,  utilizando hibernate com hbm e mysql. Rodando a aplicação localmente no meu tomcat, e apontando para o banco remoto funcionava perfeitamente, porém quando rodava do servidor acessando o banco de dados local, funcionava por um minuto e em seguida a seguinte exceção era lançada: “com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure”. Procurando na internet ( lê-se google) achei vários motivos, que em nada me ajudaram, como por exemplo não permissão de acesso ao banco via TCP/IP, banco fora do ar, etc. Então preferi passar a bola para o pessoal da hospedagem e abri um ticket (Um parenteses aqui: O serviço de suporte do Daily Razor é excelente, resolvem tudo muito rápido.) e logo em seguida foi-me passada a solução: utilizar o C3p0 setando as seguintes configurações no hibernate.cfg.xml:

<property name="hibernate.c3p0.acquire_increment">1</property>
<property name="hibernate.c3p0.idle_test_period">300</property>
<property name="hibernate.c3p0.timeout">120</property>
<property name="hibernate.c3p0.max_size">25</property>
<property name="hibernate.c3p0.min_size">1</property>
<property name="hibernate.c3p0.max_statement">0</property>
<property name="hibernate.c3p0.preferredTestQuery">select 1;</property>


Essa é a configuração default, a única coisa que precisei modificar foi o tempo de timeout, já que eles tem como tempo de timeout para o MySQL 300, segundo eles por questões de estabilidade.
Fica aí a dica, mesmo que não precise recomendo a utilização do C3p0 para pooling de conexão com o banco de dados, pois melhora a performance da aplicação. Nesse blog aqui tem algumas informações a mais.