É na hora do stop / start dos servidores Java que bate aquela inveja do PHP, que consegue fazer um refresh geral apenas com um F5 no browser.
A empresa que resolveu esse problema (ZeroTurnaround) está ganhando uma boa grana com isso, vendendo licenças a um dólar por dia com o software JRebel
Entretanto, um excelente projeto semelhante não tem ganhado o foco que merece, talvez pela falta de usuários ou de documentação.
Conheça a alternativa gratuita e livre: Dynamic Code Evolution Virtual Machine ou simplesmente DCE-VM, criada pelo desenvolvedor Thomas Würthinger que colocou sua tese em prática.
Ao contrário do JRebel, que encapsula a JVM para fazer o hotswap das classes, o DCE-VM altera o seu JRE, substituindo o hotswap limitado da JVM tradicional.
Atualmente o projeto está no github, e o link para download as versões recentes é esse: https://dcevm.github.io/
Se você usa o IntelliJ, tem um plugin pronto pra ele.
Se você usa Eclipse ou outro editor, vou explicar aqui como é simples o seu uso.
Os passos são esses para usar a sua aplicação com o Apache Tomcat 7 :
- baixar uma JDK compatível 1.7 ou 1.8 se necessário;
- instalar o DCE-VM na JDK;
- configurar o seu ambiente para usar essa JDK;
- adicionar CMSClassUnloadingEnabled nos parâmetros da JVM;
- conectar em modo Debug à JVM do Apache Tomcat 7;
- codificar, gravar e testar no browser \o/
Eu fiz o teste com a JDK 7 update 51 – 64 bits instalada em um diretório alternativo: /home/fb/jdk/jdk1.7.0_51 baixando o
instalador para essa mesma versão.
Depois iniciei o instalador:
$ java -jar installer-full-jdk7u51.3.jar
O instalador identifica as instalações de JDK existentes:
Clicando na opção “Add installation directory…“, adiciono o diretório /home/fb/jdk/jdk1.7.0_51 :
Depois escolhendo a opção “Replace by DCEVM” o instalador faz a troca:
Ao exibir a versão do Java verificamos que foi instalado com sucesso:
fb@cascao ~ > /home/fb/jdk/jdk1.7.0_51/bin/java -version java version "1.7.0_51" Java(TM) SE Runtime Environment (build 1.7.0_51-b13) Dynamic Code Evolution 64-Bit Server VM (build 24.51-b03-dcevmfull-3, mixed mode)
Nos meus projetos eu uso o plugin do Maven para subir o Tomcat 7 localmente:
<plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <port>8080</port> <path>/</path> </configuration> </plugin>
Usei um projeto bem simples com Spring, com um controller assim:
@Controller public class TesteController { @RequestMapping(value = "/teste",method = RequestMethod.GET) protected void teste(ModelMap model) { model.put("valor","Funciona ?"); } }
Que chama uma página JSP extremamente simples:
<html> <h1>${valor}</h1> </html>
Subi o servidor com o script abaixo, note os parâmetros da JVM de debug junto com o CMSClassUnloadingEnabled:
export JAVA_HOME=/home/fb/jdk/1.7 export PATH=$JAVA_HOME/bin:$PATH export MAVEN_OPTS=" -Xmx512m -XX:MaxHeapSize=512m -XX:MaxPermSize=512M -XX:+CMSClassUnloadingEnabled -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=4000,server=y,suspend=n" mvn clean install tomcat7:run
Acessando a página de teste, temos:
Agora, pelo Eclipse conectamos ao servidor em modo debug:
E vamos fazer uma alteração no sistema, criando uma nova classe:
public class Teste { public String nome() { return "Siiiim ! http://www.boaglio.com"; } }
E alterar a classe existente para chamar a classe nova:
@Controller public class TesteController { @RequestMapping(value = "/teste",method = RequestMethod.GET) protected void teste(ModelMap model) { model.put("valor","Funciona ? "+ new Teste().nome()); } }
E fazendo o reload, percebemos a página atualizada:
Uau! Atualizou sem stop / start!
Uma lágrima caiu do seu olho e finalmente você pode comparar PHP ao Java… =)
Mas calma lá, nem tudo são flores… hoje em dia sempre usamos frameworks, e as vezes nem esse hotdeploy adianta, pois, por exemplo, o Spring MVC possui um contexto que é registrado no início da aplicação, se você, pode exemplo, adicionar uma classe nova e usar @RequestMapping(value = “/outro-teste”) não vai funcionar, pois a classe nova está lá, mas o contexto do Spring continua o mesmo.
Nesse sentido o JRebel é bem mais maduro, mas com certeza o DCE-VM te salvará alguns minutos ou horas de sua vida, aproveite! . =)
Fernando Boaglio, para a comunidade