diff --git a/extensions/mongodb-client/runtime/src/main/java/io/quarkus/mongodb/MongoClientName.java b/extensions/mongodb-client/runtime/src/main/java/io/quarkus/mongodb/MongoClientName.java index e253490b4f532..0e28fa5e33581 100644 --- a/extensions/mongodb-client/runtime/src/main/java/io/quarkus/mongodb/MongoClientName.java +++ b/extensions/mongodb-client/runtime/src/main/java/io/quarkus/mongodb/MongoClientName.java @@ -27,7 +27,7 @@ * MongoClient client; * */ -@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD }) +@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER }) @Retention(RUNTIME) @Documented @Qualifier diff --git a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/client/RedisClientName.java b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/client/RedisClientName.java index dd6a9be89b46d..7c5148d2613b9 100644 --- a/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/client/RedisClientName.java +++ b/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/client/RedisClientName.java @@ -26,7 +26,7 @@ * RedisClient client; * */ -@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD }) +@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER }) @Retention(RUNTIME) @Documented @Qualifier diff --git a/integration-tests/mongodb-client/src/main/java/io/quarkus/it/mongodb/BookResourceWithParameterInjection.java b/integration-tests/mongodb-client/src/main/java/io/quarkus/it/mongodb/BookResourceWithParameterInjection.java new file mode 100644 index 0000000000000..a599c3046d5bc --- /dev/null +++ b/integration-tests/mongodb-client/src/main/java/io/quarkus/it/mongodb/BookResourceWithParameterInjection.java @@ -0,0 +1,67 @@ +package io.quarkus.it.mongodb; + +import static com.mongodb.client.model.Filters.eq; + +import java.util.ArrayList; +import java.util.List; + +import javax.annotation.PostConstruct; +import javax.inject.Inject; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.core.Response; + +import com.mongodb.client.FindIterable; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; + +import io.quarkus.mongodb.MongoClientName; + +@Path("/books-with-parameter-injection") +public class BookResourceWithParameterInjection { + private MongoClient client; + private MongoCollection collection; + + @Inject + public BookResourceWithParameterInjection(@MongoClientName("parameter-injection") MongoClient client) { + this.client = client; + } + + @PostConstruct + public void init() { + MongoDatabase database = client.getDatabase("books-with-parameter-injection"); + collection = database.getCollection("my-collection", Book.class); + } + + @GET + public List getBooks() { + FindIterable iterable = collection.find(); + List books = new ArrayList<>(); + for (Book doc : iterable) { + books.add(doc); + } + return books; + } + + @POST + public Response addBook(Book book) { + collection.insertOne(book); + return Response.accepted().build(); + } + + @GET + @Path("/{author}") + public List getBooksByAuthor(@PathParam("author") String author) { + FindIterable iterable = collection.find(eq("author", author)); + List books = new ArrayList<>(); + for (Book doc : iterable) { + String title = doc.getTitle(); + books.add(new Book().setTitle(title).setAuthor(author)); + } + return books; + } + +} diff --git a/integration-tests/mongodb-client/src/main/resources/application.properties b/integration-tests/mongodb-client/src/main/resources/application.properties index eed33da79fbf3..47c195fe3393e 100644 --- a/integration-tests/mongodb-client/src/main/resources/application.properties +++ b/integration-tests/mongodb-client/src/main/resources/application.properties @@ -1,2 +1,4 @@ quarkus.mongodb.connection-string=mongodb://localhost:27018 -quarkus.mongodb.write-concern.journal=false \ No newline at end of file +quarkus.mongodb.write-concern.journal=false +quarkus.mongodb.parameter-injection.connection-string=mongodb://localhost:27018 +quarkus.mongodb.parameter-injection.write-concern.journal=false \ No newline at end of file diff --git a/integration-tests/mongodb-client/src/test/java/io/quarkus/it/mongodb/BookResourceTest.java b/integration-tests/mongodb-client/src/test/java/io/quarkus/it/mongodb/BookResourceTest.java index 2b506aee0eb76..0f089631b1513 100644 --- a/integration-tests/mongodb-client/src/test/java/io/quarkus/it/mongodb/BookResourceTest.java +++ b/integration-tests/mongodb-client/src/test/java/io/quarkus/it/mongodb/BookResourceTest.java @@ -5,54 +5,25 @@ import static org.hamcrest.Matchers.hasKey; import static org.hamcrest.Matchers.is; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Optional; - import javax.json.bind.Jsonb; -import javax.json.bind.JsonbBuilder; import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import io.quarkus.it.mongodb.discriminator.Car; -import io.quarkus.it.mongodb.discriminator.Moto; -import io.quarkus.it.mongodb.pojo.Pojo; import io.quarkus.mongodb.health.MongoHealthCheck; import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusTest; import io.restassured.RestAssured; -import io.restassured.common.mapper.TypeRef; -import io.restassured.config.ObjectMapperConfig; -import io.restassured.mapper.ObjectMapper; -import io.restassured.mapper.ObjectMapperDeserializationContext; -import io.restassured.mapper.ObjectMapperSerializationContext; -import io.restassured.response.Response; @QuarkusTest @QuarkusTestResource(MongoTestResource.class) public class BookResourceTest { - private static Jsonb jsonb; @BeforeAll public static void giveMeAMapper() { - jsonb = JsonbBuilder.create(); - ObjectMapper mapper = new ObjectMapper() { - @Override - public Object deserialize(ObjectMapperDeserializationContext context) { - return jsonb.fromJson(context.getDataToDeserialize().asString(), context.getType()); - } - - @Override - public Object serialize(ObjectMapperSerializationContext context) { - return jsonb.toJson(context.getObjectToSerialize()); - } - }; - RestAssured.config().objectMapperConfig(ObjectMapperConfig.objectMapperConfig().defaultObjectMapper(mapper)); + jsonb = Utils.initialiseJsonb(); } @AfterAll @@ -62,63 +33,12 @@ public static void releaseMapper() throws Exception { @Test public void testBlockingClient() { - callTheEndpoint("/books"); - } - - private void callTheEndpoint(String endpoint) { - List list = get(endpoint).as(new TypeRef>() { - }); - Assertions.assertEquals(0, list.size()); - - Book book1 = new Book().setAuthor("Victor Hugo").setTitle("Les Misérables") - .setCategories(Arrays.asList("long", "very long")) - .setDetails(new BookDetail().setRating(3).setSummary("A very long book")); - Response response = RestAssured - .given() - .header("Content-Type", "application/json") - .body(book1) - .post(endpoint) - .andReturn(); - Assertions.assertEquals(202, response.statusCode()); - - Book book2 = new Book().setAuthor("Victor Hugo").setTitle("Notre-Dame de Paris") - .setCategories(Arrays.asList("long", "quasimodo")) - .setDetails(new BookDetail().setRating(4).setSummary("quasimodo and esmeralda")); - response = RestAssured - .given() - .header("Content-Type", "application/json") - .body(book2) - .post(endpoint) - .andReturn(); - Assertions.assertEquals(202, response.statusCode()); - - list = get(endpoint).as(new TypeRef>() { - }); - Assertions.assertEquals(2, list.size()); - - Book book3 = new Book().setAuthor("Charles Baudelaire").setTitle("Les fleurs du mal") - .setCategories(Collections.singletonList("poem")) - .setDetails(new BookDetail().setRating(2).setSummary("Les Fleurs du mal is a volume of poetry.")); - response = RestAssured - .given() - .header("Content-Type", "application/json") - .body(book3) - .post(endpoint) - .andReturn(); - Assertions.assertEquals(202, response.statusCode()); - - list = get(endpoint).as(new TypeRef>() { - }); - Assertions.assertEquals(3, list.size()); - - list = get(endpoint + "/Victor Hugo").as(new TypeRef>() { - }); - Assertions.assertEquals(2, list.size()); + Utils.callTheEndpoint("/books"); } @Test public void testReactiveClients() { - callTheEndpoint("/reactive-books"); + Utils.callTheEndpoint("/reactive-books"); } @Test @@ -131,36 +51,4 @@ public void health() throws Exception { "checks.name", containsInAnyOrder("MongoDB connection health check")); } - @Test - public void testVehicleEndpoint() { - Car car = new Car(); - car.name = "Renault Clio"; - car.type = "CAR"; - car.seatNumber = 5; - RestAssured.given().header("Content-Type", "application/json").body(car) - .when().post("/vehicles") - .then().statusCode(201); - - Moto moto = new Moto(); - moto.name = "Harley Davidson Sportster"; - moto.type = "MOTO"; - RestAssured.given().header("Content-Type", "application/json").body(moto) - .when().post("/vehicles") - .then().statusCode(201); - - get("/vehicles").then().statusCode(200).body("size()", is(2)); - } - - @Test - public void testPojoEndpoint() { - Pojo pojo = new Pojo(); - pojo.description = "description"; - pojo.optionalString = Optional.of("optional"); - RestAssured.given().header("Content-Type", "application/json").body(pojo) - .when().post("/pojos") - .then().statusCode(201); - - get("/pojos").then().statusCode(200).body("size()", is(1)); - } - } diff --git a/integration-tests/mongodb-client/src/test/java/io/quarkus/it/mongodb/BookResourceWithParameterInjectionTest.java b/integration-tests/mongodb-client/src/test/java/io/quarkus/it/mongodb/BookResourceWithParameterInjectionTest.java new file mode 100644 index 0000000000000..d9399564e0b7f --- /dev/null +++ b/integration-tests/mongodb-client/src/test/java/io/quarkus/it/mongodb/BookResourceWithParameterInjectionTest.java @@ -0,0 +1,34 @@ +package io.quarkus.it.mongodb; + +import static org.hamcrest.Matchers.*; + +import javax.json.bind.Jsonb; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import io.quarkus.test.common.QuarkusTestResource; +import io.quarkus.test.junit.QuarkusTest; + +@QuarkusTest +@QuarkusTestResource(MongoTestResource.class) +public class BookResourceWithParameterInjectionTest { + + private static Jsonb jsonb; + + @BeforeAll + public static void giveMeAMapper() { + jsonb = Utils.initialiseJsonb(); + } + + @AfterAll + public static void releaseMapper() throws Exception { + jsonb.close(); + } + + @Test + public void testInjectedClient() { + Utils.callTheEndpoint("/books-with-parameter-injection"); + } +} diff --git a/integration-tests/mongodb-client/src/test/java/io/quarkus/it/mongodb/NativeBookResourceWithParameterInjectionIT.java b/integration-tests/mongodb-client/src/test/java/io/quarkus/it/mongodb/NativeBookResourceWithParameterInjectionIT.java new file mode 100644 index 0000000000000..36876faebc7ee --- /dev/null +++ b/integration-tests/mongodb-client/src/test/java/io/quarkus/it/mongodb/NativeBookResourceWithParameterInjectionIT.java @@ -0,0 +1,8 @@ +package io.quarkus.it.mongodb; + +import io.quarkus.test.junit.NativeImageTest; + +@NativeImageTest +class NativeBookResourceWithParameterInjectionIT extends BookResourceWithParameterInjectionTest { + +} diff --git a/integration-tests/mongodb-client/src/test/java/io/quarkus/it/mongodb/Utils.java b/integration-tests/mongodb-client/src/test/java/io/quarkus/it/mongodb/Utils.java new file mode 100644 index 0000000000000..1981ca915baf7 --- /dev/null +++ b/integration-tests/mongodb-client/src/test/java/io/quarkus/it/mongodb/Utils.java @@ -0,0 +1,92 @@ +package io.quarkus.it.mongodb; + +import static io.restassured.RestAssured.get; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import javax.json.bind.Jsonb; +import javax.json.bind.JsonbBuilder; + +import org.junit.jupiter.api.Assertions; + +import io.restassured.RestAssured; +import io.restassured.common.mapper.TypeRef; +import io.restassured.config.ObjectMapperConfig; +import io.restassured.mapper.ObjectMapper; +import io.restassured.mapper.ObjectMapperDeserializationContext; +import io.restassured.mapper.ObjectMapperSerializationContext; +import io.restassured.response.Response; + +class Utils { + static Jsonb initialiseJsonb() { + Jsonb jsonb = JsonbBuilder.create(); + ObjectMapper mapper = new ObjectMapper() { + @Override + public Object deserialize(ObjectMapperDeserializationContext context) { + return jsonb.fromJson(context.getDataToDeserialize().asString(), context.getType()); + } + + @Override + public Object serialize(ObjectMapperSerializationContext context) { + return jsonb.toJson(context.getObjectToSerialize()); + } + }; + RestAssured.config().objectMapperConfig(ObjectMapperConfig.objectMapperConfig().defaultObjectMapper(mapper)); + + return jsonb; + } + + static void callTheEndpoint(String endpoint) { + List list = get(endpoint).as(new TypeRef>() { + }); + Assertions.assertEquals(0, list.size()); + + Book book1 = new Book().setAuthor("Victor Hugo").setTitle("Les Misérables") + .setCategories(Arrays.asList("long", "very long")) + .setDetails(new BookDetail().setRating(3).setSummary("A very long book")); + Response response = RestAssured + .given() + .header("Content-Type", "application/json") + .body(book1) + .post(endpoint) + .andReturn(); + Assertions.assertEquals(202, response.statusCode()); + + Book book2 = new Book().setAuthor("Victor Hugo").setTitle("Notre-Dame de Paris") + .setCategories(Arrays.asList("long", "quasimodo")) + .setDetails(new BookDetail().setRating(4).setSummary("quasimodo and esmeralda")); + response = RestAssured + .given() + .header("Content-Type", "application/json") + .body(book2) + .post(endpoint) + .andReturn(); + Assertions.assertEquals(202, response.statusCode()); + + list = get(endpoint).as(new TypeRef>() { + }); + Assertions.assertEquals(2, list.size()); + + Book book3 = new Book().setAuthor("Charles Baudelaire").setTitle("Les fleurs du mal") + .setCategories(Collections.singletonList("poem")) + .setDetails(new BookDetail().setRating(2).setSummary("Les Fleurs du mal is a volume of poetry.")); + response = RestAssured + .given() + .header("Content-Type", "application/json") + .body(book3) + .post(endpoint) + .andReturn(); + Assertions.assertEquals(202, response.statusCode()); + + list = get(endpoint).as(new TypeRef>() { + }); + Assertions.assertEquals(3, list.size()); + + list = get(endpoint + "/Victor Hugo").as(new TypeRef>() { + }); + Assertions.assertEquals(2, list.size()); + } + +} diff --git a/integration-tests/redis-client/src/main/java/io/quarkus/redis/it/RedisWithParameterInjectionResource.java b/integration-tests/redis-client/src/main/java/io/quarkus/redis/it/RedisWithParameterInjectionResource.java new file mode 100644 index 0000000000000..04bcf89ede084 --- /dev/null +++ b/integration-tests/redis-client/src/main/java/io/quarkus/redis/it/RedisWithParameterInjectionResource.java @@ -0,0 +1,62 @@ +package io.quarkus.redis.it; + +import java.util.Arrays; + +import javax.enterprise.context.ApplicationScoped; +import javax.inject.Inject; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; + +import io.quarkus.redis.client.RedisClient; +import io.quarkus.redis.client.RedisClientName; +import io.quarkus.redis.client.reactive.ReactiveRedisClient; +import io.smallrye.mutiny.Uni; +import io.vertx.redis.client.Response; + +@Path("/quarkus-redis-parameter-injection") +@ApplicationScoped +public class RedisWithParameterInjectionResource { + private RedisClient redisClient; + private ReactiveRedisClient reactiveRedisClient; + + @Inject + public RedisWithParameterInjectionResource(@RedisClientName("parameter-injection") RedisClient redisClient, + @RedisClientName("parameter-injection") ReactiveRedisClient reactiveRedisClient) { + this.redisClient = redisClient; + this.reactiveRedisClient = reactiveRedisClient; + } + + // synchronous + @GET + @Path("/sync/{key}") + public String getSync(@PathParam("key") String key) { + Response response = redisClient.get(key); + return response == null ? null : response.toString(); + } + + @POST + @Path("/sync/{key}") + public void setSync(@PathParam("key") String key, String value) { + this.redisClient.set(Arrays.asList(key, value)); + } + + // reactive + @GET + @Path("/reactive/{key}") + public Uni getReactive(@PathParam("key") String key) { + return reactiveRedisClient + .get(key) + .map(response -> response == null ? null : response.toString()); + } + + @POST + @Path("/reactive/{key}") + public Uni setReactive(@PathParam("key") String key, String value) { + return this.reactiveRedisClient + .set(Arrays.asList(key, value)) + .map(response -> null); + } + +} diff --git a/integration-tests/redis-client/src/main/resources/application.properties b/integration-tests/redis-client/src/main/resources/application.properties index 3088abc5ea792..22460ebee4b78 100644 --- a/integration-tests/redis-client/src/main/resources/application.properties +++ b/integration-tests/redis-client/src/main/resources/application.properties @@ -1,3 +1,4 @@ quarkus.redis.hosts=redis://localhost:6379/0 quarkus.redis.named-client.hosts=redis://localhost:6379/1 -quarkus.native.additional-build-args=-H:+TraceClassInitialization \ No newline at end of file +quarkus.redis.parameter-injection.hosts=redis://localhost:6379/2 +quarkus.native.additional-build-args=-H:+TraceClassInitialization diff --git a/integration-tests/redis-client/src/test/java/io/quarkus/redis/it/QuarkusRedisWithParameterInjectionIT.java b/integration-tests/redis-client/src/test/java/io/quarkus/redis/it/QuarkusRedisWithParameterInjectionIT.java new file mode 100644 index 0000000000000..02f89847cb8d2 --- /dev/null +++ b/integration-tests/redis-client/src/test/java/io/quarkus/redis/it/QuarkusRedisWithParameterInjectionIT.java @@ -0,0 +1,8 @@ +package io.quarkus.redis.it; + +import io.quarkus.test.junit.NativeImageTest; + +@NativeImageTest +class QuarkusRedisWithParameterInjectionIT extends QuarkusRedisWithParameterInjectionTest { + +} diff --git a/integration-tests/redis-client/src/test/java/io/quarkus/redis/it/QuarkusRedisWithParameterInjectionTest.java b/integration-tests/redis-client/src/test/java/io/quarkus/redis/it/QuarkusRedisWithParameterInjectionTest.java new file mode 100644 index 0000000000000..074447ea01b0d --- /dev/null +++ b/integration-tests/redis-client/src/test/java/io/quarkus/redis/it/QuarkusRedisWithParameterInjectionTest.java @@ -0,0 +1,62 @@ +package io.quarkus.redis.it; + +import org.hamcrest.CoreMatchers; +import org.junit.jupiter.api.Test; + +import io.quarkus.test.junit.QuarkusTest; +import io.restassured.RestAssured; + +@QuarkusTest +class QuarkusRedisWithParameterInjectionTest { + static final String SYNC_KEY = "named-sync-key"; + static final String SYNC_VALUE = "named-sync-value"; + + static final String REACTIVE_KEY = "named-reactive-key"; + static final String REACTIVE_VALUE = "named-reactive-value"; + + @Test + public void sync() { + RestAssured.given() + .when() + .get("/quarkus-redis-parameter-injection/sync/" + SYNC_KEY) + .then() + .statusCode(204); // the key is not set yet + + RestAssured.given() + .body(SYNC_VALUE) + .when() + .post("/quarkus-redis-parameter-injection/sync/" + SYNC_KEY) + .then() + .statusCode(204); + + RestAssured.given() + .when() + .get("/quarkus-redis-parameter-injection/sync/" + SYNC_KEY) + .then() + .statusCode(200) + .body(CoreMatchers.is(SYNC_VALUE)); + } + + @Test + public void reactive() { + RestAssured.given() + .when() + .get("/quarkus-redis-parameter-injection/reactive/" + REACTIVE_KEY) + .then() + .statusCode(204); // the reactive key is not set yet + + RestAssured.given() + .body(REACTIVE_VALUE) + .when() + .post("/quarkus-redis-parameter-injection/reactive/" + REACTIVE_KEY) + .then() + .statusCode(204); + + RestAssured.given() + .when() + .get("/quarkus-redis-parameter-injection/reactive/" + REACTIVE_KEY) + .then() + .statusCode(200) + .body(CoreMatchers.is(REACTIVE_VALUE)); + } +}