Desabilitando um producer de terceiros no CDI

Entrei um problema no Jboss 7 AS / 6 EAP onde o WELD reclamou ainda no deploy da aplicão que existiam ambiguidade em uma injeção, devido a presença de dois produtores capazes de instanciar a mesma classe (no meu caso o FacesContext do JSF). Veja abaixo o erro:

org.jboss.weld.exceptions.DeploymentException: WELD-001409 Ambiguous dependencies for type 
     [FacesContext] with qualifiers [@Default] at injection point...

Para resolver precisei desativar um dos produtores. Isso foi feito criando uma Extension que veta o funcionamento de um produtor, no caso abaixo, do produtor org.apache.myfaces.extensions.cdi.jsf.impl.util.FacesInformationProducer do Apache MyFaces. Veja abaixo:

import javax.enterprise.event.Observes;
import javax.enterprise.inject.spi.Extension;
import javax.enterprise.inject.spi.ProcessAnnotatedType;

import org.apache.myfaces.extensions.cdi.jsf.impl.util.FacesInformationProducer;

public class FacesProducerSolverExtension implements Extension {

	public void observe(@Observes ProcessAnnotatedType p){
		if(p.getAnnotatedType().getJavaClass()
                    .equals(FacesInformationProducer.class)){
			p.veto();			
		}
	}
}

Para que esse extension funcione, ele deve ser registrado no arquivo de texto WEB-INF/classes/META-INF/services/javax.enterprise.inject.spi.Extension no seu WAR que ficará com o seguinte conteúdo:

br.gov.demoiselle.destdemoiselle.cgpolact.cdi.extension.FacesProducerSolverExtension

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 {
    ...
}