diff --git a/common/common-application/pom.xml b/common/common-application/pom.xml
new file mode 100644
index 0000000..ef98914
--- /dev/null
+++ b/common/common-application/pom.xml
@@ -0,0 +1,26 @@
+
+
+
+ common
+ com.food.order
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ common-application
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+
+
\ No newline at end of file
diff --git a/common/common-application/src/main/java/com/food/order/system/application/handler/ErrorDTO.java b/common/common-application/src/main/java/com/food/order/system/application/handler/ErrorDTO.java
new file mode 100644
index 0000000..701dfd4
--- /dev/null
+++ b/common/common-application/src/main/java/com/food/order/system/application/handler/ErrorDTO.java
@@ -0,0 +1,7 @@
+package com.food.order.system.application.handler;
+
+import lombok.Builder;
+
+@Builder
+public record ErrorDTO(String code, String message) {
+}
diff --git a/common/common-application/src/main/java/com/food/order/system/application/handler/GlobalExceptionHandler.java b/common/common-application/src/main/java/com/food/order/system/application/handler/GlobalExceptionHandler.java
new file mode 100644
index 0000000..a8ace14
--- /dev/null
+++ b/common/common-application/src/main/java/com/food/order/system/application/handler/GlobalExceptionHandler.java
@@ -0,0 +1,59 @@
+package com.food.order.system.application.handler;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+import javax.validation.ConstraintViolation;
+import javax.validation.ConstraintViolationException;
+import javax.validation.ValidationException;
+import java.util.stream.Collectors;
+
+@Slf4j
+@ControllerAdvice
+public class GlobalExceptionHandler {
+
+ @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+ @ExceptionHandler(value = {Exception.class})
+ @ResponseBody
+ public ErrorDTO handleOrderDomainException(Exception e) {
+ log.error("Error occurred: {}", e.getMessage());
+ return ErrorDTO.builder()
+ .code(HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase())
+ .message("Unknown error occurred")
+ .build();
+ }
+
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ @ExceptionHandler(value = {ValidationException.class})
+ @ResponseBody
+ public ErrorDTO handleOrderDomainException(ValidationException e) {
+ ErrorDTO errorDTO;
+ if (e instanceof ConstraintViolationException) {
+ String violations = extractViolationsFromException((ConstraintViolationException) e);
+ log.error("Error occurred: {}", violations);
+ errorDTO = ErrorDTO.builder()
+ .code(HttpStatus.BAD_REQUEST.getReasonPhrase())
+ .message(violations)
+ .build();
+ }
+ else {
+ log.error("Error occurred: {}", e.getMessage());
+ errorDTO = ErrorDTO.builder()
+ .code(HttpStatus.BAD_REQUEST.getReasonPhrase())
+ .message(e.getMessage())
+ .build();
+ }
+ return errorDTO;
+ }
+
+ private String extractViolationsFromException(ConstraintViolationException e) {
+ return e.getConstraintViolations()
+ .stream()
+ .map(ConstraintViolation::getMessage)
+ .collect(Collectors.joining("->"));
+ }
+}
diff --git a/common/pom.xml b/common/pom.xml
index 3aaef7e..54296de 100644
--- a/common/pom.xml
+++ b/common/pom.xml
@@ -13,6 +13,7 @@
pom
common-domain
+ common-application
diff --git a/order-service/order-app/pom.xml b/order-service/order-app/pom.xml
index 06d5b62..5290602 100644
--- a/order-service/order-app/pom.xml
+++ b/order-service/order-app/pom.xml
@@ -19,6 +19,21 @@
com.food.order
order-application-service
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+
+ com.food.order
+ common-application
+
\ No newline at end of file
diff --git a/order-service/order-app/src/main/java/com/food/order/system/service/app/api/OrderController.java b/order-service/order-app/src/main/java/com/food/order/system/service/app/api/OrderController.java
new file mode 100644
index 0000000..5429e96
--- /dev/null
+++ b/order-service/order-app/src/main/java/com/food/order/system/service/app/api/OrderController.java
@@ -0,0 +1,43 @@
+package com.food.order.system.service.app.api;
+
+import com.food.order.domain.dto.create.CreateOrderCommand;
+import com.food.order.domain.dto.create.CreateOrderResponse;
+import com.food.order.domain.dto.track.TrackOrderQuery;
+import com.food.order.domain.dto.track.TrackOrderResponse;
+import com.food.order.domain.ports.input.service.OrderApplicationService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.ResponseEntity;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.context.annotation.RequestScope;
+
+import java.util.UUID;
+
+@RestController
+@CrossOrigin
+@RequestScope
+@RequiredArgsConstructor
+@Slf4j
+@Validated
+@RequestMapping(value = "/api/orders", produces = "application/vnd.api.v1+json")
+public class OrderController {
+
+ private final OrderApplicationService orderApplicationService;
+
+ @PostMapping
+ public ResponseEntity createOrder(@RequestBody CreateOrderCommand createOrderCommand) {
+ log.info("Creating order with command: {}", createOrderCommand);
+ CreateOrderResponse createOrderResponse = orderApplicationService.createOrder(createOrderCommand);
+ log.info("Created order with tracking id: {}", createOrderResponse.orderTrackingId());
+ return ResponseEntity.ok(createOrderResponse);
+ }
+
+ @GetMapping("/{orderTrackingId}")
+ public ResponseEntity trackOrder(@PathVariable("orderTrackingId") UUID orderTrackingId) {
+ TrackOrderResponse trackOrderResponse = orderApplicationService.trackOrder
+ (new TrackOrderQuery(orderTrackingId));
+ log.info("Tracked order with tracking id: {}", orderTrackingId);
+ return ResponseEntity.ok(trackOrderResponse);
+ }
+}
diff --git a/order-service/order-app/src/main/java/com/food/order/system/service/app/exception/OrderGlobalException.java b/order-service/order-app/src/main/java/com/food/order/system/service/app/exception/OrderGlobalException.java
new file mode 100644
index 0000000..113e6ca
--- /dev/null
+++ b/order-service/order-app/src/main/java/com/food/order/system/service/app/exception/OrderGlobalException.java
@@ -0,0 +1,42 @@
+package com.food.order.system.service.app.exception;
+
+import com.food.order.system.application.handler.ErrorDTO;
+import com.food.order.system.application.handler.GlobalExceptionHandler;
+import com.food.order.system.domain.exception.OrderDomainException;
+import com.food.order.system.domain.exception.OrderNotFoundException;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+@ControllerAdvice
+@Slf4j
+public class OrderGlobalException extends GlobalExceptionHandler {
+
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ @ExceptionHandler(value = {OrderDomainException.class})
+ @ResponseBody
+ public ErrorDTO handleOrderDomainException(OrderDomainException e) {
+ log.error("Error occurred: {}", e.getMessage());
+ return ErrorDTO.builder()
+ .code(HttpStatus.BAD_REQUEST.getReasonPhrase())
+ .message(e.getMessage())
+ .build();
+ }
+
+ @ResponseStatus(HttpStatus.NOT_FOUND)
+ @ExceptionHandler(value = {OrderNotFoundException.class})
+ @ResponseBody
+ public ErrorDTO handleOrderDomainException(OrderNotFoundException e) {
+ log.error("Error occurred: {}", e.getMessage());
+ return ErrorDTO.builder()
+ .code(HttpStatus.NOT_FOUND.getReasonPhrase())
+ .message(e.getMessage())
+ .build();
+ }
+
+
+
+}
diff --git a/order-service/order-domain/order-application-service/src/main/java/com/food/order/domain/dto/create/CreateOrderCommand.java b/order-service/order-domain/order-application-service/src/main/java/com/food/order/domain/dto/create/CreateOrderCommand.java
index 3fa1d62..7ba2a43 100644
--- a/order-service/order-domain/order-application-service/src/main/java/com/food/order/domain/dto/create/CreateOrderCommand.java
+++ b/order-service/order-domain/order-application-service/src/main/java/com/food/order/domain/dto/create/CreateOrderCommand.java
@@ -1,8 +1,6 @@
package com.food.order.domain.dto.create;
-import lombok.AllArgsConstructor;
import lombok.Builder;
-import lombok.Getter;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
diff --git a/order-service/order-domain/order-application-service/src/main/java/com/food/order/domain/dto/track/TrackOrderQuery.java b/order-service/order-domain/order-application-service/src/main/java/com/food/order/domain/dto/track/TrackOrderQuery.java
index 7a96a60..d0db11a 100644
--- a/order-service/order-domain/order-application-service/src/main/java/com/food/order/domain/dto/track/TrackOrderQuery.java
+++ b/order-service/order-domain/order-application-service/src/main/java/com/food/order/domain/dto/track/TrackOrderQuery.java
@@ -1,6 +1,5 @@
package com.food.order.domain.dto.track;
-import lombok.AllArgsConstructor;
import lombok.Builder;
import javax.validation.constraints.NotNull;
diff --git a/pom.xml b/pom.xml
index fb3ce3a..88843bb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -58,6 +58,11 @@
${project.version}
+
+ com.food.order
+ common-application
+ ${project.version}
+
com.food.order