diff --git a/bom/application/pom.xml b/bom/application/pom.xml
index 4e5bc32b759c5..cb7d4f28cf7b5 100644
--- a/bom/application/pom.xml
+++ b/bom/application/pom.xml
@@ -69,7 +69,7 @@
3.0.0
3.5.0
4.7.0
- 2.2.0
+ 2.3.0
2.1.2
2.1.1
4.0.1
diff --git a/extensions/smallrye-stork/runtime/src/main/java/io/quarkus/stork/ServiceConfiguration.java b/extensions/smallrye-stork/runtime/src/main/java/io/quarkus/stork/ServiceConfiguration.java
index a5d170359a1a4..7ef7b23f3f9ef 100644
--- a/extensions/smallrye-stork/runtime/src/main/java/io/quarkus/stork/ServiceConfiguration.java
+++ b/extensions/smallrye-stork/runtime/src/main/java/io/quarkus/stork/ServiceConfiguration.java
@@ -1,19 +1,23 @@
package io.quarkus.stork;
+import java.util.Optional;
+
import io.quarkus.runtime.annotations.ConfigGroup;
-import io.quarkus.runtime.annotations.ConfigItem;
@ConfigGroup
-public class ServiceConfiguration {
+public interface ServiceConfiguration {
/**
* ServiceDiscovery configuration for the service
*/
- @ConfigItem
- public StorkServiceDiscoveryConfiguration serviceDiscovery;
+ StorkServiceDiscoveryConfiguration serviceDiscovery();
/**
* LoadBalancer configuration for the service
*/
- @ConfigItem
- public StorkLoadBalancerConfiguration loadBalancer;
+ StorkLoadBalancerConfiguration loadBalancer();
+
+ /**
+ * ServiceRegistrar configuration for the service
+ */
+ Optional serviceRegistrar();
}
diff --git a/extensions/smallrye-stork/runtime/src/main/java/io/quarkus/stork/StorkConfigUtil.java b/extensions/smallrye-stork/runtime/src/main/java/io/quarkus/stork/StorkConfigUtil.java
index d6f12a67cae29..17671e5a88d51 100644
--- a/extensions/smallrye-stork/runtime/src/main/java/io/quarkus/stork/StorkConfigUtil.java
+++ b/extensions/smallrye-stork/runtime/src/main/java/io/quarkus/stork/StorkConfigUtil.java
@@ -11,17 +11,23 @@ public class StorkConfigUtil {
public static List toStorkServiceConfig(StorkConfiguration storkConfiguration) {
List storkServicesConfigs = new ArrayList<>();
- Set servicesConfigs = storkConfiguration.serviceConfiguration.keySet();
+ Set servicesConfigs = storkConfiguration.serviceConfiguration().keySet();
SimpleServiceConfig.Builder builder = new SimpleServiceConfig.Builder();
for (String serviceName : servicesConfigs) {
builder.setServiceName(serviceName);
- ServiceConfiguration serviceConfiguration = storkConfiguration.serviceConfiguration.get(serviceName);
+ ServiceConfiguration serviceConfiguration = storkConfiguration.serviceConfiguration().get(serviceName);
SimpleServiceConfig.SimpleServiceDiscoveryConfig storkServiceDiscoveryConfig = new SimpleServiceConfig.SimpleServiceDiscoveryConfig(
- serviceConfiguration.serviceDiscovery.type, serviceConfiguration.serviceDiscovery.params);
+ serviceConfiguration.serviceDiscovery().type(), serviceConfiguration.serviceDiscovery().params());
builder = builder.setServiceDiscovery(storkServiceDiscoveryConfig);
SimpleServiceConfig.SimpleLoadBalancerConfig loadBalancerConfig = new SimpleServiceConfig.SimpleLoadBalancerConfig(
- serviceConfiguration.loadBalancer.type, serviceConfiguration.loadBalancer.parameters);
+ serviceConfiguration.loadBalancer().type(), serviceConfiguration.loadBalancer().parameters());
builder.setLoadBalancer(loadBalancerConfig);
+ if (serviceConfiguration.serviceRegistrar().isPresent()) {
+ SimpleServiceConfig.SimpleServiceRegistrarConfig serviceRegistrarConfig = new SimpleServiceConfig.SimpleServiceRegistrarConfig(
+ serviceConfiguration.serviceRegistrar().get().type(),
+ serviceConfiguration.serviceRegistrar().get().parameters());
+ builder.setServiceRegistrar(serviceRegistrarConfig);
+ }
storkServicesConfigs.add(builder.build());
}
return storkServicesConfigs;
diff --git a/extensions/smallrye-stork/runtime/src/main/java/io/quarkus/stork/StorkConfiguration.java b/extensions/smallrye-stork/runtime/src/main/java/io/quarkus/stork/StorkConfiguration.java
index 9a4b2cca0cfd2..cd70cd8c584ab 100644
--- a/extensions/smallrye-stork/runtime/src/main/java/io/quarkus/stork/StorkConfiguration.java
+++ b/extensions/smallrye-stork/runtime/src/main/java/io/quarkus/stork/StorkConfiguration.java
@@ -4,22 +4,24 @@
import io.quarkus.runtime.annotations.ConfigDocMapKey;
import io.quarkus.runtime.annotations.ConfigDocSection;
-import io.quarkus.runtime.annotations.ConfigItem;
import io.quarkus.runtime.annotations.ConfigPhase;
import io.quarkus.runtime.annotations.ConfigRoot;
+import io.smallrye.config.ConfigMapping;
+import io.smallrye.config.WithParentName;
/**
* Stork configuration root.
*/
+@ConfigMapping(prefix = "quarkus.stork")
@ConfigRoot(phase = ConfigPhase.RUN_TIME)
-public class StorkConfiguration {
+public interface StorkConfiguration {
/**
- * ServiceDiscovery configuration for the service
+ * Configuration for the service
*/
- @ConfigItem(name = ConfigItem.PARENT)
+ @WithParentName
@ConfigDocSection
@ConfigDocMapKey("service-name")
- public Map serviceConfiguration;
+ Map serviceConfiguration();
}
diff --git a/extensions/smallrye-stork/runtime/src/main/java/io/quarkus/stork/StorkLoadBalancerConfiguration.java b/extensions/smallrye-stork/runtime/src/main/java/io/quarkus/stork/StorkLoadBalancerConfiguration.java
index 5b51b7f105ba3..3faeee1decab9 100644
--- a/extensions/smallrye-stork/runtime/src/main/java/io/quarkus/stork/StorkLoadBalancerConfiguration.java
+++ b/extensions/smallrye-stork/runtime/src/main/java/io/quarkus/stork/StorkLoadBalancerConfiguration.java
@@ -3,25 +3,26 @@
import java.util.Map;
import io.quarkus.runtime.annotations.ConfigGroup;
-import io.quarkus.runtime.annotations.ConfigItem;
+import io.smallrye.config.WithDefault;
+import io.smallrye.config.WithParentName;
@ConfigGroup
-public class StorkLoadBalancerConfiguration {
+public interface StorkLoadBalancerConfiguration {
/**
* Configures load balancer type, e.g. "round-robin".
* A LoadBalancerProvider for the type has to be available
*
*/
- @ConfigItem(defaultValue = "round-robin")
- public String type;
+ @WithDefault(value = "round-robin")
+ String type();
/**
* Load Balancer parameters.
* Check the documentation of the selected load balancer type for available parameters
*
*/
- @ConfigItem(name = ConfigItem.PARENT)
- public Map parameters;
+ @WithParentName
+ Map parameters();
}
diff --git a/extensions/smallrye-stork/runtime/src/main/java/io/quarkus/stork/StorkServiceDiscoveryConfiguration.java b/extensions/smallrye-stork/runtime/src/main/java/io/quarkus/stork/StorkServiceDiscoveryConfiguration.java
index f415c961b3ae7..342e5992b0a86 100644
--- a/extensions/smallrye-stork/runtime/src/main/java/io/quarkus/stork/StorkServiceDiscoveryConfiguration.java
+++ b/extensions/smallrye-stork/runtime/src/main/java/io/quarkus/stork/StorkServiceDiscoveryConfiguration.java
@@ -3,25 +3,24 @@
import java.util.Map;
import io.quarkus.runtime.annotations.ConfigGroup;
-import io.quarkus.runtime.annotations.ConfigItem;
+import io.smallrye.config.WithParentName;
@ConfigGroup
-public class StorkServiceDiscoveryConfiguration {
+public interface StorkServiceDiscoveryConfiguration {
/**
* Configures the service discovery type, e.g. "consul".
* ServiceDiscoveryProvider for the type has to be available
*
*/
- @ConfigItem
- public String type;
+ String type();
/**
* ServiceDiscovery parameters.
* Check the documentation of the selected service discovery type for available parameters.
*
*/
- @ConfigItem(name = ConfigItem.PARENT)
- public Map params;
+ @WithParentName
+ Map params();
}
diff --git a/extensions/smallrye-stork/runtime/src/main/java/io/quarkus/stork/StorkServiceRegistrarConfiguration.java b/extensions/smallrye-stork/runtime/src/main/java/io/quarkus/stork/StorkServiceRegistrarConfiguration.java
new file mode 100644
index 0000000000000..cae160b047c2f
--- /dev/null
+++ b/extensions/smallrye-stork/runtime/src/main/java/io/quarkus/stork/StorkServiceRegistrarConfiguration.java
@@ -0,0 +1,27 @@
+package io.quarkus.stork;
+
+import java.util.Map;
+
+import io.quarkus.runtime.annotations.ConfigGroup;
+import io.smallrye.config.WithParentName;
+
+@ConfigGroup
+public interface StorkServiceRegistrarConfiguration {
+
+ /**
+ * Configures service registrar type, e.g. "consul".
+ * A ServiceRegistrarProvider for the type has to be available
+ *
+ */
+ String type();
+
+ /**
+ * Service Registrar parameters.
+ * Check the documentation of the selected registrar type for available parameters
+ *
+ */
+ // @ConfigItem(name = ConfigItem.PARENT)
+ @WithParentName
+ Map parameters();
+
+}
diff --git a/independent-projects/resteasy-reactive/pom.xml b/independent-projects/resteasy-reactive/pom.xml
index d2e4485db085f..71b6ea7cc2856 100644
--- a/independent-projects/resteasy-reactive/pom.xml
+++ b/independent-projects/resteasy-reactive/pom.xml
@@ -68,7 +68,7 @@
5.3.0
1.0.0.Final
2.15.2
- 2.1.0
+ 2.3.0
3.0.2
3.0.3
3.0.0
diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml
index 7495c1b2a01cc..7f2e5546f937f 100644
--- a/integration-tests/pom.xml
+++ b/integration-tests/pom.xml
@@ -308,6 +308,7 @@
smallrye-graphql
smallrye-graphql-client
smallrye-opentracing
+ smallrye-stork-registration
jpa-without-entity
quartz
redis-client
diff --git a/integration-tests/smallrye-stork-registration/pom.xml b/integration-tests/smallrye-stork-registration/pom.xml
new file mode 100644
index 0000000000000..10cbca86a070f
--- /dev/null
+++ b/integration-tests/smallrye-stork-registration/pom.xml
@@ -0,0 +1,141 @@
+
+
+
+ quarkus-integration-tests-parent
+ io.quarkus
+ 999-SNAPSHOT
+
+ 4.0.0
+ quarkus-integration-test-smallrye-stork-registration
+ Quarkus - Integration Tests - Smallrye Stork Registration
+
+
+
+
+ io.quarkus
+ quarkus-vertx-http
+
+
+
+ io.quarkus
+ quarkus-rest-client-reactive-jackson
+
+
+ io.quarkus
+ quarkus-resteasy-reactive-jackson
+
+
+ io.smallrye.stork
+ stork-service-discovery-static-list
+
+
+
+ io.quarkus
+ quarkus-junit5
+ test
+
+
+ org.assertj
+ assertj-core
+
+
+ io.rest-assured
+ rest-assured
+ test
+
+
+ org.awaitility
+ awaitility
+ test
+
+
+
+
+ io.quarkus
+ quarkus-resteasy-reactive-jackson-deployment
+ ${project.version}
+ pom
+ test
+
+
+ *
+ *
+
+
+
+
+ io.quarkus
+ quarkus-rest-client-reactive-jackson-deployment
+ ${project.version}
+ pom
+ test
+
+
+ *
+ *
+
+
+
+
+ io.quarkus
+ quarkus-vertx-http-deployment
+ ${project.version}
+ pom
+ test
+
+
+ *
+ *
+
+
+
+
+
+
+
+
+ src/main/resources
+ true
+
+
+
+
+ io.quarkus
+ quarkus-maven-plugin
+
+
+
+ build
+
+
+
+
+
+
+
+
+
+ native-image
+
+
+ native
+
+
+
+ native
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+
+
+
+
+
+
diff --git a/integration-tests/smallrye-stork-registration/src/main/java/org/acme/ClientCallingResource.java b/integration-tests/smallrye-stork-registration/src/main/java/org/acme/ClientCallingResource.java
new file mode 100644
index 0000000000000..46110519ad351
--- /dev/null
+++ b/integration-tests/smallrye-stork-registration/src/main/java/org/acme/ClientCallingResource.java
@@ -0,0 +1,25 @@
+package org.acme;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
+
+import org.eclipse.microprofile.rest.client.inject.RestClient;
+
+/**
+ * A frontend API using our REST Client (which uses Stork to locate and select the service instance on each call).
+ */
+@Path("/api")
+public class ClientCallingResource {
+
+ @RestClient
+ MyServiceClient service;
+
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ public String invoke() {
+ return service.get();
+ }
+
+}
diff --git a/integration-tests/smallrye-stork-registration/src/main/java/org/acme/MyServiceClient.java b/integration-tests/smallrye-stork-registration/src/main/java/org/acme/MyServiceClient.java
new file mode 100644
index 0000000000000..aeba6019125d3
--- /dev/null
+++ b/integration-tests/smallrye-stork-registration/src/main/java/org/acme/MyServiceClient.java
@@ -0,0 +1,22 @@
+package org.acme;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
+
+import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
+
+/**
+ * The REST Client interface.
+ *
+ * Notice the `baseUri`. It uses `stork://` as URL scheme indicating that the called service uses Stork to locate and
+ * select the service instance. The `my-service` part is the service name. This is used to configure Stork discovery
+ * and selection in the `application.properties` file.
+ */
+@RegisterRestClient(baseUri = "stork://my-service")
+public interface MyServiceClient {
+
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ String get();
+}
diff --git a/integration-tests/smallrye-stork-registration/src/main/java/org/acme/services/BlueService.java b/integration-tests/smallrye-stork-registration/src/main/java/org/acme/services/BlueService.java
new file mode 100644
index 0000000000000..f209e90dfd910
--- /dev/null
+++ b/integration-tests/smallrye-stork-registration/src/main/java/org/acme/services/BlueService.java
@@ -0,0 +1,27 @@
+package org.acme.services;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.enterprise.event.Observes;
+
+import org.eclipse.microprofile.config.inject.ConfigProperty;
+
+import io.quarkus.runtime.StartupEvent;
+import io.vertx.mutiny.core.Vertx;
+
+@ApplicationScoped
+public class BlueService {
+
+ @ConfigProperty(name = "blue-service-port", defaultValue = "9000")
+ int port;
+
+ /**
+ * Start an HTTP server for the blue service.
+ *
+ * Note: this method is called on a worker thread, and so it is allowed to block.
+ */
+ public void init(@Observes StartupEvent ev, Vertx vertx) {
+ vertx.createHttpServer()
+ .requestHandler(req -> req.response().endAndForget("Hello from Blue!"))
+ .listenAndAwait(port);
+ }
+}
diff --git a/integration-tests/smallrye-stork-registration/src/main/java/org/acme/services/RedService.java b/integration-tests/smallrye-stork-registration/src/main/java/org/acme/services/RedService.java
new file mode 100644
index 0000000000000..475ca81eaf3a0
--- /dev/null
+++ b/integration-tests/smallrye-stork-registration/src/main/java/org/acme/services/RedService.java
@@ -0,0 +1,28 @@
+
+package org.acme.services;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.enterprise.event.Observes;
+
+import org.eclipse.microprofile.config.inject.ConfigProperty;
+
+import io.quarkus.runtime.StartupEvent;
+import io.vertx.mutiny.core.Vertx;
+
+@ApplicationScoped
+public class RedService {
+ @ConfigProperty(name = "red-service-port", defaultValue = "9001")
+ int port;
+
+ /**
+ * Start an HTTP server for the red service.
+ *
+ * Note: this method is called on a worker thread, and so it is allowed to block.
+ */
+ public void init(@Observes StartupEvent ev, Vertx vertx) {
+ vertx.createHttpServer()
+ .requestHandler(req -> req.response().endAndForget("Hello from Red!"))
+ .listenAndAwait(port);
+ }
+
+}
diff --git a/integration-tests/smallrye-stork-registration/src/main/java/org/acme/services/Registration.java b/integration-tests/smallrye-stork-registration/src/main/java/org/acme/services/Registration.java
new file mode 100644
index 0000000000000..a313868eab571
--- /dev/null
+++ b/integration-tests/smallrye-stork-registration/src/main/java/org/acme/services/Registration.java
@@ -0,0 +1,31 @@
+package org.acme.services;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.enterprise.event.Observes;
+
+import org.eclipse.microprofile.config.inject.ConfigProperty;
+
+import io.quarkus.runtime.StartupEvent;
+import io.smallrye.stork.Stork;
+import io.vertx.mutiny.core.Vertx;
+
+@ApplicationScoped
+public class Registration {
+
+ @ConfigProperty(name = "red-service-port", defaultValue = "9000")
+ int red;
+ @ConfigProperty(name = "blue-service-port", defaultValue = "9001")
+ int blue;
+
+ /**
+ * Register our two services using static list.
+ *
+ * Note: this method is called on a worker thread, and so it is allowed to block.
+ */
+ public void init(@Observes StartupEvent ev, Vertx vertx) {
+ Stork.getInstance().getService("my-service").getServiceRegistrar().registerServiceInstance("my-service", "localhost",
+ red);
+ Stork.getInstance().getService("my-service").getServiceRegistrar().registerServiceInstance("my-service", "localhost",
+ blue);
+ }
+}
diff --git a/integration-tests/smallrye-stork-registration/src/main/resources/application.properties b/integration-tests/smallrye-stork-registration/src/main/resources/application.properties
new file mode 100644
index 0000000000000..15a149ec67485
--- /dev/null
+++ b/integration-tests/smallrye-stork-registration/src/main/resources/application.properties
@@ -0,0 +1,3 @@
+quarkus.stork.my-service.service-discovery.type=static
+
+quarkus.stork.my-service.service-registrar.type=static
diff --git a/integration-tests/smallrye-stork-registration/src/test/java/org/acme/ClientCallingResourceIT.java b/integration-tests/smallrye-stork-registration/src/test/java/org/acme/ClientCallingResourceIT.java
new file mode 100644
index 0000000000000..35a7b5cef2e89
--- /dev/null
+++ b/integration-tests/smallrye-stork-registration/src/test/java/org/acme/ClientCallingResourceIT.java
@@ -0,0 +1,8 @@
+package org.acme;
+
+import io.quarkus.test.junit.QuarkusIntegrationTest;
+
+@QuarkusIntegrationTest
+public class ClientCallingResourceIT extends ClientCallingResourceTest {
+
+}
diff --git a/integration-tests/smallrye-stork-registration/src/test/java/org/acme/ClientCallingResourceTest.java b/integration-tests/smallrye-stork-registration/src/test/java/org/acme/ClientCallingResourceTest.java
new file mode 100644
index 0000000000000..530da75f8fbb6
--- /dev/null
+++ b/integration-tests/smallrye-stork-registration/src/test/java/org/acme/ClientCallingResourceTest.java
@@ -0,0 +1,24 @@
+package org.acme;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.restassured.RestAssured;
+
+@QuarkusTest
+public class ClientCallingResourceTest {
+
+ @Test
+ public void test() {
+ Set bodies = new HashSet<>();
+ for (int i = 0; i < 10; i++) {
+ bodies.add(RestAssured.get("/api").then().statusCode(200).extract().body().asString());
+ }
+ Assertions.assertEquals(2, bodies.size());
+ }
+
+}