This commit is contained in:
Jonathan Cook 2019-12-13 19:19:35 +00:00
commit c8996a936e
90 changed files with 1522 additions and 104 deletions

View File

@ -0,0 +1,5 @@
## Core Java Exceptions 2
This module contains articles about core java exceptions
###

View File

@ -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>

View File

@ -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);
}
}
}

View File

@ -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;
}
}
}

View File

@ -0,0 +1,8 @@
package com.baeldung.rethrow.custom;
public class InvalidDataException extends Exception {
public InvalidDataException(Exception e) {
super(e);
}
}

View File

@ -76,6 +76,11 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -0,0 +1,7 @@
package com.baeldung.dddhexagonalspring.domain;
class DomainException extends RuntimeException {
DomainException(final String message) {
super(message);
}
}

View File

@ -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() {
}
}

View File

@ -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);
}
}

View File

@ -0,0 +1,5 @@
package com.baeldung.dddhexagonalspring.domain;
public enum OrderStatus {
CREATED, COMPLETED
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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"));
}
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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 {
}

View File

@ -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);
}
}

View File

@ -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> {
}

View File

@ -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

View File

@ -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;
}
}

View File

@ -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());
}
}

View File

@ -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);
}
}

View File

@ -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"));
}
}

View File

@ -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*)

View File

@ -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

View File

@ -0,0 +1,12 @@
db.createUser(
{
user: "order",
pwd: "order",
roles: [
{
role: "readWrite",
db: "order-database"
}
]
}
);

View File

@ -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);

View File

@ -24,10 +24,7 @@ public class ConvertToMap {
public TreeMap<String, Book> listToSortedMap(List<Book> books) {
return books.stream()
.sorted(Comparator.comparing(Book::getName))
.collect(Collectors.toMap(Book::getName, Function.identity(), (o1, o2) -> o1, TreeMap::new));
}
}

View File

@ -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);

View File

@ -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());

View File

@ -27,6 +27,12 @@
<artifactId>h2</artifactId>
<version>1.4.200</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8.1</version>
</dependency>
</dependencies>
<properties>

View File

@ -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;
}
}

View File

@ -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>

View File

@ -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());
}
}

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -73,8 +73,8 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-cloud.version>Finchley.SR1</spring-cloud.version>
<spring-boot.version>2.0.6.RELEASE</spring-boot.version>
<spring-cloud.version>Hoxton.RELEASE</spring-cloud.version>
<spring-boot.version>2.2.2.RELEASE</spring-boot.version>
</properties>
</project>

View File

@ -12,10 +12,6 @@
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>

View File

@ -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));
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -0,0 +1,5 @@
package org.baeldung.store;
public interface Item {
}

View File

@ -0,0 +1,5 @@
package org.baeldung.store;
public class ItemImpl1 implements Item {
}

View File

@ -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;
}
}

View File

@ -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>

View File

@ -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>

View File

@ -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());
}
}

View File

@ -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());
}
}

View File

@ -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());
}
}

View File

@ -1,4 +1,4 @@
package com.baeldung.model;
package com.baeldung.controller.optionalpathvars;
public class Article {

View File

@ -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 {

View File

@ -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 {

View File

@ -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")

View File

@ -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")

View File

@ -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 {

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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;
}
}
}

View File

@ -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<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();
String set_cookie = headers.getFirst(HttpHeaders.SET_COOKIE);

View File

@ -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<String> result = testRestTemplate.getForEntity(testUrl, String.class);
ResponseEntity<String> result = testRestTemplate.getForEntity(getTestUrl(), String.class);
assertEquals(HttpStatus.UNAUTHORIZED, result.getStatusCode());
}
@Test
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
Set<String> redisResult = jedis.keys("*");
@ -80,13 +83,16 @@ public class SessionControllerIntegrationTest {
headers.add("Cookie", sessionCookie);
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
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;
}
}

View File

@ -19,10 +19,4 @@ public class BookStore {
.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();
}
}

View File

@ -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 + "]";
}
}

View File

@ -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();
}
}

View File

@ -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());

View File

@ -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);
}
}

View File

@ -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 {
}

View File

@ -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 {
}