diff --git a/docs/src/main/asciidoc/rest-client-reactive.adoc b/docs/src/main/asciidoc/rest-client-reactive.adoc index a2500c776bb16..f71ffae2a80e5 100644 --- a/docs/src/main/asciidoc/rest-client-reactive.adoc +++ b/docs/src/main/asciidoc/rest-client-reactive.adoc @@ -328,78 +328,6 @@ public class ExtensionsResource { } ---- -== Use Custom HTTP Options - -The REST Client Reactive internally uses https://vertx.io/docs/apidocs/io/vertx/core/http/HttpClient.html[the Vert.x HTTP Client] to make the network connections. The REST Client Reactive extensions allows configuring some settings via properties, for example: - -- `quarkus.rest-client.client-prefix.connect-timeout` to configure the connect timeout in milliseconds. -- `quarkus.rest-client.client-prefix.max-redirects` to limit the number of redirects. - -However, there are many more options within the Vert.x HTTP Client to configure the connections. See all the options in the Vert.x HTTP Client Options API in https://vertx.io/docs/apidocs/io/vertx/core/http/HttpClientOptions.html[this link]. - -To fully customize the Vert.x HTTP Client instance that the REST Client Reactive is internally using, you can provide your custom HTTP Client Options instance via CDI or when programmatically creating your client. - -Let's see an example about how to provide the HTTP Client Options via CDI: - -[source,java] ----- -package org.acme.rest.client; - -import javax.enterprise.inject.Produces; - -import io.vertx.core.http.HttpClientOptions; -import io.quarkus.arc.Unremovable; - -public static class Configuration { - @Produces - @Unremovable - public HttpClientOptions customHttpClientOptions() { - HttpClientOptions options = new HttpClientOptions(); - // ... - return options; - } -} ----- - -Now, all the REST Clients will be using your custom HTTP Client Options. - -Another approach is to provide the custom HTTP Client options when creating the client programmatically: - -[source,java] ----- -package org.acme.rest.client; - -import org.eclipse.microprofile.rest.client.RestClientBuilder; - -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import java.net.URI; -import java.util.Set; - -import io.vertx.core.http.HttpClientOptions; - -@Path("/extension") -public class ExtensionsResource { - - private final ExtensionsService extensionsService; - - public ExtensionsResource() { - HttpClientOptions httpOptions = new HttpClientOptions(); - // configure the options - // ... - - extensionsService = RestClientBuilder.newBuilder() - .baseUri(URI.create("https://stage.code.quarkus.io/api")) - .register(httpOptions) <1> - .build(ExtensionsService.class); - } - - // ... -} ----- - -<1> the client will use the registered HTTP Client options over the HTTP Client options provided via CDI if any. - == Update the test Next, we need to update the functional test to reflect the changes made to the endpoint. diff --git a/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/CustomHttpOptionsViaInjectedRestClientTest.java b/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/CustomHttpOptionsViaInjectedRestClientTest.java deleted file mode 100644 index 6aefb1d517704..0000000000000 --- a/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/CustomHttpOptionsViaInjectedRestClientTest.java +++ /dev/null @@ -1,88 +0,0 @@ -package io.quarkus.rest.client.reactive; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -import java.net.URI; - -import javax.enterprise.context.ApplicationScoped; -import javax.enterprise.inject.Produces; -import javax.ws.rs.GET; -import javax.ws.rs.Path; - -import org.eclipse.microprofile.rest.client.RestClientBuilder; -import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; -import org.eclipse.microprofile.rest.client.inject.RestClient; -import org.jboss.resteasy.reactive.RestResponse; -import org.jboss.shrinkwrap.api.asset.StringAsset; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.arc.Unremovable; -import io.quarkus.test.QuarkusUnitTest; -import io.quarkus.test.common.http.TestHTTPResource; -import io.vertx.core.http.HttpClientOptions; - -public class CustomHttpOptionsViaInjectedRestClientTest { - - private static final String EXPECTED_VALUE = "success"; - - @TestHTTPResource - URI baseUri; - - @RestClient - Client client; - - @RegisterExtension - static final QuarkusUnitTest app = new QuarkusUnitTest() - .withApplicationRoot((jar) -> jar.addClasses(Client.class) - .addAsResource(new StringAsset( - "custom-http-options/mp-rest/url=http://localhost:${quarkus.http.test-port:8081}"), - "application.properties")); - - @Test - void shouldUseCustomHttpOptions() { - assertThatThrownBy(() -> client.get()).hasMessageContaining("HTTP header is larger than 1 bytes."); - } - - @Test - void shouldProgrammaticallyCreatedUseTheCustomHttpOptions() { - Client programmaticClient = RestClientBuilder.newBuilder().baseUri(baseUri).build(Client.class); - assertThatThrownBy(() -> programmaticClient.get()).hasMessageContaining("HTTP header is larger than 1 bytes."); - } - - @Test - void shouldCustomHttpOptionsFromRegisterHavePriorityOverCDI() { - Client programmaticClient = RestClientBuilder.newBuilder().baseUri(baseUri) - .register(new HttpClientOptions()) // reset HTTP Header size limit - .build(Client.class); - assertThat(programmaticClient.get()).isEqualTo(EXPECTED_VALUE); - } - - @Path("/") - @ApplicationScoped - public static class Resource { - @GET - public RestResponse get() { - return RestResponse.ResponseBuilder.ok(EXPECTED_VALUE) - .header("long-header", "VERY LONNGGGGGGGGGGGGGGGGGGGGGGGGGGGG!") - .build(); - } - } - - public static class ProvidesCustomHttpClientOptions { - @Produces - @Unremovable - public HttpClientOptions httpClientOptions() { - HttpClientOptions options = new HttpClientOptions(); - options.setMaxHeaderSize(1); // this is just to verify that this HttpClientOptions is indeed used. - return options; - } - } - - @RegisterRestClient(configKey = "custom-http-options") - public interface Client { - @GET - String get(); - } -} diff --git a/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/CustomHttpOptionsViaProgrammaticallyClientCreatedTest.java b/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/CustomHttpOptionsViaProgrammaticallyClientCreatedTest.java deleted file mode 100644 index 9ca8d9d74d84c..0000000000000 --- a/extensions/resteasy-reactive/rest-client-reactive/deployment/src/test/java/io/quarkus/rest/client/reactive/CustomHttpOptionsViaProgrammaticallyClientCreatedTest.java +++ /dev/null @@ -1,62 +0,0 @@ -package io.quarkus.rest.client.reactive; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -import java.net.URI; - -import javax.enterprise.context.ApplicationScoped; -import javax.ws.rs.GET; -import javax.ws.rs.Path; - -import org.eclipse.microprofile.rest.client.RestClientBuilder; -import org.jboss.resteasy.reactive.RestResponse; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.test.QuarkusUnitTest; -import io.quarkus.test.common.http.TestHTTPResource; -import io.vertx.core.http.HttpClientOptions; - -public class CustomHttpOptionsViaProgrammaticallyClientCreatedTest { - - private static final String EXPECTED_VALUE = "success"; - - @TestHTTPResource - URI baseUri; - - @RegisterExtension - static final QuarkusUnitTest app = new QuarkusUnitTest() - .withApplicationRoot((jar) -> jar.addClasses(Client.class)); - - @Test - void shouldUseCustomHttpOptions() { - // First verify the standard configuration - assertThat(RestClientBuilder.newBuilder().baseUri(baseUri).build(Client.class).get()) - .isEqualTo(EXPECTED_VALUE); - - // Now, it should fail if we use a custom http client options with a very limited max header size: - HttpClientOptions options = new HttpClientOptions(); - options.setMaxHeaderSize(1); // this is just to verify that this HttpClientOptions is indeed used. - Client client = RestClientBuilder.newBuilder().baseUri(baseUri) - .register(options) - .build(Client.class); - assertThatThrownBy(() -> client.get()).hasMessageContaining("HTTP header is larger than 1 bytes."); - } - - @Path("/") - @ApplicationScoped - public static class Resource { - @GET - public RestResponse get() { - return RestResponse.ResponseBuilder.ok(EXPECTED_VALUE) - .header("long-header", "VERY LONNGGGGGGGGGGGGGGGGGGGGGGGGGGGG!") - .build(); - } - } - - public interface Client { - @GET - String get(); - } -} diff --git a/extensions/resteasy-reactive/rest-client-reactive/runtime/src/main/java/io/quarkus/rest/client/reactive/runtime/RestClientBuilderImpl.java b/extensions/resteasy-reactive/rest-client-reactive/runtime/src/main/java/io/quarkus/rest/client/reactive/runtime/RestClientBuilderImpl.java index 6386417eba953..12c830977b9c8 100644 --- a/extensions/resteasy-reactive/rest-client-reactive/runtime/src/main/java/io/quarkus/rest/client/reactive/runtime/RestClientBuilderImpl.java +++ b/extensions/resteasy-reactive/rest-client-reactive/runtime/src/main/java/io/quarkus/rest/client/reactive/runtime/RestClientBuilderImpl.java @@ -37,7 +37,6 @@ import io.quarkus.rest.client.reactive.runtime.ProxyAddressUtil.HostAndPort; import io.quarkus.restclient.config.RestClientLoggingConfig; import io.quarkus.restclient.config.RestClientsConfig; -import io.vertx.core.http.HttpClientOptions; /** * Builder implementation for MicroProfile Rest Client @@ -289,13 +288,6 @@ public T build(Class aClass) throws IllegalStateException, RestClientDefi register(mapper.getKey(), mapper.getValue()); } - if (!getConfiguration().isRegistered(HttpClientOptions.class)) { - InstanceHandle httpClientOptions = Arc.container().instance(HttpClientOptions.class); - if (httpClientOptions.isAvailable()) { - clientBuilder.register(httpClientOptions.get()); - } - } - Object defaultMapperDisabled = getConfiguration().getProperty(DEFAULT_MAPPER_DISABLED); Boolean globallyDisabledMapper = ConfigProvider.getConfig() .getOptionalValue(DEFAULT_MAPPER_DISABLED, Boolean.class).orElse(false); diff --git a/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/api/QuarkusRestClientProperties.java b/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/api/QuarkusRestClientProperties.java index cdd7524a5913a..a009850bddefb 100644 --- a/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/api/QuarkusRestClientProperties.java +++ b/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/api/QuarkusRestClientProperties.java @@ -10,14 +10,6 @@ public class QuarkusRestClientProperties { * maximum number of redirects for a client call. Works only if the client has `followingRedirects enabled */ public static final String MAX_REDIRECTS = "io.quarkus.rest.client.max-redirects"; - /** - * maximum length of all headers for HTTP/1.x. - */ - public static final String MAX_HEADER_SIZE = "io.quarkus.rest.client.max-header-size"; - /** - * maximum length of the initial line for HTTP/1.x. - */ - public static final String MAX_INITIAL_LINE_LENGTH = "io.quarkus.rest.client.max-initial-line-length"; public static final String READ_TIMEOUT = "io.quarkus.rest.client.read-timeout"; diff --git a/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/ClientBuilderImpl.java b/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/ClientBuilderImpl.java index 8fbab9d8ffe5c..b56f7b52b0df9 100644 --- a/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/ClientBuilderImpl.java +++ b/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/ClientBuilderImpl.java @@ -14,7 +14,6 @@ import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.util.Map; -import java.util.Optional; import java.util.concurrent.ExecutorService; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -60,6 +59,7 @@ public class ClientBuilderImpl extends ClientBuilder { private Integer loggingBodySize = 100; private MultiQueryParamMode multiQueryParamMode; + private HttpClientOptions httpClientOptions = new HttpClientOptions(); private ClientLogger clientLogger = new DefaultClientLogger(); private String userAgent = "Resteasy Reactive Client"; @@ -136,6 +136,11 @@ public ClientBuilder proxyUser(String proxyUser) { return this; } + public ClientBuilder httpClientOptions(HttpClientOptions httpClientOptions) { + this.httpClientOptions = httpClientOptions; + return this; + } + public ClientBuilder followRedirects(boolean followRedirects) { this.followRedirects = followRedirects; return this; @@ -166,8 +171,7 @@ public ClientImpl build() { Buffer keyStore = asBuffer(this.keyStore, keystorePassword); Buffer trustStore = asBuffer(this.trustStore, EMPTY_CHAR_ARARAY); - HttpClientOptions options = Optional.ofNullable(configuration.getInstance(HttpClientOptions.class)) - .orElseGet(HttpClientOptions::new); + HttpClientOptions options = httpClientOptions == null ? new HttpClientOptions() : httpClientOptions; if (trustAll) { options.setTrustAll(true); @@ -239,7 +243,7 @@ public ClientImpl build() { clientLogger.setBodySize(loggingBodySize); - return new ClientImpl(options, + return new ClientImpl(httpClientOptions, configuration, CLIENT_CONTEXT_RESOLVER.resolve(Thread.currentThread().getContextClassLoader()), hostnameVerifier, diff --git a/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/ClientImpl.java b/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/ClientImpl.java index fd6d022224fc7..6169ef6cc5cd5 100644 --- a/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/ClientImpl.java +++ b/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/ClientImpl.java @@ -3,8 +3,6 @@ import static org.jboss.resteasy.reactive.client.api.QuarkusRestClientProperties.CONNECTION_POOL_SIZE; import static org.jboss.resteasy.reactive.client.api.QuarkusRestClientProperties.CONNECTION_TTL; import static org.jboss.resteasy.reactive.client.api.QuarkusRestClientProperties.CONNECT_TIMEOUT; -import static org.jboss.resteasy.reactive.client.api.QuarkusRestClientProperties.MAX_HEADER_SIZE; -import static org.jboss.resteasy.reactive.client.api.QuarkusRestClientProperties.MAX_INITIAL_LINE_LENGTH; import static org.jboss.resteasy.reactive.client.api.QuarkusRestClientProperties.MAX_REDIRECTS; import static org.jboss.resteasy.reactive.client.api.QuarkusRestClientProperties.NAME; import static org.jboss.resteasy.reactive.client.api.QuarkusRestClientProperties.SHARED; @@ -98,6 +96,8 @@ public ClientImpl(HttpClientOptions options, ConfigurationImpl configuration, Cl ClientLogger clientLogger, String userAgent) { this.userAgent = userAgent; configuration = configuration != null ? configuration : new ConfigurationImpl(RuntimeType.CLIENT); + // TODO: ssl context + // TODO: hostnameVerifier this.configuration = configuration; this.clientContext = clientContext; this.hostnameVerifier = hostnameVerifier; @@ -128,16 +128,6 @@ public Vertx get() { options.setMaxRedirects((Integer) maxRedirects); } - Object maxHeaderSize = configuration.getProperty(MAX_HEADER_SIZE); - if (maxHeaderSize != null) { - options.setMaxHeaderSize((Integer) maxHeaderSize); - } - - Object maxInitialLineLength = configuration.getProperty(MAX_INITIAL_LINE_LENGTH); - if (maxInitialLineLength != null) { - options.setMaxInitialLineLength((Integer) maxInitialLineLength); - } - Object connectionTTL = configuration.getProperty(CONNECTION_TTL); if (connectionTTL != null) { options.setKeepAliveTimeout((int) connectionTTL); diff --git a/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/jaxrs/ConfigurationImpl.java b/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/jaxrs/ConfigurationImpl.java index 92e9d5cc1d53b..ea85e3b2d0615 100644 --- a/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/jaxrs/ConfigurationImpl.java +++ b/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/jaxrs/ConfigurationImpl.java @@ -175,15 +175,6 @@ public Set getInstances() { return new HashSet<>(allInstances.values()); } - public T getInstance(Class componentClass) { - Object object = allInstances.get(componentClass); - if (object == null) { - return null; - } - - return (T) object; - } - public void addEnabledFeature(Feature feature) { enabledFeatures.add(feature); } @@ -225,6 +216,103 @@ public void register(Object component) { register(component, (Integer) null); } + private void register(Object component, Integer priority) { + if (allInstances.containsKey(component.getClass())) { + return; + } + boolean added = false; + List> contractableClasses = new ArrayList<>(); + if (component instanceof Feature) { + contractableClasses.add(Feature.class); + + Feature thisFeature = (Feature) component; + added = true; + if (thisFeature.configure(new ConfigFeatureContext())) { + enabledFeatures.add(thisFeature); + } + } + if (component instanceof ClientRequestFilter) { + contractableClasses.add(ClientRequestFilter.class); + + added = true; + int effectivePriority = priority != null ? priority : determinePriority(component); + requestFilters.add(effectivePriority, (ClientRequestFilter) component); + } + if (component instanceof ClientResponseFilter) { + contractableClasses.add(ClientRequestFilter.class); + + added = true; + int effectivePriority = priority != null ? priority : determinePriority(component); + responseFilters.add(effectivePriority, (ClientResponseFilter) component); + } + if (component instanceof WriterInterceptor) { + contractableClasses.add(WriterInterceptor.class); + + added = true; + int effectivePriority = priority != null ? priority : determinePriority(component); + writerInterceptors.add(effectivePriority, (WriterInterceptor) component); + } + if (component instanceof ReaderInterceptor) { + contractableClasses.add(ReaderInterceptor.class); + + added = true; + int effectivePriority = priority != null ? priority : determinePriority(component); + readerInterceptors.add(effectivePriority, (ReaderInterceptor) component); + } + if (component instanceof MessageBodyReader) { + contractableClasses.add(MessageBodyReader.class); + + added = true; + Class componentClass = component.getClass(); + ConstrainedTo constrainedTo = componentClass.getAnnotation(ConstrainedTo.class); + if ((constrainedTo == null) || (constrainedTo.value() == runtimeType)) { + ResourceReader resourceReader = new ResourceReader(); + resourceReader.setFactory(new UnmanagedBeanFactory(component)); + Consumes consumes = componentClass.getAnnotation(Consumes.class); + resourceReader + .setMediaTypeStrings( + consumes != null ? Arrays.asList(consumes.value()) : WILDCARD_STRING_LIST); + Type[] args = Types.findParameterizedTypes(componentClass, MessageBodyReader.class); + resourceReaders.add(args != null && args.length == 1 ? Types.getRawType(args[0]) : Object.class, + resourceReader); + } + } + if (component instanceof MessageBodyWriter) { + contractableClasses.add(MessageBodyWriter.class); + + added = true; + Class componentClass = component.getClass(); + ConstrainedTo constrainedTo = componentClass.getAnnotation(ConstrainedTo.class); + if ((constrainedTo == null) || (constrainedTo.value() == runtimeType)) { + ResourceWriter resourceWriter = new ResourceWriter(); + resourceWriter.setFactory(new UnmanagedBeanFactory(component)); + Produces produces = componentClass.getAnnotation(Produces.class); + resourceWriter + .setMediaTypeStrings( + produces != null ? Arrays.asList(produces.value()) : WILDCARD_STRING_LIST); + Type[] args = Types.findParameterizedTypes(componentClass, MessageBodyWriter.class); + resourceWriters.add(args != null && args.length == 1 ? Types.getRawType(args[0]) : Object.class, + resourceWriter); + } + } + if (component instanceof RxInvokerProvider) { + added = true; + Class componentClass = component.getClass(); + Type[] args = Types.findParameterizedTypes(componentClass, RxInvokerProvider.class); + rxInvokerProviders.add(args != null && args.length == 1 ? Types.getRawType(args[0]) : Object.class, + (RxInvokerProvider) component); + } + if (added) { + allInstances.put(component.getClass(), component); + + Map, Integer> contracts = new HashMap<>(); + for (Class contractableClass : contractableClasses) { + contracts.put(contractableClass, priority); + } + this.contracts.put(component.getClass(), contracts); + } + } + public void register(Object component, Class[] contracts) { if (contracts == null || contracts.length == 0) { return; @@ -244,10 +332,6 @@ public void register(Class componentClass, Map, Integer> contracts) } } - public void register(Object component, int priority) { - register(component, Integer.valueOf(priority)); - } - public void register(Object component, Map, Integer> componentContracts) { if (componentContracts == null || componentContracts.isEmpty()) { return; @@ -256,32 +340,38 @@ public void register(Object component, Map, Integer> componentContracts if (allInstances.containsKey(componentClass)) { return; } - + boolean added = false; Integer priority = componentContracts.get(Feature.class); if (component instanceof Feature && priority != null) { Feature thisFeature = (Feature) component; + added = true; if (thisFeature.configure(new ConfigFeatureContext())) { enabledFeatures.add(priority, (Feature) component); } } priority = componentContracts.get(ClientRequestFilter.class); if (component instanceof ClientRequestFilter && priority != null) { + added = true; requestFilters.add(priority, (ClientRequestFilter) component); } priority = componentContracts.get(ClientResponseFilter.class); if (component instanceof ClientResponseFilter && priority != null) { + added = true; responseFilters.add(priority, (ClientResponseFilter) component); } priority = componentContracts.get(WriterInterceptor.class); if (component instanceof WriterInterceptor && priority != null) { + added = true; writerInterceptors.add(priority, (WriterInterceptor) component); } priority = componentContracts.get(ReaderInterceptor.class); if (component instanceof ReaderInterceptor && priority != null) { + added = true; readerInterceptors.add(priority, (ReaderInterceptor) component); } priority = componentContracts.get(MessageBodyReader.class); if (component instanceof MessageBodyReader && priority != null) { + added = true; ConstrainedTo constrainedTo = componentClass.getAnnotation(ConstrainedTo.class); if ((constrainedTo == null) || (constrainedTo.value() == runtimeType)) { ResourceReader resourceReader = new ResourceReader(); @@ -297,6 +387,7 @@ public void register(Object component, Map, Integer> componentContracts } priority = componentContracts.get(MessageBodyWriter.class); if (component instanceof MessageBodyWriter && priority != null) { + added = true; ConstrainedTo constrainedTo = componentClass.getAnnotation(ConstrainedTo.class); if ((constrainedTo == null) || (constrainedTo.value() == runtimeType)) { ResourceWriter resourceWriter = new ResourceWriter(); @@ -310,95 +401,15 @@ public void register(Object component, Map, Integer> componentContracts resourceWriter); } } - allInstances.put(componentClass, component); - contracts.put(componentClass, componentContracts); - } - - private void register(Object component, Integer priority) { - if (allInstances.containsKey(component.getClass())) { - return; - } - List> contractableClasses = new ArrayList<>(); - if (component instanceof Feature) { - contractableClasses.add(Feature.class); - - Feature thisFeature = (Feature) component; - if (thisFeature.configure(new ConfigFeatureContext())) { - enabledFeatures.add(thisFeature); - } - } - if (component instanceof ClientRequestFilter) { - contractableClasses.add(ClientRequestFilter.class); - - int effectivePriority = priority != null ? priority : determinePriority(component); - requestFilters.add(effectivePriority, (ClientRequestFilter) component); - } - if (component instanceof ClientResponseFilter) { - contractableClasses.add(ClientRequestFilter.class); - - int effectivePriority = priority != null ? priority : determinePriority(component); - responseFilters.add(effectivePriority, (ClientResponseFilter) component); - } - if (component instanceof WriterInterceptor) { - contractableClasses.add(WriterInterceptor.class); - - int effectivePriority = priority != null ? priority : determinePriority(component); - writerInterceptors.add(effectivePriority, (WriterInterceptor) component); + if (added) { + allInstances.put(componentClass, component); + contracts.put(componentClass, componentContracts); } - if (component instanceof ReaderInterceptor) { - contractableClasses.add(ReaderInterceptor.class); - int effectivePriority = priority != null ? priority : determinePriority(component); - readerInterceptors.add(effectivePriority, (ReaderInterceptor) component); - } - if (component instanceof MessageBodyReader) { - contractableClasses.add(MessageBodyReader.class); - - Class componentClass = component.getClass(); - ConstrainedTo constrainedTo = componentClass.getAnnotation(ConstrainedTo.class); - if ((constrainedTo == null) || (constrainedTo.value() == runtimeType)) { - ResourceReader resourceReader = new ResourceReader(); - resourceReader.setFactory(new UnmanagedBeanFactory(component)); - Consumes consumes = componentClass.getAnnotation(Consumes.class); - resourceReader - .setMediaTypeStrings( - consumes != null ? Arrays.asList(consumes.value()) : WILDCARD_STRING_LIST); - Type[] args = Types.findParameterizedTypes(componentClass, MessageBodyReader.class); - resourceReaders.add(args != null && args.length == 1 ? Types.getRawType(args[0]) : Object.class, - resourceReader); - } - } - if (component instanceof MessageBodyWriter) { - contractableClasses.add(MessageBodyWriter.class); - - Class componentClass = component.getClass(); - ConstrainedTo constrainedTo = componentClass.getAnnotation(ConstrainedTo.class); - if ((constrainedTo == null) || (constrainedTo.value() == runtimeType)) { - ResourceWriter resourceWriter = new ResourceWriter(); - resourceWriter.setFactory(new UnmanagedBeanFactory(component)); - Produces produces = componentClass.getAnnotation(Produces.class); - resourceWriter - .setMediaTypeStrings( - produces != null ? Arrays.asList(produces.value()) : WILDCARD_STRING_LIST); - Type[] args = Types.findParameterizedTypes(componentClass, MessageBodyWriter.class); - resourceWriters.add(args != null && args.length == 1 ? Types.getRawType(args[0]) : Object.class, - resourceWriter); - } - } - if (component instanceof RxInvokerProvider) { - Class componentClass = component.getClass(); - Type[] args = Types.findParameterizedTypes(componentClass, RxInvokerProvider.class); - rxInvokerProviders.add(args != null && args.length == 1 ? Types.getRawType(args[0]) : Object.class, - (RxInvokerProvider) component); - } - - allInstances.put(component.getClass(), component); + } - Map, Integer> contracts = new HashMap<>(); - for (Class contractableClass : contractableClasses) { - contracts.put(contractableClass, priority); - } - this.contracts.put(component.getClass(), contracts); + public void register(Object component, int priority) { + register(component, Integer.valueOf(priority)); } public List getRequestFilters() {