Skip to content

helperResourceBuilder.register not work in extension #14053

@seal90

Description

@seal90

Describe the bug

define class

package org.springframework.web.servlet.v3_1;

import org.springframework.core.Ordered;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.Writer;
import java.util.logging.Logger;


public class HealthCheckHandlerMappingFilter implements Filter, Ordered {
  private static final Logger logger =
      Logger.getLogger(HealthCheckHandlerMappingFilter.class.getName());

  @Override
  public void init(FilterConfig filterConfig) {}

  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
      throws ServletException, IOException {

    if (!(request instanceof HttpServletRequest) || !(response instanceof HttpServletResponse)) {
      filterChain.doFilter(request, response);
      return;
    }

    HttpServletRequest httpServletRequest = (HttpServletRequest) request;
    String requestURI = httpServletRequest.getRequestURI();
    if("/ping".equals(requestURI)) {
      HttpServletResponse httpServletResponse = (HttpServletResponse) response;
      httpServletResponse.setStatus(200);
      try(Writer writer = httpServletResponse.getWriter()) {
        writer.write("pong");
      }
    } else {
      filterChain.doFilter(request, response);
    }
  }

  @Override
  public void destroy() {}

  @Override
  public int getOrder() {
    // Run after all HIGHEST_PRECEDENCE items
    return Ordered.HIGHEST_PRECEDENCE + 2;
  }
}

register like this

  @Override
  public void registerHelperResources(HelperResourceBuilder helperResourceBuilder) {
    if (!isIndyModule()) {
      System.out.println("registerHelperResources");
      // make the filter class file loadable by ClassPathResource - in some cases (e.g.
      // spring-guice,
      // see https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/7428)
      // Spring
      // might want to read the class file metadata; this line will make the filter class file
      // visible
      // to the bean class loader
      helperResourceBuilder.register(
          "org/springframework/web/servlet/v3_1/HealthCheckHandlerMappingFilter.class");
      try {
        Object val = helperResourceBuilder.getClass().getMethod("getResources").invoke(helperResourceBuilder);
        System.out.println("registerHelperResources 22" + val);
      } catch (Exception e) {
      }

      System.out.println("registerHelperResources 2" + helperResourceBuilder);
    }
  }

load class

  public static class FilterInjectingAdvice {

    @Advice.OnMethodEnter(suppress = Throwable.class)
    public static void onEnter(@Advice.Argument(0) ConfigurableListableBeanFactory beanFactory) {
      if (beanFactory instanceof BeanDefinitionRegistry
          && !beanFactory.containsBean("healthCheckHandlerMappingFilter")) {


        // Explicitly loading classes allows to catch any class-loading issue or deal with cases
        // where the class is not visible.
        try {
          // Firstly check whether DispatcherServlet is present. We need to load an instrumented
          // class from spring-webmvc to trigger injection that makes
          // OpenTelemetryHandlerMappingFilter available.
          Class<?> dispatcherServletClass =
              beanFactory
                  .getBeanClassLoader()
                  .loadClass("org.springframework.web.servlet.DispatcherServlet");

          // Now attempt to load our injected instrumentation class from the same class loader as
          // DispatcherServlet
          Class<?> clazz =
              dispatcherServletClass
                  .getClassLoader()
                  .loadClass(
//                      HealthCheckHandlerMappingFilter.class.getName());
                      "org.springframework.web.servlet.v3_1.HealthCheckHandlerMappingFilter");
//                      "org.springframework.web.servlet.v3_1.OpenTelemetryHandlerMappingFilter");
          GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
          beanDefinition.setScope(SCOPE_SINGLETON);
          beanDefinition.setBeanClass(clazz);

          ((BeanDefinitionRegistry) beanFactory)
              .registerBeanDefinition("healthCheckHandlerMappingFilter", beanDefinition);
        } catch (ClassNotFoundException ignored) {
          // Ignore
          ignored.printStackTrace();
        }
      }
    }
  }
java.lang.ClassNotFoundException: org.springframework.web.servlet.v3_1.HealthCheckHandlerMappingFilter
	at java.net.URLClassLoader.findClass(URLClassLoader.java:387)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
	at org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext.postProcessBeanFactory(AnnotationConfigServletWebServerApplicationContext.java:201)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:529)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215)
	at io.github.seal90.opentelemetry.web.HelloWorldApplication.main(HelloWorldApplication.java:13)
java.lang.ClassNotFoundException: org.springframework.web.servlet.v3_1.HealthCheckHandlerMappingFilter
	at java.net.URLClassLoader.findClass(URLClassLoader.java:387)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.postProcessBeanFactory(ServletWebServerApplicationContext.java:133)
	at org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext.postProcessBeanFactory(AnnotationConfigServletWebServerApplicationContext.java:201)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:529)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215)
	at io.github.seal90.opentelemetry.web.HelloWorldApplication.main(HelloWorldApplication.java:13)

Steps to reproduce

https://github.com/seal90/opentelemetry-javaagent-extension

Expected behavior

Load class success

Actual behavior

Get a exception , class not found

Javaagent or library instrumentation version

opentelemetry-bom:1.50.0 opentelemetry-sdk-extension-incubator:1.51.0-alpha opentelemetry-javaagent-2.16.0

Environment

JDK: Eclipse Adoptium\jdk-8.0.412.8-hotspot
OS: windows
spring boot: 2.2.5.RELEASE

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingneeds triageNew issue that requires triage

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions