Merge branch 'master' of https://github.com/eugenp/tutorials
This commit is contained in:
commit
c8996a936e
|
@ -0,0 +1,5 @@
|
||||||
|
## Core Java Exceptions 2
|
||||||
|
|
||||||
|
This module contains articles about core java exceptions
|
||||||
|
|
||||||
|
###
|
|
@ -0,0 +1,24 @@
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>core-java-exceptions-2</artifactId>
|
||||||
|
<name>core-java-exceptions-2</name>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<artifactId>parent-java</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<relativePath>../../parent-java</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<description> </description>
|
||||||
|
<url>http://maven.apache.org</url>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
</project>
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
package com.baeldung.rethrow.custom;
|
||||||
|
|
||||||
|
public class InvalidDataException extends Exception {
|
||||||
|
|
||||||
|
public InvalidDataException(Exception e) {
|
||||||
|
super(e);
|
||||||
|
}
|
||||||
|
}
|
|
@ -76,6 +76,11 @@
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mockito</groupId>
|
||||||
|
<artifactId>mockito-core</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>de.flapdoodle.embed</groupId>
|
<groupId>de.flapdoodle.embed</groupId>
|
||||||
<artifactId>de.flapdoodle.embed.mongo</artifactId>
|
<artifactId>de.flapdoodle.embed.mongo</artifactId>
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
package com.baeldung.ddd;
|
package com.baeldung.ddd;
|
||||||
|
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
@SpringBootApplication
|
@SpringBootApplication(scanBasePackages = "com.baeldung.ddd.order")
|
||||||
public class PersistingDddAggregatesApplication {
|
public class PersistingDddAggregatesApplication {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
SpringApplication.run(PersistingDddAggregatesApplication.class, args);
|
SpringApplication.run(PersistingDddAggregatesApplication.class, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package com.baeldung.dddhexagonalspring.domain;
|
||||||
|
|
||||||
|
class DomainException extends RuntimeException {
|
||||||
|
DomainException(final String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<OrderItem> 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<OrderItem> getOrderItems() {
|
||||||
|
return Collections.unmodifiableList(orderItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Order() {
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
package com.baeldung.dddhexagonalspring.domain;
|
||||||
|
|
||||||
|
public enum OrderStatus {
|
||||||
|
CREATED, COMPLETED
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<Order> findById(UUID id);
|
||||||
|
|
||||||
|
void save(Order order);
|
||||||
|
}
|
|
@ -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"));
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 {
|
||||||
|
}
|
|
@ -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<Order> findById(final UUID id) {
|
||||||
|
return orderRepository.findById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save(final Order order) {
|
||||||
|
orderRepository.save(order);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<Order, UUID> {
|
||||||
|
}
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<Order> 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"));
|
||||||
|
}
|
||||||
|
}
|
|
@ -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*)
|
|
@ -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
|
|
@ -0,0 +1,12 @@
|
||||||
|
db.createUser(
|
||||||
|
{
|
||||||
|
user: "order",
|
||||||
|
pwd: "order",
|
||||||
|
roles: [
|
||||||
|
{
|
||||||
|
role: "readWrite",
|
||||||
|
db: "order-database"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
);
|
|
@ -34,7 +34,7 @@ public class HttpClientMultipartLiveTest {
|
||||||
// No longer available
|
// No longer available
|
||||||
// private static final String SERVER = "http://echo.200please.com";
|
// 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 TEXTFILENAME = "temp.txt";
|
||||||
private static final String IMAGEFILENAME = "image.jpg";
|
private static final String IMAGEFILENAME = "image.jpg";
|
||||||
private static final String ZIPFILENAME = "zipFile.zip";
|
private static final String ZIPFILENAME = "zipFile.zip";
|
||||||
|
@ -84,7 +84,7 @@ public class HttpClientMultipartLiveTest {
|
||||||
//
|
//
|
||||||
final MultipartEntityBuilder builder = MultipartEntityBuilder.create();
|
final MultipartEntityBuilder builder = MultipartEntityBuilder.create();
|
||||||
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
|
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
|
||||||
builder.addPart("upfile", fileBody);
|
builder.addPart("file", fileBody);
|
||||||
builder.addPart("text1", stringBody1);
|
builder.addPart("text1", stringBody1);
|
||||||
builder.addPart("text2", stringBody2);
|
builder.addPart("text2", stringBody2);
|
||||||
final HttpEntity entity = builder.build();
|
final HttpEntity entity = builder.build();
|
||||||
|
@ -112,7 +112,7 @@ public class HttpClientMultipartLiveTest {
|
||||||
final String message = "This is a multipart post";
|
final String message = "This is a multipart post";
|
||||||
final MultipartEntityBuilder builder = MultipartEntityBuilder.create();
|
final MultipartEntityBuilder builder = MultipartEntityBuilder.create();
|
||||||
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
|
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);
|
builder.addTextBody("text", message, ContentType.DEFAULT_BINARY);
|
||||||
final HttpEntity entity = builder.build();
|
final HttpEntity entity = builder.build();
|
||||||
post.setEntity(entity);
|
post.setEntity(entity);
|
||||||
|
@ -141,7 +141,7 @@ public class HttpClientMultipartLiveTest {
|
||||||
final String message = "This is a multipart post";
|
final String message = "This is a multipart post";
|
||||||
final MultipartEntityBuilder builder = MultipartEntityBuilder.create();
|
final MultipartEntityBuilder builder = MultipartEntityBuilder.create();
|
||||||
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
|
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.addBinaryBody("upstream", inputStream, ContentType.create("application/zip"), ZIPFILENAME);
|
||||||
builder.addTextBody("text", message, ContentType.TEXT_PLAIN);
|
builder.addTextBody("text", message, ContentType.TEXT_PLAIN);
|
||||||
final HttpEntity entity = builder.build();
|
final HttpEntity entity = builder.build();
|
||||||
|
@ -165,7 +165,7 @@ public class HttpClientMultipartLiveTest {
|
||||||
final byte[] bytes = "binary code".getBytes();
|
final byte[] bytes = "binary code".getBytes();
|
||||||
final MultipartEntityBuilder builder = MultipartEntityBuilder.create();
|
final MultipartEntityBuilder builder = MultipartEntityBuilder.create();
|
||||||
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
|
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);
|
builder.addTextBody("text", message, ContentType.TEXT_PLAIN);
|
||||||
final HttpEntity entity = builder.build();
|
final HttpEntity entity = builder.build();
|
||||||
post.setEntity(entity);
|
post.setEntity(entity);
|
||||||
|
|
|
@ -24,10 +24,7 @@ public class ConvertToMap {
|
||||||
|
|
||||||
public TreeMap<String, Book> listToSortedMap(List<Book> books) {
|
public TreeMap<String, Book> listToSortedMap(List<Book> books) {
|
||||||
return books.stream()
|
return books.stream()
|
||||||
.sorted(Comparator.comparing(Book::getName))
|
|
||||||
.collect(Collectors.toMap(Book::getName, Function.identity(), (o1, o2) -> o1, TreeMap::new));
|
.collect(Collectors.toMap(Book::getName, Function.identity(), (o1, o2) -> o1, TreeMap::new));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,22 +7,50 @@ import org.apache.tomcat.util.descriptor.web.FilterDef;
|
||||||
import org.apache.tomcat.util.descriptor.web.FilterMap;
|
import org.apache.tomcat.util.descriptor.web.FilterMap;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.ServerSocket;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by adi on 1/10/18.
|
* Created by adi on 1/10/18.
|
||||||
*/
|
*/
|
||||||
public class ProgrammaticTomcat {
|
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 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
|
// uncomment for live test
|
||||||
// public static void main(String[] args) throws LifecycleException, ServletException, URISyntaxException, IOException {
|
// public static void main(String[] args) throws LifecycleException, ServletException, URISyntaxException, IOException {
|
||||||
// startTomcat();
|
// startTomcat();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
public int getPort() {
|
||||||
|
return randomPort;
|
||||||
|
}
|
||||||
|
|
||||||
public void startTomcat() throws LifecycleException {
|
public void startTomcat() throws LifecycleException {
|
||||||
tomcat = new Tomcat();
|
tomcat = new Tomcat();
|
||||||
tomcat.setPort(8080);
|
tomcat.setPort(randomPort);
|
||||||
tomcat.setHostname("localhost");
|
tomcat.setHostname("localhost");
|
||||||
String appBase = ".";
|
String appBase = ".";
|
||||||
tomcat.getHost().setAppBase(appBase);
|
tomcat.getHost().setAppBase(appBase);
|
||||||
|
|
|
@ -37,7 +37,8 @@ public class ProgrammaticTomcatIntegrationTest {
|
||||||
@Test
|
@Test
|
||||||
public void givenTomcatStarted_whenAccessServlet_responseIsTestAndResponseHeaderIsSet() throws Exception {
|
public void givenTomcatStarted_whenAccessServlet_responseIsTestAndResponseHeaderIsSet() throws Exception {
|
||||||
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
|
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);
|
HttpResponse response = httpClient.execute(getServlet);
|
||||||
assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode());
|
assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode());
|
||||||
|
|
|
@ -27,6 +27,12 @@
|
||||||
<artifactId>h2</artifactId>
|
<artifactId>h2</artifactId>
|
||||||
<version>1.4.200</version>
|
<version>1.4.200</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-lang3</artifactId>
|
||||||
|
<version>3.8.1</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<!DOCTYPE hibernate-configuration PUBLIC
|
||||||
|
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
|
||||||
|
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
|
||||||
|
|
||||||
|
<hibernate-configuration>
|
||||||
|
|
||||||
|
<session-factory>
|
||||||
|
<property name="connection.driver_class">org.h2.Driver</property>
|
||||||
|
<property name="connection.url">jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1</property>
|
||||||
|
<property name="connection.username">sa</property>
|
||||||
|
<property name="connection.password"/>
|
||||||
|
|
||||||
|
<property name="connection.pool_size">1</property>
|
||||||
|
|
||||||
|
<property name="dialect">org.hibernate.dialect.H2Dialect</property>
|
||||||
|
|
||||||
|
<property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>
|
||||||
|
|
||||||
|
<property name="hibernate.generate_statistics">true</property>
|
||||||
|
|
||||||
|
<property name="hbm2ddl.auto">create</property>
|
||||||
|
|
||||||
|
<mapping class="com.baeldung.hibernate.logging.Employee"/>
|
||||||
|
</session-factory>
|
||||||
|
|
||||||
|
</hibernate-configuration>
|
|
@ -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<Employee> query = sessionFactory.openSession().createQuery("from com.baeldung.hibernate.logging.Employee", Employee.class);
|
||||||
|
List<Employee> deptEmployees = query.list();
|
||||||
|
Employee deptEmployee = deptEmployees.get(0);
|
||||||
|
assertEquals("John Smith", deptEmployee.getName());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
|
||||||
|
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
|
||||||
|
<appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
|
||||||
|
<layout class="org.apache.log4j.PatternLayout">
|
||||||
|
<param name="ConversionPattern" value="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
|
||||||
|
</layout>
|
||||||
|
</appender>
|
||||||
|
<logger name="org.hibernate">
|
||||||
|
<level value="info" />
|
||||||
|
</logger>
|
||||||
|
<logger name="org.hibernate.SQL">
|
||||||
|
<level value="debug" />
|
||||||
|
</logger>
|
||||||
|
<logger name="org.hibernate.type.descriptor.sql">
|
||||||
|
<level value="trace" />
|
||||||
|
</logger>
|
||||||
|
<logger name="org.hibernate.stat">
|
||||||
|
<level value="debug" />
|
||||||
|
</logger>
|
||||||
|
<root>
|
||||||
|
<priority value ="info" />
|
||||||
|
<appender-ref ref="STDOUT" />
|
||||||
|
</root>
|
||||||
|
</log4j:configuration>
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Configuration status="INFO">
|
||||||
|
<Appenders>
|
||||||
|
<Console name="console" target="SYSTEM_OUT">
|
||||||
|
<PatternLayout
|
||||||
|
pattern="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n" />
|
||||||
|
</Console>
|
||||||
|
</Appenders>
|
||||||
|
<Loggers>
|
||||||
|
<Logger name="org.hibernate" level="info"/>
|
||||||
|
<Logger name="org.hibernate.SQL" level="debug"/>
|
||||||
|
<Logger name="org.hibernate.type.descriptor.sql" level="trace"/>
|
||||||
|
<Logger name="org.hibernate.stat" level="debug" />
|
||||||
|
<Root level="info" additivity="false">
|
||||||
|
<AppenderRef ref="console" />
|
||||||
|
</Root>
|
||||||
|
</Loggers>
|
||||||
|
</Configuration>
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration>
|
||||||
|
|
||||||
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<encoder>
|
||||||
|
<pattern>%d{yyyy-MM-dd HH:mm:ss} | %-5p | [%thread] %logger{5}:%L - %msg%n</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<logger name="org.hibernate" level="INFO" />
|
||||||
|
<logger name="org.hibernate.SQL" level="DEBUG" />
|
||||||
|
<logger name="org.hibernate.type.descriptor.sql" level="TRACE" />
|
||||||
|
<logger name="org.hibernate.stat" level="DEBUG" />
|
||||||
|
|
||||||
|
<root level="INFO">
|
||||||
|
<appender-ref ref="STDOUT" />
|
||||||
|
</root>
|
||||||
|
</configuration>
|
|
@ -73,8 +73,8 @@
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
<spring-cloud.version>Finchley.SR1</spring-cloud.version>
|
<spring-cloud.version>Hoxton.RELEASE</spring-cloud.version>
|
||||||
<spring-boot.version>2.0.6.RELEASE</spring-boot.version>
|
<spring-boot.version>2.2.2.RELEASE</spring-boot.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -12,10 +12,6 @@
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>commons-lang3</artifactId>
|
<artifactId>commons-lang3</artifactId>
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
package com.baeldung.web.controller;
|
package com.baeldung.web.controller;
|
||||||
|
|
||||||
import com.baeldung.web.dto.Foo;
|
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.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
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.randomAlphabetic;
|
||||||
import static org.apache.commons.lang3.RandomStringUtils.randomNumeric;
|
import static org.apache.commons.lang3.RandomStringUtils.randomNumeric;
|
||||||
|
|
||||||
@Controller
|
@RestController
|
||||||
public class FooController {
|
public class FooController {
|
||||||
|
|
||||||
public FooController() {
|
@GetMapping("/foos/{id}")
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
// API - read
|
|
||||||
@RequestMapping(method = RequestMethod.GET, value = "/foos/{id}")
|
|
||||||
@ResponseBody
|
|
||||||
public Foo findById(@PathVariable final long id, HttpServletRequest req, HttpServletResponse res) {
|
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) {
|
if (req.getHeader("Test") != null) {
|
||||||
res.addHeader("Test", req.getHeader("Test"));
|
res.addHeader("Test", req.getHeader("Test"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Foo(Long.parseLong(randomNumeric(2)), randomAlphabetic(4));
|
return new Foo(Long.parseLong(randomNumeric(2)), randomAlphabetic(4));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,15 @@
|
||||||
package com.baeldung.web.dto;
|
package com.baeldung.web.dto;
|
||||||
|
|
||||||
public class Foo {
|
public class Foo {
|
||||||
|
|
||||||
private long id;
|
private long id;
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
public Foo() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Foo(final long id, final String name) {
|
public Foo(final long id, final String name) {
|
||||||
super();
|
|
||||||
|
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
public long getId() {
|
public long getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
package org.baeldung.store;
|
||||||
|
|
||||||
|
public interface Item {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
package org.baeldung.store;
|
||||||
|
|
||||||
|
public class ItemImpl1 implements Item {
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||||
|
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
|
||||||
|
|
||||||
|
<!-- Autowired injection -->
|
||||||
|
|
||||||
|
<bean id="item" class="org.baeldung.store.ItemImpl1" />
|
||||||
|
|
||||||
|
<bean id="xml-store-by-autowire-type" class="org.baeldung.store.Store" autowire="byType">
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
</beans>
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||||
|
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
|
||||||
|
|
||||||
|
<!-- Constructor injection -->
|
||||||
|
|
||||||
|
<bean id="item1" class="org.baeldung.store.ItemImpl1" />
|
||||||
|
<bean id="xml-store-by-constructor" class="org.baeldung.store.Store">
|
||||||
|
<constructor-arg type="Item" index="0" name="item" ref="item1" />
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- Setter injection -->
|
||||||
|
|
||||||
|
<bean id="xml-store-by-setter" class="org.baeldung.store.Store">
|
||||||
|
<property name="item" ref="item1" />
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- Autowired injection -->
|
||||||
|
|
||||||
|
<bean id="item" class="org.baeldung.store.ItemImpl1" />
|
||||||
|
|
||||||
|
<bean id="xml-store-by-autowire-name" class="org.baeldung.store.Store" autowire="byName">
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- Lazy instantiation -->
|
||||||
|
|
||||||
|
<bean id="item1-lazy" class="org.baeldung.store.ItemImpl1" lazy-init="true" />
|
||||||
|
<bean id="xml-store-by-setter-lazy" class="org.baeldung.store.Store">
|
||||||
|
<property name="item" ref="item1-lazy" />
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
</beans>
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package com.baeldung.model;
|
package com.baeldung.controller.optionalpathvars;
|
||||||
|
|
||||||
public class Article {
|
public class Article {
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
package com.baeldung.controller.optionalpathvars;
|
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.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import com.baeldung.model.Article;
|
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
public class ArticleViewerController {
|
public class ArticleViewerController {
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package com.baeldung.controller.optionalpathvars;
|
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;
|
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.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import com.baeldung.model.Article;
|
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping(value = "/mapParam")
|
@RequestMapping(value = "/mapParam")
|
||||||
public class ArticleViewerWithMapParamController {
|
public class ArticleViewerWithMapParamController {
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
package com.baeldung.controller.optionalpathvars;
|
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 java.util.Optional;
|
||||||
|
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;;
|
||||||
|
|
||||||
import com.baeldung.model.Article;;
|
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/optionalParam")
|
@RequestMapping("/optionalParam")
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
package com.baeldung.controller.optionalpathvars;
|
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.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;;
|
||||||
|
|
||||||
import com.baeldung.model.Article;;
|
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping(value = "/requiredAttribute")
|
@RequestMapping(value = "/requiredAttribute")
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
package com.baeldung.controller.optionalpathvars;
|
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.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import com.baeldung.model.Article;
|
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping(value = "/seperateMethods")
|
@RequestMapping(value = "/seperateMethods")
|
||||||
public class ArticleViewerWithTwoSeparateMethodsController {
|
public class ArticleViewerWithTwoSeparateMethodsController {
|
||||||
|
|
|
@ -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.result.MockMvcResultMatchers;
|
||||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||||
import org.springframework.web.context.WebApplicationContext;
|
import org.springframework.web.context.WebApplicationContext;
|
||||||
|
|
||||||
import com.baeldung.model.Article;
|
|
||||||
import org.baeldung.controller.config.WebConfig;
|
import org.baeldung.controller.config.WebConfig;
|
||||||
|
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
|
|
|
@ -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.result.MockMvcResultMatchers;
|
||||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||||
import org.springframework.web.context.WebApplicationContext;
|
import org.springframework.web.context.WebApplicationContext;
|
||||||
|
|
||||||
import com.baeldung.model.Article;
|
|
||||||
import org.baeldung.controller.config.WebConfig;
|
import org.baeldung.controller.config.WebConfig;
|
||||||
|
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
|
|
|
@ -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.result.MockMvcResultMatchers;
|
||||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||||
import org.springframework.web.context.WebApplicationContext;
|
import org.springframework.web.context.WebApplicationContext;
|
||||||
|
|
||||||
import com.baeldung.model.Article;
|
|
||||||
import org.baeldung.controller.config.WebConfig;
|
import org.baeldung.controller.config.WebConfig;
|
||||||
|
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
|
|
|
@ -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.result.MockMvcResultMatchers;
|
||||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||||
import org.springframework.web.context.WebApplicationContext;
|
import org.springframework.web.context.WebApplicationContext;
|
||||||
|
|
||||||
import com.baeldung.model.Article;
|
|
||||||
import org.baeldung.controller.config.WebConfig;
|
import org.baeldung.controller.config.WebConfig;
|
||||||
|
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
|
|
|
@ -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<UploadResultResource> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ import org.junit.runner.RunWith;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||||
|
import org.springframework.boot.web.server.LocalServerPort;
|
||||||
import org.springframework.http.HttpEntity;
|
import org.springframework.http.HttpEntity;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
|
@ -16,9 +17,12 @@ import java.util.Base64;
|
||||||
|
|
||||||
|
|
||||||
@RunWith(SpringRunner.class)
|
@RunWith(SpringRunner.class)
|
||||||
@SpringBootTest(classes = SpringSessionMongoDBApplication.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
|
@SpringBootTest(classes = SpringSessionMongoDBApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||||
public class SpringSessionMongoDBIntegrationTest {
|
public class SpringSessionMongoDBIntegrationTest {
|
||||||
|
|
||||||
|
@LocalServerPort
|
||||||
|
private int port;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private MongoOperationsSessionRepository repository;
|
private MongoOperationsSessionRepository repository;
|
||||||
|
|
||||||
|
@ -27,7 +31,7 @@ public class SpringSessionMongoDBIntegrationTest {
|
||||||
@Test
|
@Test
|
||||||
public void givenEndpointIsCalledTwiceAndResponseIsReturned_whenMongoDBIsQueriedForCount_thenCountMustBeSame() {
|
public void givenEndpointIsCalledTwiceAndResponseIsReturned_whenMongoDBIsQueriedForCount_thenCountMustBeSame() {
|
||||||
HttpEntity<String> response = restTemplate
|
HttpEntity<String> response = restTemplate
|
||||||
.exchange("http://localhost:" + 8080, HttpMethod.GET, null, String.class);
|
.exchange("http://localhost:" + port, HttpMethod.GET, null, String.class);
|
||||||
HttpHeaders headers = response.getHeaders();
|
HttpHeaders headers = response.getHeaders();
|
||||||
String set_cookie = headers.getFirst(HttpHeaders.SET_COOKIE);
|
String set_cookie = headers.getFirst(HttpHeaders.SET_COOKIE);
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,11 @@
|
||||||
package com.baeldung.spring.session;
|
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.AfterClass;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
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;
|
||||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
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.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.test.context.junit4.SpringRunner;
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
|
|
||||||
import redis.clients.jedis.Jedis;
|
import redis.clients.jedis.Jedis;
|
||||||
import redis.embedded.RedisServer;
|
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)
|
@RunWith(SpringRunner.class)
|
||||||
@SpringBootTest(classes = SessionWebApplication.class, webEnvironment = WebEnvironment.DEFINED_PORT)
|
@SpringBootTest(classes = SessionWebApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||||
public class SessionControllerIntegrationTest {
|
public class SessionControllerIntegrationTest {
|
||||||
|
|
||||||
private Jedis jedis;
|
|
||||||
private static RedisServer redisServer;
|
private static RedisServer redisServer;
|
||||||
|
|
||||||
|
@LocalServerPort
|
||||||
|
private int port;
|
||||||
|
|
||||||
|
private Jedis jedis;
|
||||||
private TestRestTemplate testRestTemplate;
|
private TestRestTemplate testRestTemplate;
|
||||||
private TestRestTemplate testRestTemplateWithAuth;
|
private TestRestTemplate testRestTemplateWithAuth;
|
||||||
private String testUrl = "http://localhost:8080/";
|
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void startRedisServer() throws IOException {
|
public static void startRedisServer() throws IOException {
|
||||||
|
@ -41,7 +44,7 @@ public class SessionControllerIntegrationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterClass
|
@AfterClass
|
||||||
public static void stopRedisServer() throws IOException {
|
public static void stopRedisServer() {
|
||||||
redisServer.stop();
|
redisServer.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,13 +66,13 @@ public class SessionControllerIntegrationTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUnauthenticatedCantAccess() {
|
public void testUnauthenticatedCantAccess() {
|
||||||
ResponseEntity<String> result = testRestTemplate.getForEntity(testUrl, String.class);
|
ResponseEntity<String> result = testRestTemplate.getForEntity(getTestUrl(), String.class);
|
||||||
assertEquals(HttpStatus.UNAUTHORIZED, result.getStatusCode());
|
assertEquals(HttpStatus.UNAUTHORIZED, result.getStatusCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRedisControlsSession() {
|
public void testRedisControlsSession() {
|
||||||
ResponseEntity<String> result = testRestTemplateWithAuth.getForEntity(testUrl, String.class);
|
ResponseEntity<String> result = testRestTemplateWithAuth.getForEntity(getTestUrl(), String.class);
|
||||||
assertEquals("hello admin", result.getBody()); // login worked
|
assertEquals("hello admin", result.getBody()); // login worked
|
||||||
|
|
||||||
Set<String> redisResult = jedis.keys("*");
|
Set<String> redisResult = jedis.keys("*");
|
||||||
|
@ -80,13 +83,16 @@ public class SessionControllerIntegrationTest {
|
||||||
headers.add("Cookie", sessionCookie);
|
headers.add("Cookie", sessionCookie);
|
||||||
HttpEntity<String> httpEntity = new HttpEntity<>(headers);
|
HttpEntity<String> 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
|
assertEquals("hello admin", result.getBody()); // access with session works worked
|
||||||
|
|
||||||
jedis.flushAll(); // clear all keys in redis
|
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
|
assertEquals(HttpStatus.UNAUTHORIZED, result.getStatusCode());// access denied after sessions are removed in redis
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getTestUrl(){
|
||||||
|
return "http://localhost:" + port;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -19,10 +19,4 @@ public class BookStore {
|
||||||
.filter(book -> Objects.equals(author, book.getAuthor()))
|
.filter(book -> Objects.equals(author, book.getAuthor()))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<Book> bookByTitle(String title) {
|
|
||||||
return books.stream()
|
|
||||||
.filter(book -> book.getTitle().equals(title))
|
|
||||||
.findFirst();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 + "]";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.baeldung.cucumberbackground.books;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class BookStore {
|
||||||
|
private List<Book> books = new ArrayList<>();
|
||||||
|
|
||||||
|
public void addBook(Book book) {
|
||||||
|
books.add(book);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addAllBooks(Collection<Book> books) {
|
||||||
|
this.books.addAll(books);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Book> booksByAuthor(String author) {
|
||||||
|
return books.stream()
|
||||||
|
.filter(book -> Objects.equals(author, book.getAuthor()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<Book> bookByTitle(String title) {
|
||||||
|
return books.stream()
|
||||||
|
.filter(book -> book.getTitle().equals(title))
|
||||||
|
.findFirst();
|
||||||
|
}
|
||||||
|
}
|
|
@ -56,11 +56,6 @@ public class BookStoreRunSteps {
|
||||||
foundBooks = store.booksByAuthor(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$")
|
@Then("^I find (\\d+) books$")
|
||||||
public void findBooks(int count) {
|
public void findBooks(int count) {
|
||||||
assertEquals(count, foundBooks.size());
|
assertEquals(count, foundBooks.size());
|
||||||
|
|
|
@ -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<Book> 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<List<String>> rows = table.asLists(String.class);
|
||||||
|
|
||||||
|
for (List<String> 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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue