Repository: helidon-io/helidon (java)

Issue:
Check delegate before Helidon wrapper in tracer `unwrap` method
## Environment Details
* Helidon Version: 4.x
* Helidon SE or Helidon MP
* JDK version:
* OS:
* Docker version (if applicable):

----------

## Problem Description
In a recent PR, the OTel implementation of the Helidon neutral `Tracer` interface implementation of the `unwrap` method added checking of the Helidon wrapper object as well as the delegate.

But that change checks the wrapper first and the delegate second, which changes some behavior (such as unwrapping as `Object` and printing the unwrapped object's `toString()` value). This is also the opposite order that the pre-existing OpenTracing `Tracer` `unwrap` method checks the two objects.

## Steps to reproduce
With the OTel tracing provider in use, invoke `helidonTracer.unwrap(Object.class).toString()` and you see the Helidon wrapper's value, not the delegate's value as before.


Pull request:
4.0.10: Reorder checking of delegate vs. wrapper in OTel tracer unwrap (

Backport of #8855 to 4.0.10

### Description

Resolves #8854

A recent PR added the ability to unwrap the OTel tracer as the Helidon Tracer wrapper (to the pre-existing ability to unwrap the OTel delegate tracer) by checking the wrapper first, then the delegate.

This broke previous behavior where users used unwrap(Object.class).toString() to display delegate information.

This PR reorders the checking in the OTel Tracer wrapper to restore the earlier behavior for unwrapping as Object while still adding the ability to unwrap as the wrapper (which was the purpose of this part of the earlier PR).

The PR also adds tests to make sure the older behavior works again.

### Documentation

Bug fix; no doc impact.



Patch:
diff --git a/tracing/providers/opentelemetry/src/main/java/io/helidon/tracing/providers/opentelemetry/OpenTelemetryTracer.java b/tracing/providers/opentelemetry/src/main/java/io/helidon/tracing/providers/opentelemetry/OpenTelemetryTracer.java
index f38bb09cad..d50c67c370 100644
--- a/tracing/providers/opentelemetry/src/main/java/io/helidon/tracing/providers/opentelemetry/OpenTelemetryTracer.java
+++ b/tracing/providers/opentelemetry/src/main/java/io/helidon/tracing/providers/opentelemetry/OpenTelemetryTracer.java
@@ -96,12 +96,13 @@ class OpenTelemetryTracer implements Tracer {
 
     @Override
     public <T> T unwrap(Class<T> tracerClass) {
-        if (tracerClass.isInstance(this)) {
-            return tracerClass.cast(this);
-        }
         if (tracerClass.isAssignableFrom(delegate.getClass())) {
             return tracerClass.cast(delegate);
         }
+        if (tracerClass.isInstance(this)) {
+            return tracerClass.cast(this);
+        }
+
         throw new IllegalArgumentException("Cannot provide an instance of " + tracerClass.getName()
                                                    + ", telemetry tracer is: " + delegate.getClass().getName());
     }


Test patch:
diff --git a/tracing/providers/opentelemetry/src/test/java/io/helidon/tracing/providers/opentelemetry/TestUnwrap.java b/tracing/providers/opentelemetry/src/test/java/io/helidon/tracing/providers/opentelemetry/TestUnwrap.java
index d654364844..387f2e8e12 100644
--- a/tracing/providers/opentelemetry/src/test/java/io/helidon/tracing/providers/opentelemetry/TestUnwrap.java
+++ b/tracing/providers/opentelemetry/src/test/java/io/helidon/tracing/providers/opentelemetry/TestUnwrap.java
@@ -22,6 +22,7 @@ import io.opentelemetry.api.trace.Tracer;
 import org.junit.jupiter.api.Test;
 
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.instanceOf;
 
 class TestUnwrap {
@@ -32,6 +33,14 @@ class TestUnwrap {
         assertThat("Tracer unwrapped",
                    tracer.unwrap(Tracer.class),
                    instanceOf(Tracer.class));
+
+        assertThat("Delegate unwrapped",
+                   tracer.unwrap(io.opentelemetry.api.trace.Tracer.class),
+                   instanceOf(io.opentelemetry.api.trace.Tracer.class));
+
+        assertThat("Object.toString()",
+                   tracer.unwrap(Object.class).toString(),
+                   containsString("io.opentelemetry"));
     }
 
     @Test