diff --git a/docs/src/main/asciidoc/rest-client.adoc b/docs/src/main/asciidoc/rest-client.adoc index bb2330f246523..3dd2f1a196a55 100644 --- a/docs/src/main/asciidoc/rest-client.adoc +++ b/docs/src/main/asciidoc/rest-client.adoc @@ -372,6 +372,11 @@ quarkus.rest-client.extensions-api.url=https://stage.code.quarkus.io/api quarkus.rest-client.extensions-api.scope=jakarta.inject.Singleton ---- +[IMPORTANT] +==== +Setting the base URL of the client is **mandatory**, however the REST Client supports per-invocation overrides of the base URL using the `@io.quarkus.rest.client.reactive.Url` annotation. +==== + === Disabling Hostname Verification To disable the SSL hostname verification for a specific REST client, add the following property to your configuration: diff --git a/extensions/resteasy-reactive/rest-client-jaxrs/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/JaxrsClientReactiveProcessor.java b/extensions/resteasy-reactive/rest-client-jaxrs/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/JaxrsClientReactiveProcessor.java index 17e5b6853fae9..24579bdde4a60 100644 --- a/extensions/resteasy-reactive/rest-client-jaxrs/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/JaxrsClientReactiveProcessor.java +++ b/extensions/resteasy-reactive/rest-client-jaxrs/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/JaxrsClientReactiveProcessor.java @@ -7,7 +7,7 @@ import static org.jboss.jandex.Type.Kind.PRIMITIVE; import static org.jboss.resteasy.reactive.client.impl.RestClientRequestContext.DEFAULT_CONTENT_TYPE_PROP; import static org.jboss.resteasy.reactive.common.processor.EndpointIndexer.extractProducesConsumesValues; -import static org.jboss.resteasy.reactive.common.processor.JandexUtil.*; +import static org.jboss.resteasy.reactive.common.processor.JandexUtil.isAssignableFrom; import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.COLLECTION; import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.COMPLETION_STAGE; import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.CONSUMES; @@ -20,13 +20,17 @@ import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.PART_TYPE_NAME; import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.REST_FORM_PARAM; import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.REST_MULTI; +import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.STRING; import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.UNI; +import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.URI; import java.io.Closeable; import java.io.File; import java.io.InputStream; import java.lang.annotation.Annotation; import java.lang.reflect.Modifier; +import java.net.URI; +import java.net.URL; import java.nio.file.Path; import java.util.AbstractMap; import java.util.ArrayList; @@ -75,6 +79,7 @@ import org.jboss.jandex.FieldInfo; import org.jboss.jandex.IndexView; import org.jboss.jandex.MethodInfo; +import org.jboss.jandex.MethodParameterInfo; import org.jboss.jandex.ParameterizedType; import org.jboss.jandex.PrimitiveType; import org.jboss.jandex.Type; @@ -218,6 +223,9 @@ public class JaxrsClientReactiveProcessor { private static final DotName NOT_BODY = DotName.createSimple("io.quarkus.rest.client.reactive.NotBody"); + private static final DotName URL = DotName.createSimple("io.quarkus.rest.client.reactive.Url"); + private static final DotName WEB_TARGET = DotName.createSimple(WebTarget.class); + private static final Set ASYNC_RETURN_TYPES = Set.of(COMPLETION_STAGE, UNI, MULTI, REST_MULTI); public static final DotName BYTE = DotName.createSimple(Byte.class.getName()); public static final MethodDescriptor MULTIPART_RESPONSE_DATA_ADD_FILLER = MethodDescriptor @@ -225,6 +233,7 @@ public class JaxrsClientReactiveProcessor { private static final MethodDescriptor ARRAY_LIST_CONSTRUCTOR = MethodDescriptor.ofConstructor(ArrayList.class); private static final MethodDescriptor COLLECTION_ADD = MethodDescriptor.ofMethod(Collection.class, "add", boolean.class, Object.class); + private static final MethodDescriptor URI_CTOR = MethodDescriptor.ofConstructor(java.net.URI.class, String.class); private static final String MULTIPART_FORM_DATA = "multipart/form-data"; @@ -330,7 +339,7 @@ void setupClientProxies(JaxrsClientReactiveRecorder recorder, .setSkipMethodParameter(new Predicate>() { @Override public boolean test(Map anns) { - return anns.containsKey(NOT_BODY); + return anns.containsKey(NOT_BODY) || anns.containsKey(URL); } }) .setResourceMethodCallback(new Consumer<>() { @@ -839,19 +848,39 @@ A more full example of generated client (with sub-resource) can is at the bottom classContext.constructor.invokeSpecialMethod(MethodDescriptor.ofConstructor(RestClientBase.class, List.class), classContext.constructor.getThis(), classContext.constructor.getMethodParam(1)); - AssignableResultHandle baseTarget = classContext.constructor.createVariable(WebTargetImpl.class); + AssignableResultHandle effectiveInputTarget = classContext.constructor.createVariable(WebTargetImpl.class); + ResultHandle inputTarget = classContext.constructor.getMethodParam(0); if (restClientInterface.isEncoded()) { - classContext.constructor.assign(baseTarget, - disableEncodingForWebTarget(classContext.constructor, classContext.constructor.getMethodParam(0))); + classContext.constructor.assign(effectiveInputTarget, + disableEncodingForWebTarget(classContext.constructor, inputTarget)); } else { - classContext.constructor.assign(baseTarget, classContext.constructor.getMethodParam(0)); + classContext.constructor.assign(effectiveInputTarget, inputTarget); } - classContext.constructor.assign(baseTarget, - classContext.constructor.invokeVirtualMethod( - MethodDescriptor.ofMethod(WebTargetImpl.class, "path", WebTargetImpl.class, String.class), - baseTarget, - classContext.constructor.load(restClientInterface.getPath()))); + // field that holds the initial value passed to the constructor (with encoding taken care of) + FieldDescriptor inputTargetField = classContext.classCreator + .getFieldCreator("inputTarget", WebTargetImpl.class.getName()) + .setModifiers(Modifier.FINAL) + .getFieldDescriptor(); + classContext.constructor.writeInstanceField(inputTargetField, classContext.constructor.getThis(), + effectiveInputTarget); + + AssignableResultHandle baseTarget = classContext.constructor.createVariable(WebTargetImpl.class); + classContext.constructor.assign(baseTarget, effectiveInputTarget); + + // method that takes the WebTarget provided as a parameter and produces the base WebTarget of the class + MethodCreator baseTargetProducer = classContext.classCreator + .getMethodCreator("baseTargetProducer", WebTargetImpl.class, + WebTargetImpl.class) + .setModifiers(Modifier.PRIVATE); + baseTargetProducer.returnValue(baseTargetProducer.invokeVirtualMethod( + MethodDescriptor.ofMethod(WebTargetImpl.class, "path", WebTargetImpl.class, String.class), + baseTargetProducer.getMethodParam(0), + baseTargetProducer.load(restClientInterface.getPath()))); + + classContext.constructor.assign(baseTarget, classContext.constructor.invokeVirtualMethod( + baseTargetProducer.getMethodDescriptor(), classContext.constructor.getThis(), baseTarget)); + // write the base WebTarget to a field FieldDescriptor baseTargetField = classContext.classCreator .getFieldCreator("baseTarget", WebTargetImpl.class.getName()) .setModifiers(Modifier.FINAL) @@ -902,20 +931,34 @@ A more full example of generated client (with sub-resource) can is at the bottom addResponseTypeIfMultipart(multipartResponseTypes, jandexMethod, index); // constructor: initializing the immutable part of the method-specific web target - FieldDescriptor webTargetForMethod = FieldDescriptor.of(name, "target" + methodIndex, WebTargetImpl.class); - classContext.classCreator.getFieldCreator(webTargetForMethod).setModifiers(Modifier.FINAL); + FieldDescriptor defaultWebTargetForMethod = FieldDescriptor.of(name, "target" + methodIndex, + WebTargetImpl.class); + classContext.classCreator.getFieldCreator(defaultWebTargetForMethod).setModifiers(Modifier.FINAL); + + // method that takes a base WebTarget and returns a WebTarget with the path of the method + MethodCreator methodTargetProducer = classContext.classCreator + .getMethodCreator("targetOfMethod" + methodIndex, + WebTargetImpl.class, WebTarget.class) + .setModifiers(Modifier.PRIVATE); + AssignableResultHandle methodWebTargetProducerResult = methodTargetProducer + .createVariable(WebTarget.class); + methodTargetProducer.assign(methodWebTargetProducerResult, methodTargetProducer.getMethodParam(0)); + if (method.getPath() != null) { + appendPath(methodTargetProducer, method.getPath(), methodWebTargetProducerResult); + } + methodTargetProducer.returnValue(methodWebTargetProducerResult); - AssignableResultHandle constructorTarget = createWebTargetForMethod(classContext.constructor, baseTarget, - method); - classContext.constructor.writeInstanceField(webTargetForMethod, classContext.constructor.getThis(), - constructorTarget); + classContext.constructor.writeInstanceField(defaultWebTargetForMethod, classContext.constructor.getThis(), + classContext.constructor.invokeVirtualMethod(methodTargetProducer.getMethodDescriptor(), + classContext.constructor.getThis(), + baseTarget)); if (observabilityIntegrationNeeded) { String templatePath = MULTIPLE_SLASH_PATTERN.matcher(restClientInterface.getPath() + method.getPath()) .replaceAll("/"); classContext.constructor.invokeVirtualMethod( MethodDescriptor.ofMethod(WebTargetImpl.class, "setPreClientSendHandler", void.class, ClientRestHandler.class), - classContext.constructor.readInstanceField(webTargetForMethod, + classContext.constructor.readInstanceField(defaultWebTargetForMethod, classContext.constructor.getThis()), classContext.constructor.newInstance( MethodDescriptor.ofConstructor(ClientObservabilityHandler.class, String.class), @@ -929,7 +972,58 @@ A more full example of generated client (with sub-resource) can is at the bottom AssignableResultHandle methodTarget = methodCreator.createVariable(WebTarget.class); methodCreator.assign(methodTarget, - methodCreator.readInstanceField(webTargetForMethod, methodCreator.getThis())); + methodCreator.readInstanceField(defaultWebTargetForMethod, methodCreator.getThis())); + + // handle the @BaseUrl annotation + List notBodyAnnotations = jandexMethod.annotations(URL).stream() + .filter(ai -> ai.target().kind() == AnnotationTarget.Kind.METHOD_PARAMETER).toList(); + if (!notBodyAnnotations.isEmpty()) { + if (notBodyAnnotations.size() > 1) { + throw new IllegalArgumentException( + "Only a single argument can be annotated with '" + URL + + "'. Offending method is '" + + jandexMethod.declaringClass().name() + "#" + jandexMethod.name()); + } + + // the idea here is to create a WebTarget that used the base URL provided by the user, + // along with the paths of the REST Client class and current method + + MethodParameterInfo baseUrlMethodParam = notBodyAnnotations.get(0).target().asMethodParameter(); + DotName notBodyTargetType = baseUrlMethodParam.type().name(); + + ResultHandle methodParam = methodCreator.getMethodParam(baseUrlMethodParam.position()); + AssignableResultHandle newUri = methodCreator.createVariable(java.net.URI.class); + BytecodeCreator methodParamNotNull = methodCreator.ifNotNull(methodParam).trueBranch(); + + if (STRING.equals(notBodyTargetType)) { + methodParamNotNull.assign(newUri, methodParamNotNull.newInstance(URI_CTOR, methodParam)); + } else if (ResteasyReactiveDotNames.URL.equals(notBodyTargetType)) { + methodParamNotNull.assign(newUri, + methodParamNotNull.invokeVirtualMethod( + MethodDescriptor.ofMethod(java.net.URL.class, "toURI", java.net.URI.class), + methodParam)); + } else if (URI.equals(notBodyTargetType)) { + methodParamNotNull.assign(newUri, methodParam); + } else { + throw new IllegalArgumentException("Unsupported type '" + notBodyTargetType + "' used with '" + + NOT_BODY + "'. Offending method is '" + jandexMethod.declaringClass().name() + "#" + + jandexMethod.name()); + } + + ResultHandle newInputTarget = methodParamNotNull.invokeVirtualMethod( + MethodDescriptor.ofMethod(WebTargetImpl.class, "withNewUri", WebTargetImpl.class, + java.net.URI.class), + methodParamNotNull.readInstanceField(inputTargetField, methodParamNotNull.getThis()), + newUri); + ResultHandle newBaseTarget = methodParamNotNull.invokeVirtualMethod( + baseTargetProducer.getMethodDescriptor(), + methodParamNotNull.getThis(), newInputTarget); + methodParamNotNull.assign(methodTarget, methodParamNotNull.invokeVirtualMethod( + methodTargetProducer.getMethodDescriptor(), methodParamNotNull.getThis(), newBaseTarget)); + } + + // if there is, we need to assign the variable to new WebTarget created by using the + // base URL and then calling the method we will create in the TODO above if (!restClientInterface.isEncoded() && method.isEncoded()) { methodCreator.assign(methodTarget, disableEncodingForWebTarget(methodCreator, methodTarget)); } @@ -1766,13 +1860,13 @@ private void handleSubResourceMethod(List } } - private AssignableResultHandle createWebTargetForMethod(MethodCreator constructor, ResultHandle baseTarget, + private AssignableResultHandle createWebTargetForMethod(MethodCreator mc, ResultHandle baseTarget, ResourceMethod method) { - AssignableResultHandle target = constructor.createVariable(WebTarget.class); - constructor.assign(target, baseTarget); + AssignableResultHandle target = mc.createVariable(WebTarget.class); + mc.assign(target, baseTarget); if (method.getPath() != null) { - appendPath(constructor, method.getPath(), target); + appendPath(mc, method.getPath(), target); } return target; } diff --git a/extensions/resteasy-reactive/rest-client/deployment/src/test/java/io/quarkus/rest/client/reactive/url/UrlOnStringParameterTest.java b/extensions/resteasy-reactive/rest-client/deployment/src/test/java/io/quarkus/rest/client/reactive/url/UrlOnStringParameterTest.java new file mode 100644 index 0000000000000..7b2dc0b48ae2c --- /dev/null +++ b/extensions/resteasy-reactive/rest-client/deployment/src/test/java/io/quarkus/rest/client/reactive/url/UrlOnStringParameterTest.java @@ -0,0 +1,64 @@ +package io.quarkus.rest.client.reactive.url; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.net.UnknownHostException; + +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; + +import org.eclipse.microprofile.config.inject.ConfigProperty; +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; +import org.eclipse.microprofile.rest.client.inject.RestClient; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.rest.client.reactive.Url; +import io.quarkus.test.QuarkusUnitTest; + +public class UrlOnStringParameterTest { + + @RegisterExtension + static final QuarkusUnitTest TEST = new QuarkusUnitTest() + .withApplicationRoot( + jar -> jar.addClasses(Resource.class, Client.class)) + .overrideConfigKey("quarkus.rest-client.client.uri", "http://does-not-exist.io"); + + @RestClient + Client client; + + @ConfigProperty(name = "quarkus.http.test-port") + Integer testPort; + + @Test + public void testOverride() { + String result = client.test(String.format("http://localhost:%d", testPort)); + assertEquals("bar", result); + + } + + @Test + public void testNoOverride() { + assertThatThrownBy(() -> client.test(null)).cause().isInstanceOf(UnknownHostException.class); + } + + @Path("test") + @RegisterRestClient(configKey = "client") + public interface Client { + + @Path("count") + @GET + String test(@Url String uri); + } + + @Path("test") + public static class Resource { + + @GET + @Path("count") + public String test() { + return "bar"; + } + } +} diff --git a/extensions/resteasy-reactive/rest-client/deployment/src/test/java/io/quarkus/rest/client/reactive/url/UrlOnUriParameterTest.java b/extensions/resteasy-reactive/rest-client/deployment/src/test/java/io/quarkus/rest/client/reactive/url/UrlOnUriParameterTest.java new file mode 100644 index 0000000000000..4a1abf2c99f80 --- /dev/null +++ b/extensions/resteasy-reactive/rest-client/deployment/src/test/java/io/quarkus/rest/client/reactive/url/UrlOnUriParameterTest.java @@ -0,0 +1,67 @@ +package io.quarkus.rest.client.reactive.url; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.net.URI; +import java.net.UnknownHostException; + +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; + +import org.eclipse.microprofile.config.inject.ConfigProperty; +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; +import org.eclipse.microprofile.rest.client.inject.RestClient; +import org.jboss.resteasy.reactive.RestQuery; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.rest.client.reactive.NotBody; +import io.quarkus.rest.client.reactive.Url; +import io.quarkus.test.QuarkusUnitTest; + +public class UrlOnUriParameterTest { + + @RegisterExtension + static final QuarkusUnitTest TEST = new QuarkusUnitTest() + .withApplicationRoot( + jar -> jar.addClasses(Resource.class, Client.class)) + .overrideConfigKey("quarkus.rest-client.\"client\".url", "http://does-not-exist.io"); + + @RestClient + Client client; + + @ConfigProperty(name = "quarkus.http.test-port") + Integer testPort; + + @Test + public void testOverride() { + String result = client.test("test", URI.create(String.format("http://localhost:%d", testPort)), "bar"); + assertEquals("bar", result); + + } + + @Test + public void testNoOverride() { + assertThatThrownBy(() -> client.test("test", null, "bar")).cause().isInstanceOf(UnknownHostException.class); + } + + @Path("test") + @RegisterRestClient(configKey = "client") + public interface Client { + + @Path("count") + @GET + String test(@NotBody String unused, @Url URI uri, @RestQuery String foo); + } + + @Path("test") + public static class Resource { + + @GET + @Path("count") + public String test(@RestQuery String foo) { + return foo; + } + } +} diff --git a/extensions/resteasy-reactive/rest-client/deployment/src/test/java/io/quarkus/rest/client/reactive/url/UrlOnUrlParameterTest.java b/extensions/resteasy-reactive/rest-client/deployment/src/test/java/io/quarkus/rest/client/reactive/url/UrlOnUrlParameterTest.java new file mode 100644 index 0000000000000..e449e1486feb8 --- /dev/null +++ b/extensions/resteasy-reactive/rest-client/deployment/src/test/java/io/quarkus/rest/client/reactive/url/UrlOnUrlParameterTest.java @@ -0,0 +1,69 @@ +package io.quarkus.rest.client.reactive.url; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.net.MalformedURLException; +import java.net.URL; +import java.net.UnknownHostException; + +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; + +import org.eclipse.microprofile.config.inject.ConfigProperty; +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; +import org.eclipse.microprofile.rest.client.inject.RestClient; +import org.jboss.resteasy.reactive.RestHeader; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.rest.client.reactive.Url; +import io.quarkus.test.QuarkusUnitTest; + +public class UrlOnUrlParameterTest { + + @RegisterExtension + static final QuarkusUnitTest TEST = new QuarkusUnitTest() + .withApplicationRoot( + jar -> jar.addClasses(Resource.class, Client.class)) + .overrideConfigKey( + "quarkus.rest-client.\"io.quarkus.rest.client.reactive.url.UrlOnUrlParameterTest$Client\".uri", + "http://does-not-exist.io"); + + @RestClient + Client client; + + @ConfigProperty(name = "quarkus.http.test-port") + Integer testPort; + + @Test + public void testOverride() throws MalformedURLException { + String result = client.test(new URL(String.format("http://localhost:%d/", testPort)), "bar"); + assertEquals("bar", result); + + } + + @Test + public void testNoOverride() { + assertThatThrownBy(() -> client.test(null, "bar")).cause().isInstanceOf(UnknownHostException.class); + } + + @Path("test") + @RegisterRestClient(configKey = "client") + public interface Client { + + @Path("count") + @GET + String test(@Url URL uri, @RestHeader String foo); + } + + @Path("test") + public static class Resource { + + @GET + @Path("count") + public String test(@RestHeader String foo) { + return foo; + } + } +} diff --git a/extensions/resteasy-reactive/rest-client/runtime/src/main/java/io/quarkus/rest/client/reactive/Url.java b/extensions/resteasy-reactive/rest-client/runtime/src/main/java/io/quarkus/rest/client/reactive/Url.java new file mode 100644 index 0000000000000..ce093a5149f99 --- /dev/null +++ b/extensions/resteasy-reactive/rest-client/runtime/src/main/java/io/quarkus/rest/client/reactive/Url.java @@ -0,0 +1,23 @@ +package io.quarkus.rest.client.reactive; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Allows for a per invocation override the base URL. + * At most a one such annotation can be used per REST Client method and the supported types are: + * + *
    + * {@link String} + * {@link java.net.URI} + * {@link java.net.URL} + *
