Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com> Reviewed-on: #35
This commit was merged in pull request #35.
This commit is contained in:
+15
-2
@@ -1,5 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
@@ -42,6 +44,16 @@
|
|||||||
<artifactId>lib</artifactId>
|
<artifactId>lib</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.datafaker</groupId>
|
||||||
|
<artifactId>datafaker</artifactId>
|
||||||
|
<version>2.0.2</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.quarkus</groupId>
|
||||||
|
<artifactId>quarkus-smallrye-graphql</artifactId>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.quarkus</groupId>
|
<groupId>io.quarkus</groupId>
|
||||||
<artifactId>quarkus-messaging-kafka</artifactId>
|
<artifactId>quarkus-messaging-kafka</artifactId>
|
||||||
@@ -144,7 +156,8 @@
|
|||||||
<configuration>
|
<configuration>
|
||||||
<argLine>@{argLine}</argLine>
|
<argLine>@{argLine}</argLine>
|
||||||
<systemPropertyVariables>
|
<systemPropertyVariables>
|
||||||
<native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path>
|
<native.image.path>
|
||||||
|
${project.build.directory}/${project.build.finalName}-runner</native.image.path>
|
||||||
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
|
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
|
||||||
<maven.home>${maven.home}</maven.home>
|
<maven.home>${maven.home}</maven.home>
|
||||||
</systemPropertyVariables>
|
</systemPropertyVariables>
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package com.drinkool.entities;
|
|||||||
import com.drinkool.lib.entities.BaseEntity;
|
import com.drinkool.lib.entities.BaseEntity;
|
||||||
import jakarta.persistence.*;
|
import jakarta.persistence.*;
|
||||||
import jakarta.transaction.Transactional;
|
import jakarta.transaction.Transactional;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@@ -18,10 +20,17 @@ public class EateryEntity extends BaseEntity {
|
|||||||
@Column(nullable = false)
|
@Column(nullable = false)
|
||||||
public boolean isVerified = false;
|
public boolean isVerified = false;
|
||||||
|
|
||||||
|
@OneToMany(
|
||||||
|
mappedBy = "eatery",
|
||||||
|
cascade = CascadeType.ALL,
|
||||||
|
orphanRemoval = true
|
||||||
|
)
|
||||||
|
public List<MenuItemEntity> menus = new ArrayList<>();
|
||||||
|
|
||||||
public EateryEntity() {}
|
public EateryEntity() {}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public void create(UUID ownerId, String name) {
|
public EateryEntity create(UUID ownerId, String name) {
|
||||||
EateryEntity existedEatery = EateryEntity.find(
|
EateryEntity existedEatery = EateryEntity.find(
|
||||||
"ownerId",
|
"ownerId",
|
||||||
ownerId
|
ownerId
|
||||||
@@ -33,5 +42,7 @@ public class EateryEntity extends BaseEntity {
|
|||||||
this.name = name;
|
this.name = name;
|
||||||
|
|
||||||
this.persist();
|
this.persist();
|
||||||
|
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,9 +9,16 @@ import java.util.*;
|
|||||||
@Table
|
@Table
|
||||||
public class MenuItemEntity extends BaseEntity {
|
public class MenuItemEntity extends BaseEntity {
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
public String name;
|
public String name;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
public double price;
|
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
|
// Danh sách các nguyên liệu cấu thành món ăn này
|
||||||
@OneToMany(
|
@OneToMany(
|
||||||
mappedBy = "menuItem",
|
mappedBy = "menuItem",
|
||||||
|
|||||||
@@ -2,12 +2,17 @@ package com.drinkool.services;
|
|||||||
|
|
||||||
import com.drinkool.dtos.event.ManagerCreate;
|
import com.drinkool.dtos.event.ManagerCreate;
|
||||||
import com.drinkool.entities.EateryEntity;
|
import com.drinkool.entities.EateryEntity;
|
||||||
|
|
||||||
import jakarta.enterprise.context.ApplicationScoped;
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
import jakarta.transaction.Transactional;
|
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;
|
import org.eclipse.microprofile.reactive.messaging.Incoming;
|
||||||
|
|
||||||
@ApplicationScoped
|
@ApplicationScoped
|
||||||
|
@GraphQLApi
|
||||||
public class EateryService {
|
public class EateryService {
|
||||||
|
|
||||||
@Incoming("manager-in")
|
@Incoming("manager-in")
|
||||||
@@ -17,4 +22,14 @@ public class EateryService {
|
|||||||
|
|
||||||
eatery.create(input.id, input.eateryName);
|
eatery.create(input.id, input.eateryName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Query("allEateries")
|
||||||
|
public List<EateryEntity> getAll() {
|
||||||
|
return EateryEntity.listAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Query("eateryById")
|
||||||
|
public EateryEntity getEatery(@Name("id") UUID id) {
|
||||||
|
return EateryEntity.findById(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,30 @@
|
|||||||
package com.drinkool.services;
|
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.dtos.event.ManagerCreate;
|
||||||
import com.drinkool.entities.EateryEntity;
|
import com.drinkool.entities.EateryEntity;
|
||||||
import io.quarkus.test.junit.QuarkusTest;
|
import io.quarkus.test.junit.QuarkusTest;
|
||||||
|
import io.restassured.http.ContentType;
|
||||||
import io.smallrye.reactive.messaging.memory.InMemoryConnector;
|
import io.smallrye.reactive.messaging.memory.InMemoryConnector;
|
||||||
import jakarta.enterprise.context.control.ActivateRequestContext;
|
import jakarta.enterprise.context.control.ActivateRequestContext;
|
||||||
import jakarta.enterprise.inject.Any;
|
import jakarta.enterprise.inject.Any;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
|
import jakarta.transaction.Transactional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import net.datafaker.Faker;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
@QuarkusTest
|
@QuarkusTest
|
||||||
public class EateryServiceTest {
|
public class EateryServiceTest {
|
||||||
|
|
||||||
|
private final Faker faker = new Faker();
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@Any
|
@Any
|
||||||
InMemoryConnector connector;
|
InMemoryConnector connector;
|
||||||
@@ -40,4 +51,59 @@ public class EateryServiceTest {
|
|||||||
Assertions.assertNotNull(eatery, "Eatery should be created in DB");
|
Assertions.assertNotNull(eatery, "Eatery should be created in DB");
|
||||||
Assertions.assertEquals("Quan Bun Cha Test", eatery.name);
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,10 @@
|
|||||||
<artifactId>jose4j</artifactId>
|
<artifactId>jose4j</artifactId>
|
||||||
<version>0.9.6</version>
|
<version>0.9.6</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.quarkus</groupId>
|
||||||
|
<artifactId>quarkus-smallrye-graphql-client</artifactId>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.drinkool</groupId>
|
<groupId>com.drinkool</groupId>
|
||||||
<artifactId>lib</artifactId>
|
<artifactId>lib</artifactId>
|
||||||
|
|||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,8 +3,9 @@ package com.drinkool.controller;
|
|||||||
import static io.restassured.RestAssured.*;
|
import static io.restassured.RestAssured.*;
|
||||||
import static org.hamcrest.CoreMatchers.*;
|
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 io.quarkus.test.junit.QuarkusTest;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ spec:
|
|||||||
env:
|
env:
|
||||||
- name: QUARKUS_REST_CLIENT_ACCOUNT_URL
|
- name: QUARKUS_REST_CLIENT_ACCOUNT_URL
|
||||||
value: "http://account-service"
|
value: "http://account-service"
|
||||||
|
- name: QUARKUS_SMALLRYE_GRAPHQL_CLIENT_EATERY_URL
|
||||||
|
value: "http://eatery-service/graphql"
|
||||||
- name: GATEWAY_JWT_SECRET
|
- name: GATEWAY_JWT_SECRET
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
|
|||||||
+1
-1
@@ -19,7 +19,7 @@ spec:
|
|||||||
- containerPort: 9000
|
- containerPort: 9000
|
||||||
env:
|
env:
|
||||||
- name: KAFKA_BROKERCONNECT
|
- name: KAFKA_BROKERCONNECT
|
||||||
value: "kafka-service:9092" # Trỏ vào service Kafka của bạn
|
value: "kafka-service:9092"
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
|
|||||||
Reference in New Issue
Block a user