From 30fc547604c59287ab319dafa53fe1037eb34214 Mon Sep 17 00:00:00 2001 From: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com> Date: Tue, 24 Mar 2026 06:56:12 +0000 Subject: [PATCH] chore: update --- .../src/main/java/com/drinkool/RestAPI.java | 9 +-- .../com/drinkool/entities/CustomerEntity.java | 9 +++ .../java/com/drinkool/models/Customer.java | 7 --- .../models/{User.java => UserModel.java} | 8 +-- eatery-service/pom.xml | 33 ++++++----- .../src/main/java/com/drinkool/MyEntity.java | 29 ---------- .../com/drinkool/MyMessagingApplication.java | 48 ---------------- .../main/java/com/drinkool/ReviewService.java | 53 ++++++++++++++++++ .../com/drinkool/entities/ReviewEntity.java | 29 ++++++++++ .../main/java/com/drinkool/models/Review.java | 7 --- .../utils/SendReviewDeserializer.java | 11 ++++ .../src/main/resources/application.properties | 36 +++++++++++- .../drinkool/MyMessagingApplicationTest.java | 14 ++--- .../java/com/drinkool/ReviewServiceTest.java | 56 +++++++++++++++++++ .../src/test/resources/application.properties | 15 +++++ .../src/main/resources/application.properties | 4 -- .../java/com/drinkool/dtos/SendReview.java | 11 ++++ .../{BaseReview.java => ReviewModel.java} | 2 +- 18 files changed, 250 insertions(+), 131 deletions(-) create mode 100644 account-service/src/main/java/com/drinkool/entities/CustomerEntity.java delete mode 100644 account-service/src/main/java/com/drinkool/models/Customer.java rename account-service/src/main/java/com/drinkool/models/{User.java => UserModel.java} (89%) delete mode 100644 eatery-service/src/main/java/com/drinkool/MyEntity.java delete mode 100644 eatery-service/src/main/java/com/drinkool/MyMessagingApplication.java create mode 100644 eatery-service/src/main/java/com/drinkool/ReviewService.java create mode 100644 eatery-service/src/main/java/com/drinkool/entities/ReviewEntity.java delete mode 100644 eatery-service/src/main/java/com/drinkool/models/Review.java create mode 100644 eatery-service/src/main/java/com/drinkool/utils/SendReviewDeserializer.java create mode 100644 eatery-service/src/test/java/com/drinkool/ReviewServiceTest.java create mode 100644 eatery-service/src/test/resources/application.properties create mode 100644 lib/src/main/java/com/drinkool/dtos/SendReview.java rename lib/src/main/java/com/drinkool/models/{BaseReview.java => ReviewModel.java} (88%) diff --git a/account-service/src/main/java/com/drinkool/RestAPI.java b/account-service/src/main/java/com/drinkool/RestAPI.java index 899474f..6bb45f0 100644 --- a/account-service/src/main/java/com/drinkool/RestAPI.java +++ b/account-service/src/main/java/com/drinkool/RestAPI.java @@ -1,7 +1,8 @@ package com.drinkool; import com.drinkool.dtos.*; -import com.drinkool.models.Customer; +import com.drinkool.entities.CustomerEntity; +import com.drinkool.entities.CustomerEntity; import com.drinkool.services.*; import jakarta.inject.Inject; import jakarta.transaction.Transactional; @@ -18,7 +19,7 @@ public class RestAPI { @Path("/signup") @Transactional public Response signup(Signup input) { - Customer newCustomer = new Customer(); + CustomerEntity newCustomer = new CustomerEntity(); newCustomer.signup(input.name, input.phone, input.password); @@ -29,7 +30,7 @@ public class RestAPI { @Path("/quickSignup") @Transactional public Response quickSignup(QuickSignup input) { - Customer newCustomer = new Customer(); + CustomerEntity newCustomer = new CustomerEntity(); newCustomer.signup(input.phone); @@ -39,7 +40,7 @@ public class RestAPI { @POST @Path("/login") public Response login(Login input) { - Customer customer = Customer.find("phone", input.phone).firstResult(); + CustomerEntity customer = CustomerEntity.find("phone", input.phone).firstResult(); if (customer == null) throw new BadRequestException("InvalidPhoneNumber"); diff --git a/account-service/src/main/java/com/drinkool/entities/CustomerEntity.java b/account-service/src/main/java/com/drinkool/entities/CustomerEntity.java new file mode 100644 index 0000000..98801ed --- /dev/null +++ b/account-service/src/main/java/com/drinkool/entities/CustomerEntity.java @@ -0,0 +1,9 @@ +package com.drinkool.entities; + +import com.drinkool.models.UserModel; + +import jakarta.persistence.*; + +@Entity +@Table(name = "customer") +public class CustomerEntity extends UserModel {} diff --git a/account-service/src/main/java/com/drinkool/models/Customer.java b/account-service/src/main/java/com/drinkool/models/Customer.java deleted file mode 100644 index 491137f..0000000 --- a/account-service/src/main/java/com/drinkool/models/Customer.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.drinkool.models; - -import jakarta.persistence.*; - -@Entity -@Table(name = "customer") -public class Customer extends User {} diff --git a/account-service/src/main/java/com/drinkool/models/User.java b/account-service/src/main/java/com/drinkool/models/UserModel.java similarity index 89% rename from account-service/src/main/java/com/drinkool/models/User.java rename to account-service/src/main/java/com/drinkool/models/UserModel.java index debaf29..d19ed1d 100644 --- a/account-service/src/main/java/com/drinkool/models/User.java +++ b/account-service/src/main/java/com/drinkool/models/UserModel.java @@ -11,7 +11,7 @@ import java.util.UUID; @Entity @Inheritance(strategy = InheritanceType.JOINED) @Table(name = "users") -public abstract class User extends PanacheEntity { +public abstract class UserModel extends PanacheEntity { @Column(nullable = false) public String name; @@ -22,10 +22,6 @@ public abstract class User extends PanacheEntity { @Column(nullable = false, length = 1024) public String hashedPassword; - public User() { - super(); - } - @Transactional public void signup(String phone) { this.signup(phone, phone, UUID.randomUUID().toString().substring(0, 32)); @@ -34,7 +30,7 @@ public abstract class User extends PanacheEntity { @Transactional public void signup(String name, String phone, String rawPassword) { // Check existed user - Customer existedUser = User.find("phone", phone).firstResult(); + UserModel existedUser = UserModel.find("phone", phone).firstResult(); if (existedUser != null) throw new BadRequestException("ExistedUser"); diff --git a/eatery-service/pom.xml b/eatery-service/pom.xml index df94b97..006b8e4 100644 --- a/eatery-service/pom.xml +++ b/eatery-service/pom.xml @@ -1,9 +1,7 @@ - - + + 4.0.0 @@ -20,11 +18,9 @@ 3.15.0 21 UTF-8 - UTF-8 + UTF-8 quarkus-bom - io.quarkus.platform + io.quarkus.platform 3.32.4 true 3.5.4 @@ -48,6 +44,11 @@ lib ${project.version} + + org.awaitility + awaitility + test + io.quarkus quarkus-hibernate-orm-panache @@ -72,6 +73,10 @@ io.quarkus quarkus-hibernate-orm + + io.quarkus + quarkus-rest-jackson + io.quarkus quarkus-junit @@ -100,8 +105,7 @@ @{argLine} - org.jboss.logmanager.LogManager + org.jboss.logmanager.LogManager ${maven.home} @@ -122,8 +126,7 @@ ${project.build.directory}/${project.build.finalName}-runner - org.jboss.logmanager.LogManager + org.jboss.logmanager.LogManager ${maven.home} @@ -146,4 +149,4 @@ - + \ No newline at end of file diff --git a/eatery-service/src/main/java/com/drinkool/MyEntity.java b/eatery-service/src/main/java/com/drinkool/MyEntity.java deleted file mode 100644 index ceb5d4a..0000000 --- a/eatery-service/src/main/java/com/drinkool/MyEntity.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.drinkool; - -import io.quarkus.hibernate.orm.panache.PanacheEntity; -import jakarta.persistence.Entity; - -/** - * Example JPA entity defined as a Panache Entity. - * An ID field of Long type is provided, if you want to define your own ID field extends PanacheEntityBase instead. - * - * This uses the active record pattern, you can also use the repository pattern instead: - * {@see https://quarkus.io/guides/hibernate-orm-panache#solution-2-using-the-repository-pattern}. - * - * Usage: - * - * {@code - * public void doSomething() { - * MyEntity entity1 = new MyEntity(); - * entity1.field = "field-1"; - * entity1.persist(); - * - * List entities = MyEntity.listAll(); - * } - * } - */ -@Entity -public class MyEntity extends PanacheEntity { - - public String field; -} diff --git a/eatery-service/src/main/java/com/drinkool/MyMessagingApplication.java b/eatery-service/src/main/java/com/drinkool/MyMessagingApplication.java deleted file mode 100644 index a9e0791..0000000 --- a/eatery-service/src/main/java/com/drinkool/MyMessagingApplication.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.drinkool; - -import io.quarkus.runtime.StartupEvent; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.event.Observes; -import java.util.stream.Stream; -import org.eclipse.microprofile.reactive.messaging.Channel; -import org.eclipse.microprofile.reactive.messaging.Emitter; -import org.eclipse.microprofile.reactive.messaging.Incoming; -import org.eclipse.microprofile.reactive.messaging.Outgoing; - -@ApplicationScoped -public class MyMessagingApplication { - - /** - * Injects an emitter to send messages to the "words-out" channel. - */ - @Channel("words-out") - Emitter emitter; - - /** - * Sends message to the "words-out" channel, can be used from a JAX-RS resource or any bean of your application. - * Messages are sent to the broker. - **/ - void onStart(@Observes StartupEvent ev) { - Stream.of("Hello", "with", "Quarkus", "Messaging", "message").forEach( - string -> emitter.send(string) - ); - } - - /** - * Consume the message from the "words-in" channel, uppercase it and send it to the uppercase channel. - * This method is called by the framework when a message is received on the "words-in" channel (from the broker). - **/ - @Incoming("words-in") - @Outgoing("uppercase") - public String toUpperCase(String message) { - return message.toUpperCase(); - } - - /** - * Consume the uppercase channel (coming from within the application) and print the messages to the console. - **/ - @Incoming("uppercase") - public void sink(String word) { - System.out.println(">> " + word); - } -} diff --git a/eatery-service/src/main/java/com/drinkool/ReviewService.java b/eatery-service/src/main/java/com/drinkool/ReviewService.java new file mode 100644 index 0000000..ea5d76f --- /dev/null +++ b/eatery-service/src/main/java/com/drinkool/ReviewService.java @@ -0,0 +1,53 @@ +package com.drinkool; + +import com.drinkool.dtos.SendReview; +import com.drinkool.entities.ReviewEntity; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.transaction.Transactional; +import org.eclipse.microprofile.reactive.messaging.Incoming; + +@ApplicationScoped +public class ReviewService { + + /** + * Injects an emitter to send messages to the "words-out" channel. + */ + // @Channel("words-out") + // Emitter emitter; + + // /** + // * Sends message to the "words-out" channel, can be used from a JAX-RS resource or any bean of your application. + // * Messages are sent to the broker. + // **/ + // void onStart(@Observes StartupEvent ev) { + // Stream.of("Hello", "with", "Quarkus", "Messaging", "message").forEach( + // string -> emitter.send(string) + // ); + // } + + /** + * Consume the message from the "words-in" channel, uppercase it and send it to the uppercase channel. + * This method is called by the framework when a message is received on the "words-in" channel (from the broker). + **/ + // @Incoming("words-in") + // @Outgoing("uppercase") + // public String toUpperCase(String message) { + // return message.toUpperCase(); + // } + + /** + * Consume the uppercase channel (coming from within the application) and print the messages to the console. + **/ + // @Incoming("uppercase") + // public void sink(String word) { + // System.out.println(">> " + word); + // } + + @Incoming("review") + @Transactional + public void receiveReview(SendReview input) { + ReviewEntity newReview = new ReviewEntity(); + + newReview.receive(input.reviewerId, input.orderId, input.review); + } +} diff --git a/eatery-service/src/main/java/com/drinkool/entities/ReviewEntity.java b/eatery-service/src/main/java/com/drinkool/entities/ReviewEntity.java new file mode 100644 index 0000000..b0a913b --- /dev/null +++ b/eatery-service/src/main/java/com/drinkool/entities/ReviewEntity.java @@ -0,0 +1,29 @@ +package com.drinkool.entities; + +import com.drinkool.models.ReviewModel; +import jakarta.persistence.*; +import jakarta.transaction.Transactional; + +import java.util.UUID; + +@Entity +@Table(name = "reviews") +public class ReviewEntity extends ReviewModel { + + public UUID reviewerId; + + public UUID eateryId; + + @Transactional + public void receive(UUID reviewerId, UUID eateryId, ReviewModel review) { + this.reviewerId = reviewerId; + + this.eateryId = eateryId; + + this.rating = review.rating; + + this.comment = review.comment; + + this.persist(); + } +} diff --git a/eatery-service/src/main/java/com/drinkool/models/Review.java b/eatery-service/src/main/java/com/drinkool/models/Review.java deleted file mode 100644 index 8c0a227..0000000 --- a/eatery-service/src/main/java/com/drinkool/models/Review.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.drinkool.models; - -import jakarta.persistence.*; - -@Entity -@Table(name = "reviews") -public class Review extends BaseReview {} diff --git a/eatery-service/src/main/java/com/drinkool/utils/SendReviewDeserializer.java b/eatery-service/src/main/java/com/drinkool/utils/SendReviewDeserializer.java new file mode 100644 index 0000000..98ca717 --- /dev/null +++ b/eatery-service/src/main/java/com/drinkool/utils/SendReviewDeserializer.java @@ -0,0 +1,11 @@ +package com.drinkool.utils; + +import com.drinkool.dtos.SendReview; + +import io.quarkus.kafka.client.serialization.ObjectMapperDeserializer; + +public class SendReviewDeserializer extends ObjectMapperDeserializer { + public SendReviewDeserializer() { + super(SendReview.class); + } +} diff --git a/eatery-service/src/main/resources/application.properties b/eatery-service/src/main/resources/application.properties index 112829f..a7a355d 100644 --- a/eatery-service/src/main/resources/application.properties +++ b/eatery-service/src/main/resources/application.properties @@ -1,3 +1,33 @@ -mp.messaging.incoming.words-in.auto.offset.reset=earliest -mp.messaging.incoming.words-in.topic=words -mp.messaging.outgoing.words-out.topic=words +# Cấu hình Database + +# Kafka +# Địa chỉ server Kafka +kafka.bootstrap.servers=localhost:9092 + +# --- CẤU HÌNH GỬI TIN (OUTGOING) --- +# Kênh "eatery-out" sẽ gửi vào topic "eatery-events" +# mp.messaging.outgoing.eatery-out.connector=smallrye-kafka +# mp.messaging.outgoing.eatery-out.topic=eatery-events +# # Tự động biến Object thành JSON +# mp.messaging.outgoing.eatery-out.value.serializer=io.quarkus.kafka.client.serialization.ObjectMapperSerializer + +# --- CẤU HÌNH NHẬN TIN (INCOMING) --- +# Kênh "review-in" sẽ nhận từ topic "review-topic" +mp.messaging.incoming.review.connector=smallrye-kafka +mp.messaging.incoming.review.topic=review-topic +# Tự động biến JSON thành Object (giả sử là class ReviewModel) +mp.messaging.incoming.review.value.deserializer=com.drinkool.utils.SendReviewDeserializer + +# Postgress +# Cấu hình Database +quarkus.datasource.db-kind=postgresql +quarkus.datasource.username=postgres +quarkus.datasource.password=password +quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/eatery + +# Tự động tạo bảng từ Entity (chỉ dùng cho môi trường dev) +quarkus.hibernate-orm.database.generation=update + +# Dependency +quarkus.index-dependency.lib.group-id=com.drinkool +quarkus.index-dependency.lib.artifact-id=lib \ No newline at end of file diff --git a/eatery-service/src/test/java/com/drinkool/MyMessagingApplicationTest.java b/eatery-service/src/test/java/com/drinkool/MyMessagingApplicationTest.java index 7573d8d..668934e 100644 --- a/eatery-service/src/test/java/com/drinkool/MyMessagingApplicationTest.java +++ b/eatery-service/src/test/java/com/drinkool/MyMessagingApplicationTest.java @@ -9,12 +9,12 @@ import org.junit.jupiter.api.Test; @QuarkusTest class MyMessagingApplicationTest { - @Inject - MyMessagingApplication application; + // @Inject + // MyMessagingApplication application; - @Test - void test() { - assertEquals("HELLO", application.toUpperCase("Hello")); - assertEquals("BONJOUR", application.toUpperCase("bonjour")); - } + // @Test + // void test() { + // assertEquals("HELLO", application.toUpperCase("Hello")); + // assertEquals("BONJOUR", application.toUpperCase("bonjour")); + // } } diff --git a/eatery-service/src/test/java/com/drinkool/ReviewServiceTest.java b/eatery-service/src/test/java/com/drinkool/ReviewServiceTest.java new file mode 100644 index 0000000..fb4892e --- /dev/null +++ b/eatery-service/src/test/java/com/drinkool/ReviewServiceTest.java @@ -0,0 +1,56 @@ +package com.drinkool; + +import static org.junit.jupiter.api.Assertions.*; + +import com.drinkool.dtos.SendReview; +import com.drinkool.entities.ReviewEntity; +import com.drinkool.models.ReviewModel; +import io.quarkus.narayana.jta.QuarkusTransaction; +import io.quarkus.test.junit.QuarkusTest; +import jakarta.inject.Inject; +import java.util.Random; +import java.util.UUID; +import java.util.concurrent.TimeUnit; +import org.awaitility.Awaitility; +import org.eclipse.microprofile.reactive.messaging.*; +import org.junit.jupiter.api.Test; + +@QuarkusTest +public class ReviewServiceTest { + + @Inject + ReviewService service; + + @Inject + @Channel("review-test") + Emitter producer; + + @Test + void receiveReview() { + Random random = new Random(); + + UUID reviewerId = UUID.randomUUID(); + UUID orderId = UUID.randomUUID(); + String comment = UUID.randomUUID().toString(); + int rating = random.nextInt(); + + SendReview input = new SendReview(); + input.reviewerId = reviewerId; + input.orderId = orderId; + ReviewModel reviewModel = new ReviewModel(); + reviewModel.comment = comment; + reviewModel.rating = rating; + input.review = reviewModel; + + producer.send(input); + + Awaitility.await() + .atMost(5, TimeUnit.SECONDS) + .untilAsserted(() -> { + ReviewEntity saved = QuarkusTransaction.requiringNew().call(() -> + ReviewEntity.find("reviewerId", reviewerId).firstResult() + ); + assertNotNull(saved); + }); + } +} diff --git a/eatery-service/src/test/resources/application.properties b/eatery-service/src/test/resources/application.properties new file mode 100644 index 0000000..8c405bc --- /dev/null +++ b/eatery-service/src/test/resources/application.properties @@ -0,0 +1,15 @@ +# Kafka +kafka.bootstrap.servers=localhost:9092 + +# --- CẤU HÌNH GỬI TIN (OUTGOING) --- +# Kênh "eatery-out" sẽ gửi vào topic "eatery-events" +# mp.messaging.outgoing.eatery-out.connector=smallrye-kafka +# mp.messaging.outgoing.eatery-out.topic=eatery-events +# # Tự động biến Object thành JSON +# mp.messaging.outgoing.eatery-out.value.serializer=io.quarkus.kafka.client.serialization.ObjectMapperSerializer + +# --- CẤU HÌNH NHẬN TIN (INCOMING) --- +mp.messaging.outgoing.review-test.connector=smallrye-kafka +mp.messaging.outgoing.review-test.topic=review-topic +# Sửa serializer cho đúng loại dành cho việc GỬI +mp.messaging.outgoing.review-test.value.serializer=io.quarkus.kafka.client.serialization.ObjectMapperSerializer \ No newline at end of file diff --git a/gateway-service/src/main/resources/application.properties b/gateway-service/src/main/resources/application.properties index 92a3501..6993984 100644 --- a/gateway-service/src/main/resources/application.properties +++ b/gateway-service/src/main/resources/application.properties @@ -1,5 +1 @@ -mp.messaging.incoming.words-in.auto.offset.reset=earliest -mp.messaging.incoming.words-in.topic=words -mp.messaging.outgoing.words-out.topic=words - quarkus.rest-client.account.url=http://localhost:502 \ No newline at end of file diff --git a/lib/src/main/java/com/drinkool/dtos/SendReview.java b/lib/src/main/java/com/drinkool/dtos/SendReview.java new file mode 100644 index 0000000..a887081 --- /dev/null +++ b/lib/src/main/java/com/drinkool/dtos/SendReview.java @@ -0,0 +1,11 @@ +package com.drinkool.dtos; + +import java.util.UUID; + +import com.drinkool.models.ReviewModel; + +public class SendReview { + public UUID reviewerId; + public UUID orderId; + public ReviewModel review; +} diff --git a/lib/src/main/java/com/drinkool/models/BaseReview.java b/lib/src/main/java/com/drinkool/models/ReviewModel.java similarity index 88% rename from lib/src/main/java/com/drinkool/models/BaseReview.java rename to lib/src/main/java/com/drinkool/models/ReviewModel.java index 5b83bc8..e7da336 100644 --- a/lib/src/main/java/com/drinkool/models/BaseReview.java +++ b/lib/src/main/java/com/drinkool/models/ReviewModel.java @@ -5,7 +5,7 @@ import jakarta.persistence.*; import java.time.LocalDateTime; @MappedSuperclass -public class BaseReview extends PanacheEntity { +public class ReviewModel extends PanacheEntity { @Column public int rating;