Reputation: 6814
The container is Glassfish 4.1
I am having a very weird issue with CDI right now. If I don't annotate my NumberGenerator
services @Dependent
, then I keep getting unsatisfied injection point error when I run the app. But if I explicitly annotate my NumberGenerator
implementations, then everything will work. In one word, if I want dependency injection with the @Dependent
which is the default scope, I must specify it explicitly.
public interface NumberGenerator {
String generateNumber();
}
The first implementation of NumberGenerator
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.enterprise.context.Dependent;
import javax.inject.Inject;
@ThirteenDigits
@Dependent
public class IsbnGenerator implements NumberGenerator {
@Inject
private Logger logger;
@Override
public String generateNumber() {
String isbn = "13-84356-" + Math.abs(new Random().nextInt());
logger.log(Level.INFO, "Generated ISBN : {0}", isbn);
return isbn;
}
}
The second implementation of NumberGenerator
import java.util.Random;
import java.util.logging.Logger;
import javax.enterprise.context.Dependent;
import javax.inject.Inject;
@EightDigits
@Dependent
public class IssnGenerator implements NumberGenerator {
@Inject
private Logger logger;
@Override
public String generateNumber() {
String issn = "8-" + Math.abs(new Random().nextInt());
logger.info("Generated ISSN : " + issn);
return issn;
}
}
This is where the NumberGenerator
will be injected
import javax.enterprise.context.Dependent;
import javax.inject.Inject;
import javax.interceptor.Interceptors;
@Dependent
public class BookService {
@Inject
@EightDigits
private NumberGenerator numberGenerator;
public Book createBook(String title, float price, String description) {
Book book = new Book(title, price, description);
book.setNumber(numberGenerator.generateNumber());
return book;
}
}
Finally, the BookService
is injected into this JSF managed bean to create a Book
instance.
import javax.enterprise.context.Dependent;
import javax.inject.Inject;
import javax.inject.Named;
@Named
@Dependent /* if I leave this out, then this bean will not display
the book instance properties on the JSF page, I just see
a blank screen, but when I add this @Dependent annotation
the JSF page displays the dummy content below.
*/
public class MyBean {
@Inject
private BookService bookService;
public Book getBook() {
return bookService.createBook("Dummy Title", 21.05f, "Dummy Description");
}
}
As you can see, I have to use @Dependent
for the default scope every time I want DI. Right now, I am injecting the IssnGenerator
with the qualifier @EightDigits
into the BookService
class, and if I remove the @Dependent
from the IssnGenerator
, I receive this compile error.
Unsatisfied dependencies for type NumberGenerator with qualifiers @EightDigits at injection point [BackedAnnotatedField] @Inject @EightDigits private BookService.numberGenerator
Thank you for any suggestion.
Upvotes: 2
Views: 1598
Reputation: 1846
If you do not specify a META-INF/beans.xml
file, which seems to be your case, you got an implicit bean archive (see CDI-1.1 §12.1).
In an implicit bean archive, only beans with a bean defining annotation will be discovered by the CDI engine.
Any scope is a bean defining annotation (see CDI-1.1 §2.5). That's why if you add a scope, like @Dependent
, you bean gets discovered by CDI and you don't have the unsatisfied dependency error.
The fact that @Dependent
is the default scope is not relevant here because without the any scope your beans is simply not discovered.
If you add a META-INF/beans.xml
file with the bean-discovery-mode
set to all
, then you got an explicit bean archive, this means that all beans in your archive will be discovered and will have the @Dependent
scope by default.
Upvotes: 5