private void validateNamedOrQualifierAnnotationPresent(Field field, Class<?> serviceType) { if(getNamedOrQualifierValue(field).isEmpty() || !getNamedOrQualifierValue(field).orElseThrow().equals(serviceListFactoryBeanName(serviceType))) { LOGGER.log(ERROR, "Injecting a list of " + serviceType.getName() + " requires a Qualifier or Named annotation with value " + serviceListFactoryBeanName(serviceType)); throw new IllegalStateException("Injecting a list of " + serviceType.getName() + " requires a Qualifier or Named annotation with value " + serviceListFactoryBeanName(serviceType)); } }
private void validateModuleUsesServiceType(Module usingModule, Class<?> serviceType) { if (!usingModule.canUse(serviceType)) { LOGGER.log(ERROR, "Module with name " + usingModule.getName() + " does not define a 'use' dependency on service of type: use " + serviceType.getName()); throw new IllegalStateException("Module with name " + usingModule.getName() + " does not define a 'use' dependency on service of type: use " + serviceType.getName()); } }
private static AnnotationConfigRegistry asAnnotationConfigRegistry(GenericApplicationContext context) { try { return (AnnotationConfigRegistry) context; } catch (ClassCastException e) { LOGGER.log(System.Logger.Level.ERROR, "The provided Application Context type " + context.getClass() + " should implement org.springframework.context.annotation.AnnotationConfigRegistry"); throw new ApplicationContextInstantiationException(e); } }
public static void boot() { LOGGER.log(INFO, "Booting modular spring application"); synchronized (moduleContexts) { for (Map.Entry<Module, GenericApplicationContext> contextEntry : moduleContexts.entrySet()) { Module module = contextEntry.getKey(); GenericApplicationContext context = contextEntry.getValue(); if (!context.isActive()) { LOGGER.log(INFO, "Starting ApplicationContext for Module " + module.getName()); context.refresh(); } else { LOGGER.log(INFO, "ApplicationContext for Module " + module.getName() + " is already active"); } } } }
private static GenericApplicationContext instantiateApplicationContext(ModuleContext moduleContext) { try { return moduleContext.applicationContextClass().getDeclaredConstructor().newInstance(); } catch (InstantiationException e) { LOGGER.log(System.Logger.Level.ERROR, "Cannot instantiate " + moduleContext.applicationContextClass()); throw new ApplicationContextInstantiationException(e); } catch (IllegalAccessException e) { LOGGER.log(System.Logger.Level.ERROR, "No access to default constructor of " + moduleContext.applicationContextClass()); throw new ApplicationContextInstantiationException(e); } catch (InvocationTargetException e) { LOGGER.log(System.Logger.Level.ERROR, "Cannot invoke default constructor of " + moduleContext.applicationContextClass()); throw new ApplicationContextInstantiationException(e); } catch (NoSuchMethodException e) { LOGGER.log(System.Logger.Level.ERROR, "No Default constructor for " + moduleContext.applicationContextClass()); throw new ApplicationContextInstantiationException(e); } }
private void log(System.Logger.Level level, String format, Object[] params) { if (LOGGER.isLoggable(level)) { var s = String.format(format, params); LOGGER.log(level, s); } }
private void registerServiceListFactoryBean(Module usingModule, Field field) { ParameterizedType listGenericType = (ParameterizedType) field.getGenericType(); Class<?> serviceType = (Class<?>) listGenericType.getActualTypeArguments()[0]; LOGGER.log(INFO, "ModuleServiceReference from module " + usingModule.getName() + " found for service of type List of " + serviceType); validateModuleUsesServiceType(usingModule, serviceType); validateNamedOrQualifierAnnotationPresent(field, serviceType); String newBeanName = serviceListFactoryBeanName(serviceType); if(!this.beanFactory.containsBean(newBeanName)) { registerAbstractServiceFactoryBean(serviceType, newBeanName, new ServiceListFactoryBean()); } }
public static <SERVICETYPE> SERVICETYPE retrieveInstanceFromContext(Class<SERVICETYPE> serviceClass) { LOGGER.log(INFO, "Providing instance of " + serviceClass.getSimpleName() + " from module " + serviceClass.getModule().getName()); GenericApplicationContext context = get(); if (!context.isActive()) { LOGGER.log(INFO, "Lazy starting ApplicationContext for module " + serviceClass.getModule().getName()); context.refresh(); } return context.getBean(serviceClass); }
private static GenericApplicationContext prepareApplicationContextFor(Module module) { ModuleContext moduleContext = module.getAnnotation(ModuleContext.class); Class<?> mainConfigurationClass = moduleContext.mainConfigurationClass(); LOGGER.log(INFO, "Preparing ApplicationContext for Module " + module.getName() + " using config class " + mainConfigurationClass.getSimpleName()); GenericApplicationContext context = instantiateApplicationContext(moduleContext); AnnotationConfigRegistry annotationConfigRegistry = asAnnotationConfigRegistry(context); annotationConfigRegistry.register(mainConfigurationClass); annotationConfigRegistry.register(ModuleServiceReferenceAnnotationPostProcessorConfiguration.class); return register(module, context); }
public static void provisionForLayer(ModuleLayer layer) { LOGGER.log(INFO, "Preparing modular spring application"); for (Module module : layer.modules()) { if (module.isAnnotationPresent(ModuleContext.class)) { prepareApplicationContextFor(module); } } }
private void registerServiceFactoryBean(Module usingModule, Field field) { Class<?> serviceType = field.getType(); LOGGER.log(INFO, "ModuleServiceReference from module " + usingModule.getName() + " found for service of type " + serviceType); String newBeanName = serviceFactoryBeanName(serviceType); validateModuleUsesServiceType(usingModule, serviceType); if(!this.beanFactory.containsBean(newBeanName)) { registerAbstractServiceFactoryBean(serviceType, newBeanName, new ServiceFactoryBean()); } }
private static GenericApplicationContext register(Module module, GenericApplicationContext applicationContext) { synchronized (moduleContexts) { LOGGER.log(INFO, "Registering spring application context for module " + module.getName()); moduleContexts.put(module, applicationContext); return applicationContext; } }