payara / Payara

Payara Server is an open source middleware platform that supports reliable and secure deployments of Java EE (Jakarta EE) and MicroProfile applications in any environment: on premise, in the cloud or hybrid.
http://www.payara.fish
Other
882 stars 304 forks source link

Bug Report: MicroProfile health checks added by CDI extension are not used/FISH-7597 #6314

Open ghunteranderson opened 1 year ago

ghunteranderson commented 1 year ago

Brief Summary

MicroProfile Health discovers CDI beans that are annotated/qualified with @Readiness, @Liveness, or @Startup. This can be seen in the excerpt below from Payara's HealthCDIExtension.java:

void processBean(@Observes ProcessBean<?> event) {
    final Annotated annotated = event.getAnnotated();
    if (annotated.isAnnotationPresent(Readiness.class)
            || annotated.isAnnotationPresent(Liveness.class)
            || annotated.isAnnotationPresent(Startup.class)) {
        this.healthCheckBeans.add(event.getBean());
    }
}

However, when health checks are created using a CDI portable extension, they are not discovered and are excluded from the health check API.

I suspect this is caused by Payara scanning the Annotated instead of the bean's full list of qualifiers. Synthetic beans may not have an Annotated but can still have CDI qualifiers. For example:

public void afterBeanDiscovery(@Observes AfterBeanDiscovery event){
  event.addBean()
    .types(HealthCheck.class)
    .qualifiers(new ReadinessAnnotation())
    .scope(ApplicationScoped.class)
    .produceWith(obj -> {
      return new CustomHealthCheck("Custom-Health-Check");
    });
}

Expected Outcome

When a MicroProfile health check is defined as a synthetic bean using CDI portable extensions, then it should be discovered by Payara and included in the health check API.

Current Outcome

When a MicroProfile health check is defined as a synthetic bean using CDI portable extensions, then it is ignored by Payara and excluded from the health check API.

Reproducer

I've created a example application demonstrating this issue on Payara 6.2023.6.

Operating System

Ubuntu 20.04.5 LTS (virtualized on WSL2 / Windows 10)

JDK Version

OpenJDK 11.0.12+7

Payara Distribution

Payara Micro

ghunteranderson commented 1 year ago

The original issue https://github.com/payara/Payara/issues/5594 was opened against Payara 5. Continuing the conversation for Payara 6.

I believe the change might be as simple as scanning the bean's qualifiers instead of the annotated class, method, or field. A modified version of HealthCDIExtension.processBean(...) might look like this:

void processBean(@Observes ProcessBean<?> event) {
  final Set<Annotation> qualifiers = event.getBean().getQualifiers();
  for(var qualifier : qualifiers){
    var annotationType = qualifier.annotationType();
    if(annotationType.equals(Readiness.class)
        || annotationType.equals(Liveness.class)
        || annotationType.equals(Startup.class)){
      this.healthCheckBeans.add(event.getBean());
      break;
    }
  }
}
felixif commented 1 year ago

Hello @ghunteranderson,

Thank you very much for your detailed report. I can confirm that the MicroProfile HealthCheck does not show the synthetic beans on Windows 11 and Ubuntu over WSL2 on the latest version of Payara Community. I have raised an internal issue FISH-7597, in which I related the details of this issue.