+ */ +@Target({ ElementType.PARAMETER }) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Url { +} diff --git a/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/WebTargetImpl.java b/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/WebTargetImpl.java index f120c4969728e..5ef736be1dd04 100644 --- a/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/WebTargetImpl.java +++ b/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/WebTargetImpl.java @@ -254,6 +254,11 @@ public WebTargetImpl queryParam(String name, Object... values) throws NullPointe return newInstance(client, copy, configuration); } + @SuppressWarnings("unused") // this is used in the REST Client to support @BaseUrl + public WebTargetImpl withNewUri(URI uri) { + return newInstance(client, UriBuilder.fromUri(uri), configuration); + } + @SuppressWarnings("unused") public WebTargetImpl queryParams(MultivaluedMap parameters) throws IllegalArgumentException, NullPointerException { diff --git a/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/ResteasyReactiveDotNames.java b/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/ResteasyReactiveDotNames.java index aa7b6b19c0fe9..15a4a10beed20 100644 --- a/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/ResteasyReactiveDotNames.java +++ b/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/ResteasyReactiveDotNames.java @@ -4,6 +4,7 @@ import java.io.OutputStream; import java.math.BigDecimal; import java.math.BigInteger; +import java.net.URI; import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; @@ -235,6 +236,8 @@ public final class ResteasyReactiveDotNames { public static final DotName INPUT_STREAM = DotName.createSimple(InputStream.class.getName()); public static final DotName OUTPUT_STREAM = DotName.createSimple(OutputStream.class.getName()); public static final DotName THROWABLE = DotName.createSimple(Throwable.class.getName()); + public static final DotName URI = DotName.createSimple(java.net.URI.class.getName()); + public static final DotName URL = DotName.createSimple(java.net.URL.class.getName()); public static final DotName JSONP_JSON_OBJECT = DotName.createSimple(jakarta.json.JsonObject.class.getName()); public static final DotName JSONP_JSON_ARRAY = DotName.createSimple(jakarta.json.JsonArray.class.getName());