This is an automated email from the ASF dual-hosted git repository.
jamesnetherton pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
The following commit(s) were added to refs/heads/main by this push:
new f66a208a00 Fix dynamic instantiation of Azure HttpResponseException
types in native mode
f66a208a00 is described below
commit f66a208a008f6fc0fb900806548190334c4a5d6d
Author: James Netherton <[email protected]>
AuthorDate: Tue Apr 29 12:01:34 2025 +0100
Fix dynamic instantiation of Azure HttpResponseException types in native
mode
Fixes #7319
---
.../deployment/AzureCoreSupportProcessor.java | 23 +++++++++++++++++++---
.../deployment/AzureServicebusProcessor.java | 6 ++++++
.../azure/eventhubs/it/AzureEventhubsResource.java | 17 ++++++++++++++++
.../azure/eventhubs/it/AzureEventhubsTest.java | 8 ++++++++
.../azure/key/vault/it/AzureKeyVaultResource.java | 17 ++++++++++++++++
.../azure/key/vault/it/AzureKeyVaultTest.java | 7 +++++++
.../servicebus/it/AzureServiceBusResource.java | 17 ++++++++++++++++
.../azure/servicebus/it/AzureServiceBusTest.java | 8 ++++++++
.../storage/blob/it/AzureStorageBlobResource.java | 17 ++++++++++++++++
.../storage/blob/it/AzureStorageBlobTest.java | 8 ++++++++
.../queue/it/AzureStorageQueueResource.java | 17 ++++++++++++++++
.../storage/queue/it/AzureStorageQueueTest.java | 7 +++++++
12 files changed, 149 insertions(+), 3 deletions(-)
diff --git
a/extensions-support/azure-core/deployment/src/main/java/org/apache/camel/quarkus/support/reactor/netty/deployment/AzureCoreSupportProcessor.java
b/extensions-support/azure-core/deployment/src/main/java/org/apache/camel/quarkus/support/reactor/netty/deployment/AzureCoreSupportProcessor.java
index 90c6cde3a1..b603a2a2c9 100644
---
a/extensions-support/azure-core/deployment/src/main/java/org/apache/camel/quarkus/support/reactor/netty/deployment/AzureCoreSupportProcessor.java
+++
b/extensions-support/azure-core/deployment/src/main/java/org/apache/camel/quarkus/support/reactor/netty/deployment/AzureCoreSupportProcessor.java
@@ -19,9 +19,11 @@ package
org.apache.camel.quarkus.support.reactor.netty.deployment;
import java.io.IOException;
import java.util.Set;
import java.util.function.BooleanSupplier;
+import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.azure.core.annotation.ServiceInterface;
+import com.azure.core.exception.HttpResponseException;
import com.azure.core.http.HttpClientProvider;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
@@ -34,18 +36,22 @@ import
io.quarkus.deployment.builditem.nativeimage.RuntimeReinitializedClassBuil
import io.quarkus.deployment.builditem.nativeimage.ServiceProviderBuildItem;
import io.quarkus.deployment.util.ServiceUtil;
import io.quarkus.utilities.OS;
+import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.DotName;
public class AzureCoreSupportProcessor {
private static final DotName SERVICE_INTERFACE_DOT_NAME =
DotName.createSimple(ServiceInterface.class.getName());
@BuildStep
- IndexDependencyBuildItem indexDependency() {
- return new IndexDependencyBuildItem("com.azure", "azure-core");
+ void indexDependency(BuildProducer<IndexDependencyBuildItem>
indexedDependencies) {
+ indexedDependencies.produce(new IndexDependencyBuildItem("com.azure",
"azure-core"));
+ indexedDependencies.produce(new IndexDependencyBuildItem("com.azure",
"azure-identity"));
}
@BuildStep
- void reflectiveClasses(BuildProducer<ReflectiveClassBuildItem>
reflectiveClasses) {
+ void reflectiveClasses(
+ CombinedIndexBuildItem combinedIndex,
+ BuildProducer<ReflectiveClassBuildItem> reflectiveClasses) {
reflectiveClasses.produce(ReflectiveClassBuildItem.builder(com.azure.core.util.DateTimeRfc1123.class,
com.azure.core.http.HttpHeaderName.class,
com.azure.core.http.rest.StreamResponse.class,
@@ -54,6 +60,17 @@ public class AzureCoreSupportProcessor {
reflectiveClasses.produce(ReflectiveClassBuildItem.builder("com.microsoft.aad.msal4j.AadInstanceDiscoveryResponse",
"com.microsoft.aad.msal4j.InstanceDiscoveryMetadataEntry").fields().build());
+ // HttpResponseException instances may be dynamically instantiated and
have methods invoked reflectively
+ Set<String> httpResponseExceptionClasses = combinedIndex.getIndex()
+ .getAllKnownSubclasses(HttpResponseException.class)
+ .stream()
+ .map(ClassInfo::name)
+ .map(DotName::toString)
+ .collect(Collectors.toUnmodifiableSet());
+
+
reflectiveClasses.produce(ReflectiveClassBuildItem.builder(httpResponseExceptionClasses.toArray(new
String[0]))
+ .methods()
+ .build());
}
@BuildStep
diff --git
a/extensions/azure-servicebus/deployment/src/main/java/org/apache/camel/quarkus/component/azure/servicebus/deployment/AzureServicebusProcessor.java
b/extensions/azure-servicebus/deployment/src/main/java/org/apache/camel/quarkus/component/azure/servicebus/deployment/AzureServicebusProcessor.java
index 5f532a5ef6..9b9ac0f863 100644
---
a/extensions/azure-servicebus/deployment/src/main/java/org/apache/camel/quarkus/component/azure/servicebus/deployment/AzureServicebusProcessor.java
+++
b/extensions/azure-servicebus/deployment/src/main/java/org/apache/camel/quarkus/component/azure/servicebus/deployment/AzureServicebusProcessor.java
@@ -21,6 +21,7 @@ import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.builditem.ExtensionSslNativeSupportBuildItem;
import io.quarkus.deployment.builditem.FeatureBuildItem;
+import io.quarkus.deployment.builditem.IndexDependencyBuildItem;
import
io.quarkus.deployment.builditem.nativeimage.RuntimeInitializedClassBuildItem;
class AzureServicebusProcessor {
@@ -43,4 +44,9 @@ class AzureServicebusProcessor {
runtimeInitializedClass
.produce(new
RuntimeInitializedClassBuildItem(DigestProxyChallengeProcessorImpl.class.getName()));
}
+
+ @BuildStep
+ IndexDependencyBuildItem indexDependency() {
+ return new IndexDependencyBuildItem("com.azure",
"azure-messaging-servicebus");
+ }
}
diff --git
a/integration-test-groups/azure/azure-eventhubs/src/main/java/org/apache/camel/quarkus/component/azure/eventhubs/it/AzureEventhubsResource.java
b/integration-test-groups/azure/azure-eventhubs/src/main/java/org/apache/camel/quarkus/component/azure/eventhubs/it/AzureEventhubsResource.java
index c69dd53710..44c3b9287d 100644
---
a/integration-test-groups/azure/azure-eventhubs/src/main/java/org/apache/camel/quarkus/component/azure/eventhubs/it/AzureEventhubsResource.java
+++
b/integration-test-groups/azure/azure-eventhubs/src/main/java/org/apache/camel/quarkus/component/azure/eventhubs/it/AzureEventhubsResource.java
@@ -23,6 +23,11 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
+import com.azure.core.exception.HttpResponseException;
+import com.azure.core.implementation.ReflectiveInvoker;
+import com.azure.core.implementation.http.UnexpectedExceptionInformation;
+import
com.azure.core.implementation.http.rest.ResponseExceptionConstructorCache;
+import
com.azure.storage.blob.implementation.models.BlobStorageExceptionInternal;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.Consumes;
@@ -146,4 +151,16 @@ public class AzureEventhubsResource {
public void stopRoute(@PathParam("routeId") String routeId) throws
Exception {
context.getRouteController().stopRoute(routeId);
}
+
+ @GET
+ @Path("exception/cache")
+ @Produces(MediaType.TEXT_PLAIN)
+ public boolean cachedHttpResponseException() {
+ UnexpectedExceptionInformation exceptionInformation = new
UnexpectedExceptionInformation(
+ BlobStorageExceptionInternal.class);
+ Class<? extends HttpResponseException> exceptionType =
exceptionInformation.getExceptionType();
+ ReflectiveInvoker reflectiveInvoker = new
ResponseExceptionConstructorCache().get(exceptionType,
+ exceptionInformation.getExceptionBodyType());
+ return reflectiveInvoker != null;
+ }
}
diff --git
a/integration-test-groups/azure/azure-eventhubs/src/test/java/org/apache/camel/quarkus/component/azure/eventhubs/it/AzureEventhubsTest.java
b/integration-test-groups/azure/azure-eventhubs/src/test/java/org/apache/camel/quarkus/component/azure/eventhubs/it/AzureEventhubsTest.java
index 8d774afa83..80f3b95260 100644
---
a/integration-test-groups/azure/azure-eventhubs/src/test/java/org/apache/camel/quarkus/component/azure/eventhubs/it/AzureEventhubsTest.java
+++
b/integration-test-groups/azure/azure-eventhubs/src/test/java/org/apache/camel/quarkus/component/azure/eventhubs/it/AzureEventhubsTest.java
@@ -441,4 +441,12 @@ class AzureEventhubsTest {
.statusCode(204);
}
}
+
+ @Test
+ void dynamicExceptionInstantiation() {
+ RestAssured.get("/azure-eventhubs/exception/cache")
+ .then()
+ .statusCode(200)
+ .body(is("true"));
+ }
}
diff --git
a/integration-test-groups/azure/azure-key-vault/src/main/java/org/apache/camel/quarkus/component/azure/key/vault/it/AzureKeyVaultResource.java
b/integration-test-groups/azure/azure-key-vault/src/main/java/org/apache/camel/quarkus/component/azure/key/vault/it/AzureKeyVaultResource.java
index 6e760768b1..b0f018e3f8 100644
---
a/integration-test-groups/azure/azure-key-vault/src/main/java/org/apache/camel/quarkus/component/azure/key/vault/it/AzureKeyVaultResource.java
+++
b/integration-test-groups/azure/azure-key-vault/src/main/java/org/apache/camel/quarkus/component/azure/key/vault/it/AzureKeyVaultResource.java
@@ -18,6 +18,11 @@ package
org.apache.camel.quarkus.component.azure.key.vault.it;
import java.util.concurrent.atomic.AtomicBoolean;
+import com.azure.core.exception.HttpResponseException;
+import com.azure.core.implementation.ReflectiveInvoker;
+import com.azure.core.implementation.http.UnexpectedExceptionInformation;
+import
com.azure.core.implementation.http.rest.ResponseExceptionConstructorCache;
+import
com.azure.security.keyvault.secrets.implementation.models.KeyVaultErrorException;
import com.azure.security.keyvault.secrets.models.KeyVaultSecret;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.event.Observes;
@@ -138,4 +143,16 @@ public class AzureKeyVaultResource {
public boolean contextReloadStatus() {
return contextReloaded.get();
}
+
+ @GET
+ @Path("exception/cache")
+ @Produces(MediaType.TEXT_PLAIN)
+ public boolean cachedHttpResponseException() {
+ UnexpectedExceptionInformation exceptionInformation = new
UnexpectedExceptionInformation(
+ KeyVaultErrorException.class);
+ Class<? extends HttpResponseException> exceptionType =
exceptionInformation.getExceptionType();
+ ReflectiveInvoker reflectiveInvoker = new
ResponseExceptionConstructorCache().get(exceptionType,
+ exceptionInformation.getExceptionBodyType());
+ return reflectiveInvoker != null;
+ }
}
diff --git
a/integration-test-groups/azure/azure-key-vault/src/test/java/org/apache/camel/quarkus/component/azure/key/vault/it/AzureKeyVaultTest.java
b/integration-test-groups/azure/azure-key-vault/src/test/java/org/apache/camel/quarkus/component/azure/key/vault/it/AzureKeyVaultTest.java
index 67a101fc68..04f4ad68dc 100644
---
a/integration-test-groups/azure/azure-key-vault/src/test/java/org/apache/camel/quarkus/component/azure/key/vault/it/AzureKeyVaultTest.java
+++
b/integration-test-groups/azure/azure-key-vault/src/test/java/org/apache/camel/quarkus/component/azure/key/vault/it/AzureKeyVaultTest.java
@@ -71,4 +71,11 @@ class AzureKeyVaultTest extends AbstractAzureKeyVaultTest {
}
}
+ @Test
+ void dynamicExceptionInstantiation() {
+ RestAssured.get("/azure-key-vault/exception/cache")
+ .then()
+ .statusCode(200)
+ .body(is("true"));
+ }
}
diff --git
a/integration-test-groups/azure/azure-servicebus/src/main/java/org/apache/camel/quarkus/component/azure/servicebus/it/AzureServiceBusResource.java
b/integration-test-groups/azure/azure-servicebus/src/main/java/org/apache/camel/quarkus/component/azure/servicebus/it/AzureServiceBusResource.java
index e7312828b4..74a3249c2f 100644
---
a/integration-test-groups/azure/azure-servicebus/src/main/java/org/apache/camel/quarkus/component/azure/servicebus/it/AzureServiceBusResource.java
+++
b/integration-test-groups/azure/azure-servicebus/src/main/java/org/apache/camel/quarkus/component/azure/servicebus/it/AzureServiceBusResource.java
@@ -26,7 +26,12 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
+import com.azure.core.exception.HttpResponseException;
+import com.azure.core.implementation.ReflectiveInvoker;
+import com.azure.core.implementation.http.UnexpectedExceptionInformation;
+import
com.azure.core.implementation.http.rest.ResponseExceptionConstructorCache;
import com.azure.core.util.BinaryData;
+import
com.azure.messaging.servicebus.administration.implementation.models.ServiceBusManagementErrorException;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.Consumes;
@@ -170,4 +175,16 @@ public class AzureServiceBusResource {
LOG.infof("Stopping route: %s", routeId);
context.getRouteController().stopRoute(routeId);
}
+
+ @GET
+ @Path("exception/cache")
+ @Produces(MediaType.TEXT_PLAIN)
+ public boolean cachedHttpResponseException() {
+ UnexpectedExceptionInformation exceptionInformation = new
UnexpectedExceptionInformation(
+ ServiceBusManagementErrorException.class);
+ Class<? extends HttpResponseException> exceptionType =
exceptionInformation.getExceptionType();
+ ReflectiveInvoker reflectiveInvoker = new
ResponseExceptionConstructorCache().get(exceptionType,
+ exceptionInformation.getExceptionBodyType());
+ return reflectiveInvoker != null;
+ }
}
diff --git
a/integration-test-groups/azure/azure-servicebus/src/test/java/org/apache/camel/quarkus/component/azure/servicebus/it/AzureServiceBusTest.java
b/integration-test-groups/azure/azure-servicebus/src/test/java/org/apache/camel/quarkus/component/azure/servicebus/it/AzureServiceBusTest.java
index 6660ebbfc2..f922f7e782 100644
---
a/integration-test-groups/azure/azure-servicebus/src/test/java/org/apache/camel/quarkus/component/azure/servicebus/it/AzureServiceBusTest.java
+++
b/integration-test-groups/azure/azure-servicebus/src/test/java/org/apache/camel/quarkus/component/azure/servicebus/it/AzureServiceBusTest.java
@@ -355,6 +355,14 @@ class AzureServiceBusTest {
}
}
+ @Test
+ void dynamicExceptionInstantiation() {
+ RestAssured.get("/azure-servicebus/exception/cache")
+ .then()
+ .statusCode(200)
+ .body(is("true"));
+ }
+
static Stream<Arguments> produceConsumeOptions() {
String destinationTypes = "queue";
diff --git
a/integration-test-groups/azure/azure-storage-blob/src/main/java/org/apache/camel/quarkus/component/azure/storage/blob/it/AzureStorageBlobResource.java
b/integration-test-groups/azure/azure-storage-blob/src/main/java/org/apache/camel/quarkus/component/azure/storage/blob/it/AzureStorageBlobResource.java
index f93789156a..156af66d5d 100644
---
a/integration-test-groups/azure/azure-storage-blob/src/main/java/org/apache/camel/quarkus/component/azure/storage/blob/it/AzureStorageBlobResource.java
+++
b/integration-test-groups/azure/azure-storage-blob/src/main/java/org/apache/camel/quarkus/component/azure/storage/blob/it/AzureStorageBlobResource.java
@@ -30,9 +30,14 @@ import java.util.Map;
import java.util.Random;
import java.util.stream.Collectors;
+import com.azure.core.exception.HttpResponseException;
import com.azure.core.http.rest.PagedIterable;
+import com.azure.core.implementation.ReflectiveInvoker;
+import com.azure.core.implementation.http.UnexpectedExceptionInformation;
+import
com.azure.core.implementation.http.rest.ResponseExceptionConstructorCache;
import com.azure.storage.blob.changefeed.models.BlobChangefeedEvent;
import com.azure.storage.blob.changefeed.models.BlobChangefeedEventType;
+import
com.azure.storage.blob.implementation.models.BlobStorageExceptionInternal;
import com.azure.storage.blob.models.BlobContainerItem;
import com.azure.storage.blob.models.BlobItem;
import com.azure.storage.blob.models.BlobStorageException;
@@ -430,6 +435,18 @@ public class AzureStorageBlobResource {
}
}
+ @GET
+ @Path("exception/cache")
+ @Produces(MediaType.TEXT_PLAIN)
+ public boolean cachedHttpResponseException() {
+ UnexpectedExceptionInformation exceptionInformation = new
UnexpectedExceptionInformation(
+ BlobStorageExceptionInternal.class);
+ Class<? extends HttpResponseException> exceptionType =
exceptionInformation.getExceptionType();
+ ReflectiveInvoker reflectiveInvoker = new
ResponseExceptionConstructorCache().get(exceptionType,
+ exceptionInformation.getExceptionBodyType());
+ return reflectiveInvoker != null;
+ }
+
private void extractBlockNames(JsonObjectBuilder builder, List<Block>
blocks, BlockListType listType) {
JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
blocks.stream().map(Block::getName).forEach(arrayBuilder::add);
diff --git
a/integration-test-groups/azure/azure-storage-blob/src/test/java/org/apache/camel/quarkus/component/azure/storage/blob/it/AzureStorageBlobTest.java
b/integration-test-groups/azure/azure-storage-blob/src/test/java/org/apache/camel/quarkus/component/azure/storage/blob/it/AzureStorageBlobTest.java
index 3ec86637f2..ec7f2f59a9 100644
---
a/integration-test-groups/azure/azure-storage-blob/src/test/java/org/apache/camel/quarkus/component/azure/storage/blob/it/AzureStorageBlobTest.java
+++
b/integration-test-groups/azure/azure-storage-blob/src/test/java/org/apache/camel/quarkus/component/azure/storage/blob/it/AzureStorageBlobTest.java
@@ -602,4 +602,12 @@ class AzureStorageBlobTest {
.statusCode(anyOf(is(204), is(404)));
}
}
+
+ @Test
+ public void dynamicExceptionInstantiation() {
+ RestAssured.get("/azure-storage-blob/exception/cache")
+ .then()
+ .statusCode(200)
+ .body(is("true"));
+ }
}
diff --git
a/integration-test-groups/azure/azure-storage-queue/src/main/java/org/apache/camel/quarkus/component/azure/storage/queue/it/AzureStorageQueueResource.java
b/integration-test-groups/azure/azure-storage-queue/src/main/java/org/apache/camel/quarkus/component/azure/storage/queue/it/AzureStorageQueueResource.java
index 9b2c4f9461..06059a05f7 100644
---
a/integration-test-groups/azure/azure-storage-queue/src/main/java/org/apache/camel/quarkus/component/azure/storage/queue/it/AzureStorageQueueResource.java
+++
b/integration-test-groups/azure/azure-storage-queue/src/main/java/org/apache/camel/quarkus/component/azure/storage/queue/it/AzureStorageQueueResource.java
@@ -23,12 +23,17 @@ import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
+import com.azure.core.exception.HttpResponseException;
import com.azure.core.http.policy.HttpLogDetailLevel;
import com.azure.core.http.policy.HttpLogOptions;
+import com.azure.core.implementation.ReflectiveInvoker;
+import com.azure.core.implementation.http.UnexpectedExceptionInformation;
+import
com.azure.core.implementation.http.rest.ResponseExceptionConstructorCache;
import com.azure.core.util.BinaryData;
import com.azure.storage.common.StorageSharedKeyCredential;
import com.azure.storage.queue.QueueServiceClient;
import com.azure.storage.queue.QueueServiceClientBuilder;
+import
com.azure.storage.queue.implementation.models.QueueStorageExceptionInternal;
import com.azure.storage.queue.models.PeekedMessageItem;
import com.azure.storage.queue.models.QueueItem;
import com.azure.storage.queue.models.QueueMessageItem;
@@ -223,6 +228,18 @@ public class AzureStorageQueueResource {
.collect(Collectors.joining("\n"));
}
+ @GET
+ @Path("exception/cache")
+ @Produces(MediaType.TEXT_PLAIN)
+ public boolean cachedHttpResponseException() {
+ UnexpectedExceptionInformation exceptionInformation = new
UnexpectedExceptionInformation(
+ QueueStorageExceptionInternal.class);
+ Class<? extends HttpResponseException> exceptionType =
exceptionInformation.getExceptionType();
+ ReflectiveInvoker reflectiveInvoker = new
ResponseExceptionConstructorCache().get(exceptionType,
+ exceptionInformation.getExceptionBodyType());
+ return reflectiveInvoker != null;
+ }
+
private String componentUri(final QueueOperationDefinition operation) {
return String.format("azure-storage-queue://%s/%s?operation=%s",
azureStorageAccountName, QUEUE_NAME,
diff --git
a/integration-test-groups/azure/azure-storage-queue/src/test/java/org/apache/camel/quarkus/component/azure/storage/queue/it/AzureStorageQueueTest.java
b/integration-test-groups/azure/azure-storage-queue/src/test/java/org/apache/camel/quarkus/component/azure/storage/queue/it/AzureStorageQueueTest.java
index 91e1c69130..a18c60357d 100644
---
a/integration-test-groups/azure/azure-storage-queue/src/test/java/org/apache/camel/quarkus/component/azure/storage/queue/it/AzureStorageQueueTest.java
+++
b/integration-test-groups/azure/azure-storage-queue/src/test/java/org/apache/camel/quarkus/component/azure/storage/queue/it/AzureStorageQueueTest.java
@@ -177,4 +177,11 @@ class AzureStorageQueueTest {
.as(List.class);
}
+ @Test
+ public void dynamicExceptionInstantiation() {
+ RestAssured.get("/azure-storage-queue/exception/cache")
+ .then()
+ .statusCode(200)
+ .body(is("true"));
+ }
}