diff --git a/admin-client/build.gradle.kts b/admin-client/build.gradle.kts index 03fc970fb..99613f8b8 100644 --- a/admin-client/build.gradle.kts +++ b/admin-client/build.gradle.kts @@ -43,6 +43,14 @@ tasks.withType { configOptions.put("openApiNullable", "false") + // This whole client is deprecated in favour of dev.restate.client.Client. We deprecate every + // generated type: + // * The custom generatedAnnotation.mustache template (see openapi-templates) adds @Deprecated to + // all the api/model/invoker classes, right after the @Generated annotation. + // * additionalEnumTypeAnnotations covers the standalone enums, which don't carry @Generated. + templateDir.set("$projectDir/openapi-templates") + configOptions.put("additionalEnumTypeAnnotations", "@Deprecated") + finalizedBy("spotlessJava") } diff --git a/admin-client/openapi-templates/generatedAnnotation.mustache b/admin-client/openapi-templates/generatedAnnotation.mustache new file mode 100644 index 000000000..9fdab2520 --- /dev/null +++ b/admin-client/openapi-templates/generatedAnnotation.mustache @@ -0,0 +1,2 @@ +@{{javaxPackage}}.annotation.Generated(value = "{{generatorClass}}"{{^hideGenerationTimestamp}}, date = "{{generatedDate}}"{{/hideGenerationTimestamp}}, comments = "Generator version: {{generatorVersion}}") +@Deprecated diff --git a/sdk-testing/src/main/java/dev/restate/sdk/testing/RestateAdminClient.java b/sdk-testing/src/main/java/dev/restate/sdk/testing/RestateAdminClient.java index 6bf7b404e..1317685b3 100644 --- a/sdk-testing/src/main/java/dev/restate/sdk/testing/RestateAdminClient.java +++ b/sdk-testing/src/main/java/dev/restate/sdk/testing/RestateAdminClient.java @@ -16,7 +16,11 @@ /** * Inject the Restate {@link dev.restate.admin.client.ApiClient}, useful to build admin clients, * such as {@link dev.restate.admin.api.DeploymentApi}. + * + * @deprecated The code-generated admin client (the {@code dev.restate.admin} package) is + * deprecated. Use {@link RestateAdminURL} instead to inject the admin URL. */ +@Deprecated @Target(value = ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) public @interface RestateAdminClient {} diff --git a/sdk-testing/src/main/java/dev/restate/sdk/testing/RestateAdminURL.java b/sdk-testing/src/main/java/dev/restate/sdk/testing/RestateAdminURL.java new file mode 100644 index 000000000..95e9e2822 --- /dev/null +++ b/sdk-testing/src/main/java/dev/restate/sdk/testing/RestateAdminURL.java @@ -0,0 +1,24 @@ +// Copyright (c) 2023 - Restate Software, Inc., Restate GmbH +// +// This file is part of the Restate Java SDK, +// which is released under the MIT license. +// +// You can find a copy of the license in file LICENSE in the root +// directory of this repository or package, or at +// https://github.com/restatedev/sdk-java/blob/main/LICENSE +package dev.restate.sdk.testing; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.net.URI; +import java.net.URL; + +/** + * Inject Restate's admin URL (either {@link String} or {@link URL} or {@link URI}) to interact with + * the admin API of the deployed server. + */ +@Target(value = ElementType.PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +public @interface RestateAdminURL {} diff --git a/sdk-testing/src/main/java/dev/restate/sdk/testing/RestateExtension.java b/sdk-testing/src/main/java/dev/restate/sdk/testing/RestateExtension.java index ef1b333cf..928e886ad 100644 --- a/sdk-testing/src/main/java/dev/restate/sdk/testing/RestateExtension.java +++ b/sdk-testing/src/main/java/dev/restate/sdk/testing/RestateExtension.java @@ -33,6 +33,8 @@ public void beforeAll(ExtensionContext extensionContext) { } @Override + @SuppressWarnings( + "deprecation") // RestateAdminClient/ApiClient are deprecated but still supported public boolean supportsParameter( ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { @@ -42,11 +44,14 @@ public boolean supportsParameter( || (parameterContext.isAnnotated(RestateClient.class) && Client.class.isAssignableFrom(parameterContext.getParameter().getType())) || (parameterContext.isAnnotated(RestateURL.class) - && (String.class.isAssignableFrom(parameterContext.getParameter().getType()) - || URL.class.isAssignableFrom(parameterContext.getParameter().getType()))); + && isStringOrUrlOrUri(parameterContext.getParameter().getType())) + || (parameterContext.isAnnotated(RestateAdminURL.class) + && isStringOrUrlOrUri(parameterContext.getParameter().getType())); } @Override + @SuppressWarnings( + "deprecation") // RestateAdminClient/ApiClient are deprecated but still supported public Object resolveParameter( ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { @@ -57,22 +62,33 @@ public Object resolveParameter( URL url = runner.getIngressUrl(); return Client.connect(url.toString()); } else if (parameterContext.isAnnotated(RestateURL.class)) { - URL url = runner.getIngressUrl(); - if (parameterContext.getParameter().getType().equals(String.class)) { - return url.toString(); - } - if (parameterContext.getParameter().getType().equals(URI.class)) { - try { - return url.toURI(); - } catch (URISyntaxException e) { - throw new RuntimeException(e); - } - } - return url; + return convertUrl(parameterContext.getParameter().getType(), runner.getIngressUrl()); + } else if (parameterContext.isAnnotated(RestateAdminURL.class)) { + return convertUrl(parameterContext.getParameter().getType(), runner.getAdminUrl()); } throw new ParameterResolutionException("The parameter is not supported"); } + private static boolean isStringOrUrlOrUri(Class type) { + return String.class.isAssignableFrom(type) + || URL.class.isAssignableFrom(type) + || URI.class.isAssignableFrom(type); + } + + private static Object convertUrl(Class type, URL url) { + if (type.equals(String.class)) { + return url.toString(); + } + if (type.equals(URI.class)) { + try { + return url.toURI(); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + } + return url; + } + private RestateRunner getOrCreateRunner(ExtensionContext extensionContext) { return extensionContext .getStore(NAMESPACE) diff --git a/sdk-testing/src/main/java/dev/restate/sdk/testing/RestateRunner.java b/sdk-testing/src/main/java/dev/restate/sdk/testing/RestateRunner.java index 2a27dfdb6..583c1bdc7 100644 --- a/sdk-testing/src/main/java/dev/restate/sdk/testing/RestateRunner.java +++ b/sdk-testing/src/main/java/dev/restate/sdk/testing/RestateRunner.java @@ -143,6 +143,8 @@ public RestateRunner build() { } /** Run restate, run the embedded service endpoint server, and register the services. */ + @SuppressWarnings( + "deprecation") // Internally still uses the deprecated code-generated admin client public void start() { // Start listening the local server try { @@ -234,6 +236,7 @@ public void close() { // -- Methods used by the JUnit5 extension + @SuppressWarnings("deprecation") // Returns the deprecated code-generated admin client ApiClient getAdminClient() { return new ApiClient() .setHost(runtimeContainer.getHost()) diff --git a/sdk-testing/src/main/java/dev/restate/sdk/testing/RestateTest.java b/sdk-testing/src/main/java/dev/restate/sdk/testing/RestateTest.java index 667cf6335..1a8a8aee8 100644 --- a/sdk-testing/src/main/java/dev/restate/sdk/testing/RestateTest.java +++ b/sdk-testing/src/main/java/dev/restate/sdk/testing/RestateTest.java @@ -45,8 +45,8 @@ * test methods. Because of this behaviour, the extension sets the {@link TestInstance} as {@link * TestInstance.Lifecycle#PER_CLASS} automatically. * - *

Use the annotations {@link RestateClient}, {@link RestateURL} and {@link RestateAdminClient} - * to interact with the deployed environment: + *

Use the annotations {@link RestateClient}, {@link RestateURL} and {@link RestateAdminURL} to + * interact with the deployed environment: * *

  * {@code @Test}
diff --git a/sdk-testing/src/test/java/dev/restate/sdk/testing/CounterTest.java b/sdk-testing/src/test/java/dev/restate/sdk/testing/CounterTest.java
index 6b3510ae5..600f5dabd 100644
--- a/sdk-testing/src/test/java/dev/restate/sdk/testing/CounterTest.java
+++ b/sdk-testing/src/test/java/dev/restate/sdk/testing/CounterTest.java
@@ -11,6 +11,11 @@
 import static org.assertj.core.api.Assertions.assertThat;
 
 import dev.restate.client.Client;
+import java.net.URI;
+import java.net.URL;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.Timeout;
 
@@ -27,4 +32,15 @@ void testGreet(@RestateClient Client ingressClient) {
     long response = client.get();
     assertThat(response).isEqualTo(0L);
   }
+
+  @Test
+  @Timeout(value = 10)
+  void adminUrlIsInjected(@RestateAdminURL URL adminUrl) throws Exception {
+    HttpResponse response =
+        HttpClient.newHttpClient()
+            .send(
+                HttpRequest.newBuilder(URI.create(adminUrl.toString()).resolve("/health")).build(),
+                HttpResponse.BodyHandlers.discarding());
+    assertThat(response.statusCode()).isEqualTo(200);
+  }
 }