f31d1a8fb0570ebcbec1e4e3a74e02added53e31
[demos/kafka/demos-kafka-payment-system-transfer] / src / main / java / de / juplo / kafka / payment / transfer / adapter / TransferController.java
1 package de.juplo.kafka.payment.transfer.adapter;
2
3
4 import de.juplo.kafka.payment.transfer.domain.Transfer;
5 import de.juplo.kafka.payment.transfer.ports.GetTransferUseCase;
6 import de.juplo.kafka.payment.transfer.ports.ReceiveTransferUseCase;
7 import lombok.RequiredArgsConstructor;
8 import lombok.extern.slf4j.Slf4j;
9 import org.springframework.http.HttpStatus;
10 import org.springframework.http.MediaType;
11 import org.springframework.http.ResponseEntity;
12 import org.springframework.validation.FieldError;
13 import org.springframework.web.bind.MethodArgumentNotValidException;
14 import org.springframework.web.bind.annotation.*;
15 import org.springframework.web.context.request.async.DeferredResult;
16
17 import javax.servlet.http.HttpServletRequest;
18 import javax.validation.Valid;
19 import java.net.URI;
20 import java.util.Date;
21 import java.util.HashMap;
22 import java.util.Map;
23
24
25 @RestController
26 @RequiredArgsConstructor
27 @Slf4j
28  public class TransferController
29 {
30   public final static String PATH = "/transfers";
31
32   private final ReceiveTransferUseCase receiveTransferUseCase;
33   private final GetTransferUseCase getTransferUseCase;
34
35
36   @PostMapping(
37       path = PATH,
38       consumes = MediaType.APPLICATION_JSON_VALUE,
39       produces = MediaType.APPLICATION_JSON_VALUE)
40   public DeferredResult<ResponseEntity<?>> transfer(
41       HttpServletRequest request,
42       @Valid @RequestBody TransferDTO transferDTO)
43   {
44     Transfer transfer =
45         Transfer
46             .builder()
47             .id(transferDTO.getId())
48             .payer(transferDTO.getPayer())
49             .payee(transferDTO.getPayee())
50             .amount(transferDTO.getAmount())
51             .build();
52
53     DeferredResult<ResponseEntity<?>> result = new DeferredResult<>();
54
55     receiveTransferUseCase
56         .receive(transfer)
57         .thenApply(
58             $ ->
59                 ResponseEntity
60                     .created(URI.create(PATH + "/" + transferDTO.getId()))
61                     .build())
62         .thenAccept(
63             responseEntity -> result.setResult(responseEntity))
64         .exceptionally(
65             e ->
66             {
67               result.setErrorResult(e);
68               return null;
69             });
70
71     return result;
72   }
73
74   @GetMapping(
75       path = PATH + "/{id}",
76       produces = MediaType.APPLICATION_JSON_VALUE)
77   public ResponseEntity<TransferDTO> get(@PathVariable Long id)
78   {
79     return
80         getTransferUseCase
81             .get(id)
82             .map(transfer -> ResponseEntity.ok(TransferDTO.of(transfer)))
83             .orElse(ResponseEntity.notFound().build());
84   }
85
86   @ResponseStatus(HttpStatus.BAD_REQUEST)
87   @ExceptionHandler(MethodArgumentNotValidException.class)
88   public Map<String, Object> handleValidationExceptions(
89       HttpServletRequest request,
90       MethodArgumentNotValidException e)
91   {
92     Map<String, Object> errorAttributes = new HashMap<>();
93     errorAttributes.put("status", HttpStatus.BAD_REQUEST.value());
94     errorAttributes.put("error", HttpStatus.BAD_REQUEST.getReasonPhrase());
95     errorAttributes.put("path", request.getRequestURI());
96     errorAttributes.put("method", request.getMethod());
97     errorAttributes.put("timestamp", new Date());
98     Map<String, String> errors = new HashMap<>();
99     e.getBindingResult().getAllErrors().forEach((error) -> {
100       String fieldName = ((FieldError) error).getField();
101       String errorMessage = error.getDefaultMessage();
102       errors.put(fieldName, errorMessage);
103     });
104     errorAttributes.put("errors", errors);
105     errorAttributes.put("message", "Validation failed: Invalid message format, error count: " + errors.size());
106     return errorAttributes;
107   }
108 }