From e2dc278cae7490bbcf18cb76e839a2e727ff124c Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Tue, 14 May 2019 20:00:53 -0700 Subject: [PATCH] Use default SslContextFactory for JettyClient Update the auto-configured Jetty `HttpClient` so that a default `SslContextFactory` is used. Prior to this commit connecting to https URLs would cause a `NullPointerException`. Fixed gh-16810 --- .../ClientHttpConnectorConfiguration.java | 13 +++- ...ClientHttpConnectorConfigurationTests.java | 69 +++++++++++++++++++ 2 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/function/client/ClientHttpConnectorConfigurationTests.java diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/function/client/ClientHttpConnectorConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/function/client/ClientHttpConnectorConfiguration.java index 794c0e3415..71faa3857e 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/function/client/ClientHttpConnectorConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/function/client/ClientHttpConnectorConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2018 the original author or authors. + * Copyright 2012-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,9 @@ package org.springframework.boot.autoconfigure.web.reactive.function.client; import java.util.function.Function; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.util.ssl.SslContextFactory; + import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; @@ -73,8 +76,12 @@ class ClientHttpConnectorConfiguration { @Bean public JettyClientHttpConnector jettyClientHttpConnector( JettyResourceFactory jettyResourceFactory) { - return new JettyClientHttpConnector(jettyResourceFactory, (httpClient) -> { - }); + SslContextFactory sslContextFactory = new SslContextFactory.Client(); + HttpClient httpClient = new HttpClient(sslContextFactory); + httpClient.setExecutor(jettyResourceFactory.getExecutor()); + httpClient.setByteBufferPool(jettyResourceFactory.getByteBufferPool()); + httpClient.setScheduler(jettyResourceFactory.getScheduler()); + return new JettyClientHttpConnector(httpClient); } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/function/client/ClientHttpConnectorConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/function/client/ClientHttpConnectorConfigurationTests.java new file mode 100644 index 0000000000..a5cd87f844 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/function/client/ClientHttpConnectorConfigurationTests.java @@ -0,0 +1,69 @@ +/* + * Copyright 2012-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.autoconfigure.web.reactive.function.client; + +import java.util.concurrent.Executor; + +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.io.ByteBufferPool; +import org.eclipse.jetty.util.thread.Scheduler; +import org.junit.Test; + +import org.springframework.http.client.reactive.JettyClientHttpConnector; +import org.springframework.http.client.reactive.JettyResourceFactory; +import org.springframework.test.util.ReflectionTestUtils; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; + +/** + * Tests for {@link ClientHttpConnectorConfiguration}. + * + * @author Phillip Webb + */ +public class ClientHttpConnectorConfigurationTests { + + @Test + public void jettyClientHttpConnectorAppliesJettyResourceFactory() { + Executor executor = mock(Executor.class); + ByteBufferPool byteBufferPool = mock(ByteBufferPool.class); + Scheduler scheduler = mock(Scheduler.class); + JettyResourceFactory jettyResourceFactory = new JettyResourceFactory(); + jettyResourceFactory.setExecutor(executor); + jettyResourceFactory.setByteBufferPool(byteBufferPool); + jettyResourceFactory.setScheduler(scheduler); + JettyClientHttpConnector connector = new ClientHttpConnectorConfiguration.JettyClient() + .jettyClientHttpConnector(jettyResourceFactory); + HttpClient httpClient = (HttpClient) ReflectionTestUtils.getField(connector, + "httpClient"); + assertThat(httpClient.getExecutor()).isSameAs(executor); + assertThat(httpClient.getByteBufferPool()).isSameAs(byteBufferPool); + assertThat(httpClient.getScheduler()).isSameAs(scheduler); + } + + @Test + public void JettyResourceFactoryHasSslContextFactory() { + // gh-16810 + JettyResourceFactory jettyResourceFactory = new JettyResourceFactory(); + JettyClientHttpConnector connector = new ClientHttpConnectorConfiguration.JettyClient() + .jettyClientHttpConnector(jettyResourceFactory); + HttpClient httpClient = (HttpClient) ReflectionTestUtils.getField(connector, + "httpClient"); + assertThat(httpClient.getSslContextFactory()).isNotNull(); + } + +}