Resolvendo falta de classes para SSL do JDK no Jboss 7 AS / 6 EAP

No Jboss AS 7 / EAP 6 enfrentei uma situação onde quando a aplicação tentava estabelecer uma conexão segura via HTTPS (no caso era um webservice), acontecia o seguinte erro:

java.lang.NoClassDefFoundError: com/sun/net/ssl/internal/ssl/Provider

Pesquisando, percebí que essa classe fazia parte da própria JRE, mas no entanto, o Jboss não estava dando visibilidade dela para o ClassLoader da aplicação.

Para resolver, basta adicionar os seguintes path no arquivo XML do módulo da JDK localizado em JBOSS_HOME/modules/sun/jdk/main/module.xml:

...   
     <path name="com/sun/net/ssl/internal"/>
     <path name="com/sun/net/ssl/internal/ssl"/>
... 

Suprindo a falta do @KeepAlive no JSF 2

Para quem programa em JSF 1.2 com RichFaces + A4j, um recurso muito popular é o @KeepAlive. Anotando um ManagedBean dessa forma ele fica com um escopo maior que o de Request e menor que o de Sessão, sobrevivendo na memória enquando o usuário navegar entre páginas que façam uso de um mesmo ManagedBean. Exemplos clássicos: 1. Páginas de listagem e edição; 2. Formulários preênchidos em etapas.

Ao pisar no terreno do JSF 2.0 essa tag deixa de existir. Ainda que existisse, você pode não querer usar o RichFaces e escolher outra biblioteca, como por exemplo a PrimeFaces. A ausência do @KeepAlive no JSF 2.0 parece não ser vista como algo grave já que existem novas possibilidades de controle de escopo tais como as anotações próprio JSF e a as anotações do CDI. O JSF 2.0 fornece por exemplo a @ViewScoped, usada para páginas recheadas de Ajax, mantendo o ManagedBean vivo enquanto existem requests para a mesma página, ou seja, quando não há navegação (métodos acionados devem ser void ou retornar String null). Já o CDI fornece o @ConversationScoped que permite dizer quando a “conversação” com o ManagedBean inicia e termina de forma programática.

Para quem ainda sente falta do simples e preciso @KeepAlive, uma solução é recorrer ao pacote CDI Extensions (CODI) do projeto Apache MyFaces, que fornece a notação @ViewAcessScoped que nos dá exatamente o comportamente desejado. Para instalá-lo via Maven, adicione as seguintes dependências ao projeto:

<dependency>
	<groupId>org.apache.myfaces.extensions.cdi.modules</groupId>
	<artifactId>myfaces-extcdi-jsf20-module-api</artifactId>
	<version>1.0.3</version>
	<scope>compile</scope>
</dependency>

<dependency>
	<groupId>org.apache.myfaces.extensions.cdi.modules</groupId>
	<artifactId>myfaces-extcdi-jsf20-module-impl</artifactId>
	<version>1.0.3</version>
	<scope>compile</scope>
</dependency>

<dependency>
	<groupId>org.apache.myfaces.extensions.cdi.core</groupId>
	<artifactId>myfaces-extcdi-core-api</artifactId>
	<version>1.0.3</version>
	<scope>compile</scope>
</dependency>

<dependency>
	<groupId>org.apache.myfaces.extensions.cdi.core</groupId>
	<artifactId>myfaces-extcdi-core-impl</artifactId>
	<version>1.0.3</version>
	<scope>compile</scope>
</dependency>

Para usar a anotação no seu ManagedBean, faça como segue:

import br.gov.frameworkdemoiselle.stereotype.ViewController;

@ViewAccessScoped
public class MeuMB {
    ...
}

JSF 1.2: Forçando a recriação de um Managed Bean

A configuração do escopo de ManagedBeans no JSF 1.2 é um tópico que gera bastante confusão. Além de poder definir se o ManagedBean vai ter um ciclo de vida atrelado do Request, Sessão ou Aplicação, existem outros modificadores como o @KeepAlive do RichFaces.

O fato é que essa farofa de escopos misturados com recursos de outras bibliotecas trazem algumas situações indesejadas. Seja em sistemas legados ou seja quando estamos em equipes muito heterogêneas, onde não dá pra garantir um bom planejamento do escopo correto de um MB, pode acontecer de você desenvolver uma solução considerando que o ManagedBean vai ser criado e inicializado ao acessar uma determianda tela, mas ao executar a aplicação, descobre erros que advém do fato do ManagedBean estar sobrevivendo na memória, sendo difícil perceber seu real ciclo de vida. Nesse instante, pode surgir a necessidade da recriação de um Managed Bean, evitando vários problemas.

A dica é implementar um método que será acionado por um commandButton ou commandLink da sua aplicação e que, ao invés de navegar diretamente para uma tela, obterá o ManagedBean via EL (no exemplo abaixo a classe DestinoMB), criará ele novamente, e em seguida chamará a tela desejada:

public class OrigemMB(){
	...
	public String onClickMeuBotao(){				
		FacesContext context = FacesContext.getCurrentInstance();
		ELContext elContext = context.getELContext();
		String elMB = "#{destinoMB}"; // Você deve conhecer a EL do seu MB
		
		ValueExpression expression = context.getApplication().getExpressionFactory()
			.createValueExpression(elContext, elMB, DestinoMB.class);
		expression.setValue(elContext, null);

		//Se necessário é possível ainda obter o MB para incializações
		DestinoMB destinoMB = (DestinoMB) context.getApplication().getExpressionFactory()
			.createValueExpression(elContext, elMB, DestinoMB.class).getValue(elContext);
                destinoMB.inicializar();
			
		return "outcomeDaTelaDesejada";
	}
	...
}

Resolvendo problemas com caracteres especiais UTF-8 no JSF 2

As aplicações JSF 2 que crio e faço deploy no Jboss 7 AS / 6 EAP sempre apresentam problemas de encoding no envio de campos de formulários. Forçar o encoding do XHTML, do form, e outros truques parece não resolver pois alguém no meio do caminho entrega os caracteres especiais já estragados para o servidor.

Pesquisando, descobri que se trata de uma configuração do Servidor de Aplicações, no meu caso o Jboss. Uma maneira mais garantida de resolver o problema, sem apelar para configurações do próprio servidor, é garantindo que todo request que chega para a aplição está com o encoding correto, no meu caso UTF-8. Para tanto, um bom e velho filtro resolve, como segue:

...
@WebFilter("*.jsf")
public class CharacterEncodingFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
      throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        chain.doFilter(request, response);
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void destroy() {
    }
}

Pra começar…

Em tempos onde ser indexado por um bom mecanismo de busca (atualmente, leia-se Google) vale ouro, melhor reservar meu espaço aqui no WordPress. Espantei-me por ver que não havia ainda o blog de prefixo odon. Bom, já que o espaço é meu agora, melhor utilizar eventualmente se pintar motivação. Mas já adianto que não curto muito falar de coisas pessoais, acho que vou acabar escrevendo algo sobre computação, música ou postar desenhos, como sempre.

Se você chegou aqui de alguma forma estranha, senão por um link que eu próprio te indiquei, por favor, deixe ao menos um comentário para eu saber que pessoas têm alcançado esse blog por meios curiosos.

Até+