I'm working in a project deployed in Glassfish 4.1. Dependency injection is made using CDI and I'm having an issue when trying to deploy the application. The error I'm getting is the following (usually I "translate" the name of my classes in the code so the whole post is in the same language, I`ll not do that now so I can copy/paste and avoid some translate typing mistakes):
org.glassfish.deployment.common.DeploymentException: CDI deployment failure:Exception List with 3 exceptions:
Exception 0 :
org.jboss.weld.exceptions.DeploymentException: WELD-001409: Ambiguous dependencies for type GestorUsuarios with qualifiers @Default
at injection point [BackedAnnotatedField] @Inject private ar.edu.unt.sigea.servicios.impl.GestorPersonasImpl.gestorUsuarios
at ar.edu.unt.sigea.servicios.impl.GestorPersonasImpl.gestorUsuarios(GestorPersonasImpl.java:0)
Possible dependencies:
- Session bean [class ar.edu.unt.sigea.servicios.impl.GestorUsuariosImpl with qualifiers [@Any @Default]; local interfaces are [GestorUsuarios],
- Managed Bean [class ar.edu.unt.sigea.servicios.impl.GestorUsuariosImpl] with qualifiers [@Any @Default]
...[Stack trace]...
Exception 0 :
org.jboss.weld.exceptions.DeploymentException: WELD-001409: Ambiguous dependencies for type RepositorioMenu with qualifiers @Default
at injection point [BackedAnnotatedField] @Inject private ar.edu.unt.sigea.servicios.impl.GestorUsuariosImpl.repositorioMenu
at ar.edu.unt.sigea.servicios.impl.GestorUsuariosImpl.repositorioMenu(GestorUsuariosImpl.java:0)
Possible dependencies:
- Managed Bean [class ar.edu.unt.sigea.repositorio.RepositorioMenu] with qualifiers [@Any @Default],
- Session bean [class ar.edu.unt.sigea.repositorio.RepositorioMenu with qualifiers [@Any @Default]; local interfaces are [RepositorioMenu]
...[Stack trace]...
Exception 0 :
org.jboss.weld.exceptions.DeploymentException: WELD-001409: Ambiguous dependencies for type RepositorioOperacion with qualifiers @Default
at injection point [BackedAnnotatedField] @Inject ar.edu.unt.sigea.repositorio.RepositorioMenu.repositorioOperacion
at ar.edu.unt.sigea.repositorio.RepositorioMenu.repositorioOperacion(RepositorioMenu.java:0)
Possible dependencies:
- Managed Bean [class ar.edu.unt.sigea.repositorio.RepositorioOperacion] with qualifiers [@Any @Default],
- Session bean [class ar.edu.unt.sigea.repositorio.RepositorioOperacion with qualifiers [@Any @Default]; local interfaces are [RepositorioOperacion]
(by the way, I don't know why it says 3 exceptions
and all appear numbered as Exception 0
)
@Stateless
public class GestorPersonasImpl implements GestorPersonas {
@Inject
private GestorUsuarios gestorUsuarios;
public GestorUsuarios getGestorUsuarios() {return gestorUsuarios;}
public void setGestorUsuarios(GestorUsuarios gestorUsuarios) {
this.gestorUsuarios = gestorUsuarios;
}
// Other fields and methods
}
@Stateless
public class GestorUsuariosImpl implements GestorUsuarios {
@Inject
private RepositorioMenu repositorioMenu;
public RepositorioMenu getRepositorioMenu() {return repositorioMenu;}
public void setRepositorioMenu(RepositorioMenu repositorioMenu) {
this.repositorioMenu = repositorioMenu;
}
// Other fields and methods
}
@Stateless
@LocalBean
public class RepositorioMenu extends RepositorioGenerico<Menu> {
@Inject
private RepositorioOperacion repositorioOperacion;
public RepositorioOperacion getRepositorioOperacion() {return repositorioOperacion;}
public void setRepositorioOperacion(RepositorioOperacion repositorioOperacion) {
this.repositorioOperacion = repositorioOperacion;
}
// Other fields and methods
}
@Dependent
@Stateless
@LocalBean
public class RepositorioOperacion extends RepositorioGenerico<Operacion> {
// This class doesn't have injection points
// just put it here for the reference made in the error message
}
The parent class RepositorioGenerico<Menu>
is just a class with some generic methods to interact with the DB and Menu
is an entity class. The interfaces are as follow:
@Local
public interface GestorPersonas {
// methods definitions, implemented by GestorPersonasImpl
}
@Local
public interface GestorUsuarios {
// methods definitions, implemented by GestorUsuariosImpl
}
I have only one injectable class for each injection point so I don't understand why the injection fails. I don't know if more details about my code is needed, so ask me and I'll edit the post; I write only the parts I think it's needed.
I've seen another post but there the @Produces
annotation is used and, AFAIK, I don't need that for this case.
Any help or guide is appreciated. Thanks in advance for your answers
I read in an article by Antonio Goncalves in the Java Magazine that CDI is made via properties (even private), setter method or constructor. Taking that into account I removed getters and setters for every injected property and settled the access to default (package) for those properties.
The getter/setter method for injected properties were only used to set the dependencies manually in my unit tests, so there's no need for them in production.
After all this changes, the error remains...
According to the Java EE 7 official documentation, my beans are compliant with the CDI Managed Bean definition, except for the point
It is not annotated with an EJB component-defining annotation or declared as an EJB bean class in ejb-jar.xml.
According to javax.ejb
javadoc EJB component-defining annotation is one of the followings: @MessageDriven
, @Stateful
, @Stateless
or @Singleton
. But I've seen other projects with CDI working with EJB (e.g., @Stateless
beans being injected somewhere else). On the other hand, I've been reading Beginning Java EE 7 by Antonio Goncalves and there says (Ch. 2 - Context and Dependency Injection):
Anatomy of a CDI Bean
According to the CDI 1.1 specification, the container treats any class that satisfies the following conditions as a CDI Bean:
- It is not a non-static inner class,
- It is a concrete class, or is annotated @Decorator, and
- It has a default constructor with no parameters, or it declares a constructor annotated @Inject.
Then a bean can have an optional scope, an optional EL name, a set of interceptor bindings, and an optional life-cycle management.
And my beans are compliant with that definition. I checked the Weld Documentation and in chapter 2 brings the definition of a CDI bean, which is closer to the first definition (from the Java EE documentation). The thing is, as I said, that I've seen other projects making dependency injection with EJB Managed Beans (@Stateless
or some other).
In conclusion, I don't know who to believe at. Can someone shed some light in this matter?
NOTE: After this attempt I have the same problem in a different place, so the server log and the involved classes are changed from the stated above, check the differences.
First, following a hunch, I added interfaces to the beans that I need to inject somewhere else.
Second, I updated my Glassfish Server from 4.1 to 4.1.1. This one has bundled the WELD-2.2.13.Final
CDI implementation (according to the server log message INFO: WELD-000900: 2.2.13 (Final)
).
Finally I tried to deploy my project and the error remains with some changes. Before showing the changes, let me say that it never caught my attention but at deployment time, JNDI generates 2 names for my beans, as states in the following log message thrown when I try to deploy the application:
INFO: Portable JNDI names for EJB RepositorioUsuarioImpl: [java:global/sigea-ear-0.8-SNAPSHOT/sigea-model-0.8-SNAPSHOT/RepositorioUsuarioImpl, java:global/sigea-ear-0.8-SNAPSHOT/sigea-model-0.8-SNAPSHOT/RepositorioUsuarioImpl!ar.edu.unt.sigea.repositorio.RepositorioUsuario]
INFO: Portable JNDI names for EJB RepositorioAlumnoImpl: [java:global/sigea-ear-0.8-SNAPSHOT/sigea-model-0.8-SNAPSHOT/RepositorioAlumnoImpl, java:global/sigea-ear-0.8-SNAPSHOT/sigea-model-0.8-SNAPSHOT/RepositorioAlumnoImpl!ar.edu.unt.sigea.repositorio.RepositorioAlumno]
INFO: Portable JNDI names for EJB RepositorioMenuImpl: [java:global/sigea-ear-0.8-SNAPSHOT/sigea-model-0.8-SNAPSHOT/RepositorioMenuImpl, java:global/sigea-ear-0.8-SNAPSHOT/sigea-model-0.8-SNAPSHOT/RepositorioMenuImpl!ar.edu.unt.sigea.repositorio.RepositorioMenu]
INFO: Portable JNDI names for EJB GestorUsuariosImpl: [java:global/sigea-ear-0.8-SNAPSHOT/sigea-model-0.8-SNAPSHOT/GestorUsuariosImpl, java:global/sigea-ear-0.8-SNAPSHOT/sigea-model-0.8-SNAPSHOT/GestorUsuariosImpl!ar.edu.unt.sigea.servicios.GestorUsuarios]
INFO: Portable JNDI names for EJB GestorPersonasImpl: [java:global/sigea-ear-0.8-SNAPSHOT/sigea-model-0.8-SNAPSHOT/GestorPersonasImpl!ar.edu.unt.sigea.servicios.GestorPersonas, java:global/sigea-ear-0.8-SNAPSHOT/sigea-model-0.8-SNAPSHOT/GestorPersonasImpl]
INFO: Portable JNDI names for EJB RepositorioPersonaImpl: [java:global/sigea-ear-0.8-SNAPSHOT/sigea-model-0.8-SNAPSHOT/RepositorioPersonaImpl, java:global/sigea-ear-0.8-SNAPSHOT/sigea-model-0.8-SNAPSHOT/RepositorioPersonaImpl!ar.edu.unt.sigea.repositorio.RepositorioPersona]
INFO: Portable JNDI names for EJB RepositorioOperacionImpl: [java:global/sigea-ear-0.8-SNAPSHOT/sigea-model-0.8-SNAPSHOT/RepositorioOperacionImpl!ar.edu.unt.sigea.repositorio.RepositorioOperacion, java:global/sigea-ear-0.8-SNAPSHOT/sigea-model-0.8-SNAPSHOT/RepositorioOperacionImpl]
I don't know if that could be causing the error in the injection point but sounds suspicious (and I don't know how to change that). It appeared in the first attempt too but, as I said, it never caught my attention. Now the logs and the classes
Fatal: Exception during lifecycle processing
org. glassfish.deployment.common.DeploymentException: CDI deployment failure:Exception List with 2 exceptions:
Exception 0 :
org.jboss.weld.exceptions.DeploymentException: WELD-001409: Ambiguous dependencies for type GestorPersonas with qualifiers @Default
at injection point [BackedAnnotatedField] @Inject ar.edu.unt.sigea.inicio.RegistroBean.gestorPersonas
at ar.edu.unt.sigea.inicio.RegistroBean.gestorPersonas(RegistroBean.java:0)
Possible dependencies:
- Session bean [class ar.edu.unt.sigea.servicios.impl.GestorPersonasImpl with qualifiers [@Any @Default]; local interfaces are [GestorPersonas],
- Managed Bean [class ar.edu.unt.sigea.servicios.impl.GestorPersonasImpl] with qualifiers [@Any @Default]
...[Stack trace]...
Exception 0 :
org.jboss.weld.exceptions.DeploymentException: WELD-001409: Ambiguous dependencies for type GestorUsuarios with qualifiers @Default
at injection point [BackedAnnotatedField] @Inject ar.edu.unt.sigea.inicio.SesionUsuarioBean.gestorUsuarios
at ar.edu.unt.sigea.inicio.SesionUsuarioBean.gestorUsuarios(SesionUsuarioBean.java:0)
Possible dependencies:
- Session bean [class ar.edu.unt.sigea.servicios.impl.GestorUsuariosImpl with qualifiers [@Any @Default]; local interfaces are [GestorUsuarios],
- Managed Bean [class ar.edu.unt.sigea.servicios.impl.GestorUsuariosImpl] with qualifiers [@Any @Default]
...[Stack trace]...
@Named(value = "registroBean")
@ViewScoped
public class RegistroBean implements Serializable {
private static final long serialVersionUID = 2181909526300424451L;
@Inject
GestorPersonas gestorPersonas;
// fields, methods, etc
}
@Named(value = "sesionUsuarioBean")
@SessionScoped
public class SesionUsuarioBean implements Serializable {
private static final long serialVersionUID = 2938631472102116238L;
@Inject
GestorUsuarios gestorUsuarios;
// fields, methods, etc
}
The injected fields are shown in the main section.
Any help you can provide me with this new info is appreciated. If you need some more info about the application just let me know.
Thanks in advance for your answers.
After turning the internet upside down for 2 weeks, I finally tried to deploy on a Wildfly 10.0.0 Server and now my application deploys with no problem. So I must conclude that it's a bug on Glassfish. Pitty, because I'm using the lastest version (4.1.1) and it's something basic (I think) as CDI discovery. Hope that Payara solves this issue, but I'll not be trying it right now.
I must say: if a server is suppose to be "Java EE 7 compliant", it should not be released with this kind of bugs.
If someone knows about a discussion forum or knows some benchmark results for the different servers, please comment it out. Shame on you Glassfish