diff --git a/ci/smoke-tests.yml b/ci/smoke-tests.yml index 8bd21c48..81324bdf 100644 --- a/ci/smoke-tests.yml +++ b/ci/smoke-tests.yml @@ -21,6 +21,7 @@ smoke_tests: - jdbc - logging-log4j2 - logging-logback + - rest-template - security-webflux - security-webmvc - scheduled diff --git a/rest-template/README.adoc b/rest-template/README.adoc new file mode 100644 index 00000000..6e084c64 --- /dev/null +++ b/rest-template/README.adoc @@ -0,0 +1 @@ +Tests if `RestTemplate` works diff --git a/rest-template/build.gradle b/rest-template/build.gradle new file mode 100644 index 00000000..4ccc25b8 --- /dev/null +++ b/rest-template/build.gradle @@ -0,0 +1,16 @@ +plugins { + id 'java' + id 'org.springframework.boot' + id 'org.springframework.aot.smoke-test' + id 'org.graalvm.buildtools.native' +} + +dependencies { + implementation(platform(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES)) + implementation("org.springframework.boot:spring-boot-starter-web") + + testImplementation("org.springframework.boot:spring-boot-starter-test") + + aotTestImplementation(project(":aot-smoke-test-support")) + aotTestImplementation("org.awaitility:awaitility:4.2.0") +} diff --git a/rest-template/src/aotTest/java/com/example/resttemplate/RestTemplateApplicationAotTests.java b/rest-template/src/aotTest/java/com/example/resttemplate/RestTemplateApplicationAotTests.java new file mode 100644 index 00000000..e011b36f --- /dev/null +++ b/rest-template/src/aotTest/java/com/example/resttemplate/RestTemplateApplicationAotTests.java @@ -0,0 +1,34 @@ +package com.example.resttemplate; + +import java.time.Duration; + +import org.awaitility.Awaitility; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable; + +import org.springframework.aot.smoketest.support.assertj.AssertableOutput; +import org.springframework.aot.smoketest.support.junit.AotSmokeTest; + +import static org.assertj.core.api.Assertions.assertThat; + +@AotSmokeTest +class RestTemplateApplicationAotTests { + + @Test + @DisabledIfEnvironmentVariable(named = "CI", matches = "true", disabledReason = "HTTP is blocked on CI") + void httpWorks(AssertableOutput output) { + Awaitility.await().atMost(Duration.ofSeconds(30)).untilAsserted(() -> { + assertThat(output) + .hasSingleLineContaining("http: DataDto{url='http://httpbin.org/anything', method='GET'}"); + }); + } + + @Test + void httpsWorks(AssertableOutput output) { + Awaitility.await().atMost(Duration.ofSeconds(30)).untilAsserted(() -> { + assertThat(output) + .hasSingleLineContaining("https: DataDto{url='https://httpbin.org/anything', method='GET'}"); + }); + } + +} diff --git a/rest-template/src/main/java/com/example/resttemplate/CLR.java b/rest-template/src/main/java/com/example/resttemplate/CLR.java new file mode 100644 index 00000000..750a8c48 --- /dev/null +++ b/rest-template/src/main/java/com/example/resttemplate/CLR.java @@ -0,0 +1,54 @@ +package com.example.resttemplate; + +import java.net.URI; +import java.time.Duration; + +import com.example.resttemplate.DataDto.DataDtoRuntimeHints; + +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.context.annotation.ImportRuntimeHints; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +@Component +@ImportRuntimeHints(DataDtoRuntimeHints.class) +class CLR implements CommandLineRunner { + + private final RestTemplateBuilder restTemplateBuilder; + + CLR(RestTemplateBuilder restTemplateBuilder) { + this.restTemplateBuilder = restTemplateBuilder; + } + + @Override + public void run(String... args) { + RestTemplate restTemplate = this.restTemplateBuilder.setConnectTimeout(Duration.ofSeconds(5)) + .setReadTimeout(Duration.ofSeconds(5)).build(); + http(restTemplate); + https(restTemplate); + } + + private void http(RestTemplate restTemplate) { + try { + DataDto dto = restTemplate.getForObject(URI.create("http://httpbin.org/anything"), DataDto.class); + System.out.printf("http: %s%n", dto); + } + catch (Exception ex) { + System.out.println("http failed:"); + ex.printStackTrace(System.out); + } + } + + private void https(RestTemplate restTemplate) { + try { + DataDto dto = restTemplate.getForObject(URI.create("https://httpbin.org/anything"), DataDto.class); + System.out.printf("https: %s%n", dto); + } + catch (Exception ex) { + System.out.println("https failed:"); + ex.printStackTrace(System.out); + } + } + +} diff --git a/rest-template/src/main/java/com/example/resttemplate/DataDto.java b/rest-template/src/main/java/com/example/resttemplate/DataDto.java new file mode 100644 index 00000000..4d7a1128 --- /dev/null +++ b/rest-template/src/main/java/com/example/resttemplate/DataDto.java @@ -0,0 +1,48 @@ +package com.example.resttemplate; + +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.RuntimeHintsRegistrar; +import org.springframework.context.aot.BindingReflectionHintsRegistrar; + +public class DataDto { + + private String url; + + private String method; + + public DataDto() { + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getMethod() { + return method; + } + + public void setMethod(String method) { + this.method = method; + } + + @Override + public String toString() { + return "DataDto{" + "url='" + url + '\'' + ", method='" + method + '\'' + '}'; + } + + static class DataDtoRuntimeHints implements RuntimeHintsRegistrar { + + private final BindingReflectionHintsRegistrar bindingReflectionHintsRegistrar = new BindingReflectionHintsRegistrar(); + + @Override + public void registerHints(RuntimeHints hints, ClassLoader classLoader) { + this.bindingReflectionHintsRegistrar.registerReflectionHints(hints.reflection(), DataDto.class); + } + + } + +} diff --git a/rest-template/src/main/java/com/example/resttemplate/RestTemplateApplication.java b/rest-template/src/main/java/com/example/resttemplate/RestTemplateApplication.java new file mode 100644 index 00000000..bb173dc1 --- /dev/null +++ b/rest-template/src/main/java/com/example/resttemplate/RestTemplateApplication.java @@ -0,0 +1,17 @@ +package com.example.resttemplate; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class RestTemplateApplication { + + public static void main(String[] args) throws InterruptedException { + SpringApplication application = new SpringApplication(RestTemplateApplication.class); + application.setWebApplicationType(WebApplicationType.NONE); + application.run(args); + Thread.currentThread().join(); // To be able to measure memory consumption + } + +} diff --git a/rest-template/src/test/java/com/example/resttemplate/RestTemplateApplicationTests.java b/rest-template/src/test/java/com/example/resttemplate/RestTemplateApplicationTests.java new file mode 100644 index 00000000..b2478f2e --- /dev/null +++ b/rest-template/src/test/java/com/example/resttemplate/RestTemplateApplicationTests.java @@ -0,0 +1,14 @@ +package com.example.resttemplate; + +import org.junit.jupiter.api.Test; + +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class RestTemplateApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/settings.gradle b/settings.gradle index 42ee405e..00891a84 100644 --- a/settings.gradle +++ b/settings.gradle @@ -49,6 +49,7 @@ include "hateoas" include "jdbc" include "logging-log4j2" include "logging-logback" +include "rest-template" include "scheduled" include "security-webflux" include "security-webmvc"