+++ /dev/null
-package de.juplo.demos.pwreset.adapter;
-
-import de.juplo.demos.pwreset.domain.User;
-import de.juplo.demos.pwreset.domain.UsersService;
-import lombok.RequiredArgsConstructor;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.client.RestTemplate;
-
-import java.util.Optional;
-
-
-@RequiredArgsConstructor
-public class RemoteUsersServiceConsumer implements UsersService
-{
- private final String uriTemplate;
- private final RestTemplate restTemplate;
-
-
- @Override
- public Optional<User> getUserByEmail(String email) {
- ResponseEntity<UserDTO> response =
- restTemplate.getForEntity(uriTemplate, UserDTO.class, email);
- HttpStatus status = response.getStatusCode();
- UserDTO dto = response.getBody();
- switch (response.getStatusCode()) {
- case OK:
- return
- Optional.of(
- User.builder()
- .id(dto.id)
- .email(dto.email)
- .build());
- case NOT_FOUND:
- return Optional.empty();
- default:
- throw new RuntimeException(status.toString());
- }
- }
-}
+++ /dev/null
-package de.juplo.demos.pwreset.adapter;
-
-import lombok.Setter;
-
-import java.util.UUID;
-
-
-@Setter
-public class UserDTO
-{
- UUID id;
- String email;
-}
--- /dev/null
+package de.juplo.demos.pwreset.adapters.out;
+
+import de.juplo.demos.pwreset.domain.api.User;
+import de.juplo.demos.pwreset.domain.api.UsersService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Optional;
+
+
+@RequiredArgsConstructor
+public class RemoteUsersServiceConsumer implements UsersService
+{
+ private final String uriTemplate;
+ private final RestTemplate restTemplate;
+
+
+ @Override
+ public Optional<User> getUserByEmail(String email) {
+ ResponseEntity<UserDTO> response =
+ restTemplate.getForEntity(uriTemplate, UserDTO.class, email);
+ HttpStatus status = response.getStatusCode();
+ UserDTO dto = response.getBody();
+ switch (response.getStatusCode()) {
+ case OK:
+ return
+ Optional.of(
+ User.builder()
+ .id(dto.id)
+ .email(dto.email)
+ .build());
+ case NOT_FOUND:
+ return Optional.empty();
+ default:
+ throw new RuntimeException(status.toString());
+ }
+ }
+}
--- /dev/null
+package de.juplo.demos.pwreset.adapters.out;
+
+import lombok.Setter;
+
+import java.util.UUID;
+
+
+@Setter
+public class UserDTO
+{
+ UUID id;
+ String email;
+}
+++ /dev/null
-package de.juplo.demos.pwreset.domain;
-
-import lombok.Builder;
-import lombok.Data;
-
-import java.util.UUID;
-
-
-@Data
-@Builder
-public class User
-{
- private UUID id;
- private String email;
-}
+++ /dev/null
-package de.juplo.demos.pwreset.domain;
-
-import java.util.Optional;
-
-
-public interface UsersService
-{
- Optional<User> getUserByEmail(String email);
-}
--- /dev/null
+package de.juplo.demos.pwreset.domain.api;
+
+import lombok.Builder;
+import lombok.Data;
+
+import java.util.UUID;
+
+
+@Data
+@Builder
+public class User
+{
+ private UUID id;
+ private String email;
+}
--- /dev/null
+package de.juplo.demos.pwreset.domain.api;
+
+import java.util.Optional;
+
+
+public interface UsersService
+{
+ Optional<User> getUserByEmail(String email);
+}
--- /dev/null
+<!DOCTYPE HTML>
+<html xmlns:th="http://www.thymeleaf.org" th:replace="~{layout :: pagelayout(~{:: title}, ~{:: h1}, ~{:: div.card-text})}">
+ <head>
+ <title th:text="'400: ' + ${exception.getClass().getSimpleName()}">Testing Exception-Handling - Template for 400</title>
+ <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ </head>
+ <body>
+ <h1 th:text="'400: ' + ${exception.getClass().getSimpleName()}">Template for 400</h1>
+ <div class="card-text table">
+ <p><strong th:text="'Catched exception: ' + ${exception}">EXCEPTION</strong></p>
+ <p><a href="#" th:href="@{/}" class="btn btn-primary">Back to HOME</a></p>
+ </div>
+ </body>
+</html>
--- /dev/null
+<!doctype html>
+<html xmlns:th="http://www.thymeleaf.org" th:replace="~{layout :: pagelayout(~{:: title}, ~{:: h1}, ~{:: table.card-text})}">
+ <head>
+ <title th:text="|${status}: ${error}">XXX: ERROR</title>
+ <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ </head>
+ <body>
+ <h1 th:text="|${status}: ${error}">XXX: ERROR</h1>
+ <table class="card-text table">
+ <tbody>
+ <tr class="border-top-0">
+ <th scope="row">Status</th>
+ <td th:text="${status}">ERROR.STATUS</td>
+ </tr>
+ <tr>
+ <th scope="row">Error</th>
+ <td th:text="${error}">ERROR.ERROR</td>
+ </tr>
+ <tr th:if="!${#strings.isEmpty(message)}">
+ <th scope="row">Message</th>
+ <td th:text="${message}">ERROR.MESSAGE</td>
+ </tr>
+ <tr th:if="!${#strings.isEmpty(requestId)}">
+ <th class="text-nowrap" scope="row">Request-ID</th>
+ <td th:text="${requestId}">ERROR.REQUEST_ID</td>
+ </tr>
+ <tr>
+ <th scope="row">Timstamp</th>
+ <td th:text="${timestamp}">ERROR.TIMESTAMP</td>
+ </tr>
+ <tr th:if="!${#strings.isEmpty(path)}">
+ <th scope="row">Path</th>
+ <td th:text="${path}">ERROR.PATH</td>
+ </tr>
+ <!--/**-->
+ <tr th:if="!${#strings.isEmpty(trace)}">
+ <th scope="row">Trace</th>
+ <td>
+ <div class="overflow-hidden">
+ <pre class="overflow-hidden" th:text="${trace}">ERROR.TRACE</pre>
+ </div>
+ </td>
+ </tr>
+ <!--**/-->
+ </tbody>
+ </table>
+ <p><a href="#" th:href="@{/}" class="btn btn-primary">Back to HOME</a>
+ </div>
+ </body>
+</html>
--- /dev/null
+<!DOCTYPE HTML>
+<html xmlns:th="http://www.thymeleaf.org" th:replace="~{layout :: pagelayout(~{:: title}, ~{:: h1}, ~{:: div.card-text})}">
+ <head>
+ <title>Home</title>
+ <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ </head>
+ <body>
+ <h1>Home</h1>
+ <div class="card-text">
+ <ul>
+ <li th:each="site : ${sites}">
+ <a href="#" th:href="'/' + ${site}" th:text="${site}">SITE</a>
+ </li>
+ </ul>
+ </div>
+ <div class="card-text">
+ <p>
+ <em>
+ This page links to the pages, that are served by the dynamically created beans.
+ </em>
+ </p>
+ </div>
+ </body>
+</html>
--- /dev/null
+<!doctype html>
+<html lang="en" xmlns:th="http://www.thymeleaf.org" th:fragment="pagelayout(title,header,body)">
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+ <title th:replace="${title}">TITLE</title>
+ <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" th:href="@{/webjars/bootstrap/4.5.2/css/bootstrap.min.css}">
+ </head>
+ <body>
+ <nav class="navbar navbar-dark bg-primary navbar-expand navbar-dark flex-column">
+ <h2 class="navbar-brand">Demo: Creating Multiple Beans In Spring-Boot Pogrammatically</h2>
+ </nav>
+ <main class="container mt-5">
+ <div id="content" class="card">
+ <div class="card-header"><h1 th:replace="${header}">HEADER</h1></div>
+ <div class="card-body"><div th:replace="${body}">BODY</div></div>
+ </div>
+ </main>
+ </body>
+</html>
+++ /dev/null
-package de.juplo.demos.pwreset.adapter;
-
-import au.com.dius.pact.consumer.MockServer;
-import au.com.dius.pact.consumer.dsl.PactDslWithProvider;
-import au.com.dius.pact.consumer.junit5.PactConsumerTestExt;
-import au.com.dius.pact.consumer.junit5.PactTestFor;
-import au.com.dius.pact.core.model.RequestResponsePact;
-import au.com.dius.pact.core.model.annotations.Pact;
-import de.juplo.demos.pwreset.domain.User;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.springframework.boot.web.client.RestTemplateBuilder;
-import org.springframework.web.client.RestTemplate;
-
-import java.util.Map;
-import java.util.Optional;
-import java.util.UUID;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.fail;
-
-
-@ExtendWith(PactConsumerTestExt.class)
-@PactTestFor(providerName = "UsersProvider")
-public class RemoteUsersServiceConsumerIT
-{
- @Pact(consumer="EmailServicesConsumer")
- public RequestResponsePact getExistingUserByEmail(PactDslWithProvider builder) {
- return builder
- .given("User with email pact@juplo.de exists")
- .uponReceiving("Request for user with email pact@juplo.de")
- .path("/get")
- .query("email=pact@juplo.de")
- .method("GET")
- .willRespondWith()
- .status(200)
- .headers(Map.of("Content-Type", "application/json;charset=UTF-8"))
- .body("{\"id\": \"123e4567-e89b-12d3-a456-426614174000\", \"email\": \"pact@juplo.de\"}")
- .toPact();
- }
-
- @Test
- @PactTestFor(pactMethod = "getExistingUserByEmail")
- public void testGetExistingUserByEmail(MockServer mockServer) {
- RestTemplate restTemplate = new RestTemplateBuilder().rootUri(mockServer.getUrl()).build();
- RemoteUsersServiceConsumer usersService = new RemoteUsersServiceConsumer("/get?email={email}", restTemplate);
- try {
- Optional<User> result = usersService.getUserByEmail("pact@juplo.de");
-
- assertThat(result.isPresent()).isTrue();
- User user = result.get();
- assertThat(user.getId()).isEqualTo(UUID.fromString("123e4567-e89b-12d3-a456-426614174000"));
- assertThat(user.getEmail()).isEqualTo("pact@juplo.de");
- }
- catch (Exception e) {
- fail("Unexpected exception", e);
- }
- }
-}
--- /dev/null
+package de.juplo.demos.pwreset.adapters.out;
+
+import au.com.dius.pact.consumer.MockServer;
+import au.com.dius.pact.consumer.dsl.PactDslWithProvider;
+import au.com.dius.pact.consumer.junit5.PactConsumerTestExt;
+import au.com.dius.pact.consumer.junit5.PactTestFor;
+import au.com.dius.pact.core.model.RequestResponsePact;
+import au.com.dius.pact.core.model.annotations.Pact;
+import de.juplo.demos.pwreset.domain.api.User;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.boot.web.client.RestTemplateBuilder;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Map;
+import java.util.Optional;
+import java.util.UUID;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.fail;
+
+
+@ExtendWith(PactConsumerTestExt.class)
+@PactTestFor(providerName = "UsersProvider")
+public class RemoteUsersServiceConsumerIT
+{
+ @Pact(consumer="EmailServicesConsumer")
+ public RequestResponsePact getExistingUserByEmail(PactDslWithProvider builder) {
+ return builder
+ .given("User with email pact@juplo.de exists")
+ .uponReceiving("Request for user with email pact@juplo.de")
+ .path("/get")
+ .query("email=pact@juplo.de")
+ .method("GET")
+ .willRespondWith()
+ .status(200)
+ .headers(Map.of("Content-Type", "application/json;charset=UTF-8"))
+ .body("{\"id\": \"123e4567-e89b-12d3-a456-426614174000\", \"email\": \"pact@juplo.de\"}")
+ .toPact();
+ }
+
+ @Test
+ @PactTestFor(pactMethod = "getExistingUserByEmail")
+ public void testGetExistingUserByEmail(MockServer mockServer) {
+ RestTemplate restTemplate = new RestTemplateBuilder().rootUri(mockServer.getUrl()).build();
+ RemoteUsersServiceConsumer usersService = new RemoteUsersServiceConsumer("/get?email={email}", restTemplate);
+ try {
+ Optional<User> result = usersService.getUserByEmail("pact@juplo.de");
+
+ assertThat(result.isPresent()).isTrue();
+ User user = result.get();
+ assertThat(user.getId()).isEqualTo(UUID.fromString("123e4567-e89b-12d3-a456-426614174000"));
+ assertThat(user.getEmail()).isEqualTo("pact@juplo.de");
+ }
+ catch (Exception e) {
+ fail("Unexpected exception", e);
+ }
+ }
+}