Guia Java Enterprise Edition - Java EE

CDI Ambiguous Dependencies: Aprenda o que é e como resolver

Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Para efetuar o download você precisa estar logado. Clique aqui para efetuar o login
Confirmar voto
0
 (7)  (0)

Veja neste artigo qual a origem do erro “Ambiguous Dependencies” do CDI no Java e como resolvê-lo.

Motivação

Com o CDI (Contexts and Dependency Injection), e suas anotações, podemos delegar ao container a tarefa de injetar dependências entre as classes da aplicação. O uso inadequado desse recurso, no entanto, pode nos levar a erros como o de “Ambiguous Dependencies”, que ocorre quando o container não sabe qual dependência injetar. Nesse artigo veremos as causas desse erro e como solucioná-lo.

saiba mais Saiba mais sobre CDI

Origem do erro Ambiguous Dependencies

O CDI é responsável por gerenciar as dependências entre classes da aplicação, desde que elas estejam sinalizadas por meio de anotações. Um bom exemplo de anotação do CDI é a @Named, que informa algo como: “Gerencie essa dependência para mim”.

Quando essa anotação é encontrada sem o parâmetro “value”, o CDI cria em seu repositório de dependências a referência para esse objeto através do nome da classe usando a técnica lowerCamelCase. Assim, se sua classe tem o nome “PrinterService”, como no código abaixo, o CDI irá criar uma referência a ela com o nome “printerService”:

  import javax.inject.Named;
  import java.io.Serializable;
  @Named
  public class PrinterService implements Serializable{}
  

A partir desse trecho de código o CDI já conseguirá gerenciar a criação de objetos “printerService”. Se desejarmos escolher um nome diferente, podemos declarar o atributo “value”. Por exemplo, podemos chamar de “printer” a nossa classe PrinterService, da seguinte forma:

  import javax.inject.Named;
  import java.io.Serializable;
  @Named(value=”printer”)
  public class PrinterService implements Serializable{}
  

Compreendendo o funcionamento dessa anotação, podemos entender o erro “Ambiguous Dependencies”, que ocorre quando duas classes diferentes são registradas com o mesmo nome no repositório de dependências do CDI.

Existem pelo menos duas formas desse erro ocorrer e veremos a seguir como evitá-las.

Classes diferentes com mesmo valor em @Named

O caso mais comum ocorre quando temos classes distintas usando o mesmo valor (value) na anotação @Named, como podemos observar na Listagem 1.

  @Named(value = "printer")
  public class PrinterService implements Serializable {
  }
  ...
  @Named(value = "printer")
  public class FaxService implements Serializable {
  }
  
Listagem 1. Classes com mesmo valor na anotação @Named

Nesse caso, não conseguiremos nem iniciar o servidor de aplicação, e o erro deve ser parecido com o mostrado na Listagem 2.

  Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-001414: Bean name is ambiguous. Name printer resolves to beans:
    - Managed Bean [class br.com.devmedia.service.PrinterService] with qualifiers [@Default @Named @Any],
    - Managed Bean [class br.com.devmedia.service.FaxService] with qualifiers [@Default @Named @Any]
  
Listagem 2. Erro causado pela classe PrinterService e FaxService

De forma resumida, esse erro quer dizer: “O CDI não sabe qual das classes injetar no seu repositório de dependências, pois ambas têm o mesmo nome para ele”. A solução para esse erro é muito simples: trocar o “value” de uma das classes na anotação @Named. Por exemplo, podemos mudar o valor da classe FaxService para “fax”: @Named (value = "fax").

Classe gerenciável herdando de outra classe gerenciável pelo CDI

Outra situação em que ocorre o erro Ambiguous Dependencies é quando você possui uma classe que já é gerenciável pelo CDI, a faz herdar de outra classe que também é gerenciável e resolve injetar a classe pai (super classe) em algum bean.

Para demonstrar esse caso, vamos utilizar a classe PrinterService, vista anteriormente, e mudar FaxService para herdar da primeira, como mostra a Listagem 3.

  package br.com.devmedia.service;
  import javax.inject.Named;
  @Named(value = "fax")
  public class FaxService extends PrinterService {
  }
  
Listagem 3. Classe FaxService herdando de PrinterService

Feito isso, se injetarmos a super classe PrinterService dentro de uma classe chamada UtilService, por exemplo, como mostra a Listagem 4, ao iniciar o servidor de aplicação, novamente receberemos o erro “Ambiguous Dependencies”, como mostra a Listagem 5.

  package br.com.devmedia.service;
  import javax.inject.Inject;
  import javax.inject.Named;
  import java.io.Serializable;
  @Named
  public class UtilService implements Serializable {
      @Inject
      private PrinterService printerService;
  }
  
Listagem 4. Injetando a classe PrinterService
  Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-001409: Ambiguous dependencies for type PrinterService with qualifiers @Default
    at injection point [BackedAnnotatedField] @Inject private br.com.devmedia.service.UtilService.printerService
    at br.com.devmedia.service.UtilService.printerService(UtilService.java:0)
    Possible dependencies:
    - Managed Bean [class br.com.devmedia.service.PrinterService] with qualifiers [@Default @Named @Any],
    - Managed Bean [class br.com.devmedia.service.FaxService] with qualifiers [@Default @Named @Any]
  
Listagem 5. Erro Ambiguous Dependencies causado por herança

Assim como no caso anterior, o CDI não quem injetar (neste caso, se PrinterService ou FaxService). Para resolver isso, na classe UtilService, devemos utilizar a anotação @Named com o atributo value especificando o bean que deve ser injetado, como mostra o trecho abaixo:

  @Inject
  @Named(value = "printer")
  private PrinterService printerService;
  

Com isso, resolvemos as duas causas mais recorrentes que levam ao erro “Ambiguous Dependencies”. Em ambos os casos precisamos especificar qual bean o CDI deve injetar e para isso utilizamos o atributo value da anotação @Named.

 
Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Receba nossas novidades
Ficou com alguma dúvida?