@Override public CharSequence debugInfo() { return Strings.customized( "{} bootstrap module type {} DEPENDS UPON {} {} impls", _appAndComponent, _module, _otherAppAndComponent, _dependencies); }
/** * Returns the implementation type (REST, Bean, Mock, etc) of every services bootstrap module * listed at [appCode].client.properties.xml file to do so, it scans the packages under {core * appCode}.internal for types implementing {@link ServicesCoreBootstrapGuiceModule} * * <p>Some times a services implementation NEEDS (or DEPENDS UPON) another service implementation, * for example, the REST services implementation NEEDS the Bean services implementation because * REST services is only an ACCESS LAYER on top of the Bean services layer that is where the real * services logic resides. * * @return */ public Map<CoreAppAndModule, Collection<Class<? extends ServicesCoreBootstrapGuiceModule>>> findBootstrapGuiceModuleTypes() { if (_coreAppAndModules == null) return Maps.newHashMap(); // do not return a null config Map<CoreAppAndModule, Collection<Class<? extends ServicesCoreBootstrapGuiceModule>>> outModuleTypes = Maps.newHashMap(); // Iterate over all the app/module collection (each app/module can have many // ServicesCoreGuiceModules, ie: REST, Bean, etc.. one of them is the DEFAULT one) // NOTE: If more than one implementation is found, the BEAN has the highest priority followed by // the REST implementation // // for each app/module // 1.- Find the available ServicesCoreGuiceModules // 2.- For each found module found, try to find the needed modules // (sometimes a module (ie REST) NEEDS another modules (ie Bean or EJB) to do delegate the // work) // ... this task is a bit tricky since the order in which the modules are found is important // ... the checking of the presence of needed modules MUST be done AFTER all modules are // processed // Find guice modules implementing ServicesCoreGuiceModule either // BeanImplementedServicesGuiceModuleBase, RESTImplementedServicesGuiceModuleBase, // EJBImplementedServicesGuiceModuleBase, etc) Map<CoreAppAndModule, Collection<Class<? extends ServicesCoreBootstrapGuiceModule>>> coreBootstrapModuleTypesByApp = _findCoreBootstrapGuiceModuleTypesByAppModule(_coreAppAndModules); Collection<BootstrapModuleDependency> dependencies = Lists.newArrayList(); for (CoreAppAndModule coreAppModule : _coreAppAndModules) { CoreAppCode coreAppCode = coreAppModule.getAppCode(); CoreModule module = coreAppModule.getModule(); // [1] - Get the modules for the appCode Collection<Class<? extends ServicesCoreBootstrapGuiceModule>> appModuleCoreBootstrapModuleTypes = coreBootstrapModuleTypesByApp.get(coreAppModule); if (appModuleCoreBootstrapModuleTypes == null) { log.warn( "\t\t-{} core will NOT be bootstraped: There's NO type implementing {} at package {} or the {} package is NOT in the classpath. " + "If the {} core is to be bootstraped there MUST be AT LEAST a guice binding module extending {} at {} ", coreAppModule, ServicesCoreBootstrapGuiceModule.class, ServicesPackages.coreGuiceModulePackage(coreAppCode), ServicesPackages.coreGuiceModulePackage(coreAppCode), coreAppModule, ServicesCoreBootstrapGuiceModule.class, ServicesPackages.coreGuiceModulePackage(coreAppCode)); continue; } log.warn( "\t\t-{} core will be bootstraped with: {}", coreAppModule, coreBootstrapModuleTypesByApp.get(coreAppModule)); // [2] - for each found core bootstrap module try to find the needed modules (ie REST // bootstrap modules depends on BEAN bootstrap modules) for (Class<? extends ServicesCoreBootstrapGuiceModule> foundModuleType : appModuleCoreBootstrapModuleTypes) { if (ReflectionUtils.isInterface(foundModuleType)) continue; // Check if there's any module dependency set at @ServicesCore annotation ServicesCore servicesCoreAnnot = ReflectionUtils.typeAnnotation(foundModuleType, ServicesCore.class); // find the needed impl (the ServicesGuiceModule-implementing type MUST be annotated with // ServicesGuiceModuleDependencies) // (sometimes a service impl requires of another service impl, for example, REST services // USES Bean services) if (!CollectionUtils.of(servicesCoreAnnot.dependsOn()).contains(ServicesImpl.NULL)) { CoreAppAndModule ac = Strings.isNullOrEmpty(servicesCoreAnnot.fromOtherCoreAppCodeAndModule()) ? coreAppModule // by default dependencies are at the same coreAppCode/module : CoreAppAndModule.of(servicesCoreAnnot.fromOtherCoreAppCodeAndModule()); Collection<ServicesImpl> impls = Arrays.asList(servicesCoreAnnot.dependsOn()); BootstrapModuleDependency dependency = new BootstrapModuleDependency(coreAppModule, foundModuleType, ac, impls); dependencies.add(dependency); log.warn( "\t\t\t- Found {} CORE services bootstrap module (it has a dependency on other core component {}): {}", foundModuleType, dependency.debugInfo()); } else { log.warn( "\t\t\t- Found {} CORE services bootstrap module (no other bootstrap type dependency)", foundModuleType); } } // for bindingModules // [3] - put the core bootstrap modules in the output collection indexed by the // appCode/component outModuleTypes.put(coreAppModule, appModuleCoreBootstrapModuleTypes); } // for configuredBindingModules // Finally, make sure that the dependencies are satisfied if (CollectionUtils.hasData(dependencies)) { for (BootstrapModuleDependency dependency : dependencies) { Collection<Class<? extends ServicesCoreBootstrapGuiceModule>> otherCoreMods = outModuleTypes.get(dependency.getOtherAppAndComponent()); for (ServicesImpl depImpl : dependency.getDependencies()) { boolean isLoaded = false; if (CollectionUtils.hasData(otherCoreMods)) { for (Class<? extends ServicesCoreBootstrapGuiceModule> otherCoreMod : otherCoreMods) { if (ServicesImpl.fromBindingModule(otherCoreMod) == depImpl) { isLoaded = true; break; } } } if (!isLoaded) throw new IllegalStateException( Strings.customized( "{} (see @{})." + "BUT this module could NOT be loaded." + "Please ensure that a {} annotated type with impl={} attribute is accesible in the run-time classpath (maybe de dependent project is NOT deployed and available at the classpath)", dependency.debugInfo(), ServicesCore.class.getSimpleName(), ServicesCoreBootstrapGuiceModule.class, depImpl)); } } } // Return return outModuleTypes; }