From 39974e2d6d06dac05617c07ddf2110d170249b90 Mon Sep 17 00:00:00 2001 From: Abhinav Pandey Date: Thu, 4 Jan 2024 15:35:39 +0530 Subject: [PATCH] BAEL-6751 - reactive apis with micronaut (#14824) * BAEL-6751 - reactive apis with micronaut * BAEL-6751 - reactive apis with micronaut * BAEL-6751 - added error handling * BAEL-6751 - removed unused property * BAEL-6751 - formatting changes * BAEL-6751 - added missing class * BAEL-6751 - moving module to parent pom * BAEL-6751 - moving version number to property --- .../micronaut-reactive/README.md | 5 + .../micronaut-reactive/pom.xml | 199 ++++++++++++++++++ .../micronautreactive/Application.java | 10 + .../controller/BookController.java | 82 ++++++++ .../dtos/BookNotFoundException.java | 7 + .../micronautreactive/entity/Author.java | 34 +++ .../micronautreactive/entity/Book.java | 73 +++++++ .../repository/BookRepository.java | 17 ++ .../service/BookService.java | 38 ++++ .../src/main/resources/application.properties | 4 + .../src/main/resources/logback.xml | 14 ++ .../MicronautReactiveTest.java | 21 ++ microservices-modules/pom.xml | 1 + 13 files changed, 505 insertions(+) create mode 100644 microservices-modules/micronaut-reactive/README.md create mode 100644 microservices-modules/micronaut-reactive/pom.xml create mode 100644 microservices-modules/micronaut-reactive/src/main/java/com/baeldung/micronautreactive/Application.java create mode 100644 microservices-modules/micronaut-reactive/src/main/java/com/baeldung/micronautreactive/controller/BookController.java create mode 100644 microservices-modules/micronaut-reactive/src/main/java/com/baeldung/micronautreactive/dtos/BookNotFoundException.java create mode 100644 microservices-modules/micronaut-reactive/src/main/java/com/baeldung/micronautreactive/entity/Author.java create mode 100644 microservices-modules/micronaut-reactive/src/main/java/com/baeldung/micronautreactive/entity/Book.java create mode 100644 microservices-modules/micronaut-reactive/src/main/java/com/baeldung/micronautreactive/repository/BookRepository.java create mode 100644 microservices-modules/micronaut-reactive/src/main/java/com/baeldung/micronautreactive/service/BookService.java create mode 100644 microservices-modules/micronaut-reactive/src/main/resources/application.properties create mode 100644 microservices-modules/micronaut-reactive/src/main/resources/logback.xml create mode 100644 microservices-modules/micronaut-reactive/src/test/java/com/baeldung/micronautreactive/MicronautReactiveTest.java diff --git a/microservices-modules/micronaut-reactive/README.md b/microservices-modules/micronaut-reactive/README.md new file mode 100644 index 0000000000..3e892a7eba --- /dev/null +++ b/microservices-modules/micronaut-reactive/README.md @@ -0,0 +1,5 @@ +## Micronaut Reactive + +This module contains articles about Micronaut Reactive + +### Relevant Articles: \ No newline at end of file diff --git a/microservices-modules/micronaut-reactive/pom.xml b/microservices-modules/micronaut-reactive/pom.xml new file mode 100644 index 0000000000..4e0af0afe6 --- /dev/null +++ b/microservices-modules/micronaut-reactive/pom.xml @@ -0,0 +1,199 @@ + + + 4.0.0 + com.baeldung + micronaut-reactive + 0.1 + ${packaging} + + + io.micronaut.platform + micronaut-parent + 4.1.2 + + + jar + 17 + 17 + netty + false + com.baeldung.aot.generated + true + com.baeldung.micronautreactive.Application + 2.1.0 + + + + + central + https://repo.maven.apache.org/maven2 + + + + + + io.micronaut + micronaut-http-server-netty + compile + + + io.micronaut.validation + micronaut-validation + compile + + + jakarta.validation + jakarta.validation-api + compile + + + io.micronaut.data + micronaut-data-mongodb + compile + + + io.micronaut.mongodb + micronaut-mongo-reactive + compile + + + io.micronaut.reactor + micronaut-reactor + compile + + + io.micronaut.serde + micronaut-serde-bson + compile + + + ch.qos.logback + logback-classic + runtime + + + org.mongodb + mongodb-driver-reactivestreams + runtime + + + io.micronaut.testresources + micronaut-test-resources-client + provided + + + io.micronaut + micronaut-http-client + test + + + + io.micronaut.testresources + micronaut-test-resources-testcontainers + ${micronaut-test-resources-testcontainers.version} + + + + io.micronaut.test + micronaut-test-junit5 + test + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + + + + io.micronaut.maven + micronaut-maven-plugin + + aot-${packaging}.properties + + + + org.apache.maven.plugins + maven-enforcer-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + + + io.micronaut + micronaut-inject-java + ${micronaut.core.version} + + + + io.micronaut.data + micronaut-data-processor + ${micronaut.data.version} + + + io.micronaut + micronaut-inject + + + + + io.micronaut.data + micronaut-data-document-processor + ${micronaut.data.version} + + + io.micronaut + micronaut-inject + + + + + io.micronaut + micronaut-graal + ${micronaut.core.version} + + + io.micronaut.serde + micronaut-serde-processor + ${micronaut.serialization.version} + + + io.micronaut + micronaut-inject + + + + + io.micronaut.validation + micronaut-validation-processor + ${micronaut.validation.version} + + + io.micronaut + micronaut-inject + + + + + + -Amicronaut.processing.group=com.baeldung + -Amicronaut.processing.module=micronaut-reactive + + + + + + + diff --git a/microservices-modules/micronaut-reactive/src/main/java/com/baeldung/micronautreactive/Application.java b/microservices-modules/micronaut-reactive/src/main/java/com/baeldung/micronautreactive/Application.java new file mode 100644 index 0000000000..8225b710b7 --- /dev/null +++ b/microservices-modules/micronaut-reactive/src/main/java/com/baeldung/micronautreactive/Application.java @@ -0,0 +1,10 @@ +package com.baeldung.micronautreactive; + +import io.micronaut.runtime.Micronaut; + +public class Application { + + public static void main(String[] args) { + Micronaut.run(Application.class, args); + } +} \ No newline at end of file diff --git a/microservices-modules/micronaut-reactive/src/main/java/com/baeldung/micronautreactive/controller/BookController.java b/microservices-modules/micronaut-reactive/src/main/java/com/baeldung/micronautreactive/controller/BookController.java new file mode 100644 index 0000000000..171844b29c --- /dev/null +++ b/microservices-modules/micronaut-reactive/src/main/java/com/baeldung/micronautreactive/controller/BookController.java @@ -0,0 +1,82 @@ +package com.baeldung.micronautreactive.controller; + +import com.baeldung.micronautreactive.dtos.BookNotFoundException; +import com.baeldung.micronautreactive.entity.Book; +import com.baeldung.micronautreactive.service.BookService; +import io.micronaut.core.annotation.Nullable; +import io.micronaut.http.HttpResponse; +import io.micronaut.http.MutableHttpResponse; +import io.micronaut.http.annotation.Error; +import io.micronaut.http.annotation.*; +import jakarta.validation.ConstraintViolationException; +import jakarta.validation.Valid; +import org.bson.types.ObjectId; +import reactor.core.publisher.Flux; + +@Controller("/books") +public class BookController { + + private final BookService bookService; + + public BookController(BookService bookService) { + this.bookService = bookService; + } + + @Post + public String createBook(@Valid @Body Book book) { + @Nullable ObjectId bookId = bookService.save(book); + if (null == bookId) { + return "Book not created"; + } else { + return "Book created with id: " + bookId; + } + } + + @Put + public String updateBook(@Valid @Body Book book) { + @Nullable ObjectId bookId = bookService.update(book); + if (null == bookId) { + return "Book not updated"; + } else { + return "Book updated with id: " + bookId; + } + } + + @Delete("/{id}") + public String deleteBook(String id) throws BookNotFoundException { + Long bookId = bookService.deleteById(id); + if (1 == bookId) { + return "Book deleted"; + } else { + throw new BookNotFoundException(id); + } + } + + @Get("/{id}") + public Book findById(@PathVariable("id") String identifier) throws BookNotFoundException { + Book book = bookService.findById(identifier); + if (null == book) { + throw new BookNotFoundException(identifier); + } else { + return book; + } + } + + @Get("/published-after") + public Flux findByYearGreaterThan(@QueryValue(value = "year") int year) { + return bookService.findByYearGreaterThan(year); + } + + @Error(exception = ConstraintViolationException.class) + public MutableHttpResponse onSavedFailed(ConstraintViolationException ex) { + return HttpResponse.badRequest(ex.getConstraintViolations().stream() + .map(cv -> cv.getPropertyPath() + " " + cv.getMessage()) + .toList().toString()); + } + + @Error(exception = BookNotFoundException.class) + public HttpResponse onSavedFailed(BookNotFoundException ex) { + return HttpResponse.notFound(ex.getMessage()); + } + +} diff --git a/microservices-modules/micronaut-reactive/src/main/java/com/baeldung/micronautreactive/dtos/BookNotFoundException.java b/microservices-modules/micronaut-reactive/src/main/java/com/baeldung/micronautreactive/dtos/BookNotFoundException.java new file mode 100644 index 0000000000..a739881b35 --- /dev/null +++ b/microservices-modules/micronaut-reactive/src/main/java/com/baeldung/micronautreactive/dtos/BookNotFoundException.java @@ -0,0 +1,7 @@ +package com.baeldung.micronautreactive.dtos; + +public class BookNotFoundException extends Exception { + public BookNotFoundException(String id) { + super("Book with id " + id + " not found"); + } +} diff --git a/microservices-modules/micronaut-reactive/src/main/java/com/baeldung/micronautreactive/entity/Author.java b/microservices-modules/micronaut-reactive/src/main/java/com/baeldung/micronautreactive/entity/Author.java new file mode 100644 index 0000000000..cb1e363a49 --- /dev/null +++ b/microservices-modules/micronaut-reactive/src/main/java/com/baeldung/micronautreactive/entity/Author.java @@ -0,0 +1,34 @@ +package com.baeldung.micronautreactive.entity; + +import io.micronaut.core.annotation.Introspected; +import io.micronaut.serde.annotation.Serdeable; + +@Serdeable +public class Author { + private String firstName; + private String lastName; + + public Author() { + } + + public Author(String firstName, String lastName) { + this.firstName = firstName; + this.lastName = lastName; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } +} \ No newline at end of file diff --git a/microservices-modules/micronaut-reactive/src/main/java/com/baeldung/micronautreactive/entity/Book.java b/microservices-modules/micronaut-reactive/src/main/java/com/baeldung/micronautreactive/entity/Book.java new file mode 100644 index 0000000000..684924ef24 --- /dev/null +++ b/microservices-modules/micronaut-reactive/src/main/java/com/baeldung/micronautreactive/entity/Book.java @@ -0,0 +1,73 @@ +package com.baeldung.micronautreactive.entity; + +import io.micronaut.core.annotation.Generated; +import io.micronaut.core.annotation.Nullable; +import io.micronaut.data.annotation.Id; +import io.micronaut.data.annotation.MappedEntity; +import io.micronaut.serde.annotation.Serdeable; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import org.bson.types.ObjectId; + +@Serdeable +@MappedEntity +public class Book { + @Id + @Generated + private @Nullable ObjectId id; + @NotBlank + private String title; + + @NotNull + private Author author; + private int year; + + public Book() { + } + + public Book(@Nullable ObjectId id, String title, Author author, int year) { + this.id = id; + this.title = title; + this.author = author; + this.year = year; + } + + public Book(String title, Author author, int year) { + this.title = title; + this.author = author; + this.year = year; + } + + public @Nullable ObjectId getId() { + return id; + } + + public void setId(@Nullable ObjectId id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Author getAuthor() { + return author; + } + + public void setAuthor(Author author) { + this.author = author; + } + + public int getYear() { + return year; + } + + public void setYear(int year) { + this.year = year; + } +} diff --git a/microservices-modules/micronaut-reactive/src/main/java/com/baeldung/micronautreactive/repository/BookRepository.java b/microservices-modules/micronaut-reactive/src/main/java/com/baeldung/micronautreactive/repository/BookRepository.java new file mode 100644 index 0000000000..37cf5c9af3 --- /dev/null +++ b/microservices-modules/micronaut-reactive/src/main/java/com/baeldung/micronautreactive/repository/BookRepository.java @@ -0,0 +1,17 @@ +package com.baeldung.micronautreactive.repository; + +import com.baeldung.micronautreactive.entity.Book; +import io.micronaut.context.annotation.Parameter; +import io.micronaut.core.async.annotation.SingleResult; +import io.micronaut.data.mongodb.annotation.MongoFindQuery; +import io.micronaut.data.mongodb.annotation.MongoRepository; +import io.micronaut.data.repository.reactive.ReactorCrudRepository; +import org.bson.types.ObjectId; +import reactor.core.publisher.Flux; + +@MongoRepository +public interface BookRepository extends ReactorCrudRepository { + + @MongoFindQuery("{year: {$gt: :year}}") + Flux findByYearGreaterThan(int year); +} diff --git a/microservices-modules/micronaut-reactive/src/main/java/com/baeldung/micronautreactive/service/BookService.java b/microservices-modules/micronaut-reactive/src/main/java/com/baeldung/micronautreactive/service/BookService.java new file mode 100644 index 0000000000..56782da457 --- /dev/null +++ b/microservices-modules/micronaut-reactive/src/main/java/com/baeldung/micronautreactive/service/BookService.java @@ -0,0 +1,38 @@ +package com.baeldung.micronautreactive.service; + +import com.baeldung.micronautreactive.entity.Book; +import com.baeldung.micronautreactive.repository.BookRepository; +import jakarta.inject.Singleton; +import org.bson.types.ObjectId; +import reactor.core.publisher.Flux; + +@Singleton +public class BookService { + private final BookRepository bookRepository; + + public BookService(BookRepository bookRepository) { + this.bookRepository = bookRepository; + } + + public ObjectId save(Book book) { + Book savedBook = bookRepository.save(book).block(); + return null != savedBook ? savedBook.getId() : null; + } + + public ObjectId update(Book book) { + Book updatedBook = bookRepository.update(book).block(); + return null != updatedBook ? updatedBook.getId() : null; + } + + public Long deleteById(String id) { + return bookRepository.deleteById(new ObjectId(id)).block(); + } + + public Flux findByYearGreaterThan(int year) { + return bookRepository.findByYearGreaterThan(year); + } + + public Book findById(String id) { + return bookRepository.findById(new ObjectId(id)).block(); + } +} diff --git a/microservices-modules/micronaut-reactive/src/main/resources/application.properties b/microservices-modules/micronaut-reactive/src/main/resources/application.properties new file mode 100644 index 0000000000..5f1d7e6141 --- /dev/null +++ b/microservices-modules/micronaut-reactive/src/main/resources/application.properties @@ -0,0 +1,4 @@ +#Sun Aug 27 12:03:55 GMT 2023 +micronaut.application.name=micronaut-reactive +mongodb.uri: mongodb://${MONGO_HOST:localhost}:${MONGO_PORT:27017}/someDb + diff --git a/microservices-modules/micronaut-reactive/src/main/resources/logback.xml b/microservices-modules/micronaut-reactive/src/main/resources/logback.xml new file mode 100644 index 0000000000..44b79c40d4 --- /dev/null +++ b/microservices-modules/micronaut-reactive/src/main/resources/logback.xml @@ -0,0 +1,14 @@ + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + diff --git a/microservices-modules/micronaut-reactive/src/test/java/com/baeldung/micronautreactive/MicronautReactiveTest.java b/microservices-modules/micronaut-reactive/src/test/java/com/baeldung/micronautreactive/MicronautReactiveTest.java new file mode 100644 index 0000000000..080da794fe --- /dev/null +++ b/microservices-modules/micronaut-reactive/src/test/java/com/baeldung/micronautreactive/MicronautReactiveTest.java @@ -0,0 +1,21 @@ +package com.baeldung.micronautreactive; + +import io.micronaut.runtime.EmbeddedApplication; +import io.micronaut.test.extensions.junit5.annotation.MicronautTest; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Assertions; + +import jakarta.inject.Inject; + +@MicronautTest(transactional = false) +class MicronautReactiveTest { + + @Inject + EmbeddedApplication application; + + @Test + void testItWorks() { + Assertions.assertTrue(application.isRunning()); + } + +} diff --git a/microservices-modules/pom.xml b/microservices-modules/pom.xml index 4b46e7cd1b..a88b6e0fd6 100644 --- a/microservices-modules/pom.xml +++ b/microservices-modules/pom.xml @@ -17,6 +17,7 @@ helidon micronaut + micronaut-reactive microprofile msf4j open-liberty