Great, i got twice -2 votes (-4 reputation) because i asked an advanced topic for software developers?
I searched in about stackoverflow and found this
Founded in 2008, Stack Overflow is the largest, most trusted online community for developers to learn, share their knowledge, and build their careers...
If any interested in this topic, then:
After some hours understanding differences between CDI Beans and EJBs lifecycle when used as independent modules (JBoss Modules), i found:
Singleton CDI Beans are instantiated one time per module, not really singleton among all modules.
To avoid this i had to create Registry as a Singleton Enterprise Session Bean.
This cames with new problems, CDI injection doesn't works among modules, so i had to package a CDI producer (i don't care if it's singleton or not, its only a producer) which can be instantiated by any module. Main responsibility of this producer is to lookup Registry EJB, this to avoid hardcoding jndi path each time i need access the Registry.
I changed my trivial example to support JSF plugins also, this is an example of what i am using currently.
Module facelets:
Registry interface:
public interface FaceletsModuleRegistry {
void registerModule(String module);
List<String> getRegisteredModules();
}
Registry implementation:
@Local(FaceletsModuleRegistry.class)
@Singleton(name="FaceletsModuleRegistry")
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
@Vetoed
public class FaceletsModuleRegistryImpl implements FaceletsModuleRegistry {
private Set<String> registeredModuleNames = new TreeSet<>();
@Override
public void registerModule(String module) {
registeredModuleNames.add(module);
}
@Override
public List<String> getRegisteredModules() {
return Collections.unmodifiableList(new ArrayList<>(registeredModuleNames));
}
}
Registry producer:
@ApplicationScoped
public class FaceletsModuleRegistryBuilder {
@EJB(lookup="java:global/facelets/FaceletsModuleRegistry!co.hatit.enterprise.facelets.services.FaceletsModuleRegistry")
protected FaceletsModuleRegistry faceletsModuleRegistry;
@Produces
public FaceletsModuleRegistry getFaceletsModuleRegistry(){
return faceletsModuleRegistry;
}
}
Any other module that i want to plugin implements this code (please see @Inject
can be used on any module requiring access the Registry singleton instance):
@ApplicationScoped
public class InmueblesActivator {
@Inject
private FaceletsModuleRegistry faceletsModuleRegistry;
public void init(@Observes @Initialized(ApplicationScoped.class) Object init){
String moduleName = Module.getCallerModule().getIdentifier().getName();
String name = StringUtils.substringBetween(moduleName, "deployment.", ".jar");
faceletsModuleRegistry.registerModule(name);
}
}
Then i can reference Registry from any module as a really singleton instance (solved my problem having multiple instances of same class when used CDI singleton beans among several modules).
Now, i can plugin JEE modules, not just java code, but facelets resources also:
public class FaceletsResourceHandler extends ResourceHandlerWrapper {
Logger logger = LoggerFactory.getLogger(FaceletsResourceHandler.class);
@Inject
FaceletsModuleRegistry faceletsModuleRegistry;
private ResourceHandler wrapped;
public FaceletsResourceHandler(ResourceHandler wrapped) {
this.wrapped = wrapped;
}
@Override
public ViewResource createViewResource(FacesContext context, final String name) {
ViewResource resource = super.createViewResource(context, name);
if (resource == null) {
resource = new ViewResource() {
@Override
public URL getURL() {
try {
//iterates over plugins to find the required resource.
for(String module : faceletsModuleRegistry.getRegisteredModules()){
URL resource = Module.getCallerModule().getModuleLoader()
.loadModule(ModuleIdentifier.create("deployment." + module + ".jar"))
.getExportedResource("META-INF/resources" + name);
if (resource != null) return resource;
}
} catch (ModuleLoadException e) {
throw new FacesException(e);
}
return null;
}
};
}
return resource;
}
@Override
public ResourceHandler getWrapped() {
return wrapped;
}
}