I have a simple case where I have a REST Service MyService
that should get injected with a bean beanB
of type BeanB
which implements interface BeanBInterface
. The error I get is the classic WELD-001408 one shown below:
org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type BeanBInterface with qualifiers @BeanBQualifier
at injection point [BackedAnnotatedField] @Inject @BeanBQualifier public com.example.MyService.beanB
at com.example.MyService.beanB(MyService.java:0)
The REST Service:
import javax.ws.rs.Path;
import javax.inject.Inject;
@Path("/")
public class MyService {
@Inject
@BeanBQualifier(BeanBQualifier.Type.PROD)
public BeanBInterface beanB;
public MyService() {}
}
Bean Interface:
public interface BeanBInterface {
}
Bean Implementation:
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.enterprise.inject.Produces;
@Startup
@Singleton
@BeanBQualifier(BeanBQualifier.Type.PROD)
public class BeanB implements BeanBInterface {
private String name = "B";
public BeanB() {}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
}
The Bean Qualifier
import javax.inject.Qualifier;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Qualifier
@Retention(RUNTIME)
@Target({FIELD, TYPE})
public @interface BeanBQualifier {
Type value();
enum Type{PROD, TEST}
}
Beans.xml (tried in META-INF/beans.xml and also tried in WEB-INF/beans.xml)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
bean-discovery-mode="annotated">
</beans>
I also tried a bean-discovery-mode="all"
with no luck.
If I make the declaration of beanB
to use the concrete class BeanB
rather than its interface in MyService
it works (but that defeats the purpose of an interface):
If I add an @Produces
factory method to MyService
to construct the bean it also works but this defeats the purpose of letting the container instantiate my beans for me:
@javax.enterprise.inject.Produces
public static BeanB get() {
return new BeanB();
}
but if this @Produces factory method returns the interface instead it won't work:
@javax.enterprise.inject.Produces
public static BeanBInterface get() {
return new BeanB();
}
EJBs have some weird rules about what interfaces are actually exposed as implemented. Only interfaces marked as @Local/@Remote will be exposed. If you want to use the bean with the interface and with the class you need to add @LocalBean to the ejb.
In short: add @Local to the interface or @Local(BeanBInterface.class) to BeanB