Skip to content

Apache Dubbo instrumentation causes ClassCastException: RegistryCapturingInvoker cannot be cast to ClusterInvoker #19427

Description

@PapaPiya

Describe the bug

After enabling the OpenTelemetry Javaagent for an Apache Dubbo consumer application, the application fails during Spring Boot startup while injecting a @DubboReference.

This appears to be a regression introduced by commit 5303808 / PR #17244 (Retrieve dubbo server.address/server.port according to latest SemConv). That commit added RegistryCapturingClusterWrapper, which wraps the Invoker
returned by Cluster.join(...) with RegistryCapturingInvoker.

The problem is that RegistryCapturingInvoker only implements org.apache.dubbo.rpc.Invoker. In Dubbo's registry/service-discovery migration path, Dubbo expects the invoker returned by Cluster.join(...) to still be a
org.apache.dubbo.rpc.cluster.ClusterInvoker and casts it accordingly in RegistryProtocol.doCreateInvoker(...).

As a result, the OpenTelemetry wrapper breaks Dubbo's internal type expectation and causes startup failure:

java.lang.ClassCastException: class io.opentelemetry.javaagent.shaded.instrumentation.apachedubbo.v2_7.internal.RegistryCapturingInvoker cannot be cast to class org.apache.dubbo.rpc.cluster.ClusterInvoker

Steps to reproduce

A minimal reproducer should contain a Dubbo consumer application using Spring Boot and @DubboReference, with Dubbo's registry/service-discovery migration path enabled.

Recipe:

  1. Create a Spring Boot application using Apache Dubbo.
  2. Define a bean with a Dubbo reference, for example:
  @Service
  public class ProcessMessageService {
    @DubboReference
    private SomeDubboService someDubboService;
  }
  1. Configure the application to consume a Dubbo service through a registry/service-discovery setup that goes through Dubbo classes such as:
  org.apache.dubbo.registry.integration.InterfaceCompatibleRegistryProtocol
  org.apache.dubbo.registry.client.migration.MigrationInvoker
  org.apache.dubbo.registry.integration.RegistryProtocol
  1. Start the application with an OpenTelemetry Javaagent build that contains commit 5303808 / PR Retrieve dubbo server.address/server.port according to latest SemConv #17244.

Example:

  java \
    -javaagent:/path/to/opentelemetry-javaagent.jar \
    -jar app.jar

Expected behavior

The application should start successfully with the OpenTelemetry Javaagent enabled.

The Apache Dubbo instrumentation should not change the runtime type contract of the invoker returned by Dubbo's Cluster.join(...). If the delegate invoker is a ClusterInvoker, the wrapped invoker should remain compatible with
ClusterInvoker, or the instrumentation should avoid wrapping in a way that breaks Dubbo's registry/service-discovery migration path.

Actual behavior

The application fails to start during Spring bean creation / @DubboReference injection.

Relevant stack trace:

  org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'websocketController': Unsatisfied dependency expressed through field 'processMessageService';
  nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'processMessageService': Injection of @DubboReference dependencies is failed;
  nested exception is java.lang.ClassCastException: class io.opentelemetry.javaagent.shaded.instrumentation.apachedubbo.v2_7.internal.RegistryCapturingInvoker cannot be cast to class org.apache.dubbo.rpc.cluster.ClusterInvoker

The failing Dubbo path is:

  Caused by: java.lang.ClassCastException: class io.opentelemetry.javaagent.shaded.instrumentation.apachedubbo.v2_7.internal.RegistryCapturingInvoker cannot be cast to class org.apache.dubbo.rpc.cluster.ClusterInvoker
    at org.apache.dubbo.registry.integration.RegistryProtocol.doCreateInvoker(RegistryProtocol.java:528)
    at org.apache.dubbo.registry.integration.InterfaceCompatibleRegistryProtocol.getServiceDiscoveryInvoker(InterfaceCompatibleRegistryProtocol.java:77)
    at org.apache.dubbo.registry.client.migration.MigrationInvoker.refreshServiceDiscoveryInvoker(MigrationInvoker.java:295)
    at org.apache.dubbo.registry.client.migration.MigrationInvoker.migrateToServiceDiscoveryInvoker(MigrationInvoker.java:112)
    at org.apache.dubbo.registry.client.migration.MigrationRuleHandler.doMigrate(MigrationRuleHandler.java:58)
    at org.apache.dubbo.registry.client.migration.MigrationRuleListener.onRefer(MigrationRuleListener.java:103)
    at org.apache.dubbo.registry.integration.RegistryProtocol.interceptInvoker(RegistryProtocol.java:499)
    at org.apache.dubbo.registry.integration.RegistryProtocol.doRefer(RegistryProtocol.java:484)
    at org.apache.dubbo.registry.integration.RegistryProtocol.refer(RegistryProtocol.java:478)
    at org.apache.dubbo.config.ReferenceConfig.createProxy(ReferenceConfig.java:378)
    at org.apache.dubbo.config.ReferenceConfig.init(ReferenceConfig.java:313)
    at org.apache.dubbo.config.ReferenceConfig.get(ReferenceConfig.java:206)
    at org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor.doGetInjectedBean(ReferenceAnnotationBeanPostProcessor.java:165)

Javaagent or library instrumentation version

v2.30.0

Environment

JDK:
OS:

Additional context

No response

Tip

No response

Metadata

Metadata

Assignees

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