use of io.micronaut.context.annotation.Parallel in project micronaut-core by micronaut-projects.
the class DefaultBeanContext method initializeContext.
/**
* Initialize the context with the given {@link io.micronaut.context.annotation.Context} scope beans.
*
* @param contextScopeBeans The context scope beans
* @param processedBeans The beans that require {@link ExecutableMethodProcessor} handling
* @param parallelBeans The parallel bean definitions
*/
protected void initializeContext(@NonNull List<BeanDefinitionReference> contextScopeBeans, @NonNull List<BeanDefinitionReference> processedBeans, @NonNull List<BeanDefinitionReference> parallelBeans) {
if (CollectionUtils.isNotEmpty(contextScopeBeans)) {
final Collection<BeanDefinition> contextBeans = new ArrayList<>(contextScopeBeans.size());
for (BeanDefinitionReference contextScopeBean : contextScopeBeans) {
try {
loadContextScopeBean(contextScopeBean, contextBeans::add);
} catch (Throwable e) {
throw new BeanInstantiationException("Bean definition [" + contextScopeBean.getName() + "] could not be loaded: " + e.getMessage(), e);
}
}
filterProxiedTypes((Collection) contextBeans, true, false, null);
filterReplacedBeans(null, (Collection) contextBeans);
for (BeanDefinition contextScopeDefinition : contextBeans) {
try {
loadContextScopeBean(contextScopeDefinition);
} catch (DisabledBeanException e) {
if (AbstractBeanContextConditional.LOG.isDebugEnabled()) {
AbstractBeanContextConditional.LOG.debug("Bean of type [{}] disabled for reason: {}", contextScopeDefinition.getBeanType().getSimpleName(), e.getMessage());
}
} catch (Throwable e) {
throw new BeanInstantiationException("Bean definition [" + contextScopeDefinition.getName() + "] could not be loaded: " + e.getMessage(), e);
}
}
}
if (!processedBeans.isEmpty()) {
@SuppressWarnings("unchecked") Stream<BeanDefinitionMethodReference<?, ?>> methodStream = processedBeans.stream().filter(ref -> ref.isEnabled(this)).map((Function<BeanDefinitionReference, BeanDefinition<?>>) reference -> {
try {
return reference.load(this);
} catch (Exception e) {
throw new BeanInstantiationException("Bean definition [" + reference.getName() + "] could not be loaded: " + e.getMessage(), e);
}
}).filter(bean -> bean.isEnabled(this)).flatMap(beanDefinition -> beanDefinition.getExecutableMethods().parallelStream().filter(method -> method.hasStereotype(Executable.class)).map((Function<ExecutableMethod<?, ?>, BeanDefinitionMethodReference<?, ?>>) executableMethod -> BeanDefinitionMethodReference.of((BeanDefinition) beanDefinition, executableMethod)));
// group the method references by annotation type such that we have a map of Annotation -> MethodReference
// ie. Class<Scheduled> -> @Scheduled void someAnnotation()
Map<Class<? extends Annotation>, List<BeanDefinitionMethodReference<?, ?>>> byAnnotation = new HashMap<>(processedBeans.size());
methodStream.forEach(reference -> {
List<Class<? extends Annotation>> annotations = reference.getAnnotationTypesByStereotype(Executable.class);
annotations.forEach(annotation -> byAnnotation.compute(annotation, (ann, list) -> {
if (list == null) {
list = new ArrayList<>(10);
}
list.add(reference);
return list;
}));
});
// Find ExecutableMethodProcessor for each annotation and process the BeanDefinitionMethodReference
byAnnotation.forEach((annotationType, methods) -> streamOfType(ExecutableMethodProcessor.class, Qualifiers.byTypeArguments(annotationType)).forEach(processor -> {
if (processor instanceof LifeCycle<?>) {
((LifeCycle<?>) processor).start();
}
for (BeanDefinitionMethodReference<?, ?> method : methods) {
BeanDefinition<?> beanDefinition = method.getBeanDefinition();
// If declared at the class level it will already have been processed by AnnotationProcessorListener
if (!beanDefinition.hasStereotype(annotationType)) {
// noinspection unchecked
if (method.hasDeclaredStereotype(Parallel.class)) {
ForkJoinPool.commonPool().execute(() -> {
try {
processor.process(beanDefinition, method);
} catch (Throwable e) {
if (LOG.isErrorEnabled()) {
LOG.error("Error processing bean method " + beanDefinition + "." + method + " with processor (" + processor + "): " + e.getMessage(), e);
}
Boolean shutdownOnError = method.booleanValue(Parallel.class, "shutdownOnError").orElse(true);
if (shutdownOnError) {
stop();
}
}
});
} else {
processor.process(beanDefinition, method);
}
}
}
if (processor instanceof LifeCycle<?>) {
((LifeCycle<?>) processor).stop();
}
}));
}
if (CollectionUtils.isNotEmpty(parallelBeans)) {
processParallelBeans(parallelBeans);
}
final Runnable runnable = () -> beanDefinitionsClasses.removeIf((BeanDefinitionReference beanDefinitionReference) -> !beanDefinitionReference.isEnabled(this));
ForkJoinPool.commonPool().execute(runnable);
}
use of io.micronaut.context.annotation.Parallel in project micronaut-core by micronaut-projects.
the class DefaultBeanContext method processParallelBeans.
/**
* Processes parallel bean definitions.
*
* @param parallelBeans The parallel beans
*/
protected void processParallelBeans(List<BeanDefinitionReference> parallelBeans) {
if (!parallelBeans.isEmpty()) {
List<BeanDefinitionReference> finalParallelBeans = parallelBeans.stream().filter(bdr -> bdr.isEnabled(this)).collect(Collectors.toList());
if (!finalParallelBeans.isEmpty()) {
new Thread(() -> {
Collection<BeanDefinition> parallelDefinitions = new ArrayList<>();
finalParallelBeans.forEach(beanDefinitionReference -> {
try {
synchronized (singletonObjects) {
loadContextScopeBean(beanDefinitionReference, parallelDefinitions::add);
}
} catch (Throwable e) {
LOG.error("Parallel Bean definition [" + beanDefinitionReference.getName() + "] could not be loaded: " + e.getMessage(), e);
Boolean shutdownOnError = beanDefinitionReference.getAnnotationMetadata().booleanValue(Parallel.class, "shutdownOnError").orElse(true);
if (shutdownOnError) {
stop();
}
}
});
filterProxiedTypes((Collection) parallelDefinitions, true, false, null);
filterReplacedBeans(null, (Collection) parallelDefinitions);
parallelDefinitions.forEach(beanDefinition -> ForkJoinPool.commonPool().execute(() -> {
try {
synchronized (singletonObjects) {
loadContextScopeBean(beanDefinition);
}
} catch (Throwable e) {
LOG.error("Parallel Bean definition [" + beanDefinition.getName() + "] could not be loaded: " + e.getMessage(), e);
Boolean shutdownOnError = beanDefinition.getAnnotationMetadata().booleanValue(Parallel.class, "shutdownOnError").orElse(true);
if (shutdownOnError) {
stop();
}
}
}));
parallelDefinitions.clear();
}).start();
}
}
}
Aggregations