Skip to content

Commit

Permalink
Only contribute hints for matching methods
Browse files Browse the repository at this point in the history
Closes gh-33203
  • Loading branch information
snicoll committed Nov 15, 2022
1 parent 54a977c commit 2baac78
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 49 deletions.
Expand Up @@ -17,14 +17,13 @@
package org.springframework.boot.web.client;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.HttpURLConnection;
import java.util.function.Consumer;

import org.springframework.aot.hint.ExecutableMode;
import org.springframework.aot.hint.ReflectionHints;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.aot.hint.TypeHint;
import org.springframework.aot.hint.TypeReference;
import org.springframework.http.client.AbstractClientHttpRequestFactoryWrapper;
import org.springframework.http.client.ClientHttpRequestFactory;
Expand Down Expand Up @@ -52,35 +51,33 @@ public void registerHints(RuntimeHints hints, ClassLoader classLoader) {

private void registerHints(ReflectionHints hints, ClassLoader classLoader) {
hints.registerField(findField(AbstractClientHttpRequestFactoryWrapper.class, "requestFactory"));
if (ClassUtils.isPresent(ClientHttpRequestFactories.APACHE_HTTP_CLIENT_CLASS, classLoader)) {
registerReflectionHints(hints, HttpComponentsClientHttpRequestFactory.class, this::onReachableHttpClient);
}
if (ClassUtils.isPresent(ClientHttpRequestFactories.OKHTTP_CLIENT_CLASS, classLoader)) {
registerReflectionHints(hints, OkHttp3ClientHttpRequestFactory.class, this::onReachableOkHttpClient);
}
registerReflectionHints(hints, SimpleClientHttpRequestFactory.class, this::onReachableHttpUrlConnection);
}

private void onReachableHttpUrlConnection(TypeHint.Builder typeHint) {
typeHint.onReachableType(HttpURLConnection.class);
}

private void onReachableHttpClient(TypeHint.Builder typeHint) {
typeHint.onReachableType(TypeReference.of(ClientHttpRequestFactories.APACHE_HTTP_CLIENT_CLASS));
hints.registerTypeIfPresent(classLoader, ClientHttpRequestFactories.APACHE_HTTP_CLIENT_CLASS, (typeHint) -> {
typeHint.onReachableType(TypeReference.of(ClientHttpRequestFactories.APACHE_HTTP_CLIENT_CLASS));
registerReflectionHints(hints, HttpComponentsClientHttpRequestFactory.class);
});
hints.registerTypeIfPresent(classLoader, ClientHttpRequestFactories.OKHTTP_CLIENT_CLASS, (typeHint) -> {
typeHint.onReachableType(TypeReference.of(ClientHttpRequestFactories.OKHTTP_CLIENT_CLASS));
registerReflectionHints(hints, OkHttp3ClientHttpRequestFactory.class);
});
hints.registerType(SimpleClientHttpRequestFactory.class, (typeHint) -> {
typeHint.onReachableType(HttpURLConnection.class);
registerReflectionHints(hints, SimpleClientHttpRequestFactory.class);
});
}

private void onReachableOkHttpClient(TypeHint.Builder typeHint) {
typeHint.onReachableType(TypeReference.of(ClientHttpRequestFactories.OKHTTP_CLIENT_CLASS));
private void registerReflectionHints(ReflectionHints hints,
Class<? extends ClientHttpRequestFactory> requestFactoryType) {
registerMethod(hints, requestFactoryType, "setConnectTimeout", int.class);
registerMethod(hints, requestFactoryType, "setReadTimeout", int.class);
registerMethod(hints, requestFactoryType, "setBufferRequestBody", boolean.class);
}

private void registerReflectionHints(ReflectionHints hints,
Class<? extends ClientHttpRequestFactory> requestFactoryType, Consumer<TypeHint.Builder> hintCustomizer) {
hints.registerType(requestFactoryType, (typeHint) -> {
typeHint.withMethod("setConnectTimeout", TypeReference.listOf(int.class), ExecutableMode.INVOKE);
typeHint.withMethod("setReadTimeout", TypeReference.listOf(int.class), ExecutableMode.INVOKE);
typeHint.withMethod("setBufferRequestBody", TypeReference.listOf(boolean.class), ExecutableMode.INVOKE);
hintCustomizer.accept(typeHint);
});
private void registerMethod(ReflectionHints hints, Class<? extends ClientHttpRequestFactory> requestFactoryType,
String methodName, Class<?>... parameterTypes) {
Method method = ReflectionUtils.findMethod(requestFactoryType, methodName, parameterTypes);
if (method != null) {
hints.registerMethod(method, ExecutableMode.INVOKE);
}
}

private Field findField(Class<?> type, String name) {
Expand Down
Expand Up @@ -16,6 +16,9 @@

package org.springframework.boot.web.client;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

import org.junit.jupiter.api.Test;

import org.springframework.aot.hint.RuntimeHints;
Expand All @@ -33,6 +36,7 @@
* Tests for {@link ClientHttpRequestFactoriesRuntimeHints}.
*
* @author Andy Wilkinson
* @author Stephane Nicoll
*/
class ClientHttpRequestFactoriesRuntimeHintsTests {

Expand All @@ -41,51 +45,58 @@ void shouldRegisterHints() {
RuntimeHints hints = new RuntimeHints();
new ClientHttpRequestFactoriesRuntimeHints().registerHints(hints, getClass().getClassLoader());
ReflectionHintsPredicates reflection = RuntimeHintsPredicates.reflection();
assertThat(reflection
.onField(ReflectionUtils.findField(AbstractClientHttpRequestFactoryWrapper.class, "requestFactory")))
.accepts(hints);
Field requestFactoryField = ReflectionUtils.findField(AbstractClientHttpRequestFactoryWrapper.class,
"requestFactory");
assertThat(requestFactoryField).isNotNull();
assertThat(reflection.onField(requestFactoryField)).accepts(hints);
}

@Test
void shouldRegisterHttpComponentHints() {
RuntimeHints hints = new RuntimeHints();
new ClientHttpRequestFactoriesRuntimeHints().registerHints(hints, getClass().getClassLoader());
ReflectionHintsPredicates reflection = RuntimeHintsPredicates.reflection();
assertThat(reflection.onMethod(ReflectionUtils.findMethod(HttpComponentsClientHttpRequestFactory.class,
"setConnectTimeout", int.class))).accepts(hints);
assertThat(reflection.onMethod(
ReflectionUtils.findMethod(HttpComponentsClientHttpRequestFactory.class, "setReadTimeout", int.class)))
assertThat(reflection
.onMethod(method(HttpComponentsClientHttpRequestFactory.class, "setConnectTimeout", int.class)))
.accepts(hints);
assertThat(
reflection.onMethod(method(HttpComponentsClientHttpRequestFactory.class, "setReadTimeout", int.class)))
.accepts(hints);
assertThat(reflection
.onMethod(method(HttpComponentsClientHttpRequestFactory.class, "setBufferRequestBody", boolean.class)))
.accepts(hints);
assertThat(reflection.onMethod(ReflectionUtils.findMethod(HttpComponentsClientHttpRequestFactory.class,
"setBufferRequestBody", boolean.class))).accepts(hints);
}

@Test
void shouldRegisterOkHttpHints() {
RuntimeHints hints = new RuntimeHints();
new ClientHttpRequestFactoriesRuntimeHints().registerHints(hints, getClass().getClassLoader());
ReflectionHintsPredicates reflection = RuntimeHintsPredicates.reflection();
assertThat(reflection.onMethod(
ReflectionUtils.findMethod(OkHttp3ClientHttpRequestFactory.class, "setConnectTimeout", int.class)))
.accepts(hints);
assertThat(reflection.onMethod(
ReflectionUtils.findMethod(OkHttp3ClientHttpRequestFactory.class, "setReadTimeout", int.class)))
.accepts(hints);
assertThat(reflection.onMethod(method(OkHttp3ClientHttpRequestFactory.class, "setConnectTimeout", int.class)))
.accepts(hints);
assertThat(reflection.onMethod(method(OkHttp3ClientHttpRequestFactory.class, "setReadTimeout", int.class)))
.accepts(hints);
assertThat(hints.reflection().getTypeHint(OkHttp3ClientHttpRequestFactory.class).methods()).hasSize(2);
}

@Test
void shouldRegisterSimpleHttpHints() {
RuntimeHints hints = new RuntimeHints();
new ClientHttpRequestFactoriesRuntimeHints().registerHints(hints, getClass().getClassLoader());
ReflectionHintsPredicates reflection = RuntimeHintsPredicates.reflection();
assertThat(reflection.onMethod(
ReflectionUtils.findMethod(SimpleClientHttpRequestFactory.class, "setConnectTimeout", int.class)))
.accepts(hints);
assertThat(reflection.onMethod(
ReflectionUtils.findMethod(SimpleClientHttpRequestFactory.class, "setReadTimeout", int.class)))
assertThat(reflection.onMethod(method(SimpleClientHttpRequestFactory.class, "setConnectTimeout", int.class)))
.accepts(hints);
assertThat(reflection.onMethod(method(SimpleClientHttpRequestFactory.class, "setReadTimeout", int.class)))
.accepts(hints);
assertThat(reflection
.onMethod(method(SimpleClientHttpRequestFactory.class, "setBufferRequestBody", boolean.class)))
.accepts(hints);
assertThat(reflection.onMethod(ReflectionUtils.findMethod(SimpleClientHttpRequestFactory.class,
"setBufferRequestBody", boolean.class))).accepts(hints);
}

private static Method method(Class<?> target, String name, Class<?>... parameterTypes) {
Method method = ReflectionUtils.findMethod(target, name, parameterTypes);
assertThat(method).isNotNull();
return method;
}

}

0 comments on commit 2baac78

Please sign in to comment.