Integrando Apache com Glassfish
Após fazer a migração das minhas aplicações do Tomcat para o Glassfish ainda faltou fazer com que o Apache (httpd) redirecionasse requisições para o Glassfish. Isto é útil quando temos aplicações (em PHP, por exemplo) que rodam no Apache e ainda queremos usar a porta http default 80 para aplicações desenvolvidas em Java rodando no Glassfish.
Para habilitar no Glassfish (versão v2) a integração com o Apache, temos que copiar os jars commons-modeler, commons-logging e tomcat-ajp de uma instalação existente do Tomcat (importante: não pode ser a última versão do Tomcat que não funciona, eu usei a 5.5.17) para o diretório $GLASSFISH_HOME/lib. No meu caso comecei a ter problemas com o log4j e tive que tirá-lo do pacote da minha aplicação e colocá-lo no diretório lib também para o servidor inicializar sem erro. Só que minha aplicação parou de mostrar os logs do log4j, isso ainda é um problema que tenho que contornar.
Após ter copiado os jars, ainda temos que definir uma propriedade na inicialização do Glassfish que definirá a porta utilizada pelo mod_jk do Apache para se comunicar com o Glassfish:
-Dcom.sun.enterprise.web.connector.enableJK=8009
Isso pode ser feito pela interface de administração (por exemplo, http://localhost:4848) ou usando o comando:
$GLASSFISH_HOME/bin/asadmin create-jvm-options -Dcom.sun.enterprise.web.connector.enableJK=8009
Não vou explicar a parte do Apache que utilizaria o mod_jk, é só procurar no Google como faz a integração Tomcat com Apache que é igual.
Se alguém quiser mais detalhes, ver em essa página em inglês: Running GlassFish with Apache httpd
Netbeans 6.1, Glassfish v2 e Maven 2
Aqui tenho 2 aplicações web que utilizam uma base comum, e queria que o Spring inicializasse somente uma vez. Como o Spring que gerencia a utilização do Hibernate eu criaria somente um sessionFactory e também unificaria o cache. Procurando na net descobri um artigo onde ensinava a fazer isso, mas eu precisaria empacotar minha aplicação como um ear. Como o Tomcat que eu utilizava atualmente não suporta ears, depois de testar rapidamente JBoss, Geronimo e Glassfish acabei optando pelo Glassfish. Não foi nenhuma pesquisa muito profunda, o Glassfish foi o que eu consegui fazer funcionar mais rapidamente minha aplicação e eu gostei da interface de administração.
Na configuração do Glassfish eu precisei criar o Realm de Segurança (e um sun-web.xml que vai no war para mapear os roles), os DataSources para conexão com o MySQL e configurar o JMS. A vantagem que ele já tem um servidor JMS integrado e quando eu utilizava o Tomcat dependia do ActiveMQ rodando em separado, mais uma razão para eu mudar para um servidor de aplicação.
Daí parti para integrar o Glassfish com o Eclipse, mas o plugin do Glassfish não estava funcionando. Resolvi testar o Netbeans que tem uma ótima integração com o Glassfish (é tudo da Sun
). Só precisei instalar os plugins do Maven (dentro dele tem uma opção de instalar plugins) e importar meus projetos foi extremamente fácil.
Agora para fazer o deploy do meu projeto Maven no Glassfish eu não consegui de um jeito bom, estou fazendo pela linha de comando mesmo usando o comando asadmin (criei um shell script pra isso). O Glassfish eu rodo por dentro do Netbeans, perto de onde tem a estrutura do projeto tem uma aba Serviços. Ali tem Servidores e dentro o Glassfish, só clicar com o botão direito e mandar rodar ou parar.
Meu ear ficou com 2 wars dentro e com todos os jars comuns aos dois wars. Cada war tem somente os jars específicos utilizados somente neles. Depois de alguns problemas com classloaders consegui fazer a minha aplicação funcionar. Tive que colocar a opção class-loader delegate=”false” nos meus arquivos sun-web.xml e tomar cuidado para que cada dependência que fosse procurada ou estivesse no mesmo classloader ou no classloader pai. Para saber mais sobre a “hierarquia” de classloaders é só dar uma olhada na documentação do Glassfish.
Fica aqui o relato que talvez ajude alguém, não entrei em muitos detalhes para não ficar muito extenso. Me surpreendi com a qualidade do Glassfish e do Netbeans que não via fazia muito tempo. E pensar que eu odiava servidor da Sun (iPlanet argh!!).
Encontre bugs no Java com FindBugs
Nem me lembro como ouvi falar do FindBugs, mas agora acho uma ferramenta essencial. O que ele faz é vasculhar todo o seu código e mostrar lugares onde possam existir possíveis bugs. Sabe aqueles lugares que não foram testados direitos, que são pouco utilizados e que ninguém percebeu que tem um erro ali? O FindBugs pode te ajudar com isso.
Por exemplo, ele acha comparações de String usando == (o certo seria usar o método equals). Outro exemplo, no meu código eu tinha uma lista de estados e estava vendo se ela tinha uma cidade. O código compilava, mas o que eu queria realmente era saber se na lista de estados tinha um estado e não uma cidade! (pra achar bugs desse tipo acho que só a partir do Java 5 onde as Collections podem ter tipos)
E para cada tipo de aviso ele dá uma explicação do porque. Com isso você pode além de achar os bugs aprender mais coisas sobre a linguagem Java.
Outra coisa legal do FindBugs é a integração com outras ferramentas. Pode usá-lo como plugin do Eclipse ou com o Maven para gerar relatórios do projeto.
Criando arquivos Excel com tabelas dinâmicas em Java
Estava com esse problema recentemente e vou dar dicas sobre o que pode ser feito:
- Criar um arquivo usando o próprio Excel que servirá de template. Escrever os dados e dar nome ao range de dados (“Name a Range” no Excel em Inglês).
- Neste template definir as tabelas dinâmicas (pivot tables) usando o range definido no item anterior (não utilizar seleção manual de células). Entrando nas opções da tabela dinâmica, marcar a opção para fazer refresh ao abrir o documento.
- Utilizando o POI, escrever os comandos no java que abra o arquivo template, insira os dados reais por cima dos dados de exemplo, reajuste o named range de células para refletir a quantidade de linhas que tem os dados inseridos e salvar o arquivo com outro nome.
Expliquei bem por cima o que tem que fazer para ajudar aqueles que não tem nenhuma idéia. Outra coisa é que o POI deu problema ao tentar abrir um arquivo meu que tinha filtros, então devemos tirar todos os filtros do arquivo Excel. Uma coisa que não sei é se as tabelas dinâmicas feitas vão funcionar no Open Office.
Integrando Stripes com Jasper Reports
Vou falar aqui de como fazer a integração do Jasper Reports com o Stripes. Mais especificamente de como fazer o método num ActionBean do Stripes.
Uma das maneiras de se gerar relatórios com o Jasper é utilizando um OutputStream que conterá o relatório gerado. Sabendo disso, segue um exemplo de método de um ActionBean do Stripes que exporta um pdf, por exemplo:
public Resolution exportaPdf() {
ByteArrayOuputStream output = new ByteArrayOutputStream();
geraRelatorioPdf(output);
return new StreamingResolution("application/pdf",
new ByteArrayInputStream(output.toByteArray()))
.setFileName("relatorio.pdf");
}
Este método ao ser chamado da tela, irá gerar o relatório em output e retornará um StreamingResolution com os dados do relatório, fazendo com que o navegador apresente a janela pedindo para salvar o arquivo.
Caso se deseje exibir no navegador um relatório gerado em html, podemos fazer de forma semelhante:
public Resolution exibeRelatorioHtml() {
ByteArrayOuputStream output = new ByteArrayOutputStream();
geraRelatorioHtml(output);
return new StreamingResolution("text/html",
new ByteArrayInputStream(output.toByteArray()));
}
Em ambos os casos, utilizei os métodos geraRelatorio somente para simplificar a explicação do ActionBean. Estes métodos que se utilizariam do Jasper Reports para a confecção dos relatórios.
Subversion no Eclipse 3.4 Ganymede
O plugin subversive agora faz parte do Eclipse como um componente opcional. Para instalá-lo deve-se entrar em Help, Software Updates e escolher a opção Available Software. Clicar na seta do lado do Ganymede para abrir as categorias, escolher a categoria Collaboration Tools e selecionar a opção SVN Team Provider.
Ainda ficarão faltando os conectores SVN que devem ser baixados do site da Polarion (empresa que faz o subversive). Para isso devemos usar, ainda em Software Updates do Eclipse, o botão Add Site e colocar a seguinte url:
http://www.polarion.org/projects/subversive/download/eclipse/2.0/update-site/
Assim aparecerá na janela o site adicionado e será possível selecionar os conectores. Eu selecionei todos, acho que é possível escolher um diferente do default após a instalação caso queira mudar.
Depois de feito tudo isso é só mandar instalar e reiniciar o Eclipse.
Cobertura de testes 100% não indica software perfeito
Existem ferramentas que mostram a cobertura do código conseguida pelos testes automatizados (por exemplo, uma de Java é o Cobertura, que pode ser integrado com Ant e Maven inclusive). Quanto mais código testado melhor e a ferramenta de cobertura vai mostrar as linhas de código por onde os testes estão passando. Olhando os resultados você poderia ver que algum else não está sendo executado nos testes e escrever um teste que passe nesse else.
Mas se por um acaso alguém conseguisse uma cobertura de 100% de testes, o que é difícil (Exceptions de diversos tipos que são difíceis de testar) e não prático (setters e getters simples não precisam ser testados, não tem muito o que dar errado), não teria um software perfeito.
E por que isso? A cobertura pode dar 100%, só que quando tem alguma coisa faltando também é um erro. Posso ter esquecido de escrever algum if no código. Código que não existe não aparece na cobertura.
Outra coisa, os erros podem ocorrer com cada combinação de decisões que o software toma. Um teste pode entrar num if, outro teste pode entrar em outro, mas um bug pode acontecer justamente quando se entra nos dois.
Além dessas razões, só passar pelo código é apenas uma parte do teste. A outra são os assertions, os trechos de códigos exercitados devem ter uma confirmação do teste que o retorno do resultado é correto.
Então, a lição que fica é, não tente uma cobertura de 100% porque vai ser muito difícil e também porque isso não vai indicar um software perfeito. Use a cobertura de testes para encontrar trechos chaves do código que deveriam ser testados, mas não estão sendo.
Parando uma Thread em Java
Afinal, quando a execução de uma thread acaba? A execução acaba quando o método run() termina.
Ok, mas minha thread é um serviço que fica sempre em loop (ouvindo uma porta, por exemplo), ela não vai terminar nunca!
Uma hora ela vai precisar terminar, ou se seu programa for finalizado ou, caso seja um serviço do sistema, quando o sistema for desligado. Neste caso, o que eu mais vi sendo utilizado é uma variável boolean que é modificada pela classe “dona” que invocou a thread, parando a execução. O código seria nesse estilo:
public class SempreEmLoop implements Runnable {
private volatile boolean stop = false;
public void run() {
while (!stop) {
// ... faz o que tem que fazer
try {
Thread.sleep(100); // para nao deixar a cpu fervendo
} catch (InterruptedException ex) {
// nao ligo caso a thread seja interrompida durante o sleep
}
}
// o laco acabou... alguem parou a execucao, liberar recursos
finalizaFechandoArquivosSocketsEOutrasCoisas();
}
/**
* Método que vai ser chamado para parar a thread
*/
public void parar() {
this.stop = true;
}
}
Agora na classe que chama a Thread:
public class DonaDaThread() {
private SempreEmLoop meuRunnableSempreEmLoop;
public void iniciaMinhaThread() {
meuRunnableSempreEmLoop = new SempreEmLoop();
Thread minhaThread = new Thread(meuRunnableSempreEmLoop);
minhaThread.start();
}
public void paraMinhaThread() {
meuRunnableSempreEmLoop.parar();
}
}
A classe DonaDaThread é que vai controlar a execução da thread que contém SempreEmLoop. Chamando o método donaDaThread.iniciaMinhaThread() vai inicializar uma thread que roda o método run() da classe SempreEmLoop. Chamando o método donaDaThread.paraMinhaThread() vai chamar o método parar() da SempreEmLoop que faz com que o laço while pare e libere os recursos que a thread estava utilizando.
Note que a variável boolean da SempreEmLoop é definida como volatile. O que eu li em outros lugares é que ela deve ser volatile para que o compilador não tente otimizar o laço while. Como a variável stop nunca é alterada dentro do laço, o compilador pode querer supor que stop é sempre false. Se colocar volatile o compilador não faz essa suposição e deixa stop do jeito que está, fazendo com que stop seja sempre verificada a cada iteração de while.
Existe também o método interrupt() na classe Thread, só que esse método interrompe a thread somente se ela estiver bloqueada (pelos métodos wait, join ou sleep).
Atalhos do Eclipse
Olá a todos!
Vou falar aqui sobre alguns atalhos úteis do Eclipse que é a IDE que eu uso.
ctrl-shift-t – Open Type – Atalho para abrir o código de um tipo do Java para edição. Por exemplo, em algum lugar do seu projeto tem uma classe GenericDAO. Então se você quiser abrí-la para edição, aperta crtl-shift-t, começa a escrever GenericDAO e clica nela na lista.
ctrl-shift-r – Open Resource – Serve para você abrir um arquivo qualquer. Por exemplo, você tem um arquivo header.html, aperta ctrl-shift-r, começa a escrever header.html e clica nele na lista.
ctrl-o – Com o cursor numa classe, navega dentro dela abrindo uma lista de métodos e atributos. Aperte ctrl-o e vá digitando o nome do método, por exemplo, getName. Selecione na lista que o cursor vai direto para o método getName.
alt-shift-R – Rename – Refatoração para mudança de nome de um atributo, método, nome, classe em que o cursor estiver em cima. Usando a refatoração, todos os lugares onde estiver sendo utilizado o alvo da mudança também serão modificados.
alt-shift-L – Extract Local variable – Refatoração que transforma a parte selecionada numa variável local. Por exemplo, você seleciona no código:
if (number >= 0) { ...
Aperta alt-shift-L, e escreve isPositiveNumber, ficando assim:
boolean isPositiveNumber = number >= 0;
if (isPositiveNumber) { ...
alt-shift-M – Extract Method – Refatoração que transforma a parte selecionada num método. Por exemplo, você seleciona no código:
if (number >= 0) { ...
Aperta alt-shift-m, e escreve isPositiveNumber. Isso irá criar um novo método ficando assim:
if (isPositiveNumber()) { ...
E mais abaixo terá o método:
private boolean isPositiveNumber() {
return number >= 0;
}
Aprender a usar bem os métodos de refatoração é muito importante, pois assim naturalmente o seu código fica mais legível, limpo e organizado (que é o objetivo de refatorações
).
Fico por aqui, espero que tenha ajudado!
Conhece o Hudson?
Conhece o Hudson? Aquele que… faz Continuous Integration.
Página do Hudson: https://hudson.dev.java.net/
Descobri esta ferramenta através do livro Java Power Tools – edição de 2008.
Achei fácil de usar, você configura seu projeto todo por tela (nada de xml), com uma interface bem limpa e ele é extensível com o uso de plugins. Tem vários plugins no site, para todos os gostos.
Para meu projeto com Maven e Subversion foi muito simples fazer a configuração.
