diff --git a/loan-agreement/src/main/java/de/weinbrecht/luc/bpm/architecture/loan/agreement/adapter/in/web/RestExceptionHandlerAdvice.java b/loan-agreement/src/main/java/de/weinbrecht/luc/bpm/architecture/loan/agreement/adapter/in/web/RestExceptionHandlerAdvice.java new file mode 100644 index 0000000..968a814 --- /dev/null +++ b/loan-agreement/src/main/java/de/weinbrecht/luc/bpm/architecture/loan/agreement/adapter/in/web/RestExceptionHandlerAdvice.java @@ -0,0 +1,27 @@ +package de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.in.web; + +import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.service.LoanAgreementException; +import io.github.domainprimitives.validation.InvariantException; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.context.request.WebRequest; +import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; + +import static org.springframework.http.HttpStatus.BAD_REQUEST; +import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; + +@ControllerAdvice +public class RestExceptionHandlerAdvice extends ResponseEntityExceptionHandler { + + @ExceptionHandler(value = LoanAgreementException.class) + protected ResponseEntity handleDomainException(LoanAgreementException ex, WebRequest request) { + return handleExceptionInternal(ex, ex.getMessage(), new HttpHeaders(), INTERNAL_SERVER_ERROR, request); + } + + @ExceptionHandler(value = InvariantException.class) + protected ResponseEntity handleInvariantConflict(InvariantException ex, WebRequest request) { + return handleExceptionInternal(ex, ex.getMessage(), new HttpHeaders(), BAD_REQUEST, request); + } +} diff --git a/loan-agreement/src/main/java/de/weinbrecht/luc/bpm/architecture/loan/agreement/domain/service/LoanAgreementException.java b/loan-agreement/src/main/java/de/weinbrecht/luc/bpm/architecture/loan/agreement/domain/service/LoanAgreementException.java index 1e2104c..03fec6a 100644 --- a/loan-agreement/src/main/java/de/weinbrecht/luc/bpm/architecture/loan/agreement/domain/service/LoanAgreementException.java +++ b/loan-agreement/src/main/java/de/weinbrecht/luc/bpm/architecture/loan/agreement/domain/service/LoanAgreementException.java @@ -2,10 +2,6 @@ package de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.service; public class LoanAgreementException extends RuntimeException { - public LoanAgreementException(String message) { - super(message); - } - public LoanAgreementException(String message, Throwable cause) { super(message, cause); } diff --git a/loan-agreement/src/test/java/de/weinbrecht/luc/bpm/architecture/loan/agreement/adapter/in/web/DemoController.java b/loan-agreement/src/test/java/de/weinbrecht/luc/bpm/architecture/loan/agreement/adapter/in/web/DemoController.java new file mode 100644 index 0000000..c88c6ae --- /dev/null +++ b/loan-agreement/src/test/java/de/weinbrecht/luc/bpm/architecture/loan/agreement/adapter/in/web/DemoController.java @@ -0,0 +1,24 @@ +package de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.in.web; + +import de.weinbrecht.luc.bpm.architecture.loan.agreement.domain.service.LoanAgreementException; +import io.github.domainprimitives.validation.InvariantException; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RequiredArgsConstructor +@RestController +@RequestMapping("error") +public class DemoController { + + @GetMapping("/invariant") + public void provideInvariant() { + throw new InvariantException("Foo", "Testing"); + } + + @GetMapping("/domain") + public void provideDomainException() { + throw new LoanAgreementException("Bar", null); + } +} diff --git a/loan-agreement/src/test/java/de/weinbrecht/luc/bpm/architecture/loan/agreement/adapter/in/web/RestExceptionHandlerAdviceTest.java b/loan-agreement/src/test/java/de/weinbrecht/luc/bpm/architecture/loan/agreement/adapter/in/web/RestExceptionHandlerAdviceTest.java new file mode 100644 index 0000000..d2148cc --- /dev/null +++ b/loan-agreement/src/test/java/de/weinbrecht/luc/bpm/architecture/loan/agreement/adapter/in/web/RestExceptionHandlerAdviceTest.java @@ -0,0 +1,27 @@ +package de.weinbrecht.luc.bpm.architecture.loan.agreement.adapter.in.web; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.test.web.servlet.MockMvc; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + + +@WebMvcTest(DemoController.class) +class RestExceptionHandlerAdviceTest { + + @Autowired + private MockMvc mockMvc; + + @Test + void should_handle_invariants() throws Exception { + mockMvc.perform(get("/error/invariant")).andExpect(status().isBadRequest()); + } + + @Test + void should_handle_domain_exception() throws Exception { + mockMvc.perform(get("/error/domain")).andExpect(status().isInternalServerError()); + } +} \ No newline at end of file diff --git a/loan-agreement/src/test/java/de/weinbrecht/luc/bpm/architecture/loan/agreement/domain/service/LoanAgreementServiceTest.java b/loan-agreement/src/test/java/de/weinbrecht/luc/bpm/architecture/loan/agreement/domain/service/LoanAgreementServiceTest.java index 948417b..b2c6668 100644 --- a/loan-agreement/src/test/java/de/weinbrecht/luc/bpm/architecture/loan/agreement/domain/service/LoanAgreementServiceTest.java +++ b/loan-agreement/src/test/java/de/weinbrecht/luc/bpm/architecture/loan/agreement/domain/service/LoanAgreementServiceTest.java @@ -56,7 +56,7 @@ class LoanAgreementServiceTest { assertThrows(LoanAgreementException.class, () -> classUnderTest.create(loanAgreement, caseId)); - verify(recommendationTrigger, never()).startLoanAgreement(caseId, any()); + verify(recommendationTrigger, never()).startLoanAgreement(eq(caseId), any()); } @Test diff --git a/recommendation/src/main/java/de/weinbrecht/luc/bpm/architecture/recommendation/adapter/in/web/RestExceptionHandlerAdvice.java b/recommendation/src/main/java/de/weinbrecht/luc/bpm/architecture/recommendation/adapter/in/web/RestExceptionHandlerAdvice.java new file mode 100644 index 0000000..eed729f --- /dev/null +++ b/recommendation/src/main/java/de/weinbrecht/luc/bpm/architecture/recommendation/adapter/in/web/RestExceptionHandlerAdvice.java @@ -0,0 +1,20 @@ +package de.weinbrecht.luc.bpm.architecture.recommendation.adapter.in.web; + +import io.github.domainprimitives.validation.InvariantException; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.context.request.WebRequest; +import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; + +import static org.springframework.http.HttpStatus.BAD_REQUEST; + +@ControllerAdvice +public class RestExceptionHandlerAdvice extends ResponseEntityExceptionHandler { + + @ExceptionHandler(value = InvariantException.class) + protected ResponseEntity handleInvariantConflict(InvariantException ex, WebRequest request) { + return handleExceptionInternal(ex, ex.getMessage(), new HttpHeaders(), BAD_REQUEST, request); + } +} diff --git a/recommendation/src/test/java/de/weinbrecht/luc/bpm/architecture/recommendation/adapter/in/web/DemoController.java b/recommendation/src/test/java/de/weinbrecht/luc/bpm/architecture/recommendation/adapter/in/web/DemoController.java new file mode 100644 index 0000000..86aef03 --- /dev/null +++ b/recommendation/src/test/java/de/weinbrecht/luc/bpm/architecture/recommendation/adapter/in/web/DemoController.java @@ -0,0 +1,18 @@ +package de.weinbrecht.luc.bpm.architecture.recommendation.adapter.in.web; + +import io.github.domainprimitives.validation.InvariantException; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RequiredArgsConstructor +@RestController +@RequestMapping("error") +public class DemoController { + + @GetMapping() + public void provideInvariant() { + throw new InvariantException("Foo", "Testing"); + } +} diff --git a/recommendation/src/test/java/de/weinbrecht/luc/bpm/architecture/recommendation/adapter/in/web/RestExceptionHandlerAdviceTest.java b/recommendation/src/test/java/de/weinbrecht/luc/bpm/architecture/recommendation/adapter/in/web/RestExceptionHandlerAdviceTest.java new file mode 100644 index 0000000..dbf3b2f --- /dev/null +++ b/recommendation/src/test/java/de/weinbrecht/luc/bpm/architecture/recommendation/adapter/in/web/RestExceptionHandlerAdviceTest.java @@ -0,0 +1,22 @@ +package de.weinbrecht.luc.bpm.architecture.recommendation.adapter.in.web; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.test.web.servlet.MockMvc; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + + +@WebMvcTest(DemoController.class) +class RestExceptionHandlerAdviceTest { + + @Autowired + private MockMvc mockMvc; + + @Test + void should_handle_invariants() throws Exception { + mockMvc.perform(get("/error")).andExpect(status().isBadRequest()); + } +} \ No newline at end of file