Why @Singleton over @ApplicationScoped in Producers?
cdi, ejb-3.1, jakarta-ee, java, thread-safety
Solution
The `@Singleton` annotation provides not only transaction but also thread-safety by default. So if you will replace it with `@ApplicationScoped`, you will loose the synchronization. So in order to make it properly you need to do like this:
@ApplicationScoped
public class LoggerProducer {
private final ConcurrentMap<String, Logger> loggers = new ConcurrentHashMap<>();
@Produces
public Logger getProducer(InjectionPoint ip) {
String key = getKeyFromIp(ip);
loggers.putIfAbsent(key, Logger.getLogger(key));
return loggers.get(key);
}
private String getKeyFromIp(InjectionPoint ip) {
return ip.getMember().getDeclaringClass().getCanonicalName();
}
}
Also you can make it completely without any scope if you make the map as static
Problem
LoggerProducer.java is a class used to produce Loggers to be injected in CDI beans with: ``` @Inject Logger LOG; ``` Full code: ``` import javax.ejb.Singleton; /** * @author rveldpau */ @Singleton public class LoggerProducer { private Map<String, Logger> loggers = new HashMap<>(); @Produces public Logger getProducer(InjectionPoint ip) { String key = getKeyFromIp(ip); if (!loggers.containsKey(key)) { loggers.put(key, Logger.getLogger(key)); } return loggers.get(key); } private String getKeyFromIp(InjectionPoint ip) { return ip.getMember().getDeclaringClass().getCanonicalName(); } } ``` QUESTION: can `@Singleton` be safely turned into `@ApplicationScoped` ? I mean, why would anyone want an EJB here ? Are there technical reasons, since no transactions are involved, and (AFAIK) it would be thread-safe anyway ? I'm obviously referring to `javax.enterprise.context.ApplicationScoped`, not to `javax.faces.bean.ApplicationScoped`.