Migrando uma aplicação Java 6/Jboss 4 para Java 11/Wildfly 18
Tags: java, jboss, wildfly
Published: 2022-06-03 14:37:13

O desenvolvimento no setor público tem algumas características peculiares, e uma delas é a longevidade que uma aplicação pode ter. Neste caso específico em que vou relatar, a aplicação começou a ser desenvolvida no segundo semestre de 2012 e continua em operação até hoje, ainda com muitos anos de operação previstos e contínuas melhorias a serem implementadas. 

Com o depreciamento do Java 6 e a recusa dos navegadores em aceitar os protocolos TLS inferiores a 1.2,tive que fazer uma migração da JVM e servidor para que a aplicação continuasse em operação sem problemas. E é nesses momentos que você sente aquela felicidade por ter escolhido a plataforma Java para desenvolvimento, pois a retrocompatibilidade de versões do Java é uma grande vantagem nessas horas. Vou compartilhar com vocês alguns problemas que eu tive durante essa migração.

Por ser uma aplicação em que eu era o principal desenvolvedor e tinha profundo conhecimento das regras de negócio, sabia exatamente o que e como testar após as mudanças. Isso facilitou muito todo o trabalho, já que eu pude me concentrar mais a fundo nas funcionalidades com maior potencial de problemas. 

A stack principal da aplicação era o combo Struts 1.3, Hibernate 3.2, PostgreSQL 8 e Jquery 1.11, tipicamente no modelo MVC. Para realizar a migração, eu fiz a atualização de todas as bibliotecas usadas no projeto para a versão mais recente compatível possível, mas como existiam algumas bibliotecas internas que não podiam ser alteradas, nem sempre foi possível atualizar para a última versão disponível. Esse foi caso do Hibernate, em que tive que usar uma versão intermediária, pois a construção de algumas bibliotecas internas dependiam de recursos que não existem nas versões mais novas. 

Outro empecilho, foi a impossibilidade de migrar o Struts para uma camada de _Controller_ mais atualizada, pois demandaria um grande esforço de reimplementação de todas as páginas da aplicação, que não eram poucas. 

Assim, o esforço foi concentrado mais na camada de modelo e acesso a dados, onde eu reescrevi todas as consultas ao banco de dados que estavam implementadas em Criteria ou HQL do Hibernate, para Criteria JPA 2. Isso foi mais por preciosismo que por necessidade, já que essa migração foi uma oportunidade para me familiarizar com o JPA 2, ao qual tinha tido pouco contato até então.

Embora muito verboso e pouco intuitivo pelos nomes, gostei bastante de usar Criteria do JPA, principalmente com o modelo de static metamodel, que elimina as strings da sua implementação e ajuda bastante na manutenção e alteração das aplicações.

Voltando a migração, os principais problemas que tive foram:

- Erro em indexed properties dos forms struts após atualizar a biblioteca commons-beautils. A solução é mudar o nome do métodos get/set sem index dos List do form do struts.(http://javabreaks.blogspot.com/2016/01/indexoutofboundsexception-when-using.html), (http://commons.apache.org/proper/commons-beanutils/javadocs/v1.9.4/RELEASE-NOTES.txt)
- Erro em indexed properties dos forms struts com indices negativos.
- Erro com BigDecimal null após atualizar a biblioteca commons-beautils. Usar `BeanUtilsBean.getInstance().getConvertUtils().register(false, false, 0)`.
- Problema com jquery.ajax e arrays nos forms do struts por causa da atualização do commons-beautils. Usar `jQuery.param(data, true)`.
- Erro ao obter arquivos ".jasper" porque o `class.getClassLoader().getResourceAsStream` mudou a partir do java 9.
- Usar `@NotFound(action = NotFoundAction.IGNORE)` nos casos de erro de associação não encontrada que passaram a ocorrer após atualizar a biblioteca do hibernate.
- @ManyToMany com @JoinTable retirar cascade = CascadeType.ALL.
- @ManyToMany usar JoinType.INNER e não JoinType.LEFT nas queries, senão vai retornar listas com `null`.
- @ManyToOne(cascade = CascadeType.ALL) causa erro ao incluir um entidade com associação de objeto já salvo. Usar entityManager.merge.
- @OneToMany(cascade = CascadeType.ALL, mappedBy = "xxx") não exclui o filho e não causa causa erro. remover o CascadeType.ALL.
- `entityManager.find` retorna nulo se a transação não foi comitada. JPA não aceita _transaction isolation_.
- Todas as sequences definidas no `@GeneratedValue(generator=xx)` tiveram que ser alterados para ter um nome único no sistema.

Basicamente, os maiores problemas foram mudanças e comportamento das bibliotecas commons-beautils e hibernate após a atualização. No meu caso a commons-beautils foi atualizada para a versão 1.9.4 e o hibernate para a versão 4.3.11.

Espero ter ajudado algum guerreiro que tenha a mesma tarefa.