diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 01c7c39..b962ff1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,9 +29,9 @@ jobs: - name: Run build steps and generate coverage report with Maven run: | mvn verify javadoc:javadoc jacoco:report -Pcoverage -B -V -# - name: Upload coverage report to Codecov -# uses: codecov/codecov-action@v1 -# with: -# file: ./**/target/site/jacoco/jacoco.xml -# name: codecov -# fail_ci_if_error: true + - name: Upload coverage report to Codecov + uses: codecov/codecov-action@v5 + with: + file: ./**/target/site/jacoco/jacoco.xml + name: codecov + fail_ci_if_error: true diff --git a/pom.xml b/pom.xml index 45fbb39..d399b29 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 gooddata-rest-common - 3.0.0-SNAPSHOT + 3.0.1-SNAPSHOT ${project.artifactId} GoodData REST Common Library https://github.com/gooddata/gooddata-rest-common @@ -74,7 +74,7 @@ org.jacoco jacoco-maven-plugin - 0.8.11 + 0.7.0 jacoco-prepare-agent diff --git a/src/main/java/com/gooddata/sdk/common/UriPrefixingClientHttpRequestFactory.java b/src/main/java/com/gooddata/sdk/common/UriPrefixingClientHttpRequestFactory.java new file mode 100644 index 0000000..fccf6a2 --- /dev/null +++ b/src/main/java/com/gooddata/sdk/common/UriPrefixingClientHttpRequestFactory.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2004-2017, GoodData(R) Corporation. All rights reserved. + * This source code is licensed under the BSD-style license found in the + * LICENSE.txt file in the root directory of this source tree. + */ +package com.gooddata.sdk.common; + +import org.springframework.http.HttpMethod; +import org.springframework.http.client.ClientHttpRequest; +import org.springframework.http.client.ClientHttpRequestFactory; +import org.springframework.web.util.UriComponentsBuilder; + +import java.io.IOException; +import java.net.URI; + +import static com.gooddata.sdk.common.util.Validate.notNull; + + +// AsyncClientHttpRequestFactory and createAsyncRequest was removed in Spring 5.0/6.0 +// so this class is no longer used in the SDK. It is kept here for backward compatibility + +/** + * now for calling use RestTemplate with UriPrefixingClientHttpRequestFactory + * + * import org.springframework.web.client.RestTemplate; + import java.util.concurrent.CompletableFuture; + import java.util.concurrent.ExecutorService; + import java.util.concurrent.Executors; + + public class AsyncRestTemplateExample { + + private final RestTemplate restTemplate; + private final ExecutorService executor = Executors.newFixedThreadPool(8); + + public AsyncRestTemplateExample(RestTemplate restTemplate) { + this.restTemplate = restTemplate; + } + + public CompletableFuture getAsync(String url) { + return CompletableFuture.supplyAsync(() -> + restTemplate.getForObject(url, String.class), executor); + } + } + + + and used: + + // Create a RestTemplate with a URI prefixing factory + RestTemplate restTemplate = new RestTemplate( + new UriPrefixingClientHttpRequestFactory( + * e.g., HttpComponentsClientHttpRequestFactory *, + "https://my-api.example.com" + ) + ); + + // Create an instance of the asynchronous RestTemplate wrapper + AsyncRestTemplateExample asyncExample = new AsyncRestTemplateExample(restTemplate); + + // Perform an asynchronous GET request and print the response when ready + asyncExample.getAsync("/my/resource") + .thenAccept(response -> System.out.println("Response: " + response)); + + * + * + * + */ + + + +public class UriPrefixingClientHttpRequestFactory implements ClientHttpRequestFactory { + + private final ClientHttpRequestFactory wrapped; + private final UriPrefixer prefixer; + + public UriPrefixingClientHttpRequestFactory(final ClientHttpRequestFactory factory, final URI uriPrefix) { + this(factory, new UriPrefixer(uriPrefix)); + } + + public UriPrefixingClientHttpRequestFactory(final ClientHttpRequestFactory factory, final String uri) { + this(factory, URI.create(uri)); + } + + public UriPrefixingClientHttpRequestFactory(final ClientHttpRequestFactory factory, + final String protocol, + final String hostname, + final int port) { + this(factory, UriComponentsBuilder.newInstance().scheme(protocol).host(hostname).port(port).build().toUri()); + } + + private UriPrefixingClientHttpRequestFactory(final ClientHttpRequestFactory factory, final UriPrefixer prefixer) { + this.wrapped = notNull(factory, "factory"); + this.prefixer = notNull(prefixer, "prefixer"); + } + + @Override + public ClientHttpRequest createRequest(final URI uri, final HttpMethod httpMethod) throws IOException { + final URI merged = prefixer.mergeUris(uri); + return wrapped.createRequest(merged, httpMethod); + } +} diff --git a/src/main/java/com/gooddata/sdk/common/UriPrefixingWebClient.java b/src/main/java/com/gooddata/sdk/common/UriPrefixingWebClient.java deleted file mode 100644 index 0e0461b..0000000 --- a/src/main/java/com/gooddata/sdk/common/UriPrefixingWebClient.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2004-2017, GoodData(R) Corporation. All rights reserved. - * This source code is licensed under the BSD-style license found in the - * LICENSE.txt file in the root directory of this source tree. - */ -package com.gooddata.sdk.common; - -import org.springframework.http.HttpMethod; -import org.springframework.web.reactive.function.client.WebClient; -import org.springframework.web.util.UriComponentsBuilder; - -import java.net.URI; - -import static com.gooddata.sdk.common.util.Validate.notNull; - -/** - * Factory for creating HTTP requests using WebClient. - * The factory allows you to specify hostname and port for Spring REST client which by default requires absolute URI. - */ -public class UriPrefixingWebClient { - - private final WebClient webClient; - private final UriPrefixer prefixer; - - /** - * Create an instance that uses the given {@link WebClient.Builder} - * and URI prefix for all HTTP requests. - * - * @param webClientBuilder the WebClient builder - * @param uriPrefix the URI for setting hostname and port of all HTTP requests - */ - public UriPrefixingWebClient(final WebClient.Builder webClientBuilder, final URI uriPrefix) { - this(webClientBuilder, new UriPrefixer(uriPrefix)); - } - - /** - * Create an instance that uses the given {@link WebClient.Builder} - * and URI prefix for all HTTP requests. - * - * @param webClientBuilder the WebClient builder - * @param uri the URI for setting hostname and port of all HTTP requests - */ - public UriPrefixingWebClient(final WebClient.Builder webClientBuilder, final String uri) { - this(webClientBuilder, URI.create(uri)); - } - - private UriPrefixingWebClient(final WebClient.Builder webClientBuilder, final UriPrefixer prefixer) { - this.webClient = notNull(webClientBuilder, "webClientBuilder").build(); - this.prefixer = notNull(prefixer, "prefixer"); - } - - /** - * Create a request with the given path and HTTP method. - * - * @param path the path for the HTTP request - * @param httpMethod the HTTP method (e.g., GET, POST) - * @return the WebClient.RequestHeadersSpec to customize and execute the request - */ - public WebClient.RequestHeadersSpec createRequest(final String path, final HttpMethod httpMethod) { - final URI prefixedUri = prefixer.prefixUri(URI.create(path)); - return webClient.method(httpMethod).uri(prefixedUri); - } -} diff --git a/src/test/groovy/com/gooddata/sdk/common/UriPrefixingWebClientTest.groovy b/src/test/groovy/com/gooddata/sdk/common/UriPrefixingWebClientTest.groovy index cfc5e03..baa9736 100644 --- a/src/test/groovy/com/gooddata/sdk/common/UriPrefixingWebClientTest.groovy +++ b/src/test/groovy/com/gooddata/sdk/common/UriPrefixingWebClientTest.groovy @@ -6,45 +6,26 @@ package com.gooddata.sdk.common import org.springframework.http.HttpMethod -import org.springframework.web.reactive.function.client.WebClient +import org.springframework.http.client.SimpleClientHttpRequestFactory import spock.lang.Shared import spock.lang.Specification -class UriPrefixingWebClientTest extends Specification { +class UriPrefixingClientHttpRequestFactoryTest extends Specification { @Shared - def webClientBuilder = WebClient.builder() + def WRAPPED = new SimpleClientHttpRequestFactory() def "should create prefixed request"() { - given: - def prefixer = new UriPrefixer('http://localhost:1234') - def requestFactory = new UriPrefixingWebClient(webClientBuilder, prefixer) - when: - def uri = prefixer.prefixUri(URI.create('/gdc/resource')) + def request = requestFactory.createRequest(URI.create('/gdc/resource'), HttpMethod.GET) then: - uri.toString() == 'http://localhost:1234/gdc/resource' - } - - def "should handle invalid URI gracefully"() { - given: - def prefixer = new UriPrefixer('http://localhost:1234') - def requestFactory = new UriPrefixingWebClient(webClientBuilder, prefixer) + request.URI.toString() == 'http://localhost:1234/gdc/resource' - when: - requestFactory.createRequest('/invalid uri', HttpMethod.GET) - - then: - thrown(IllegalArgumentException) - } - - def "should handle multiple constructors of UriPrefixer"() { - when: - def prefixer1 = new UriPrefixer('http://localhost:1234') - def prefixer2 = new UriPrefixer(URI.create('http://localhost:1234')) - - then: - prefixer1.getUriPrefix() == prefixer2.getUriPrefix() + where: + requestFactory << [ + new UriPrefixingClientHttpRequestFactory(WRAPPED, 'http', 'localhost', 1234), + new UriPrefixingClientHttpRequestFactory(WRAPPED, 'http://localhost:1234') + ] } }