diff --git a/eatery-service/pom.xml b/eatery-service/pom.xml
index 9f926e5..c3be3c3 100644
--- a/eatery-service/pom.xml
+++ b/eatery-service/pom.xml
@@ -1,5 +1,7 @@
-
+
4.0.0
@@ -42,6 +44,16 @@
lib
${project.version}
+
+ net.datafaker
+ datafaker
+ 2.0.2
+ test
+
+
+ io.quarkus
+ quarkus-smallrye-graphql
+
io.quarkus
quarkus-messaging-kafka
@@ -144,7 +156,8 @@
@{argLine}
- ${project.build.directory}/${project.build.finalName}-runner
+
+ ${project.build.directory}/${project.build.finalName}-runner
org.jboss.logmanager.LogManager
${maven.home}
@@ -168,4 +181,4 @@
-
+
\ No newline at end of file
diff --git a/eatery-service/src/main/java/com/drinkool/entities/EateryEntity.java b/eatery-service/src/main/java/com/drinkool/entities/EateryEntity.java
index ae47d29..d8e16d9 100644
--- a/eatery-service/src/main/java/com/drinkool/entities/EateryEntity.java
+++ b/eatery-service/src/main/java/com/drinkool/entities/EateryEntity.java
@@ -3,6 +3,8 @@ package com.drinkool.entities;
import com.drinkool.lib.entities.BaseEntity;
import jakarta.persistence.*;
import jakarta.transaction.Transactional;
+import java.util.ArrayList;
+import java.util.List;
import java.util.UUID;
@Entity
@@ -18,10 +20,17 @@ public class EateryEntity extends BaseEntity {
@Column(nullable = false)
public boolean isVerified = false;
+ @OneToMany(
+ mappedBy = "eatery",
+ cascade = CascadeType.ALL,
+ orphanRemoval = true
+ )
+ public List menus = new ArrayList<>();
+
public EateryEntity() {}
@Transactional
- public void create(UUID ownerId, String name) {
+ public EateryEntity create(UUID ownerId, String name) {
EateryEntity existedEatery = EateryEntity.find(
"ownerId",
ownerId
@@ -33,5 +42,7 @@ public class EateryEntity extends BaseEntity {
this.name = name;
this.persist();
+
+ return this;
}
}
diff --git a/eatery-service/src/main/java/com/drinkool/entities/MenuItemEntity.java b/eatery-service/src/main/java/com/drinkool/entities/MenuItemEntity.java
index efbd32a..39ddb09 100644
--- a/eatery-service/src/main/java/com/drinkool/entities/MenuItemEntity.java
+++ b/eatery-service/src/main/java/com/drinkool/entities/MenuItemEntity.java
@@ -9,9 +9,16 @@ import java.util.*;
@Table
public class MenuItemEntity extends BaseEntity {
+ @Column(nullable = false)
public String name;
+
+ @Column(nullable = false)
public double price;
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "eatery_id")
+ public EateryEntity eatery;
+
// Danh sách các nguyên liệu cấu thành món ăn này
@OneToMany(
mappedBy = "menuItem",
diff --git a/eatery-service/src/main/java/com/drinkool/services/EateryService.java b/eatery-service/src/main/java/com/drinkool/services/EateryService.java
index 68844ef..50a26af 100644
--- a/eatery-service/src/main/java/com/drinkool/services/EateryService.java
+++ b/eatery-service/src/main/java/com/drinkool/services/EateryService.java
@@ -2,12 +2,17 @@ package com.drinkool.services;
import com.drinkool.dtos.event.ManagerCreate;
import com.drinkool.entities.EateryEntity;
-
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.transaction.Transactional;
+import java.util.List;
+import java.util.UUID;
+import org.eclipse.microprofile.graphql.GraphQLApi;
+import org.eclipse.microprofile.graphql.Name;
+import org.eclipse.microprofile.graphql.Query;
import org.eclipse.microprofile.reactive.messaging.Incoming;
@ApplicationScoped
+@GraphQLApi
public class EateryService {
@Incoming("manager-in")
@@ -17,4 +22,14 @@ public class EateryService {
eatery.create(input.id, input.eateryName);
}
+
+ @Query("allEateries")
+ public List getAll() {
+ return EateryEntity.listAll();
+ }
+
+ @Query("eateryById")
+ public EateryEntity getEatery(@Name("id") UUID id) {
+ return EateryEntity.findById(id);
+ }
}
diff --git a/eatery-service/src/test/java/com/drinkool/services/EateryServiceTest.java b/eatery-service/src/test/java/com/drinkool/services/EateryServiceTest.java
index 897be96..16bde3e 100644
--- a/eatery-service/src/test/java/com/drinkool/services/EateryServiceTest.java
+++ b/eatery-service/src/test/java/com/drinkool/services/EateryServiceTest.java
@@ -1,19 +1,30 @@
package com.drinkool.services;
+import static io.restassured.RestAssured.given;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.Matchers.hasItems;
+
import com.drinkool.dtos.event.ManagerCreate;
import com.drinkool.entities.EateryEntity;
import io.quarkus.test.junit.QuarkusTest;
+import io.restassured.http.ContentType;
import io.smallrye.reactive.messaging.memory.InMemoryConnector;
import jakarta.enterprise.context.control.ActivateRequestContext;
import jakarta.enterprise.inject.Any;
import jakarta.inject.Inject;
+import jakarta.transaction.Transactional;
import java.util.UUID;
+import net.datafaker.Faker;
import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@QuarkusTest
public class EateryServiceTest {
+ private final Faker faker = new Faker();
+
@Inject
@Any
InMemoryConnector connector;
@@ -40,4 +51,59 @@ public class EateryServiceTest {
Assertions.assertNotNull(eatery, "Eatery should be created in DB");
Assertions.assertEquals("Quan Bun Cha Test", eatery.name);
}
+
+ private UUID lastSavedId;
+ private String lastSavedName;
+
+ @BeforeEach
+ @Transactional
+ void setup() {
+ EateryEntity.deleteAll();
+
+ lastSavedName = faker.restaurant().name();
+
+ EateryEntity eatery = new EateryEntity();
+ lastSavedId = eatery.create(UUID.randomUUID(), lastSavedName).id;
+
+ for (int i = 0; i < 2; i++) {
+ EateryEntity e = new EateryEntity();
+ e.create(UUID.randomUUID(), faker.restaurant().name());
+ }
+ }
+
+ @Test
+ void testGetAllEateries() {
+ // Cấu trúc query GraphQL
+ String query = "{ \"query\": \"{ allEateries { ownerId name } }\" }";
+
+ given()
+ .contentType(ContentType.JSON)
+ .body(query)
+ .when()
+ .post("/graphql")
+ .then()
+ .statusCode(200)
+ // GraphQL trả về dữ liệu bọc trong object "data"
+ .body("data.allEateries", notNullValue())
+ .body("data.allEateries.name", hasItems(lastSavedName));
+ }
+
+ @Test
+ void testGetEateryById() {
+ // Sử dụng biến id đã lưu ở setup
+ // Lưu ý: Trong GraphQL, String/UUID phải nằm trong dấu ngoặc kép
+ String query = String.format(
+ "{ \"query\": \"{ eateryById(id: \\\"%s\\\") { ownerId name } }\" }",
+ lastSavedId
+ );
+
+ given()
+ .contentType(ContentType.JSON)
+ .body(query)
+ .when()
+ .post("/graphql")
+ .then()
+ .statusCode(200)
+ .body("data.eateryById.name", is(lastSavedName));
+ }
}
diff --git a/gateway-service/pom.xml b/gateway-service/pom.xml
index 1743d61..ecbdb89 100644
--- a/gateway-service/pom.xml
+++ b/gateway-service/pom.xml
@@ -48,6 +48,10 @@
jose4j
0.9.6
+
+ io.quarkus
+ quarkus-smallrye-graphql-client
+
com.drinkool
lib
diff --git a/gateway-service/src/main/java/com/drinkool/controller/EateryController.java b/gateway-service/src/main/java/com/drinkool/controller/EateryController.java
new file mode 100644
index 0000000..3e98288
--- /dev/null
+++ b/gateway-service/src/main/java/com/drinkool/controller/EateryController.java
@@ -0,0 +1,34 @@
+package com.drinkool.controller;
+
+import io.smallrye.graphql.client.GraphQLClient;
+import io.smallrye.graphql.client.dynamic.api.DynamicGraphQLClient;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.core.Response;
+import java.util.concurrent.ExecutionException;
+
+@Path("/api/eatery")
+public class EateryController {
+
+ @GraphQLClient("eatery")
+ DynamicGraphQLClient dynamicClient;
+
+ @POST
+ @Path("/graphql")
+ public Response forward(String query)
+ throws ExecutionException, InterruptedException {
+ io.smallrye.graphql.client.Response response = dynamicClient.executeSync(
+ query
+ );
+
+ if (response.hasError()) {
+ return jakarta.ws.rs.core.Response.status(500)
+ .entity(response.getErrors())
+ .build();
+ }
+
+ return jakarta.ws.rs.core.Response.ok(
+ response.getData().toString()
+ ).build();
+ }
+}
diff --git a/gateway-service/src/test/java/com/drinkool/controller/BaseControllerTest.java b/gateway-service/src/test/java/com/drinkool/controller/BaseControllerTest.java
index 3b04780..2382510 100644
--- a/gateway-service/src/test/java/com/drinkool/controller/BaseControllerTest.java
+++ b/gateway-service/src/test/java/com/drinkool/controller/BaseControllerTest.java
@@ -3,8 +3,9 @@ package com.drinkool.controller;
import static io.restassured.RestAssured.*;
import static org.hamcrest.CoreMatchers.*;
-import com.drinkool.*;
-
+import com.drinkool.InternalValue;
+import com.drinkool.Role;
+import com.drinkool.Url;
import io.quarkus.test.junit.QuarkusTest;
import org.junit.jupiter.api.Test;
diff --git a/k8s/gateway.yaml b/k8s/gateway.yaml
index d4bc419..47f2316 100644
--- a/k8s/gateway.yaml
+++ b/k8s/gateway.yaml
@@ -21,6 +21,8 @@ spec:
env:
- name: QUARKUS_REST_CLIENT_ACCOUNT_URL
value: "http://account-service"
+ - name: QUARKUS_SMALLRYE_GRAPHQL_CLIENT_EATERY_URL
+ value: "http://eatery-service/graphql"
- name: GATEWAY_JWT_SECRET
valueFrom:
secretKeyRef:
diff --git a/k8s/kafdrop.yaml b/k8s/kafdrop.yaml
index 9e0a2ed..129d0ea 100644
--- a/k8s/kafdrop.yaml
+++ b/k8s/kafdrop.yaml
@@ -13,13 +13,13 @@ spec:
app: kafdrop
spec:
containers:
- - name: kafdrop
- image: obsidiandynamics/kafdrop
- ports:
- - containerPort: 9000
- env:
- - name: KAFKA_BROKERCONNECT
- value: "kafka-service:9092" # Trỏ vào service Kafka của bạn
+ - name: kafdrop
+ image: obsidiandynamics/kafdrop
+ ports:
+ - containerPort: 9000
+ env:
+ - name: KAFKA_BROKERCONNECT
+ value: "kafka-service:9092"
---
apiVersion: v1
kind: Service
@@ -30,6 +30,6 @@ spec:
selector:
app: kafdrop
ports:
- - protocol: TCP
- port: 9000
- nodePort: 30900
\ No newline at end of file
+ - protocol: TCP
+ port: 9000
+ nodePort: 30900