segunda-feira, 26 de julho de 2010

Upload de arquivos no JSF2 no escopo de conversação

Há algum tempo vinha procurando uma solução para fazer upload de arquivo no JSF2 no escopo de conversação.

Existem vários sites que mostram como fazer upload de arquivo no JSF{1,2}, porém nenhum deles leva em consideração o escopo de conversação: http://forums.sun.com/thread.jspa?threadID=5399669, http://ironicprogrammer.blogspot.com/2010/03/file-upload-in-jsf2.html, http://dominikdorn.com/?p=169, http://balusc.blogspot.com/2009/12/uploading-files-with-jsf-20-and-servlet.html

Além destes sites também vi uma solução no livro Core Java Server Faces 3ª edição, no entanto nesta solução o mesmo problema existia. Ao submeter um arquivo, enquanto no escopo de conversação, o escopo era simplesmente destruído.

Entrei em contato com os diversos autores para verificar se eles me davam uma luz, pois ainda sou bastante cru para mexer com filtros em JSF. Algum tempo depois recebi a resposta do autor do Core Java Server Faces, o Cay Horstmann, que me sugeriu olhar como o Seam resolvia o problema, pois esta foi a tecnologia pioneira do escopo de conversação.

Ele me deu esse conselho no dia 30 de Junho, mas apenas hoje consegui finalizar a implementação.

Primeiro olhei o código do RichFaces, pois ele que contém o componente de file upload e então percebi que ele não implementava o filtro, que é o componente que analisa a requisição e processa os cabeçalhos para extrair o arquivo e os outros elementos da requisição. Descobri que quem fazia isso era o próprio Seam.

Coloquei no liquidificador a implementação do Seam e do Cay Horstmann e o sabor ficou muito bom, um componente de upload de arquivos simples e que funciona no escopo de conversação. Pefeito!

Porém não me peça para explicar porque o filtro do Seam funciona para salvar a conversação, ainda não consegui entender, mas se você souber, ficaria muito satisfeito em ouvir.

O projeto do NetBeans que criei pode ser baixado através do seguinte link: http://sites.google.com/site/cerdiogenes/java/jsf2/fileupload.zip?attredirects=0

Nele não existe nenhum tipo de validação, mas pretendo começar a trabalhar nisso em breve, pois vou precisar integrá-lo em um sistema e os requisitos se tornam mais específicos. Que venham os problemas então! E que sejam fáceis de resolver :D

sexta-feira, 2 de julho de 2010

Enviar comandos de teclado a uma aplicação através do terminal

Estou tentando treinar um controlador para aprender a dirigir em uma pista através de aprendizado não supervisionado. Estou rodando meu experimento no simulador TORCS, o que envolve reiniciar a corrida muitas vezes. O TORCS tem um bug que depois de re-iniciada a corrida centenas de vezes acaba gerando um segmentation fault. Ou seja, é um bug bastante chato de ser reproduzido e consequentemente bastante difícil de depurar e corrigir.

Para contornar este problema e ganhar tempo de simulação resolvi procurar uma solução para verificar se o TORCS estava rodando, em caso negativo (aconteceu o segfault) eu o reiniciaria, porém teria que mandar 4 enters para iniciar a simulação.

Após uma googleada encontrei a solução rapidamente. Utilizando o comando xsendkeycode é possível enviar sinais de teclados para a aplicação que está com foco. Com o comando ps e grep consegui verificar se o programa estava rodando.

No link http://www.anyexample.com/linux_bsd/bash/check_if_program_is_running_with_bash_shell_script.xml encontrei o script que verifica se um programa está rodando e nos links http://linux.die.net/man/8/xsendkeycode, http://www.linuxforums.org/forum/linux-programming-scripting/136576-simulating-pressed-keys-shell-script-3.html achei as peças para enviar os comandos enter.

No final criei o seguinte script:

#!/bin/bash
GAME='torcs'

OUT=$(ps ax | grep -v grep | grep $GAME)

if [ "x$OUT" != "x" ]
then
sleep 30
else
$GAME & sleep 2; xsendkeycode 36 1; xsendkeycode 36 0; xsendkeycode 36 1; xsendkeycode 36 0; xsendkeycode 36 1; xsendkeycode 36 0; xsendkeycode 36 1; xsendkeycode 36 0;
fi


E chamei-o com a seguinte linha para ficar em um loop infinito:

while [ 1 ]; do ./run_game.sh; done