use of io.quarkus.arc.RemovedBean in project quarkus by quarkusio.
the class ArcContainerImpl method getMatchingBeans.
List<InjectableBean<?>> getMatchingBeans(Resolvable resolvable) {
List<InjectableBean<?>> matching = new ArrayList<>();
for (InjectableBean<?> bean : beans) {
if (matches(bean, resolvable.requiredType, resolvable.qualifiers)) {
matching.add(bean);
}
}
if (matching.isEmpty() && !removedBeans.isEmpty()) {
List<RemovedBean> removedMatching = new ArrayList<>();
for (RemovedBean removedBean : removedBeans) {
if (matches(removedBean.getTypes(), removedBean.getQualifiers(), resolvable.requiredType, resolvable.qualifiers)) {
removedMatching.add(removedBean);
}
}
if (!removedMatching.isEmpty()) {
String separator = "====================";
String msg = "\n%1$s%1$s%1$s%1$s\n" + "CDI: programmatic lookup problem detected\n" + "-----------------------------------------\n" + "At least one bean matched the required type and qualifiers but was marked as unused and removed during build\n\n" + "Stack frame: %5$s\n" + "Required type: %3$s\n" + "Required qualifiers: %4$s\n" + "Removed beans:\n\t- %2$s\n" + "Solutions:\n" + "\t- Application developers can eliminate false positives via the @Unremovable annotation\n" + "\t- Extensions can eliminate false positives via build items, e.g. using the UnremovableBeanBuildItem\n" + "\t- See also https://quarkus.io/guides/cdi-reference#remove_unused_beans\n" + "\t- Enable the DEBUG log level to see the full stack trace\n" + "%1$s%1$s%1$s%1$s\n";
StackWalker walker = StackWalker.getInstance();
StackFrame frame = walker.walk(this::findCaller);
LOGGER.warnf(msg, separator, removedMatching.stream().map(Object::toString).collect(Collectors.joining("\n\t- ")), resolvable.requiredType, Arrays.toString(resolvable.qualifiers), frame != null ? frame : "n/a");
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("\nCDI: programmatic lookup stack trace:\n" + walker.walk(this::collectStack));
}
}
}
return matching;
}
use of io.quarkus.arc.RemovedBean in project quarkus by quarkusio.
the class ArcDevRecorder method createRemovedBeansHandler.
public Handler<RoutingContext> createRemovedBeansHandler(List<String[]> removedInterceptorsDecorators) {
return new Handler<RoutingContext>() {
@Override
public void handle(RoutingContext ctx) {
ArcContainerImpl container = ArcContainerImpl.instance();
ctx.response().putHeader("Content-Type", "application/json");
JsonArrayBuilder removed = Json.array();
for (RemovedBean removedBean : container.getRemovedBeans()) {
JsonObjectBuilder bean = Json.object();
bean.put("kind", removedBean.getKind().toString());
bean.put("description", removedBean.getDescription());
JsonArrayBuilder types = Json.array();
for (Type beanType : removedBean.getTypes()) {
types.add(beanType instanceof Class ? ((Class<?>) beanType).getName() : beanType.toString());
}
// java.lang.Object is always skipped
types.add(Object.class.getName());
bean.put("types", types);
JsonArrayBuilder qualifiers = Json.array();
for (Annotation qualifier : removedBean.getQualifiers()) {
if (qualifier.annotationType().equals(Any.class) || qualifier.annotationType().equals(Default.class)) {
qualifiers.add("@" + qualifier.annotationType().getSimpleName());
} else {
qualifiers.add(qualifier.toString());
}
}
bean.put("qualifiers", qualifiers);
removed.add(bean);
}
for (String[] interceptorDecorator : removedInterceptorsDecorators) {
JsonObjectBuilder bean = Json.object();
bean.put("kind", interceptorDecorator[0]);
bean.put("description", interceptorDecorator[1]);
removed.add(bean);
}
ctx.response().end(removed.build());
}
};
}
Aggregations