diff --git a/core-java-modules/core-java-exceptions-2/README.md b/core-java-modules/core-java-exceptions-2/README.md
new file mode 100644
index 0000000000..3ad5189b5e
--- /dev/null
+++ b/core-java-modules/core-java-exceptions-2/README.md
@@ -0,0 +1,5 @@
+## Core Java Exceptions 2
+
+This module contains articles about core java exceptions
+
+###
diff --git a/core-java-modules/core-java-exceptions-2/pom.xml b/core-java-modules/core-java-exceptions-2/pom.xml
new file mode 100644
index 0000000000..2f7f613faf
--- /dev/null
+++ b/core-java-modules/core-java-exceptions-2/pom.xml
@@ -0,0 +1,24 @@
+
+ 4.0.0
+
+ core-java-exceptions-2
+ core-java-exceptions-2
+ jar
+
+
+ com.baeldung
+ parent-java
+ 0.0.1-SNAPSHOT
+ ../../parent-java
+
+
+
+ http://maven.apache.org
+
+
+ UTF-8
+
+
+
diff --git a/core-java-modules/core-java-exceptions-2/src/main/java/com/baeldung/rethrow/RethrowDifferentExceptionDemo.java b/core-java-modules/core-java-exceptions-2/src/main/java/com/baeldung/rethrow/RethrowDifferentExceptionDemo.java
new file mode 100644
index 0000000000..ce2fcb2c7a
--- /dev/null
+++ b/core-java-modules/core-java-exceptions-2/src/main/java/com/baeldung/rethrow/RethrowDifferentExceptionDemo.java
@@ -0,0 +1,29 @@
+package com.baeldung.rethrow;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.baeldung.rethrow.custom.InvalidDataException;
+
+public class RethrowDifferentExceptionDemo {
+
+ private final static Logger LOGGER = Logger.getLogger(RethrowDifferentExceptionDemo.class.getName());
+
+ public static void main(String[] args) throws Exception {
+ String name = null;
+
+ try {
+
+ // Below line will throw NullPointerException
+ if (name.equals("Joe")) {
+ // Do blah blah..
+ }
+
+ } catch (Exception e) {
+ LOGGER.log(Level.WARNING, "So and so user is unable to cast vote because he is found uneligible");
+ throw new InvalidDataException(e);
+ }
+
+ }
+
+}
diff --git a/core-java-modules/core-java-exceptions-2/src/main/java/com/baeldung/rethrow/RethrowSameExceptionDemo.java b/core-java-modules/core-java-exceptions-2/src/main/java/com/baeldung/rethrow/RethrowSameExceptionDemo.java
new file mode 100644
index 0000000000..bf53f67d34
--- /dev/null
+++ b/core-java-modules/core-java-exceptions-2/src/main/java/com/baeldung/rethrow/RethrowSameExceptionDemo.java
@@ -0,0 +1,27 @@
+package com.baeldung.rethrow;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class RethrowSameExceptionDemo {
+
+ private final static Logger LOGGER = Logger.getLogger(RethrowDifferentExceptionDemo.class.getName());
+
+ public static void main(String[] args) throws Exception {
+ String name = null;
+
+ try {
+
+ // Below line will throw NullPointerException
+ if (name.equals("Joe")) {
+ // Do blah blah..
+ }
+
+ } catch (Exception e) {
+ LOGGER.log(Level.WARNING, "Exception occurred due to invalid name");
+ throw e;
+ }
+
+ }
+
+}
diff --git a/core-java-modules/core-java-exceptions-2/src/main/java/com/baeldung/rethrow/custom/InvalidDataException.java b/core-java-modules/core-java-exceptions-2/src/main/java/com/baeldung/rethrow/custom/InvalidDataException.java
new file mode 100644
index 0000000000..5a74e32012
--- /dev/null
+++ b/core-java-modules/core-java-exceptions-2/src/main/java/com/baeldung/rethrow/custom/InvalidDataException.java
@@ -0,0 +1,8 @@
+package com.baeldung.rethrow.custom;
+
+public class InvalidDataException extends Exception {
+
+ public InvalidDataException(Exception e) {
+ super(e);
+ }
+}
diff --git a/ddd/pom.xml b/ddd/pom.xml
index 508bccdbf2..9a0523a4c6 100644
--- a/ddd/pom.xml
+++ b/ddd/pom.xml
@@ -76,6 +76,11 @@
spring-boot-starter-test
test
+
+ org.mockito
+ mockito-core
+ test
+
de.flapdoodle.embed
de.flapdoodle.embed.mongo
diff --git a/ddd/src/main/java/com/baeldung/ddd/PersistingDddAggregatesApplication.java b/ddd/src/main/java/com/baeldung/ddd/PersistingDddAggregatesApplication.java
index cd9be34278..3a52fd0440 100644
--- a/ddd/src/main/java/com/baeldung/ddd/PersistingDddAggregatesApplication.java
+++ b/ddd/src/main/java/com/baeldung/ddd/PersistingDddAggregatesApplication.java
@@ -1,12 +1,12 @@
-package com.baeldung.ddd;
-
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-
-@SpringBootApplication
-public class PersistingDddAggregatesApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(PersistingDddAggregatesApplication.class, args);
- }
-}
+package com.baeldung.ddd;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication(scanBasePackages = "com.baeldung.ddd.order")
+public class PersistingDddAggregatesApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(PersistingDddAggregatesApplication.class, args);
+ }
+}
diff --git a/ddd/src/main/java/com/baeldung/dddhexagonalspring/DomainLayerApplication.java b/ddd/src/main/java/com/baeldung/dddhexagonalspring/DomainLayerApplication.java
new file mode 100644
index 0000000000..988f96042b
--- /dev/null
+++ b/ddd/src/main/java/com/baeldung/dddhexagonalspring/DomainLayerApplication.java
@@ -0,0 +1,13 @@
+package com.baeldung.dddhexagonalspring;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.PropertySource;
+
+@SpringBootApplication
+@PropertySource(value = { "classpath:ddd-layers.properties" })
+public class DomainLayerApplication {
+ public static void main(final String[] args) {
+ SpringApplication.run(DomainLayerApplication.class, args);
+ }
+}
diff --git a/ddd/src/main/java/com/baeldung/dddhexagonalspring/application/controller/OrderController.java b/ddd/src/main/java/com/baeldung/dddhexagonalspring/application/controller/OrderController.java
new file mode 100644
index 0000000000..80ba36d01b
--- /dev/null
+++ b/ddd/src/main/java/com/baeldung/dddhexagonalspring/application/controller/OrderController.java
@@ -0,0 +1,45 @@
+package com.baeldung.dddhexagonalspring.application.controller;
+
+import com.baeldung.dddhexagonalspring.application.request.AddProductRequest;
+import com.baeldung.dddhexagonalspring.application.request.CreateOrderRequest;
+import com.baeldung.dddhexagonalspring.application.response.CreateOrderResponse;
+import com.baeldung.dddhexagonalspring.domain.service.OrderService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.UUID;
+
+@RestController
+@RequestMapping("/orders")
+public class OrderController {
+
+ private final OrderService orderService;
+
+ @Autowired
+ public OrderController(OrderService orderService) {
+ this.orderService = orderService;
+ }
+
+ @PostMapping(produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
+ CreateOrderResponse createOrder(@RequestBody final CreateOrderRequest createOrderRequest) {
+ final UUID id = orderService.createOrder(createOrderRequest.getProduct());
+
+ return new CreateOrderResponse(id);
+ }
+
+ @PostMapping(value = "/{id}/products", consumes = MediaType.APPLICATION_JSON_VALUE)
+ void addProduct(@PathVariable final UUID id, @RequestBody final AddProductRequest addProductRequest) {
+ orderService.addProduct(id, addProductRequest.getProduct());
+ }
+
+ @DeleteMapping(value = "/{id}/products", consumes = MediaType.APPLICATION_JSON_VALUE)
+ void deleteProduct(@PathVariable final UUID id, @RequestParam final UUID productId) {
+ orderService.deleteProduct(id, productId);
+ }
+
+ @PostMapping("/{id}/complete")
+ void completeOrder(@PathVariable final UUID id) {
+ orderService.completeOrder(id);
+ }
+}
diff --git a/ddd/src/main/java/com/baeldung/dddhexagonalspring/application/request/AddProductRequest.java b/ddd/src/main/java/com/baeldung/dddhexagonalspring/application/request/AddProductRequest.java
new file mode 100644
index 0000000000..ec107d635b
--- /dev/null
+++ b/ddd/src/main/java/com/baeldung/dddhexagonalspring/application/request/AddProductRequest.java
@@ -0,0 +1,20 @@
+package com.baeldung.dddhexagonalspring.application.request;
+
+import com.baeldung.dddhexagonalspring.domain.Product;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import javax.validation.constraints.NotNull;
+
+public class AddProductRequest {
+ @NotNull private Product product;
+
+ @JsonCreator
+ public AddProductRequest(@JsonProperty("product") final Product product) {
+ this.product = product;
+ }
+
+ public Product getProduct() {
+ return product;
+ }
+}
diff --git a/ddd/src/main/java/com/baeldung/dddhexagonalspring/application/request/CreateOrderRequest.java b/ddd/src/main/java/com/baeldung/dddhexagonalspring/application/request/CreateOrderRequest.java
new file mode 100644
index 0000000000..8c51fbe479
--- /dev/null
+++ b/ddd/src/main/java/com/baeldung/dddhexagonalspring/application/request/CreateOrderRequest.java
@@ -0,0 +1,20 @@
+package com.baeldung.dddhexagonalspring.application.request;
+
+import com.baeldung.dddhexagonalspring.domain.Product;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import javax.validation.constraints.NotNull;
+
+public class CreateOrderRequest {
+ @NotNull private Product product;
+
+ @JsonCreator
+ public CreateOrderRequest(@JsonProperty("product") @NotNull final Product product) {
+ this.product = product;
+ }
+
+ public Product getProduct() {
+ return product;
+ }
+}
diff --git a/ddd/src/main/java/com/baeldung/dddhexagonalspring/application/response/CreateOrderResponse.java b/ddd/src/main/java/com/baeldung/dddhexagonalspring/application/response/CreateOrderResponse.java
new file mode 100644
index 0000000000..72ee1134c3
--- /dev/null
+++ b/ddd/src/main/java/com/baeldung/dddhexagonalspring/application/response/CreateOrderResponse.java
@@ -0,0 +1,15 @@
+package com.baeldung.dddhexagonalspring.application.response;
+
+import java.util.UUID;
+
+public class CreateOrderResponse {
+ private final UUID id;
+
+ public CreateOrderResponse(final UUID id) {
+ this.id = id;
+ }
+
+ public UUID getId() {
+ return id;
+ }
+}
diff --git a/ddd/src/main/java/com/baeldung/dddhexagonalspring/domain/DomainException.java b/ddd/src/main/java/com/baeldung/dddhexagonalspring/domain/DomainException.java
new file mode 100644
index 0000000000..7baef7bab6
--- /dev/null
+++ b/ddd/src/main/java/com/baeldung/dddhexagonalspring/domain/DomainException.java
@@ -0,0 +1,7 @@
+package com.baeldung.dddhexagonalspring.domain;
+
+class DomainException extends RuntimeException {
+ DomainException(final String message) {
+ super(message);
+ }
+}
diff --git a/ddd/src/main/java/com/baeldung/dddhexagonalspring/domain/Order.java b/ddd/src/main/java/com/baeldung/dddhexagonalspring/domain/Order.java
new file mode 100644
index 0000000000..7d40007411
--- /dev/null
+++ b/ddd/src/main/java/com/baeldung/dddhexagonalspring/domain/Order.java
@@ -0,0 +1,82 @@
+package com.baeldung.dddhexagonalspring.domain;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.UUID;
+
+public class Order {
+ private UUID id;
+ private OrderStatus status;
+ private List orderItems;
+ private BigDecimal price;
+
+ public Order(final UUID id, final Product product) {
+ this.id = id;
+ this.orderItems = new ArrayList<>(Collections.singletonList(new OrderItem(product)));
+ this.status = OrderStatus.CREATED;
+ this.price = product.getPrice();
+ }
+
+ public void complete() {
+ validateState();
+ this.status = OrderStatus.COMPLETED;
+ }
+
+ public void addOrder(final Product product) {
+ validateState();
+ validateProduct(product);
+ orderItems.add(new OrderItem(product));
+ price = price.add(product.getPrice());
+ }
+
+ public void removeOrder(final UUID id) {
+ validateState();
+ final OrderItem orderItem = getOrderItem(id);
+ orderItems.remove(orderItem);
+
+ price = price.subtract(orderItem.getPrice());
+ }
+
+ private OrderItem getOrderItem(final UUID id) {
+ return orderItems
+ .stream()
+ .filter(orderItem -> orderItem
+ .getProductId()
+ .equals(id))
+ .findFirst()
+ .orElseThrow(() -> new DomainException("Product with " + id + " doesn't exist."));
+ }
+
+ private void validateState() {
+ if (OrderStatus.COMPLETED.equals(status)) {
+ throw new DomainException("The order is in completed state.");
+ }
+ }
+
+ private void validateProduct(final Product product) {
+ if (product == null) {
+ throw new DomainException("The product cannot be null.");
+ }
+ }
+
+ public UUID getId() {
+ return id;
+ }
+
+ public OrderStatus getStatus() {
+ return status;
+ }
+
+ public BigDecimal getPrice() {
+ return price;
+ }
+
+ public List getOrderItems() {
+ return Collections.unmodifiableList(orderItems);
+ }
+
+ private Order() {
+ }
+}
diff --git a/ddd/src/main/java/com/baeldung/dddhexagonalspring/domain/OrderItem.java b/ddd/src/main/java/com/baeldung/dddhexagonalspring/domain/OrderItem.java
new file mode 100644
index 0000000000..9debb02680
--- /dev/null
+++ b/ddd/src/main/java/com/baeldung/dddhexagonalspring/domain/OrderItem.java
@@ -0,0 +1,39 @@
+package com.baeldung.dddhexagonalspring.domain;
+
+import java.math.BigDecimal;
+import java.util.Objects;
+import java.util.UUID;
+
+public class OrderItem {
+ private UUID productId;
+ private BigDecimal price;
+
+ public OrderItem(final Product product) {
+ this.productId = product.getId();
+ this.price = product.getPrice();
+ }
+
+ public UUID getProductId() {
+ return productId;
+ }
+
+ public BigDecimal getPrice() {
+ return price;
+ }
+
+ private OrderItem() {
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ OrderItem orderItem = (OrderItem) o;
+ return Objects.equals(productId, orderItem.productId) && Objects.equals(price, orderItem.price);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(productId, price);
+ }
+}
diff --git a/ddd/src/main/java/com/baeldung/dddhexagonalspring/domain/OrderStatus.java b/ddd/src/main/java/com/baeldung/dddhexagonalspring/domain/OrderStatus.java
new file mode 100644
index 0000000000..2ee5df3ab7
--- /dev/null
+++ b/ddd/src/main/java/com/baeldung/dddhexagonalspring/domain/OrderStatus.java
@@ -0,0 +1,5 @@
+package com.baeldung.dddhexagonalspring.domain;
+
+public enum OrderStatus {
+ CREATED, COMPLETED
+}
diff --git a/ddd/src/main/java/com/baeldung/dddhexagonalspring/domain/Product.java b/ddd/src/main/java/com/baeldung/dddhexagonalspring/domain/Product.java
new file mode 100644
index 0000000000..e05b4afe62
--- /dev/null
+++ b/ddd/src/main/java/com/baeldung/dddhexagonalspring/domain/Product.java
@@ -0,0 +1,46 @@
+package com.baeldung.dddhexagonalspring.domain;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.math.BigDecimal;
+import java.util.Objects;
+import java.util.UUID;
+
+public class Product {
+ private final UUID id;
+ private final BigDecimal price;
+ private final String name;
+
+ @JsonCreator
+ public Product(@JsonProperty("id") final UUID id, @JsonProperty("price") final BigDecimal price, @JsonProperty("name") final String name) {
+ this.id = id;
+ this.price = price;
+ this.name = name;
+ }
+
+ public BigDecimal getPrice() {
+ return price;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public UUID getId() {
+ return id;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ Product product = (Product) o;
+ return Objects.equals(id, product.id) && Objects.equals(price, product.price) && Objects.equals(name, product.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id, price, name);
+ }
+}
diff --git a/ddd/src/main/java/com/baeldung/dddhexagonalspring/domain/repository/OrderRepository.java b/ddd/src/main/java/com/baeldung/dddhexagonalspring/domain/repository/OrderRepository.java
new file mode 100644
index 0000000000..14b34e13f3
--- /dev/null
+++ b/ddd/src/main/java/com/baeldung/dddhexagonalspring/domain/repository/OrderRepository.java
@@ -0,0 +1,12 @@
+package com.baeldung.dddhexagonalspring.domain.repository;
+
+import com.baeldung.dddhexagonalspring.domain.Order;
+
+import java.util.Optional;
+import java.util.UUID;
+
+public interface OrderRepository {
+ Optional findById(UUID id);
+
+ void save(Order order);
+}
diff --git a/ddd/src/main/java/com/baeldung/dddhexagonalspring/domain/service/DomainOrderService.java b/ddd/src/main/java/com/baeldung/dddhexagonalspring/domain/service/DomainOrderService.java
new file mode 100644
index 0000000000..4fb2377745
--- /dev/null
+++ b/ddd/src/main/java/com/baeldung/dddhexagonalspring/domain/service/DomainOrderService.java
@@ -0,0 +1,54 @@
+package com.baeldung.dddhexagonalspring.domain.service;
+
+import com.baeldung.dddhexagonalspring.domain.Order;
+import com.baeldung.dddhexagonalspring.domain.Product;
+import com.baeldung.dddhexagonalspring.domain.repository.OrderRepository;
+
+import java.util.UUID;
+
+public class DomainOrderService implements OrderService {
+
+ private final OrderRepository orderRepository;
+
+ public DomainOrderService(final OrderRepository orderRepository) {
+ this.orderRepository = orderRepository;
+ }
+
+ @Override
+ public UUID createOrder(final Product product) {
+ final Order order = new Order(UUID.randomUUID(), product);
+ orderRepository.save(order);
+
+ return order.getId();
+ }
+
+ @Override
+ public void addProduct(final UUID id, final Product product) {
+ final Order order = getOrder(id);
+ order.addOrder(product);
+
+ orderRepository.save(order);
+ }
+
+ @Override
+ public void completeOrder(final UUID id) {
+ final Order order = getOrder(id);
+ order.complete();
+
+ orderRepository.save(order);
+ }
+
+ @Override
+ public void deleteProduct(final UUID id, final UUID productId) {
+ final Order order = getOrder(id);
+ order.removeOrder(productId);
+
+ orderRepository.save(order);
+ }
+
+ private Order getOrder(UUID id) {
+ return orderRepository
+ .findById(id)
+ .orElseThrow(() -> new RuntimeException("Order with given id doesn't exist"));
+ }
+}
diff --git a/ddd/src/main/java/com/baeldung/dddhexagonalspring/domain/service/OrderService.java b/ddd/src/main/java/com/baeldung/dddhexagonalspring/domain/service/OrderService.java
new file mode 100644
index 0000000000..37297d74c4
--- /dev/null
+++ b/ddd/src/main/java/com/baeldung/dddhexagonalspring/domain/service/OrderService.java
@@ -0,0 +1,15 @@
+package com.baeldung.dddhexagonalspring.domain.service;
+
+import com.baeldung.dddhexagonalspring.domain.Product;
+
+import java.util.UUID;
+
+public interface OrderService {
+ UUID createOrder(Product product);
+
+ void addProduct(UUID id, Product product);
+
+ void completeOrder(UUID id);
+
+ void deleteProduct(UUID id, UUID productId);
+}
diff --git a/ddd/src/main/java/com/baeldung/dddhexagonalspring/infrastracture/configuration/BeanConfiguration.java b/ddd/src/main/java/com/baeldung/dddhexagonalspring/infrastracture/configuration/BeanConfiguration.java
new file mode 100644
index 0000000000..4be5d84ba7
--- /dev/null
+++ b/ddd/src/main/java/com/baeldung/dddhexagonalspring/infrastracture/configuration/BeanConfiguration.java
@@ -0,0 +1,19 @@
+package com.baeldung.dddhexagonalspring.infrastracture.configuration;
+
+import com.baeldung.dddhexagonalspring.DomainLayerApplication;
+import com.baeldung.dddhexagonalspring.domain.repository.OrderRepository;
+import com.baeldung.dddhexagonalspring.domain.service.DomainOrderService;
+import com.baeldung.dddhexagonalspring.domain.service.OrderService;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ComponentScan(basePackageClasses = DomainLayerApplication.class)
+public class BeanConfiguration {
+
+ @Bean
+ OrderService orderService(final OrderRepository orderRepository) {
+ return new DomainOrderService(orderRepository);
+ }
+}
diff --git a/ddd/src/main/java/com/baeldung/dddhexagonalspring/infrastracture/configuration/MongoDBConfiguration.java b/ddd/src/main/java/com/baeldung/dddhexagonalspring/infrastracture/configuration/MongoDBConfiguration.java
new file mode 100644
index 0000000000..fd76b2eb0e
--- /dev/null
+++ b/ddd/src/main/java/com/baeldung/dddhexagonalspring/infrastracture/configuration/MongoDBConfiguration.java
@@ -0,0 +1,8 @@
+package com.baeldung.dddhexagonalspring.infrastracture.configuration;
+
+import com.baeldung.dddhexagonalspring.infrastracture.repository.SpringDataOrderRepository;
+import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
+
+@EnableMongoRepositories(basePackageClasses = SpringDataOrderRepository.class)
+public class MongoDBConfiguration {
+}
diff --git a/ddd/src/main/java/com/baeldung/dddhexagonalspring/infrastracture/repository/MongoDbOrderRepository.java b/ddd/src/main/java/com/baeldung/dddhexagonalspring/infrastracture/repository/MongoDbOrderRepository.java
new file mode 100644
index 0000000000..3123ef3e2f
--- /dev/null
+++ b/ddd/src/main/java/com/baeldung/dddhexagonalspring/infrastracture/repository/MongoDbOrderRepository.java
@@ -0,0 +1,30 @@
+package com.baeldung.dddhexagonalspring.infrastracture.repository;
+
+import com.baeldung.dddhexagonalspring.domain.Order;
+import com.baeldung.dddhexagonalspring.domain.repository.OrderRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.Optional;
+import java.util.UUID;
+
+@Component
+public class MongoDbOrderRepository implements OrderRepository {
+
+ private final SpringDataOrderRepository orderRepository;
+
+ @Autowired
+ public MongoDbOrderRepository(final SpringDataOrderRepository orderRepository) {
+ this.orderRepository = orderRepository;
+ }
+
+ @Override
+ public Optional findById(final UUID id) {
+ return orderRepository.findById(id);
+ }
+
+ @Override
+ public void save(final Order order) {
+ orderRepository.save(order);
+ }
+}
diff --git a/ddd/src/main/java/com/baeldung/dddhexagonalspring/infrastracture/repository/SpringDataOrderRepository.java b/ddd/src/main/java/com/baeldung/dddhexagonalspring/infrastracture/repository/SpringDataOrderRepository.java
new file mode 100644
index 0000000000..0279a5ce4a
--- /dev/null
+++ b/ddd/src/main/java/com/baeldung/dddhexagonalspring/infrastracture/repository/SpringDataOrderRepository.java
@@ -0,0 +1,11 @@
+package com.baeldung.dddhexagonalspring.infrastracture.repository;
+
+import com.baeldung.dddhexagonalspring.domain.Order;
+import org.springframework.data.mongodb.repository.MongoRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.UUID;
+
+@Repository
+public interface SpringDataOrderRepository extends MongoRepository {
+}
diff --git a/ddd/src/main/resources/ddd-layers.properties b/ddd/src/main/resources/ddd-layers.properties
new file mode 100644
index 0000000000..0479996b17
--- /dev/null
+++ b/ddd/src/main/resources/ddd-layers.properties
@@ -0,0 +1,5 @@
+spring.data.mongodb.host=localhost
+spring.data.mongodb.port=27017
+spring.data.mongodb.database=order-database
+spring.data.mongodb.username=order
+spring.data.mongodb.password=order
\ No newline at end of file
diff --git a/ddd/src/test/java/com/baeldung/dddhexagonalspring/domain/OrderProvider.java b/ddd/src/test/java/com/baeldung/dddhexagonalspring/domain/OrderProvider.java
new file mode 100644
index 0000000000..c534713ca3
--- /dev/null
+++ b/ddd/src/test/java/com/baeldung/dddhexagonalspring/domain/OrderProvider.java
@@ -0,0 +1,17 @@
+package com.baeldung.dddhexagonalspring.domain;
+
+import java.math.BigDecimal;
+import java.util.UUID;
+
+public class OrderProvider {
+ public static Order getCreatedOrder() {
+ return new Order(UUID.randomUUID(), new Product(UUID.randomUUID(), BigDecimal.TEN, "productName"));
+ }
+
+ public static Order getCompletedOrder() {
+ final Order order = getCreatedOrder();
+ order.complete();
+
+ return order;
+ }
+}
diff --git a/ddd/src/test/java/com/baeldung/dddhexagonalspring/domain/OrderUnitTest.java b/ddd/src/test/java/com/baeldung/dddhexagonalspring/domain/OrderUnitTest.java
new file mode 100644
index 0000000000..eceed999d8
--- /dev/null
+++ b/ddd/src/test/java/com/baeldung/dddhexagonalspring/domain/OrderUnitTest.java
@@ -0,0 +1,65 @@
+package com.baeldung.dddhexagonalspring.domain;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.function.Executable;
+
+import java.math.BigDecimal;
+import java.util.UUID;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class OrderUnitTest {
+
+ @Test
+ void shouldCompleteOrder_thenChangeStatus() {
+ final Order order = OrderProvider.getCreatedOrder();
+
+ order.complete();
+
+ assertEquals(OrderStatus.COMPLETED, order.getStatus());
+ }
+
+ @Test
+ void shouldAddProduct_thenUpdatePrice() {
+ final Order order = OrderProvider.getCreatedOrder();
+ final int orderOriginalProductSize = order
+ .getOrderItems()
+ .size();
+ final BigDecimal orderOriginalPrice = order.getPrice();
+ final Product productToAdd = new Product(UUID.randomUUID(), new BigDecimal("20"), "secondProduct");
+
+ order.addOrder(productToAdd);
+
+ assertEquals(orderOriginalProductSize + 1, order
+ .getOrderItems()
+ .size());
+ assertEquals(orderOriginalPrice.add(productToAdd.getPrice()), order.getPrice());
+ }
+
+ @Test
+ void shouldAddProduct_thenThrowException() {
+ final Order order = OrderProvider.getCompletedOrder();
+ final Product productToAdd = new Product(UUID.randomUUID(), new BigDecimal("20"), "secondProduct");
+
+ final Executable executable = () -> order.addOrder(productToAdd);
+
+ Assertions.assertThrows(DomainException.class, executable);
+ }
+
+ @Test
+ void shouldRemoveProduct_thenUpdatePrice() {
+ final Order order = OrderProvider.getCreatedOrder();
+ final UUID productId = order
+ .getOrderItems()
+ .get(0)
+ .getProductId();
+
+ order.removeOrder(productId);
+
+ assertEquals(0, order
+ .getOrderItems()
+ .size());
+ assertEquals(BigDecimal.ZERO, order.getPrice());
+ }
+}
\ No newline at end of file
diff --git a/ddd/src/test/java/com/baeldung/dddhexagonalspring/domain/service/DomainOrderServiceUnitTest.java b/ddd/src/test/java/com/baeldung/dddhexagonalspring/domain/service/DomainOrderServiceUnitTest.java
new file mode 100644
index 0000000000..797068a30a
--- /dev/null
+++ b/ddd/src/test/java/com/baeldung/dddhexagonalspring/domain/service/DomainOrderServiceUnitTest.java
@@ -0,0 +1,91 @@
+package com.baeldung.dddhexagonalspring.domain.service;
+
+import com.baeldung.dddhexagonalspring.domain.Order;
+import com.baeldung.dddhexagonalspring.domain.OrderProvider;
+import com.baeldung.dddhexagonalspring.domain.Product;
+import com.baeldung.dddhexagonalspring.domain.repository.OrderRepository;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.function.Executable;
+
+import java.math.BigDecimal;
+import java.util.Optional;
+import java.util.UUID;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.*;
+
+class DomainOrderServiceUnitTest {
+
+ private OrderRepository orderRepository;
+ private DomainOrderService tested;
+
+ @BeforeEach
+ void setUp() {
+ orderRepository = mock(OrderRepository.class);
+ tested = new DomainOrderService(orderRepository);
+ }
+
+ @Test
+ void shouldCreateOrder_thenSaveIt() {
+ final Product product = new Product(UUID.randomUUID(), BigDecimal.TEN, "productName");
+
+ final UUID id = tested.createOrder(product);
+
+ verify(orderRepository).save(any(Order.class));
+ assertNotNull(id);
+ }
+
+ @Test
+ void shouldAddProduct_thenSaveOrder() {
+ final Order order = spy(OrderProvider.getCreatedOrder());
+ final Product product = new Product(UUID.randomUUID(), BigDecimal.TEN, "test");
+ when(orderRepository.findById(order.getId())).thenReturn(Optional.of(order));
+
+ tested.addProduct(order.getId(), product);
+
+ verify(orderRepository).save(order);
+ verify(order).addOrder(product);
+ }
+
+ @Test
+ void shouldAddProduct_thenThrowException() {
+ final Product product = new Product(UUID.randomUUID(), BigDecimal.TEN, "test");
+ final UUID id = UUID.randomUUID();
+ when(orderRepository.findById(id)).thenReturn(Optional.empty());
+
+ final Executable executable = () -> tested.addProduct(id, product);
+
+ verify(orderRepository, times(0)).save(any(Order.class));
+ assertThrows(RuntimeException.class, executable);
+ }
+
+ @Test
+ void shouldCompleteOrder_thenSaveIt() {
+ final Order order = spy(OrderProvider.getCreatedOrder());
+ when(orderRepository.findById(order.getId())).thenReturn(Optional.of(order));
+
+ tested.completeOrder(order.getId());
+
+ verify(orderRepository).save(any(Order.class));
+ verify(order).complete();
+ }
+
+ @Test
+ void shouldDeleteProduct_thenSaveOrder() {
+ final Order order = spy(OrderProvider.getCreatedOrder());
+ final UUID productId = order
+ .getOrderItems()
+ .get(0)
+ .getProductId();
+
+ when(orderRepository.findById(order.getId())).thenReturn(Optional.of(order));
+
+ tested.deleteProduct(order.getId(), productId);
+
+ verify(orderRepository).save(order);
+ verify(order).removeOrder(productId);
+ }
+}
\ No newline at end of file
diff --git a/ddd/src/test/java/com/baeldung/dddhexagonalspring/infrastracture/repository/MongoDbOrderRepositoryUnitTest.java b/ddd/src/test/java/com/baeldung/dddhexagonalspring/infrastracture/repository/MongoDbOrderRepositoryUnitTest.java
new file mode 100644
index 0000000000..8f7e8260a3
--- /dev/null
+++ b/ddd/src/test/java/com/baeldung/dddhexagonalspring/infrastracture/repository/MongoDbOrderRepositoryUnitTest.java
@@ -0,0 +1,51 @@
+package com.baeldung.dddhexagonalspring.infrastracture.repository;
+
+import com.baeldung.dddhexagonalspring.domain.Order;
+import com.baeldung.dddhexagonalspring.domain.Product;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.math.BigDecimal;
+import java.util.Optional;
+import java.util.UUID;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+class MongoDbOrderRepositoryUnitTest {
+
+ private SpringDataOrderRepository springDataOrderRepository;
+ private MongoDbOrderRepository tested;
+
+ @BeforeEach
+ void setUp(){
+ springDataOrderRepository = mock(SpringDataOrderRepository.class);
+
+ tested = new MongoDbOrderRepository(springDataOrderRepository);
+ }
+
+ @Test
+ void shouldFindById_thenReturnOrder() {
+ final UUID id = UUID.randomUUID();
+ final Order order = createOrder(id);
+ when(springDataOrderRepository.findById(id)).thenReturn(Optional.of(order));
+
+ final Optional result = tested.findById(id);
+
+ assertEquals(order, result.get());
+ }
+
+ @Test
+ void shouldSaveOrder_viaSpringDataOrderRepository() {
+ final UUID id = UUID.randomUUID();
+ final Order order = createOrder(id);
+
+ tested.save(order);
+
+ verify(springDataOrderRepository).save(order);
+ }
+
+ private Order createOrder(UUID id) {
+ return new Order(id, new Product(UUID.randomUUID(), BigDecimal.TEN, "product"));
+ }
+}
\ No newline at end of file
diff --git a/ddd/src/test/resources/com/baeldung/dddhexagonalspring/README.md b/ddd/src/test/resources/com/baeldung/dddhexagonalspring/README.md
new file mode 100644
index 0000000000..e0337498fc
--- /dev/null
+++ b/ddd/src/test/resources/com/baeldung/dddhexagonalspring/README.md
@@ -0,0 +1,7 @@
+## Setup DDD Hexagonal Spring Application
+
+To run this project, follow these steps:
+
+* Run the application database by executing `docker-compose up` in this directory.
+* Launch the Spring Boot Application (DomainLayerApplication).
+* By default, application will connect to this database (configuration in *ddd-layers.properties*)
\ No newline at end of file
diff --git a/ddd/src/test/resources/com/baeldung/dddhexagonalspring/docker-compose.yml b/ddd/src/test/resources/com/baeldung/dddhexagonalspring/docker-compose.yml
new file mode 100644
index 0000000000..d85ddf4a0e
--- /dev/null
+++ b/ddd/src/test/resources/com/baeldung/dddhexagonalspring/docker-compose.yml
@@ -0,0 +1,14 @@
+version: '3'
+
+services:
+ order-mongo-database:
+ image: mongo:3.4.13
+ restart: always
+ ports:
+ - 27017:27017
+ environment:
+ MONGO_INITDB_ROOT_USERNAME: admin
+ MONGO_INITDB_ROOT_PASSWORD: admin
+ MONGO_INITDB_DATABASE: order-database
+ volumes:
+ - ./mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro
\ No newline at end of file
diff --git a/ddd/src/test/resources/com/baeldung/dddhexagonalspring/mongo-init.js b/ddd/src/test/resources/com/baeldung/dddhexagonalspring/mongo-init.js
new file mode 100644
index 0000000000..b1564df50a
--- /dev/null
+++ b/ddd/src/test/resources/com/baeldung/dddhexagonalspring/mongo-init.js
@@ -0,0 +1,12 @@
+db.createUser(
+ {
+ user: "order",
+ pwd: "order",
+ roles: [
+ {
+ role: "readWrite",
+ db: "order-database"
+ }
+ ]
+ }
+);
\ No newline at end of file
diff --git a/httpclient/src/test/java/org/baeldung/httpclient/HttpClientMultipartLiveTest.java b/httpclient/src/test/java/org/baeldung/httpclient/HttpClientMultipartLiveTest.java
index 9912e73c2b..1752c27286 100644
--- a/httpclient/src/test/java/org/baeldung/httpclient/HttpClientMultipartLiveTest.java
+++ b/httpclient/src/test/java/org/baeldung/httpclient/HttpClientMultipartLiveTest.java
@@ -34,7 +34,7 @@ public class HttpClientMultipartLiveTest {
// No longer available
// private static final String SERVER = "http://echo.200please.com";
- private static final String SERVER = "http://posttestserver.com/post.php";
+ private static final String SERVER = "http://localhost:8080/spring-mvc-java/stub/multipart";
private static final String TEXTFILENAME = "temp.txt";
private static final String IMAGEFILENAME = "image.jpg";
private static final String ZIPFILENAME = "zipFile.zip";
@@ -84,7 +84,7 @@ public class HttpClientMultipartLiveTest {
//
final MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
- builder.addPart("upfile", fileBody);
+ builder.addPart("file", fileBody);
builder.addPart("text1", stringBody1);
builder.addPart("text2", stringBody2);
final HttpEntity entity = builder.build();
@@ -112,7 +112,7 @@ public class HttpClientMultipartLiveTest {
final String message = "This is a multipart post";
final MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
- builder.addBinaryBody("upfile", file, ContentType.DEFAULT_BINARY, TEXTFILENAME);
+ builder.addBinaryBody("file", file, ContentType.DEFAULT_BINARY, TEXTFILENAME);
builder.addTextBody("text", message, ContentType.DEFAULT_BINARY);
final HttpEntity entity = builder.build();
post.setEntity(entity);
@@ -141,7 +141,7 @@ public class HttpClientMultipartLiveTest {
final String message = "This is a multipart post";
final MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
- builder.addBinaryBody("upfile", file, ContentType.DEFAULT_BINARY, IMAGEFILENAME);
+ builder.addBinaryBody("file", file, ContentType.DEFAULT_BINARY, IMAGEFILENAME);
builder.addBinaryBody("upstream", inputStream, ContentType.create("application/zip"), ZIPFILENAME);
builder.addTextBody("text", message, ContentType.TEXT_PLAIN);
final HttpEntity entity = builder.build();
@@ -165,7 +165,7 @@ public class HttpClientMultipartLiveTest {
final byte[] bytes = "binary code".getBytes();
final MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
- builder.addBinaryBody("upfile", bytes, ContentType.DEFAULT_BINARY, TEXTFILENAME);
+ builder.addBinaryBody("file", bytes, ContentType.DEFAULT_BINARY, TEXTFILENAME);
builder.addTextBody("text", message, ContentType.TEXT_PLAIN);
final HttpEntity entity = builder.build();
post.setEntity(entity);
diff --git a/java-collections-conversions/src/main/java/com/baeldung/convertToMap/ConvertToMap.java b/java-collections-conversions/src/main/java/com/baeldung/convertToMap/ConvertToMap.java
index e33d9ee212..317cdca529 100644
--- a/java-collections-conversions/src/main/java/com/baeldung/convertToMap/ConvertToMap.java
+++ b/java-collections-conversions/src/main/java/com/baeldung/convertToMap/ConvertToMap.java
@@ -24,10 +24,7 @@ public class ConvertToMap {
public TreeMap listToSortedMap(List books) {
return books.stream()
- .sorted(Comparator.comparing(Book::getName))
.collect(Collectors.toMap(Book::getName, Function.identity(), (o1, o2) -> o1, TreeMap::new));
}
-
-
}
diff --git a/libraries-server/src/main/java/com/baeldung/tomcat/ProgrammaticTomcat.java b/libraries-server/src/main/java/com/baeldung/tomcat/ProgrammaticTomcat.java
index 6c4fed6d07..f42db2d3de 100644
--- a/libraries-server/src/main/java/com/baeldung/tomcat/ProgrammaticTomcat.java
+++ b/libraries-server/src/main/java/com/baeldung/tomcat/ProgrammaticTomcat.java
@@ -7,22 +7,50 @@ import org.apache.tomcat.util.descriptor.web.FilterDef;
import org.apache.tomcat.util.descriptor.web.FilterMap;
import java.io.File;
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.util.Random;
/**
* Created by adi on 1/10/18.
*/
public class ProgrammaticTomcat {
+ private static boolean isFree(int port) {
+ try {
+ new ServerSocket(port).close();
+ return true;
+ } catch (IOException e) {
+ return false;
+ }
+ }
+
private Tomcat tomcat = null;
+ private int randomPort;
+
+ public ProgrammaticTomcat() {
+ // Get a random port number in range 6000 (inclusive) - 9000 (exclusive)
+ this.randomPort = new Random()
+ .ints(6000, 9000)
+ .filter(ProgrammaticTomcat::isFree)
+ .findFirst()
+ .orElse(8080);
+ }
+
// uncomment for live test
// public static void main(String[] args) throws LifecycleException, ServletException, URISyntaxException, IOException {
// startTomcat();
// }
+
+ public int getPort() {
+ return randomPort;
+ }
+
public void startTomcat() throws LifecycleException {
tomcat = new Tomcat();
- tomcat.setPort(8080);
+ tomcat.setPort(randomPort);
tomcat.setHostname("localhost");
String appBase = ".";
tomcat.getHost().setAppBase(appBase);
diff --git a/libraries-server/src/test/java/com/baeldung/tomcat/ProgrammaticTomcatIntegrationTest.java b/libraries-server/src/test/java/com/baeldung/tomcat/ProgrammaticTomcatIntegrationTest.java
index 9224561341..888fb8e366 100644
--- a/libraries-server/src/test/java/com/baeldung/tomcat/ProgrammaticTomcatIntegrationTest.java
+++ b/libraries-server/src/test/java/com/baeldung/tomcat/ProgrammaticTomcatIntegrationTest.java
@@ -37,7 +37,8 @@ public class ProgrammaticTomcatIntegrationTest {
@Test
public void givenTomcatStarted_whenAccessServlet_responseIsTestAndResponseHeaderIsSet() throws Exception {
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
- HttpGet getServlet = new HttpGet("http://localhost:8080/my-servlet");
+ String uri = "http://localhost:" + tomcat.getPort() + "/my-servlet";
+ HttpGet getServlet = new HttpGet(uri);
HttpResponse response = httpClient.execute(getServlet);
assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode());
diff --git a/persistence-modules/hibernate5-2/src/main/java/com/baeldung/fetchMode/Customer.java b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/fetchMode/Customer.java
similarity index 100%
rename from persistence-modules/hibernate5-2/src/main/java/com/baeldung/fetchMode/Customer.java
rename to persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/fetchMode/Customer.java
diff --git a/persistence-modules/hibernate5-2/src/main/java/com/baeldung/fetchMode/Order.java b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/fetchMode/Order.java
similarity index 100%
rename from persistence-modules/hibernate5-2/src/main/java/com/baeldung/fetchMode/Order.java
rename to persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/fetchMode/Order.java
diff --git a/persistence-modules/hibernate5-2/pom.xml b/persistence-modules/hibernate5-2/pom.xml
index 516ab83997..16f6c10a7a 100644
--- a/persistence-modules/hibernate5-2/pom.xml
+++ b/persistence-modules/hibernate5-2/pom.xml
@@ -27,6 +27,12 @@
h2
1.4.200
+
+
+ org.apache.commons
+ commons-lang3
+ 3.8.1
+
diff --git a/persistence-modules/hibernate5-2/src/main/java/com/baeldung/hibernate/logging/Employee.java b/persistence-modules/hibernate5-2/src/main/java/com/baeldung/hibernate/logging/Employee.java
new file mode 100644
index 0000000000..9dcf4058a7
--- /dev/null
+++ b/persistence-modules/hibernate5-2/src/main/java/com/baeldung/hibernate/logging/Employee.java
@@ -0,0 +1,59 @@
+package com.baeldung.hibernate.logging;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+
+@Entity
+public class Employee {
+ @Id
+ @GeneratedValue(strategy = GenerationType.SEQUENCE)
+ private long id;
+
+ private String employeeNumber;
+
+ private String title;
+
+ private String name;
+
+ public Employee() {
+ }
+
+ public Employee(String name, String employeeNumber) {
+ this.name = name;
+ this.employeeNumber = employeeNumber;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public String getEmployeeNumber() {
+ return employeeNumber;
+ }
+
+ public void setEmployeeNumber(String employeeNumber) {
+ this.employeeNumber = employeeNumber;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+}
diff --git a/persistence-modules/hibernate5-2/src/main/resources/hibernate-logging.cfg.xml b/persistence-modules/hibernate5-2/src/main/resources/hibernate-logging.cfg.xml
new file mode 100644
index 0000000000..52ef1ee685
--- /dev/null
+++ b/persistence-modules/hibernate5-2/src/main/resources/hibernate-logging.cfg.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+ org.h2.Driver
+ jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1
+ sa
+
+
+ 1
+
+ org.hibernate.dialect.H2Dialect
+
+ org.hibernate.cache.internal.NoCacheProvider
+
+ true
+
+ create
+
+
+
+
+
\ No newline at end of file
diff --git a/persistence-modules/hibernate5-2/src/test/java/com/baeldung/hibernatelogging/HibernateLoggingIntegrationTest.java b/persistence-modules/hibernate5-2/src/test/java/com/baeldung/hibernatelogging/HibernateLoggingIntegrationTest.java
new file mode 100644
index 0000000000..8ec722671d
--- /dev/null
+++ b/persistence-modules/hibernate5-2/src/test/java/com/baeldung/hibernatelogging/HibernateLoggingIntegrationTest.java
@@ -0,0 +1,50 @@
+package com.baeldung.hibernatelogging;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.boot.MetadataSources;
+import org.hibernate.boot.registry.StandardServiceRegistry;
+import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
+import org.hibernate.query.Query;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.baeldung.hibernate.logging.Employee;
+
+public class HibernateLoggingIntegrationTest {
+
+ private SessionFactory sessionFactory;
+
+ @Before
+ public void setUp() throws IOException {
+ final StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure("hibernate-logging.cfg.xml")
+ .build();
+ try {
+ sessionFactory = new MetadataSources(registry).buildMetadata()
+ .buildSessionFactory();
+ Session session = sessionFactory.openSession();
+ session.beginTransaction();
+ session.save(new Employee("John Smith", "001"));
+ session.getTransaction()
+ .commit();
+ session.close();
+ } catch (Exception e) {
+ fail(e);
+ StandardServiceRegistryBuilder.destroy(registry);
+ }
+ }
+
+ @Test
+ public void whenAllEmployeesAreSelected_ThenSuccess() {
+ Query query = sessionFactory.openSession().createQuery("from com.baeldung.hibernate.logging.Employee", Employee.class);
+ List deptEmployees = query.list();
+ Employee deptEmployee = deptEmployees.get(0);
+ assertEquals("John Smith", deptEmployee.getName());
+ }
+}
diff --git a/persistence-modules/hibernate5-2/src/test/resources/log4j.xml b/persistence-modules/hibernate5-2/src/test/resources/log4j.xml
new file mode 100644
index 0000000000..2d153af124
--- /dev/null
+++ b/persistence-modules/hibernate5-2/src/test/resources/log4j.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/persistence-modules/hibernate5-2/src/test/resources/log4j2.xml b/persistence-modules/hibernate5-2/src/test/resources/log4j2.xml
new file mode 100644
index 0000000000..c5d0f12462
--- /dev/null
+++ b/persistence-modules/hibernate5-2/src/test/resources/log4j2.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/persistence-modules/hibernate5-2/src/test/resources/logback.xml b/persistence-modules/hibernate5-2/src/test/resources/logback.xml
new file mode 100644
index 0000000000..9e591977d7
--- /dev/null
+++ b/persistence-modules/hibernate5-2/src/test/resources/logback.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+ %d{yyyy-MM-dd HH:mm:ss} | %-5p | [%thread] %logger{5}:%L - %msg%n
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-cloud/spring-cloud-zuul/pom.xml b/spring-cloud/spring-cloud-zuul/pom.xml
index 1593bc59e9..b1f2e886de 100644
--- a/spring-cloud/spring-cloud-zuul/pom.xml
+++ b/spring-cloud/spring-cloud-zuul/pom.xml
@@ -73,8 +73,8 @@
UTF-8
UTF-8
- Finchley.SR1
- 2.0.6.RELEASE
+ Hoxton.RELEASE
+ 2.2.2.RELEASE
diff --git a/spring-cloud/spring-cloud-zuul/spring-zuul-foos-resource/pom.xml b/spring-cloud/spring-cloud-zuul/spring-zuul-foos-resource/pom.xml
index 57e566657b..f5a8c3b613 100644
--- a/spring-cloud/spring-cloud-zuul/spring-zuul-foos-resource/pom.xml
+++ b/spring-cloud/spring-cloud-zuul/spring-zuul-foos-resource/pom.xml
@@ -12,10 +12,6 @@
-
- org.springframework.boot
- spring-boot-starter-web
-
org.apache.commons
commons-lang3
diff --git a/spring-cloud/spring-cloud-zuul/spring-zuul-foos-resource/src/main/java/com/baeldung/web/controller/FooController.java b/spring-cloud/spring-cloud-zuul/spring-zuul-foos-resource/src/main/java/com/baeldung/web/controller/FooController.java
index 87f237b75c..f8f07342f6 100644
--- a/spring-cloud/spring-cloud-zuul/spring-zuul-foos-resource/src/main/java/com/baeldung/web/controller/FooController.java
+++ b/spring-cloud/spring-cloud-zuul/spring-zuul-foos-resource/src/main/java/com/baeldung/web/controller/FooController.java
@@ -1,11 +1,9 @@
package com.baeldung.web.controller;
import com.baeldung.web.dto.Foo;
-import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -13,22 +11,15 @@ import javax.servlet.http.HttpServletResponse;
import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
import static org.apache.commons.lang3.RandomStringUtils.randomNumeric;
-@Controller
+@RestController
public class FooController {
- public FooController() {
- super();
- }
-
- // API - read
- @RequestMapping(method = RequestMethod.GET, value = "/foos/{id}")
- @ResponseBody
+ @GetMapping("/foos/{id}")
public Foo findById(@PathVariable final long id, HttpServletRequest req, HttpServletResponse res) {
- // System.out.println(req.getHeaderNames());
- // System.out.println("------" + req.getHeader("Test"));
if (req.getHeader("Test") != null) {
res.addHeader("Test", req.getHeader("Test"));
}
+
return new Foo(Long.parseLong(randomNumeric(2)), randomAlphabetic(4));
}
diff --git a/spring-cloud/spring-cloud-zuul/spring-zuul-foos-resource/src/main/java/com/baeldung/web/dto/Foo.java b/spring-cloud/spring-cloud-zuul/spring-zuul-foos-resource/src/main/java/com/baeldung/web/dto/Foo.java
index 107f982f98..b25aef266d 100644
--- a/spring-cloud/spring-cloud-zuul/spring-zuul-foos-resource/src/main/java/com/baeldung/web/dto/Foo.java
+++ b/spring-cloud/spring-cloud-zuul/spring-zuul-foos-resource/src/main/java/com/baeldung/web/dto/Foo.java
@@ -1,22 +1,15 @@
package com.baeldung.web.dto;
public class Foo {
+
private long id;
private String name;
- public Foo() {
- super();
- }
-
public Foo(final long id, final String name) {
- super();
-
this.id = id;
this.name = name;
}
- //
-
public long getId() {
return id;
}
diff --git a/spring-di/src/main/java/org/baeldung/store/AppConfig.java b/spring-di/src/main/java/org/baeldung/store/AppConfig.java
new file mode 100644
index 0000000000..80b6733dff
--- /dev/null
+++ b/spring-di/src/main/java/org/baeldung/store/AppConfig.java
@@ -0,0 +1,23 @@
+package org.baeldung.store;
+
+import org.springframework.context.annotation.Bean;
+
+public class AppConfig {
+
+ @Bean
+ public Item item1() {
+ return new ItemImpl1();
+ }
+
+ @Bean
+ public Store storeThroughConstructorInjection() {
+ return new Store(item1());
+ }
+
+ @Bean
+ public Store storeThroughSetterInjection() {
+ Store store = new Store();
+ store.setItem(item1());
+ return store;
+ }
+}
diff --git a/spring-di/src/main/java/org/baeldung/store/Item.java b/spring-di/src/main/java/org/baeldung/store/Item.java
new file mode 100644
index 0000000000..1d7292fc35
--- /dev/null
+++ b/spring-di/src/main/java/org/baeldung/store/Item.java
@@ -0,0 +1,5 @@
+package org.baeldung.store;
+
+public interface Item {
+
+}
diff --git a/spring-di/src/main/java/org/baeldung/store/ItemImpl1.java b/spring-di/src/main/java/org/baeldung/store/ItemImpl1.java
new file mode 100644
index 0000000000..8bda9f24c9
--- /dev/null
+++ b/spring-di/src/main/java/org/baeldung/store/ItemImpl1.java
@@ -0,0 +1,5 @@
+package org.baeldung.store;
+
+public class ItemImpl1 implements Item {
+
+}
diff --git a/spring-di/src/main/java/org/baeldung/store/Store.java b/spring-di/src/main/java/org/baeldung/store/Store.java
new file mode 100644
index 0000000000..dcc2c3be48
--- /dev/null
+++ b/spring-di/src/main/java/org/baeldung/store/Store.java
@@ -0,0 +1,23 @@
+package org.baeldung.store;
+
+import org.springframework.beans.factory.annotation.Autowired;
+
+public class Store {
+
+ @Autowired
+ private Item item;
+
+ public Store() {}
+
+ public Store(Item item) {
+ this.item = item;
+ }
+
+ public Item getItem() {
+ return item;
+ }
+
+ public void setItem(Item item) {
+ this.item = item;
+ }
+}
diff --git a/spring-di/src/main/resources/ioc-context-by-type.xml b/spring-di/src/main/resources/ioc-context-by-type.xml
new file mode 100644
index 0000000000..1249ce51af
--- /dev/null
+++ b/spring-di/src/main/resources/ioc-context-by-type.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-di/src/main/resources/ioc-context.xml b/spring-di/src/main/resources/ioc-context.xml
new file mode 100644
index 0000000000..0e1d0ac29c
--- /dev/null
+++ b/spring-di/src/main/resources/ioc-context.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-di/src/test/java/org/baeldung/store/AppConfigUnitTest.java b/spring-di/src/test/java/org/baeldung/store/AppConfigUnitTest.java
new file mode 100644
index 0000000000..3260114679
--- /dev/null
+++ b/spring-di/src/test/java/org/baeldung/store/AppConfigUnitTest.java
@@ -0,0 +1,35 @@
+package org.baeldung.store;
+
+import static org.junit.Assert.assertNotNull;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = AppConfig.class)
+public class AppConfigUnitTest {
+
+ @Autowired
+ @Qualifier("storeThroughConstructorInjection")
+ private Store storeByConstructorInjection;
+
+ @Autowired
+ @Qualifier("storeThroughSetterInjection")
+ private Store storeBySetterInjection;
+
+ @Test
+ public void givenValidXmlConfig_WhenInjectStoreByConstructorInjection_ThenBeanIsNotNull() {
+ assertNotNull(storeByConstructorInjection);
+ assertNotNull(storeByConstructorInjection.getItem());
+ }
+
+ @Test
+ public void givenValidXmlConfig_WhenInjectStoreBySetterInjection_ThenBeanIsNotNull() {
+ assertNotNull(storeBySetterInjection);
+ assertNotNull(storeByConstructorInjection.getItem());
+ }
+}
diff --git a/spring-di/src/test/java/org/baeldung/store/XmlAppConfigByTypeUnitTest.java b/spring-di/src/test/java/org/baeldung/store/XmlAppConfigByTypeUnitTest.java
new file mode 100644
index 0000000000..036399e537
--- /dev/null
+++ b/spring-di/src/test/java/org/baeldung/store/XmlAppConfigByTypeUnitTest.java
@@ -0,0 +1,30 @@
+package org.baeldung.store;
+
+import static org.junit.Assert.assertNotNull;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+/**
+ * Separate unit test class where only one Item object is available for
+ * autowiring. If the ioc-context.xml were used for autowiring by type, there
+ * would be multiple qualifying Item objects, causing a failure.
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration("classpath:/ioc-context-by-type.xml")
+public class XmlAppConfigByTypeUnitTest {
+
+ @Autowired
+ @Qualifier("xml-store-by-autowire-type")
+ private Store storeByAutowireInjectionByType;
+
+ @Test
+ public void givenValidXmlConfig_WhenInjectStoreByAutowireInjectionByType_ThenBeanIsNotNull() {
+ assertNotNull(storeByAutowireInjectionByType);
+ assertNotNull(storeByAutowireInjectionByType.getItem());
+ }
+}
diff --git a/spring-di/src/test/java/org/baeldung/store/XmlAppConfigUnitTest.java b/spring-di/src/test/java/org/baeldung/store/XmlAppConfigUnitTest.java
new file mode 100644
index 0000000000..2dd4d6ccd6
--- /dev/null
+++ b/spring-di/src/test/java/org/baeldung/store/XmlAppConfigUnitTest.java
@@ -0,0 +1,55 @@
+package org.baeldung.store;
+
+import static org.junit.Assert.assertNotNull;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration("classpath:/ioc-context.xml")
+public class XmlAppConfigUnitTest {
+
+ @Autowired
+ @Qualifier("xml-store-by-constructor")
+ private Store storeByConstructorInjection;
+
+ @Autowired
+ @Qualifier("xml-store-by-setter")
+ private Store storeBySetterInjection;
+
+ @Autowired
+ @Qualifier("xml-store-by-autowire-name")
+ private Store storeByAutowireInjectionByName;
+
+ @Autowired
+ @Qualifier("xml-store-by-setter-lazy")
+ private Store storeBySetterInjectionLazy;
+
+ @Test
+ public void givenValidXmlConfig_WhenInjectStoreByConstructorInjection_ThenBeanIsNotNull() {
+ assertNotNull(storeByConstructorInjection);
+ assertNotNull(storeByConstructorInjection.getItem());
+ }
+
+ @Test
+ public void givenValidXmlConfig_WhenInjectStoreBySetterInjection_ThenBeanIsNotNull() {
+ assertNotNull(storeBySetterInjection);
+ assertNotNull(storeByConstructorInjection.getItem());
+ }
+
+ @Test
+ public void givenValidXmlConfig_WhenInjectStoreByAutowireInjectionByName_ThenBeanIsNotNull() {
+ assertNotNull(storeByAutowireInjectionByName);
+ assertNotNull(storeByAutowireInjectionByName.getItem());
+ }
+
+ @Test
+ public void givenValidXmlConfig_WhenInjectStoreBySetterInjectionLazy_ThenBeanIsNotNull() {
+ assertNotNull(storeBySetterInjectionLazy);
+ assertNotNull(storeByConstructorInjection.getItem());
+ }
+}
diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/model/Article.java b/spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/Article.java
similarity index 87%
rename from spring-mvc-basics-2/src/main/java/com/baeldung/model/Article.java
rename to spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/Article.java
index 141bd17db7..f6675295ed 100644
--- a/spring-mvc-basics-2/src/main/java/com/baeldung/model/Article.java
+++ b/spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/Article.java
@@ -1,4 +1,4 @@
-package com.baeldung.model;
+package com.baeldung.controller.optionalpathvars;
public class Article {
diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerController.java b/spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerController.java
index 62c2502242..14b16e148b 100644
--- a/spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerController.java
+++ b/spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerController.java
@@ -1,13 +1,11 @@
package com.baeldung.controller.optionalpathvars;
-import static com.baeldung.model.Article.DEFAULT_ARTICLE;
+import static com.baeldung.controller.optionalpathvars.Article.DEFAULT_ARTICLE;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
-import com.baeldung.model.Article;
-
@RestController
public class ArticleViewerController {
diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithMapParamController.java b/spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithMapParamController.java
index d16cf4115c..50744b6067 100644
--- a/spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithMapParamController.java
+++ b/spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithMapParamController.java
@@ -1,6 +1,6 @@
package com.baeldung.controller.optionalpathvars;
-import static com.baeldung.model.Article.DEFAULT_ARTICLE;
+import static com.baeldung.controller.optionalpathvars.Article.DEFAULT_ARTICLE;
import java.util.Map;
@@ -8,8 +8,6 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
-import com.baeldung.model.Article;
-
@RestController
@RequestMapping(value = "/mapParam")
public class ArticleViewerWithMapParamController {
diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithOptionalParamController.java b/spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithOptionalParamController.java
index fd7b900535..ff645fbcc7 100644
--- a/spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithOptionalParamController.java
+++ b/spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithOptionalParamController.java
@@ -1,14 +1,12 @@
package com.baeldung.controller.optionalpathvars;
-import static com.baeldung.model.Article.DEFAULT_ARTICLE;
+import static com.baeldung.controller.optionalpathvars.Article.DEFAULT_ARTICLE;
import java.util.Optional;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-import com.baeldung.model.Article;;
+import org.springframework.web.bind.annotation.RestController;;
@RestController
@RequestMapping("/optionalParam")
diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithRequiredAttributeController.java b/spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithRequiredAttributeController.java
index d9b36f93e8..8cd1539391 100644
--- a/spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithRequiredAttributeController.java
+++ b/spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithRequiredAttributeController.java
@@ -1,12 +1,10 @@
package com.baeldung.controller.optionalpathvars;
-import static com.baeldung.model.Article.DEFAULT_ARTICLE;
+import static com.baeldung.controller.optionalpathvars.Article.DEFAULT_ARTICLE;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-import com.baeldung.model.Article;;
+import org.springframework.web.bind.annotation.RestController;;
@RestController
@RequestMapping(value = "/requiredAttribute")
diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithTwoSeparateMethodsController.java b/spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithTwoSeparateMethodsController.java
index 0b66b6cf43..0ea401a589 100644
--- a/spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithTwoSeparateMethodsController.java
+++ b/spring-mvc-basics-2/src/main/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithTwoSeparateMethodsController.java
@@ -1,13 +1,11 @@
package com.baeldung.controller.optionalpathvars;
-import static com.baeldung.model.Article.DEFAULT_ARTICLE;
+import static com.baeldung.controller.optionalpathvars.Article.DEFAULT_ARTICLE;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
-import com.baeldung.model.Article;
-
@RestController
@RequestMapping(value = "/seperateMethods")
public class ArticleViewerWithTwoSeparateMethodsController {
diff --git a/spring-mvc-basics-2/src/test/java/com/baeldung/controller/optionalpathvars/ArticleViewerControllerWithOptionalParamIntegrationTest.java b/spring-mvc-basics-2/src/test/java/com/baeldung/controller/optionalpathvars/ArticleViewerControllerWithOptionalParamIntegrationTest.java
index 629e37f963..c7b568b68e 100644
--- a/spring-mvc-basics-2/src/test/java/com/baeldung/controller/optionalpathvars/ArticleViewerControllerWithOptionalParamIntegrationTest.java
+++ b/spring-mvc-basics-2/src/test/java/com/baeldung/controller/optionalpathvars/ArticleViewerControllerWithOptionalParamIntegrationTest.java
@@ -12,8 +12,6 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
-
-import com.baeldung.model.Article;
import org.baeldung.controller.config.WebConfig;
@RunWith(SpringJUnit4ClassRunner.class)
diff --git a/spring-mvc-basics-2/src/test/java/com/baeldung/controller/optionalpathvars/ArticleViewerControllerWithRequiredAttributeIntegrationTest.java b/spring-mvc-basics-2/src/test/java/com/baeldung/controller/optionalpathvars/ArticleViewerControllerWithRequiredAttributeIntegrationTest.java
index 00494171c0..760d94af17 100644
--- a/spring-mvc-basics-2/src/test/java/com/baeldung/controller/optionalpathvars/ArticleViewerControllerWithRequiredAttributeIntegrationTest.java
+++ b/spring-mvc-basics-2/src/test/java/com/baeldung/controller/optionalpathvars/ArticleViewerControllerWithRequiredAttributeIntegrationTest.java
@@ -12,8 +12,6 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
-
-import com.baeldung.model.Article;
import org.baeldung.controller.config.WebConfig;
@RunWith(SpringJUnit4ClassRunner.class)
diff --git a/spring-mvc-basics-2/src/test/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithMapParamIntegrationTest.java b/spring-mvc-basics-2/src/test/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithMapParamIntegrationTest.java
index 3c82b11578..fca6bba5fd 100644
--- a/spring-mvc-basics-2/src/test/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithMapParamIntegrationTest.java
+++ b/spring-mvc-basics-2/src/test/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithMapParamIntegrationTest.java
@@ -12,8 +12,6 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
-
-import com.baeldung.model.Article;
import org.baeldung.controller.config.WebConfig;
@RunWith(SpringJUnit4ClassRunner.class)
diff --git a/spring-mvc-basics-2/src/test/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithTwoSeparateMethodsIntegrationTest.java b/spring-mvc-basics-2/src/test/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithTwoSeparateMethodsIntegrationTest.java
index 9532270c43..5d2733ec92 100644
--- a/spring-mvc-basics-2/src/test/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithTwoSeparateMethodsIntegrationTest.java
+++ b/spring-mvc-basics-2/src/test/java/com/baeldung/controller/optionalpathvars/ArticleViewerWithTwoSeparateMethodsIntegrationTest.java
@@ -12,8 +12,6 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
-
-import com.baeldung.model.Article;
import org.baeldung.controller.config.WebConfig;
@RunWith(SpringJUnit4ClassRunner.class)
diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/MultipartFileUploadStubController.java b/spring-mvc-java/src/main/java/com/baeldung/web/controller/MultipartFileUploadStubController.java
new file mode 100644
index 0000000000..28c35e8603
--- /dev/null
+++ b/spring-mvc-java/src/main/java/com/baeldung/web/controller/MultipartFileUploadStubController.java
@@ -0,0 +1,58 @@
+package com.baeldung.web.controller;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.multipart.MultipartFile;
+
+@Controller
+public class MultipartFileUploadStubController {
+
+ @PostMapping("/stub/multipart")
+ public ResponseEntity uploadFile(MultipartFile file, String text, String text1, String text2, MultipartFile upstream) {
+ UploadResultResource result = new UploadResultResource(file, text, text1, text2, upstream);
+ return new ResponseEntity<>(result, HttpStatus.OK);
+ }
+
+ public static class UploadResultResource {
+
+ private final String file;
+ private final String text;
+ private final String text1;
+ private final String text2;
+ private final String upstream;
+
+ public UploadResultResource(MultipartFile file, String text, String text1, String text2, MultipartFile upstream) {
+ this.file = format(file);
+ this.text = text;
+ this.text1 = text1;
+ this.text2 = text2;
+ this.upstream = format(upstream);
+ }
+
+ private static String format(MultipartFile file) {
+ return file == null ? null : file.getOriginalFilename() + " (size: " + file.getSize() + " bytes)";
+ }
+
+ public String getFile() {
+ return file;
+ }
+
+ public String getText() {
+ return text;
+ }
+
+ public String getText1() {
+ return text1;
+ }
+
+ public String getText2() {
+ return text2;
+ }
+
+ public String getUpstream() {
+ return upstream;
+ }
+ }
+}
diff --git a/spring-core-2/src/main/java/org/baeldung/cachedrequest/CachedBodyHttpServletRequest.java b/spring-mvc-simple-2/src/main/java/org/baeldung/cachedrequest/CachedBodyHttpServletRequest.java
similarity index 100%
rename from spring-core-2/src/main/java/org/baeldung/cachedrequest/CachedBodyHttpServletRequest.java
rename to spring-mvc-simple-2/src/main/java/org/baeldung/cachedrequest/CachedBodyHttpServletRequest.java
diff --git a/spring-core-2/src/main/java/org/baeldung/cachedrequest/CachedBodyServletInputStream.java b/spring-mvc-simple-2/src/main/java/org/baeldung/cachedrequest/CachedBodyServletInputStream.java
similarity index 100%
rename from spring-core-2/src/main/java/org/baeldung/cachedrequest/CachedBodyServletInputStream.java
rename to spring-mvc-simple-2/src/main/java/org/baeldung/cachedrequest/CachedBodyServletInputStream.java
diff --git a/spring-core-2/src/main/java/org/baeldung/cachedrequest/ContentCachingFilter.java b/spring-mvc-simple-2/src/main/java/org/baeldung/cachedrequest/ContentCachingFilter.java
similarity index 100%
rename from spring-core-2/src/main/java/org/baeldung/cachedrequest/ContentCachingFilter.java
rename to spring-mvc-simple-2/src/main/java/org/baeldung/cachedrequest/ContentCachingFilter.java
diff --git a/spring-core-2/src/main/java/org/baeldung/cachedrequest/HttpRequestDemoConfig.java b/spring-mvc-simple-2/src/main/java/org/baeldung/cachedrequest/HttpRequestDemoConfig.java
similarity index 100%
rename from spring-core-2/src/main/java/org/baeldung/cachedrequest/HttpRequestDemoConfig.java
rename to spring-mvc-simple-2/src/main/java/org/baeldung/cachedrequest/HttpRequestDemoConfig.java
diff --git a/spring-core-2/src/main/java/org/baeldung/cachedrequest/Person.java b/spring-mvc-simple-2/src/main/java/org/baeldung/cachedrequest/Person.java
similarity index 100%
rename from spring-core-2/src/main/java/org/baeldung/cachedrequest/Person.java
rename to spring-mvc-simple-2/src/main/java/org/baeldung/cachedrequest/Person.java
diff --git a/spring-core-2/src/main/java/org/baeldung/cachedrequest/PersonController.java b/spring-mvc-simple-2/src/main/java/org/baeldung/cachedrequest/PersonController.java
similarity index 100%
rename from spring-core-2/src/main/java/org/baeldung/cachedrequest/PersonController.java
rename to spring-mvc-simple-2/src/main/java/org/baeldung/cachedrequest/PersonController.java
diff --git a/spring-core-2/src/main/java/org/baeldung/cachedrequest/PrintRequestContentFilter.java b/spring-mvc-simple-2/src/main/java/org/baeldung/cachedrequest/PrintRequestContentFilter.java
similarity index 100%
rename from spring-core-2/src/main/java/org/baeldung/cachedrequest/PrintRequestContentFilter.java
rename to spring-mvc-simple-2/src/main/java/org/baeldung/cachedrequest/PrintRequestContentFilter.java
diff --git a/spring-core-2/src/test/java/org/baeldung/cachedrequest/CachedBodyHttpServletRequestUnitTest.java b/spring-mvc-simple-2/src/test/java/org/baeldung/cachedrequest/CachedBodyHttpServletRequestUnitTest.java
similarity index 100%
rename from spring-core-2/src/test/java/org/baeldung/cachedrequest/CachedBodyHttpServletRequestUnitTest.java
rename to spring-mvc-simple-2/src/test/java/org/baeldung/cachedrequest/CachedBodyHttpServletRequestUnitTest.java
diff --git a/spring-core-2/src/test/java/org/baeldung/cachedrequest/CachedBodyServletInputStreamUnitTest.java b/spring-mvc-simple-2/src/test/java/org/baeldung/cachedrequest/CachedBodyServletInputStreamUnitTest.java
similarity index 100%
rename from spring-core-2/src/test/java/org/baeldung/cachedrequest/CachedBodyServletInputStreamUnitTest.java
rename to spring-mvc-simple-2/src/test/java/org/baeldung/cachedrequest/CachedBodyServletInputStreamUnitTest.java
diff --git a/spring-core-2/src/test/java/org/baeldung/cachedrequest/ContentCachingFilterUnitTest.java b/spring-mvc-simple-2/src/test/java/org/baeldung/cachedrequest/ContentCachingFilterUnitTest.java
similarity index 100%
rename from spring-core-2/src/test/java/org/baeldung/cachedrequest/ContentCachingFilterUnitTest.java
rename to spring-mvc-simple-2/src/test/java/org/baeldung/cachedrequest/ContentCachingFilterUnitTest.java
diff --git a/spring-core-2/src/test/java/org/baeldung/cachedrequest/PersonControllerIntegrationTest.java b/spring-mvc-simple-2/src/test/java/org/baeldung/cachedrequest/PersonControllerIntegrationTest.java
similarity index 100%
rename from spring-core-2/src/test/java/org/baeldung/cachedrequest/PersonControllerIntegrationTest.java
rename to spring-mvc-simple-2/src/test/java/org/baeldung/cachedrequest/PersonControllerIntegrationTest.java
diff --git a/spring-core-2/src/test/java/org/baeldung/cachedrequest/PrintRequestContentFilterUnitTest.java b/spring-mvc-simple-2/src/test/java/org/baeldung/cachedrequest/PrintRequestContentFilterUnitTest.java
similarity index 100%
rename from spring-core-2/src/test/java/org/baeldung/cachedrequest/PrintRequestContentFilterUnitTest.java
rename to spring-mvc-simple-2/src/test/java/org/baeldung/cachedrequest/PrintRequestContentFilterUnitTest.java
diff --git a/spring-session/spring-session-mongodb/src/test/java/com/baeldung/springsessionmongodb/SpringSessionMongoDBIntegrationTest.java b/spring-session/spring-session-mongodb/src/test/java/com/baeldung/springsessionmongodb/SpringSessionMongoDBIntegrationTest.java
index 9dc45c5b32..de41019e49 100644
--- a/spring-session/spring-session-mongodb/src/test/java/com/baeldung/springsessionmongodb/SpringSessionMongoDBIntegrationTest.java
+++ b/spring-session/spring-session-mongodb/src/test/java/com/baeldung/springsessionmongodb/SpringSessionMongoDBIntegrationTest.java
@@ -6,6 +6,7 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
+import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
@@ -16,9 +17,12 @@ import java.util.Base64;
@RunWith(SpringRunner.class)
-@SpringBootTest(classes = SpringSessionMongoDBApplication.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
+@SpringBootTest(classes = SpringSessionMongoDBApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class SpringSessionMongoDBIntegrationTest {
+ @LocalServerPort
+ private int port;
+
@Autowired
private MongoOperationsSessionRepository repository;
@@ -27,7 +31,7 @@ public class SpringSessionMongoDBIntegrationTest {
@Test
public void givenEndpointIsCalledTwiceAndResponseIsReturned_whenMongoDBIsQueriedForCount_thenCountMustBeSame() {
HttpEntity response = restTemplate
- .exchange("http://localhost:" + 8080, HttpMethod.GET, null, String.class);
+ .exchange("http://localhost:" + port, HttpMethod.GET, null, String.class);
HttpHeaders headers = response.getHeaders();
String set_cookie = headers.getFirst(HttpHeaders.SET_COOKIE);
diff --git a/spring-session/spring-session-redis/src/test/java/com/baeldung/spring/session/SessionControllerIntegrationTest.java b/spring-session/spring-session-redis/src/test/java/com/baeldung/spring/session/SessionControllerIntegrationTest.java
index f739aeb3ab..7ee0294315 100644
--- a/spring-session/spring-session-redis/src/test/java/com/baeldung/spring/session/SessionControllerIntegrationTest.java
+++ b/spring-session/spring-session-redis/src/test/java/com/baeldung/spring/session/SessionControllerIntegrationTest.java
@@ -1,16 +1,11 @@
package com.baeldung.spring.session;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.io.IOException;
-import java.util.Set;
-
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.springframework.boot.context.embedded.LocalServerPort;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.client.TestRestTemplate;
@@ -20,19 +15,27 @@ import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;
-
import redis.clients.jedis.Jedis;
import redis.embedded.RedisServer;
+import java.io.IOException;
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
@RunWith(SpringRunner.class)
-@SpringBootTest(classes = SessionWebApplication.class, webEnvironment = WebEnvironment.DEFINED_PORT)
+@SpringBootTest(classes = SessionWebApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT)
public class SessionControllerIntegrationTest {
- private Jedis jedis;
private static RedisServer redisServer;
+
+ @LocalServerPort
+ private int port;
+
+ private Jedis jedis;
private TestRestTemplate testRestTemplate;
private TestRestTemplate testRestTemplateWithAuth;
- private String testUrl = "http://localhost:8080/";
@BeforeClass
public static void startRedisServer() throws IOException {
@@ -41,7 +44,7 @@ public class SessionControllerIntegrationTest {
}
@AfterClass
- public static void stopRedisServer() throws IOException {
+ public static void stopRedisServer() {
redisServer.stop();
}
@@ -63,13 +66,13 @@ public class SessionControllerIntegrationTest {
@Test
public void testUnauthenticatedCantAccess() {
- ResponseEntity result = testRestTemplate.getForEntity(testUrl, String.class);
+ ResponseEntity result = testRestTemplate.getForEntity(getTestUrl(), String.class);
assertEquals(HttpStatus.UNAUTHORIZED, result.getStatusCode());
}
@Test
public void testRedisControlsSession() {
- ResponseEntity result = testRestTemplateWithAuth.getForEntity(testUrl, String.class);
+ ResponseEntity result = testRestTemplateWithAuth.getForEntity(getTestUrl(), String.class);
assertEquals("hello admin", result.getBody()); // login worked
Set redisResult = jedis.keys("*");
@@ -80,13 +83,16 @@ public class SessionControllerIntegrationTest {
headers.add("Cookie", sessionCookie);
HttpEntity httpEntity = new HttpEntity<>(headers);
- result = testRestTemplate.exchange(testUrl, HttpMethod.GET, httpEntity, String.class);
+ result = testRestTemplate.exchange(getTestUrl(), HttpMethod.GET, httpEntity, String.class);
assertEquals("hello admin", result.getBody()); // access with session works worked
jedis.flushAll(); // clear all keys in redis
- result = testRestTemplate.exchange(testUrl, HttpMethod.GET, httpEntity, String.class);
+ result = testRestTemplate.exchange(getTestUrl(), HttpMethod.GET, httpEntity, String.class);
assertEquals(HttpStatus.UNAUTHORIZED, result.getStatusCode());// access denied after sessions are removed in redis
+ }
+ private String getTestUrl(){
+ return "http://localhost:" + port;
}
}
\ No newline at end of file
diff --git a/testing-modules/testing-libraries/src/main/java/com/baeldung/cucumber/books/BookStore.java b/testing-modules/testing-libraries/src/main/java/com/baeldung/cucumber/books/BookStore.java
index 4ccfe61542..da9b711a16 100644
--- a/testing-modules/testing-libraries/src/main/java/com/baeldung/cucumber/books/BookStore.java
+++ b/testing-modules/testing-libraries/src/main/java/com/baeldung/cucumber/books/BookStore.java
@@ -19,10 +19,4 @@ public class BookStore {
.filter(book -> Objects.equals(author, book.getAuthor()))
.collect(Collectors.toList());
}
-
- public Optional bookByTitle(String title) {
- return books.stream()
- .filter(book -> book.getTitle().equals(title))
- .findFirst();
- }
}
diff --git a/testing-modules/testing-libraries/src/main/java/com/baeldung/cucumberbackground/books/Book.java b/testing-modules/testing-libraries/src/main/java/com/baeldung/cucumberbackground/books/Book.java
new file mode 100644
index 0000000000..5fd1e680a0
--- /dev/null
+++ b/testing-modules/testing-libraries/src/main/java/com/baeldung/cucumberbackground/books/Book.java
@@ -0,0 +1,35 @@
+package com.baeldung.cucumberbackground.books;
+
+public class Book {
+
+ private String title;
+ private String author;
+
+ public Book(String title, String author) {
+ this.title = title;
+ this.author = author;
+ }
+
+ public Book() {}
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getAuthor() {
+ return author;
+ }
+
+ public void setAuthor(String author) {
+ this.author = author;
+ }
+
+ @Override
+ public String toString() {
+ return "Book [title=" + title + ", author=" + author + "]";
+ }
+}
diff --git a/testing-modules/testing-libraries/src/main/java/com/baeldung/cucumberbackground/books/BookStore.java b/testing-modules/testing-libraries/src/main/java/com/baeldung/cucumberbackground/books/BookStore.java
new file mode 100644
index 0000000000..f22eecb5f3
--- /dev/null
+++ b/testing-modules/testing-libraries/src/main/java/com/baeldung/cucumberbackground/books/BookStore.java
@@ -0,0 +1,28 @@
+package com.baeldung.cucumberbackground.books;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+public class BookStore {
+ private List books = new ArrayList<>();
+
+ public void addBook(Book book) {
+ books.add(book);
+ }
+
+ public void addAllBooks(Collection books) {
+ this.books.addAll(books);
+ }
+
+ public List booksByAuthor(String author) {
+ return books.stream()
+ .filter(book -> Objects.equals(author, book.getAuthor()))
+ .collect(Collectors.toList());
+ }
+
+ public Optional bookByTitle(String title) {
+ return books.stream()
+ .filter(book -> book.getTitle().equals(title))
+ .findFirst();
+ }
+}
diff --git a/testing-modules/testing-libraries/src/test/java/com/baeldung/cucumber/books/BookStoreRunSteps.java b/testing-modules/testing-libraries/src/test/java/com/baeldung/cucumber/books/BookStoreRunSteps.java
index 995a3469f0..a0c759ab26 100644
--- a/testing-modules/testing-libraries/src/test/java/com/baeldung/cucumber/books/BookStoreRunSteps.java
+++ b/testing-modules/testing-libraries/src/test/java/com/baeldung/cucumber/books/BookStoreRunSteps.java
@@ -56,11 +56,6 @@ public class BookStoreRunSteps {
foundBooks = store.booksByAuthor(author);
}
- @When("^I search for a book titled (.+)$")
- public void searchForBookByTitle(String title) {
- foundBook = store.bookByTitle(title).orElse(null);
- }
-
@Then("^I find (\\d+) books$")
public void findBooks(int count) {
assertEquals(count, foundBooks.size());
diff --git a/testing-modules/testing-libraries/src/test/java/com/baeldung/cucumberbackground/books/BookStoreRunSteps.java b/testing-modules/testing-libraries/src/test/java/com/baeldung/cucumberbackground/books/BookStoreRunSteps.java
new file mode 100644
index 0000000000..981fe41f11
--- /dev/null
+++ b/testing-modules/testing-libraries/src/test/java/com/baeldung/cucumberbackground/books/BookStoreRunSteps.java
@@ -0,0 +1,58 @@
+package com.baeldung.cucumberbackground.books;
+
+import io.cucumber.datatable.DataTable;
+import io.cucumber.java.Before;
+import io.cucumber.java.en.Given;
+import io.cucumber.java.en.Then;
+import io.cucumber.java.en.When;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.Assert.*;
+
+public class BookStoreRunSteps {
+ private BookStore store;
+ private List foundBooks;
+ private Book foundBook;
+
+ @Before
+ public void setUp() {
+ store = new BookStore();
+ foundBooks = new ArrayList<>();
+ }
+
+ @Given("^I have the following books in the store$")
+ public void haveBooksInTheStore(DataTable table) {
+ List> rows = table.asLists(String.class);
+
+ for (List columns: rows) {
+ store.addBook(new Book(columns.get(0), columns.get(1)));
+ }
+ }
+
+ @When("^I search for books by author (.+)$")
+ public void searchForBooksByAuthor(String author) {
+ foundBooks = store.booksByAuthor(author);
+ }
+
+ @When("^I search for a book titled (.+)$")
+ public void searchForBookByTitle(String title) {
+ foundBook = store.bookByTitle(title).orElse(null);
+ }
+
+ @Then("^I find (\\d+) books$")
+ public void findBooks(int count) {
+ assertEquals(count, foundBooks.size());
+ }
+
+ @Then("^I find a book$")
+ public void findABook() {
+ assertNotNull(foundBook);
+ }
+
+ @Then("^I find no book$")
+ public void findNoBook() {
+ assertNull(foundBook);
+ }
+}
diff --git a/testing-modules/testing-libraries/src/test/java/com/baeldung/cucumberbackground/books/BookStoreWithBackgroundIntegrationTest.java b/testing-modules/testing-libraries/src/test/java/com/baeldung/cucumberbackground/books/BookStoreWithBackgroundIntegrationTest.java
new file mode 100644
index 0000000000..528ccbc882
--- /dev/null
+++ b/testing-modules/testing-libraries/src/test/java/com/baeldung/cucumberbackground/books/BookStoreWithBackgroundIntegrationTest.java
@@ -0,0 +1,12 @@
+package com.baeldung.cucumberbackground.books;
+
+import io.cucumber.junit.Cucumber;
+import io.cucumber.junit.CucumberOptions;
+import org.junit.runner.RunWith;
+
+@RunWith(Cucumber.class)
+@CucumberOptions(features = "classpath:features/book-store-with-background.feature")
+public class BookStoreWithBackgroundIntegrationTest {
+
+}
+
diff --git a/testing-modules/testing-libraries/src/test/java/com/baeldung/cucumberbackground/books/BookStoreWithoutBackgroundIntegrationTest.java b/testing-modules/testing-libraries/src/test/java/com/baeldung/cucumberbackground/books/BookStoreWithoutBackgroundIntegrationTest.java
new file mode 100644
index 0000000000..6343a52cdc
--- /dev/null
+++ b/testing-modules/testing-libraries/src/test/java/com/baeldung/cucumberbackground/books/BookStoreWithoutBackgroundIntegrationTest.java
@@ -0,0 +1,12 @@
+package com.baeldung.cucumberbackground.books;
+
+import io.cucumber.junit.Cucumber;
+import io.cucumber.junit.CucumberOptions;
+import org.junit.runner.RunWith;
+
+@RunWith(Cucumber.class)
+@CucumberOptions(features = "classpath:features/book-store-without-background.feature")
+public class BookStoreWithoutBackgroundIntegrationTest {
+
+}
+